From 4bdc0d676a643140bdf17dbf7eafedee3d496a3c Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Mon, 6 Jan 2020 09:43:50 +0100 Subject: remove ioremap_nocache and devm_ioremap_nocache ioremap has provided non-cached semantics by default since the Linux 2.6 days, so remove the additional ioremap_nocache interface. Signed-off-by: Christoph Hellwig Acked-by: Arnd Bergmann --- drivers/input/keyboard/pxa930_rotary.c | 2 +- drivers/input/keyboard/sh_keysc.c | 2 +- drivers/input/mouse/pxa930_trkball.c | 2 +- drivers/input/serio/gscps2.c | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers/input') diff --git a/drivers/input/keyboard/pxa930_rotary.c b/drivers/input/keyboard/pxa930_rotary.c index f7414091d94e..2fe9dcfe0a6f 100644 --- a/drivers/input/keyboard/pxa930_rotary.c +++ b/drivers/input/keyboard/pxa930_rotary.c @@ -107,7 +107,7 @@ static int pxa930_rotary_probe(struct platform_device *pdev) if (!r) return -ENOMEM; - r->mmio_base = ioremap_nocache(res->start, resource_size(res)); + r->mmio_base = ioremap(res->start, resource_size(res)); if (r->mmio_base == NULL) { dev_err(&pdev->dev, "failed to remap IO memory\n"); err = -ENXIO; diff --git a/drivers/input/keyboard/sh_keysc.c b/drivers/input/keyboard/sh_keysc.c index 27ad73f43451..c155adebf96e 100644 --- a/drivers/input/keyboard/sh_keysc.c +++ b/drivers/input/keyboard/sh_keysc.c @@ -195,7 +195,7 @@ static int sh_keysc_probe(struct platform_device *pdev) memcpy(&priv->pdata, dev_get_platdata(&pdev->dev), sizeof(priv->pdata)); pdata = &priv->pdata; - priv->iomem_base = ioremap_nocache(res->start, resource_size(res)); + priv->iomem_base = ioremap(res->start, resource_size(res)); if (priv->iomem_base == NULL) { dev_err(&pdev->dev, "failed to remap I/O memory\n"); error = -ENXIO; diff --git a/drivers/input/mouse/pxa930_trkball.c b/drivers/input/mouse/pxa930_trkball.c index 41acde60b60f..3332b77eef2a 100644 --- a/drivers/input/mouse/pxa930_trkball.c +++ b/drivers/input/mouse/pxa930_trkball.c @@ -167,7 +167,7 @@ static int pxa930_trkball_probe(struct platform_device *pdev) goto failed; } - trkball->mmio_base = ioremap_nocache(res->start, resource_size(res)); + trkball->mmio_base = ioremap(res->start, resource_size(res)); if (!trkball->mmio_base) { dev_err(&pdev->dev, "failed to ioremap registers\n"); error = -ENXIO; diff --git a/drivers/input/serio/gscps2.c b/drivers/input/serio/gscps2.c index 96f9b5397367..2f9775de3c5b 100644 --- a/drivers/input/serio/gscps2.c +++ b/drivers/input/serio/gscps2.c @@ -349,7 +349,7 @@ static int __init gscps2_probe(struct parisc_device *dev) ps2port->port = serio; ps2port->padev = dev; - ps2port->addr = ioremap_nocache(hpa, GSC_STATUS + 4); + ps2port->addr = ioremap(hpa, GSC_STATUS + 4); spin_lock_init(&ps2port->lock); gscps2_reset(ps2port); -- cgit v1.2.3 From e2379b30324ca5ba808f16cb3d2504349264912f Mon Sep 17 00:00:00 2001 From: Dexuan Cui Date: Mon, 6 Jan 2020 14:40:44 -0800 Subject: Input: hyperv-keyboard: Add the support of hibernation Add suspend() and resume() functions so the Hyper-V virtual keyboard can participate in VM hibernation. Note that the keyboard is a "wakeup" device that could abort an in-progress hibernation if there is keyboard event. No attempt is made to suppress this behavior. If desired, a sysadmin can disable the keyboard as a wakeup device using standard mechanisms such as: echo disabled > /sys/bus/vmbus/drivers/hyperv_keyboard/XXX/power/wakeup (where XXX is the device's GUID) Reviewed-by: Michael Kelley Signed-off-by: Dexuan Cui Signed-off-by: Sasha Levin --- drivers/input/serio/hyperv-keyboard.c | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) (limited to 'drivers/input') diff --git a/drivers/input/serio/hyperv-keyboard.c b/drivers/input/serio/hyperv-keyboard.c index e486a8a74c40..df4e9f6f4529 100644 --- a/drivers/input/serio/hyperv-keyboard.c +++ b/drivers/input/serio/hyperv-keyboard.c @@ -259,6 +259,8 @@ static int hv_kbd_connect_to_vsp(struct hv_device *hv_dev) u32 proto_status; int error; + reinit_completion(&kbd_dev->wait_event); + request = &kbd_dev->protocol_req; memset(request, 0, sizeof(struct synth_kbd_protocol_request)); request->header.type = __cpu_to_le32(SYNTH_KBD_PROTOCOL_REQUEST); @@ -380,6 +382,29 @@ static int hv_kbd_remove(struct hv_device *hv_dev) return 0; } +static int hv_kbd_suspend(struct hv_device *hv_dev) +{ + vmbus_close(hv_dev->channel); + + return 0; +} + +static int hv_kbd_resume(struct hv_device *hv_dev) +{ + int ret; + + ret = vmbus_open(hv_dev->channel, + KBD_VSC_SEND_RING_BUFFER_SIZE, + KBD_VSC_RECV_RING_BUFFER_SIZE, + NULL, 0, + hv_kbd_on_channel_callback, + hv_dev); + if (ret == 0) + ret = hv_kbd_connect_to_vsp(hv_dev); + + return ret; +} + static const struct hv_vmbus_device_id id_table[] = { /* Keyboard guid */ { HV_KBD_GUID, }, @@ -393,6 +418,8 @@ static struct hv_driver hv_kbd_drv = { .id_table = id_table, .probe = hv_kbd_probe, .remove = hv_kbd_remove, + .suspend = hv_kbd_suspend, + .resume = hv_kbd_resume, .driver = { .probe_type = PROBE_PREFER_ASYNCHRONOUS, }, -- cgit v1.2.3 From 97a32539b9568bb653683349e5a76d02ff3c3e2c Mon Sep 17 00:00:00 2001 From: Alexey Dobriyan Date: Mon, 3 Feb 2020 17:37:17 -0800 Subject: proc: convert everything to "struct proc_ops" The most notable change is DEFINE_SHOW_ATTRIBUTE macro split in seq_file.h. Conversion rule is: llseek => proc_lseek unlocked_ioctl => proc_ioctl xxx => proc_xxx delete ".owner = THIS_MODULE" line [akpm@linux-foundation.org: fix drivers/isdn/capi/kcapi_proc.c] [sfr@canb.auug.org.au: fix kernel/sched/psi.c] Link: http://lkml.kernel.org/r/20200122180545.36222f50@canb.auug.org.au Link: http://lkml.kernel.org/r/20191225172546.GB13378@avx2 Signed-off-by: Alexey Dobriyan Signed-off-by: Stephen Rothwell Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/alpha/kernel/srm_env.c | 17 ++-- arch/arm/kernel/atags_proc.c | 8 +- arch/arm/mm/alignment.c | 14 +-- arch/ia64/kernel/salinfo.c | 24 ++--- arch/m68k/kernel/bootinfo_proc.c | 8 +- arch/mips/lasat/picvue_proc.c | 31 +++--- arch/powerpc/kernel/proc_powerpc.c | 10 +- arch/powerpc/kernel/rtas-proc.c | 70 ++++++------- arch/powerpc/kernel/rtas_flash.c | 34 +++---- arch/powerpc/kernel/rtasd.c | 14 +-- arch/powerpc/mm/numa.c | 12 +-- arch/powerpc/platforms/pseries/lpar.c | 24 ++--- arch/powerpc/platforms/pseries/lparcfg.c | 14 +-- arch/powerpc/platforms/pseries/reconfig.c | 8 +- arch/powerpc/platforms/pseries/scanlog.c | 15 ++- arch/sh/mm/alignment.c | 17 ++-- arch/sparc/kernel/led.c | 15 ++- arch/um/drivers/mconsole_kern.c | 9 +- arch/um/kernel/exitcode.c | 15 ++- arch/um/kernel/process.c | 15 ++- arch/x86/kernel/cpu/mtrr/if.c | 21 ++-- arch/x86/platform/uv/tlb_uv.c | 14 +-- arch/xtensa/platforms/iss/simdisk.c | 10 +- drivers/acpi/battery.c | 15 ++- drivers/acpi/proc.c | 15 ++- drivers/hwmon/dell-smm-hwmon.c | 15 ++- drivers/ide/ide-proc.c | 19 ++-- drivers/input/input.c | 28 +++--- drivers/isdn/capi/kcapi_proc.c | 6 +- drivers/macintosh/via-pmu.c | 17 ++-- drivers/md/md.c | 15 ++- drivers/misc/sgi-gru/gruprocfs.c | 42 ++++---- drivers/net/wireless/cisco/airo.c | 98 +++++++++---------- drivers/net/wireless/intel/ipw2x00/libipw_module.c | 15 ++- drivers/net/wireless/intersil/hostap/hostap_hw.c | 4 +- drivers/net/wireless/intersil/hostap/hostap_proc.c | 14 +-- drivers/net/wireless/intersil/hostap/hostap_wlan.h | 2 +- drivers/net/wireless/ray_cs.c | 20 ++-- drivers/parisc/led.c | 17 ++-- drivers/pci/proc.c | 25 ++--- drivers/platform/x86/thinkpad_acpi.c | 15 ++- drivers/platform/x86/toshiba_acpi.c | 60 ++++++------ drivers/pnp/isapnp/proc.c | 9 +- drivers/pnp/pnpbios/proc.c | 17 ++-- drivers/s390/block/dasd_proc.c | 15 ++- drivers/s390/cio/blacklist.c | 14 +-- drivers/s390/cio/css.c | 11 +-- drivers/scsi/esas2r/esas2r_main.c | 9 +- drivers/scsi/scsi_devinfo.c | 15 ++- drivers/scsi/scsi_proc.c | 29 +++--- drivers/scsi/sg.c | 30 +++--- .../staging/rtl8192u/ieee80211/ieee80211_module.c | 14 +-- drivers/tty/sysrq.c | 8 +- drivers/usb/gadget/function/rndis.c | 17 ++-- drivers/video/fbdev/via/viafbdev.c | 105 ++++++++++---------- drivers/zorro/proc.c | 9 +- fs/cifs/cifs_debug.c | 108 ++++++++++----------- fs/cifs/dfs_cache.c | 13 +-- fs/cifs/dfs_cache.h | 2 +- fs/fscache/internal.h | 2 +- fs/fscache/object-list.c | 11 ++- fs/fscache/proc.c | 2 +- fs/jbd2/journal.c | 13 ++- fs/jfs/jfs_debug.c | 14 +-- fs/lockd/procfs.c | 12 +-- fs/nfsd/nfsctl.c | 13 ++- fs/nfsd/stats.c | 12 +-- fs/proc/cpuinfo.c | 12 +-- fs/proc/kcore.c | 13 ++- fs/proc/kmsg.c | 14 +-- fs/proc/page.c | 24 ++--- fs/proc/stat.c | 12 +-- fs/proc/vmcore.c | 10 +- include/linux/seq_file.h | 13 +++ include/linux/sunrpc/stats.h | 4 +- ipc/util.c | 14 +-- kernel/configs.c | 9 +- kernel/irq/proc.c | 42 ++++---- kernel/kallsyms.c | 12 +-- kernel/latencytop.c | 14 +-- kernel/locking/lockdep_proc.c | 15 ++- kernel/module.c | 12 +-- kernel/profile.c | 24 ++--- kernel/sched/psi.c | 48 ++++----- mm/slab_common.c | 15 ++- mm/swapfile.c | 14 +-- net/atm/mpoa_proc.c | 17 ++-- net/atm/proc.c | 8 +- net/core/pktgen.c | 44 ++++----- net/ipv4/ipconfig.c | 10 +- net/ipv4/netfilter/ipt_CLUSTERIP.c | 16 +-- net/ipv4/route.c | 24 ++--- net/netfilter/xt_recent.c | 17 ++-- net/sunrpc/auth_gss/svcauth_gss.c | 10 +- net/sunrpc/cache.c | 45 +++++---- net/sunrpc/stats.c | 21 ++-- samples/kfifo/bytestream-example.c | 11 +-- samples/kfifo/inttype-example.c | 11 +-- samples/kfifo/record-example.c | 11 +-- sound/core/info.c | 36 ++++--- 100 files changed, 961 insertions(+), 1006 deletions(-) (limited to 'drivers/input') diff --git a/arch/alpha/kernel/srm_env.c b/arch/alpha/kernel/srm_env.c index 7268222cf4e1..528d2be58182 100644 --- a/arch/alpha/kernel/srm_env.c +++ b/arch/alpha/kernel/srm_env.c @@ -119,13 +119,12 @@ static ssize_t srm_env_proc_write(struct file *file, const char __user *buffer, return res; } -static const struct file_operations srm_env_proc_fops = { - .owner = THIS_MODULE, - .open = srm_env_proc_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, - .write = srm_env_proc_write, +static const struct proc_ops srm_env_proc_ops = { + .proc_open = srm_env_proc_open, + .proc_read = seq_read, + .proc_lseek = seq_lseek, + .proc_release = single_release, + .proc_write = srm_env_proc_write, }; static int __init @@ -182,7 +181,7 @@ srm_env_init(void) entry = srm_named_entries; while (entry->name && entry->id) { if (!proc_create_data(entry->name, 0644, named_dir, - &srm_env_proc_fops, (void *)entry->id)) + &srm_env_proc_ops, (void *)entry->id)) goto cleanup; entry++; } @@ -194,7 +193,7 @@ srm_env_init(void) char name[4]; sprintf(name, "%ld", var_num); if (!proc_create_data(name, 0644, numbered_dir, - &srm_env_proc_fops, (void *)var_num)) + &srm_env_proc_ops, (void *)var_num)) goto cleanup; } diff --git a/arch/arm/kernel/atags_proc.c b/arch/arm/kernel/atags_proc.c index 312cb89ec364..4247ebf4b893 100644 --- a/arch/arm/kernel/atags_proc.c +++ b/arch/arm/kernel/atags_proc.c @@ -17,9 +17,9 @@ static ssize_t atags_read(struct file *file, char __user *buf, return simple_read_from_buffer(buf, count, ppos, b->data, b->size); } -static const struct file_operations atags_fops = { - .read = atags_read, - .llseek = default_llseek, +static const struct proc_ops atags_proc_ops = { + .proc_read = atags_read, + .proc_lseek = default_llseek, }; #define BOOT_PARAMS_SIZE 1536 @@ -61,7 +61,7 @@ static int __init init_atags_procfs(void) b->size = size; memcpy(b->data, atags_copy, size); - tags_entry = proc_create_data("atags", 0400, NULL, &atags_fops, b); + tags_entry = proc_create_data("atags", 0400, NULL, &atags_proc_ops, b); if (!tags_entry) goto nomem; diff --git a/arch/arm/mm/alignment.c b/arch/arm/mm/alignment.c index 788c5cf46de5..84718eddae60 100644 --- a/arch/arm/mm/alignment.c +++ b/arch/arm/mm/alignment.c @@ -162,12 +162,12 @@ static ssize_t alignment_proc_write(struct file *file, const char __user *buffer return count; } -static const struct file_operations alignment_proc_fops = { - .open = alignment_proc_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, - .write = alignment_proc_write, +static const struct proc_ops alignment_proc_ops = { + .proc_open = alignment_proc_open, + .proc_read = seq_read, + .proc_lseek = seq_lseek, + .proc_release = single_release, + .proc_write = alignment_proc_write, }; #endif /* CONFIG_PROC_FS */ @@ -1016,7 +1016,7 @@ static int __init alignment_init(void) struct proc_dir_entry *res; res = proc_create("cpu/alignment", S_IWUSR | S_IRUGO, NULL, - &alignment_proc_fops); + &alignment_proc_ops); if (!res) return -ENOMEM; #endif diff --git a/arch/ia64/kernel/salinfo.c b/arch/ia64/kernel/salinfo.c index b392c0a50346..a25ab9b37953 100644 --- a/arch/ia64/kernel/salinfo.c +++ b/arch/ia64/kernel/salinfo.c @@ -331,10 +331,10 @@ retry: return size; } -static const struct file_operations salinfo_event_fops = { - .open = salinfo_event_open, - .read = salinfo_event_read, - .llseek = noop_llseek, +static const struct proc_ops salinfo_event_proc_ops = { + .proc_open = salinfo_event_open, + .proc_read = salinfo_event_read, + .proc_lseek = noop_llseek, }; static int @@ -534,12 +534,12 @@ salinfo_log_write(struct file *file, const char __user *buffer, size_t count, lo return count; } -static const struct file_operations salinfo_data_fops = { - .open = salinfo_log_open, - .release = salinfo_log_release, - .read = salinfo_log_read, - .write = salinfo_log_write, - .llseek = default_llseek, +static const struct proc_ops salinfo_data_proc_ops = { + .proc_open = salinfo_log_open, + .proc_release = salinfo_log_release, + .proc_read = salinfo_log_read, + .proc_write = salinfo_log_write, + .proc_lseek = default_llseek, }; static int salinfo_cpu_online(unsigned int cpu) @@ -617,13 +617,13 @@ salinfo_init(void) continue; entry = proc_create_data("event", S_IRUSR, dir, - &salinfo_event_fops, data); + &salinfo_event_proc_ops, data); if (!entry) continue; *sdir++ = entry; entry = proc_create_data("data", S_IRUSR | S_IWUSR, dir, - &salinfo_data_fops, data); + &salinfo_data_proc_ops, data); if (!entry) continue; *sdir++ = entry; diff --git a/arch/m68k/kernel/bootinfo_proc.c b/arch/m68k/kernel/bootinfo_proc.c index 3b9cab84917d..857fa2aaa748 100644 --- a/arch/m68k/kernel/bootinfo_proc.c +++ b/arch/m68k/kernel/bootinfo_proc.c @@ -26,9 +26,9 @@ static ssize_t bootinfo_read(struct file *file, char __user *buf, bootinfo_size); } -static const struct file_operations bootinfo_fops = { - .read = bootinfo_read, - .llseek = default_llseek, +static const struct proc_ops bootinfo_proc_ops = { + .proc_read = bootinfo_read, + .proc_lseek = default_llseek, }; void __init save_bootinfo(const struct bi_record *bi) @@ -67,7 +67,7 @@ static int __init init_bootinfo_procfs(void) if (!bootinfo_copy) return -ENOMEM; - pde = proc_create_data("bootinfo", 0400, NULL, &bootinfo_fops, NULL); + pde = proc_create_data("bootinfo", 0400, NULL, &bootinfo_proc_ops, NULL); if (!pde) { kfree(bootinfo_copy); return -ENOMEM; diff --git a/arch/mips/lasat/picvue_proc.c b/arch/mips/lasat/picvue_proc.c index 8126f15b8e09..61c033494af5 100644 --- a/arch/mips/lasat/picvue_proc.c +++ b/arch/mips/lasat/picvue_proc.c @@ -89,13 +89,12 @@ static ssize_t pvc_line_proc_write(struct file *file, const char __user *buf, return count; } -static const struct file_operations pvc_line_proc_fops = { - .owner = THIS_MODULE, - .open = pvc_line_proc_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, - .write = pvc_line_proc_write, +static const struct proc_ops pvc_line_proc_ops = { + .proc_open = pvc_line_proc_open, + .proc_read = seq_read, + .proc_lseek = seq_lseek, + .proc_release = single_release, + .proc_write = pvc_line_proc_write, }; static ssize_t pvc_scroll_proc_write(struct file *file, const char __user *buf, @@ -148,13 +147,12 @@ static int pvc_scroll_proc_open(struct inode *inode, struct file *file) return single_open(file, pvc_scroll_proc_show, NULL); } -static const struct file_operations pvc_scroll_proc_fops = { - .owner = THIS_MODULE, - .open = pvc_scroll_proc_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, - .write = pvc_scroll_proc_write, +static const struct proc_ops pvc_scroll_proc_ops = { + .proc_open = pvc_scroll_proc_open, + .proc_read = seq_read, + .proc_lseek = seq_lseek, + .proc_release = single_release, + .proc_write = pvc_scroll_proc_write, }; void pvc_proc_timerfunc(struct timer_list *unused) @@ -189,12 +187,11 @@ static int __init pvc_proc_init(void) } for (i = 0; i < PVC_NLINES; i++) { proc_entry = proc_create_data(pvc_linename[i], 0644, dir, - &pvc_line_proc_fops, &pvc_linedata[i]); + &pvc_line_proc_ops, &pvc_linedata[i]); if (proc_entry == NULL) goto error; } - proc_entry = proc_create("scroll", 0644, dir, - &pvc_scroll_proc_fops); + proc_entry = proc_create("scroll", 0644, dir, &pvc_scroll_proc_ops); if (proc_entry == NULL) goto error; diff --git a/arch/powerpc/kernel/proc_powerpc.c b/arch/powerpc/kernel/proc_powerpc.c index be3758d54e59..877817471e3c 100644 --- a/arch/powerpc/kernel/proc_powerpc.c +++ b/arch/powerpc/kernel/proc_powerpc.c @@ -39,10 +39,10 @@ static int page_map_mmap( struct file *file, struct vm_area_struct *vma ) return 0; } -static const struct file_operations page_map_fops = { - .llseek = page_map_seek, - .read = page_map_read, - .mmap = page_map_mmap +static const struct proc_ops page_map_proc_ops = { + .proc_lseek = page_map_seek, + .proc_read = page_map_read, + .proc_mmap = page_map_mmap, }; @@ -51,7 +51,7 @@ static int __init proc_ppc64_init(void) struct proc_dir_entry *pde; pde = proc_create_data("powerpc/systemcfg", S_IFREG | 0444, NULL, - &page_map_fops, vdso_data); + &page_map_proc_ops, vdso_data); if (!pde) return 1; proc_set_size(pde, PAGE_SIZE); diff --git a/arch/powerpc/kernel/rtas-proc.c b/arch/powerpc/kernel/rtas-proc.c index 487dcd8da4de..2d33f342a293 100644 --- a/arch/powerpc/kernel/rtas-proc.c +++ b/arch/powerpc/kernel/rtas-proc.c @@ -159,12 +159,12 @@ static int poweron_open(struct inode *inode, struct file *file) return single_open(file, ppc_rtas_poweron_show, NULL); } -static const struct file_operations ppc_rtas_poweron_operations = { - .open = poweron_open, - .read = seq_read, - .llseek = seq_lseek, - .write = ppc_rtas_poweron_write, - .release = single_release, +static const struct proc_ops ppc_rtas_poweron_proc_ops = { + .proc_open = poweron_open, + .proc_read = seq_read, + .proc_lseek = seq_lseek, + .proc_write = ppc_rtas_poweron_write, + .proc_release = single_release, }; static int progress_open(struct inode *inode, struct file *file) @@ -172,12 +172,12 @@ static int progress_open(struct inode *inode, struct file *file) return single_open(file, ppc_rtas_progress_show, NULL); } -static const struct file_operations ppc_rtas_progress_operations = { - .open = progress_open, - .read = seq_read, - .llseek = seq_lseek, - .write = ppc_rtas_progress_write, - .release = single_release, +static const struct proc_ops ppc_rtas_progress_proc_ops = { + .proc_open = progress_open, + .proc_read = seq_read, + .proc_lseek = seq_lseek, + .proc_write = ppc_rtas_progress_write, + .proc_release = single_release, }; static int clock_open(struct inode *inode, struct file *file) @@ -185,12 +185,12 @@ static int clock_open(struct inode *inode, struct file *file) return single_open(file, ppc_rtas_clock_show, NULL); } -static const struct file_operations ppc_rtas_clock_operations = { - .open = clock_open, - .read = seq_read, - .llseek = seq_lseek, - .write = ppc_rtas_clock_write, - .release = single_release, +static const struct proc_ops ppc_rtas_clock_proc_ops = { + .proc_open = clock_open, + .proc_read = seq_read, + .proc_lseek = seq_lseek, + .proc_write = ppc_rtas_clock_write, + .proc_release = single_release, }; static int tone_freq_open(struct inode *inode, struct file *file) @@ -198,12 +198,12 @@ static int tone_freq_open(struct inode *inode, struct file *file) return single_open(file, ppc_rtas_tone_freq_show, NULL); } -static const struct file_operations ppc_rtas_tone_freq_operations = { - .open = tone_freq_open, - .read = seq_read, - .llseek = seq_lseek, - .write = ppc_rtas_tone_freq_write, - .release = single_release, +static const struct proc_ops ppc_rtas_tone_freq_proc_ops = { + .proc_open = tone_freq_open, + .proc_read = seq_read, + .proc_lseek = seq_lseek, + .proc_write = ppc_rtas_tone_freq_write, + .proc_release = single_release, }; static int tone_volume_open(struct inode *inode, struct file *file) @@ -211,12 +211,12 @@ static int tone_volume_open(struct inode *inode, struct file *file) return single_open(file, ppc_rtas_tone_volume_show, NULL); } -static const struct file_operations ppc_rtas_tone_volume_operations = { - .open = tone_volume_open, - .read = seq_read, - .llseek = seq_lseek, - .write = ppc_rtas_tone_volume_write, - .release = single_release, +static const struct proc_ops ppc_rtas_tone_volume_proc_ops = { + .proc_open = tone_volume_open, + .proc_read = seq_read, + .proc_lseek = seq_lseek, + .proc_write = ppc_rtas_tone_volume_write, + .proc_release = single_release, }; static int ppc_rtas_find_all_sensors(void); @@ -238,17 +238,17 @@ static int __init proc_rtas_init(void) return -ENODEV; proc_create("powerpc/rtas/progress", 0644, NULL, - &ppc_rtas_progress_operations); + &ppc_rtas_progress_proc_ops); proc_create("powerpc/rtas/clock", 0644, NULL, - &ppc_rtas_clock_operations); + &ppc_rtas_clock_proc_ops); proc_create("powerpc/rtas/poweron", 0644, NULL, - &ppc_rtas_poweron_operations); + &ppc_rtas_poweron_proc_ops); proc_create_single("powerpc/rtas/sensors", 0444, NULL, ppc_rtas_sensors_show); proc_create("powerpc/rtas/frequency", 0644, NULL, - &ppc_rtas_tone_freq_operations); + &ppc_rtas_tone_freq_proc_ops); proc_create("powerpc/rtas/volume", 0644, NULL, - &ppc_rtas_tone_volume_operations); + &ppc_rtas_tone_volume_proc_ops); proc_create_single("powerpc/rtas/rmo_buffer", 0400, NULL, ppc_rtas_rmo_buf_show); return 0; diff --git a/arch/powerpc/kernel/rtas_flash.c b/arch/powerpc/kernel/rtas_flash.c index 84f794782c62..a99179d83538 100644 --- a/arch/powerpc/kernel/rtas_flash.c +++ b/arch/powerpc/kernel/rtas_flash.c @@ -655,7 +655,7 @@ struct rtas_flash_file { const char *filename; const char *rtas_call_name; int *status; - const struct file_operations fops; + const struct proc_ops ops; }; static const struct rtas_flash_file rtas_flash_files[] = { @@ -663,36 +663,36 @@ static const struct rtas_flash_file rtas_flash_files[] = { .filename = "powerpc/rtas/" FIRMWARE_FLASH_NAME, .rtas_call_name = "ibm,update-flash-64-and-reboot", .status = &rtas_update_flash_data.status, - .fops.read = rtas_flash_read_msg, - .fops.write = rtas_flash_write, - .fops.release = rtas_flash_release, - .fops.llseek = default_llseek, + .ops.proc_read = rtas_flash_read_msg, + .ops.proc_write = rtas_flash_write, + .ops.proc_release = rtas_flash_release, + .ops.proc_lseek = default_llseek, }, { .filename = "powerpc/rtas/" FIRMWARE_UPDATE_NAME, .rtas_call_name = "ibm,update-flash-64-and-reboot", .status = &rtas_update_flash_data.status, - .fops.read = rtas_flash_read_num, - .fops.write = rtas_flash_write, - .fops.release = rtas_flash_release, - .fops.llseek = default_llseek, + .ops.proc_read = rtas_flash_read_num, + .ops.proc_write = rtas_flash_write, + .ops.proc_release = rtas_flash_release, + .ops.proc_lseek = default_llseek, }, { .filename = "powerpc/rtas/" VALIDATE_FLASH_NAME, .rtas_call_name = "ibm,validate-flash-image", .status = &rtas_validate_flash_data.status, - .fops.read = validate_flash_read, - .fops.write = validate_flash_write, - .fops.release = validate_flash_release, - .fops.llseek = default_llseek, + .ops.proc_read = validate_flash_read, + .ops.proc_write = validate_flash_write, + .ops.proc_release = validate_flash_release, + .ops.proc_lseek = default_llseek, }, { .filename = "powerpc/rtas/" MANAGE_FLASH_NAME, .rtas_call_name = "ibm,manage-flash-image", .status = &rtas_manage_flash_data.status, - .fops.read = manage_flash_read, - .fops.write = manage_flash_write, - .fops.llseek = default_llseek, + .ops.proc_read = manage_flash_read, + .ops.proc_write = manage_flash_write, + .ops.proc_lseek = default_llseek, } }; @@ -723,7 +723,7 @@ static int __init rtas_flash_init(void) const struct rtas_flash_file *f = &rtas_flash_files[i]; int token; - if (!proc_create(f->filename, 0600, NULL, &f->fops)) + if (!proc_create(f->filename, 0600, NULL, &f->ops)) goto enomem; /* diff --git a/arch/powerpc/kernel/rtasd.c b/arch/powerpc/kernel/rtasd.c index 8d02e047f96a..89b798f8f656 100644 --- a/arch/powerpc/kernel/rtasd.c +++ b/arch/powerpc/kernel/rtasd.c @@ -385,12 +385,12 @@ static __poll_t rtas_log_poll(struct file *file, poll_table * wait) return 0; } -static const struct file_operations proc_rtas_log_operations = { - .read = rtas_log_read, - .poll = rtas_log_poll, - .open = rtas_log_open, - .release = rtas_log_release, - .llseek = noop_llseek, +static const struct proc_ops rtas_log_proc_ops = { + .proc_read = rtas_log_read, + .proc_poll = rtas_log_poll, + .proc_open = rtas_log_open, + .proc_release = rtas_log_release, + .proc_lseek = noop_llseek, }; static int enable_surveillance(int timeout) @@ -572,7 +572,7 @@ static int __init rtas_init(void) return -ENODEV; entry = proc_create("powerpc/rtas/error_log", 0400, NULL, - &proc_rtas_log_operations); + &rtas_log_proc_ops); if (!entry) printk(KERN_ERR "Failed to create error_log proc entry\n"); diff --git a/arch/powerpc/mm/numa.c b/arch/powerpc/mm/numa.c index 50d68d21ddcc..3c7dec70cda0 100644 --- a/arch/powerpc/mm/numa.c +++ b/arch/powerpc/mm/numa.c @@ -1616,11 +1616,11 @@ static ssize_t topology_write(struct file *file, const char __user *buf, return count; } -static const struct file_operations topology_ops = { - .read = seq_read, - .write = topology_write, - .open = topology_open, - .release = single_release +static const struct proc_ops topology_proc_ops = { + .proc_read = seq_read, + .proc_write = topology_write, + .proc_open = topology_open, + .proc_release = single_release, }; static int topology_update_init(void) @@ -1630,7 +1630,7 @@ static int topology_update_init(void) if (vphn_enabled) topology_schedule_update(); - if (!proc_create("powerpc/topology_updates", 0644, NULL, &topology_ops)) + if (!proc_create("powerpc/topology_updates", 0644, NULL, &topology_proc_ops)) return -ENOMEM; topology_inited = 1; diff --git a/arch/powerpc/platforms/pseries/lpar.c b/arch/powerpc/platforms/pseries/lpar.c index 60cb29ae4739..3c3da25b445c 100644 --- a/arch/powerpc/platforms/pseries/lpar.c +++ b/arch/powerpc/platforms/pseries/lpar.c @@ -582,12 +582,12 @@ static int vcpudispatch_stats_open(struct inode *inode, struct file *file) return single_open(file, vcpudispatch_stats_display, NULL); } -static const struct file_operations vcpudispatch_stats_proc_ops = { - .open = vcpudispatch_stats_open, - .read = seq_read, - .write = vcpudispatch_stats_write, - .llseek = seq_lseek, - .release = single_release, +static const struct proc_ops vcpudispatch_stats_proc_ops = { + .proc_open = vcpudispatch_stats_open, + .proc_read = seq_read, + .proc_write = vcpudispatch_stats_write, + .proc_lseek = seq_lseek, + .proc_release = single_release, }; static ssize_t vcpudispatch_stats_freq_write(struct file *file, @@ -626,12 +626,12 @@ static int vcpudispatch_stats_freq_open(struct inode *inode, struct file *file) return single_open(file, vcpudispatch_stats_freq_display, NULL); } -static const struct file_operations vcpudispatch_stats_freq_proc_ops = { - .open = vcpudispatch_stats_freq_open, - .read = seq_read, - .write = vcpudispatch_stats_freq_write, - .llseek = seq_lseek, - .release = single_release, +static const struct proc_ops vcpudispatch_stats_freq_proc_ops = { + .proc_open = vcpudispatch_stats_freq_open, + .proc_read = seq_read, + .proc_write = vcpudispatch_stats_freq_write, + .proc_lseek = seq_lseek, + .proc_release = single_release, }; static int __init vcpudispatch_stats_procfs_init(void) diff --git a/arch/powerpc/platforms/pseries/lparcfg.c b/arch/powerpc/platforms/pseries/lparcfg.c index e33e8bc4b69b..f43e778dd7c8 100644 --- a/arch/powerpc/platforms/pseries/lparcfg.c +++ b/arch/powerpc/platforms/pseries/lparcfg.c @@ -698,12 +698,12 @@ static int lparcfg_open(struct inode *inode, struct file *file) return single_open(file, lparcfg_data, NULL); } -static const struct file_operations lparcfg_fops = { - .read = seq_read, - .write = lparcfg_write, - .open = lparcfg_open, - .release = single_release, - .llseek = seq_lseek, +static const struct proc_ops lparcfg_proc_ops = { + .proc_read = seq_read, + .proc_write = lparcfg_write, + .proc_open = lparcfg_open, + .proc_release = single_release, + .proc_lseek = seq_lseek, }; static int __init lparcfg_init(void) @@ -714,7 +714,7 @@ static int __init lparcfg_init(void) if (firmware_has_feature(FW_FEATURE_SPLPAR)) mode |= 0200; - if (!proc_create("powerpc/lparcfg", mode, NULL, &lparcfg_fops)) { + if (!proc_create("powerpc/lparcfg", mode, NULL, &lparcfg_proc_ops)) { printk(KERN_ERR "Failed to create powerpc/lparcfg\n"); return -EIO; } diff --git a/arch/powerpc/platforms/pseries/reconfig.c b/arch/powerpc/platforms/pseries/reconfig.c index 8a9c4fb95b8b..7f7369fec46b 100644 --- a/arch/powerpc/platforms/pseries/reconfig.c +++ b/arch/powerpc/platforms/pseries/reconfig.c @@ -391,9 +391,9 @@ out: return rv ? rv : count; } -static const struct file_operations ofdt_fops = { - .write = ofdt_write, - .llseek = noop_llseek, +static const struct proc_ops ofdt_proc_ops = { + .proc_write = ofdt_write, + .proc_lseek = noop_llseek, }; /* create /proc/powerpc/ofdt write-only by root */ @@ -401,7 +401,7 @@ static int proc_ppc64_create_ofdt(void) { struct proc_dir_entry *ent; - ent = proc_create("powerpc/ofdt", 0200, NULL, &ofdt_fops); + ent = proc_create("powerpc/ofdt", 0200, NULL, &ofdt_proc_ops); if (ent) proc_set_size(ent, 0); diff --git a/arch/powerpc/platforms/pseries/scanlog.c b/arch/powerpc/platforms/pseries/scanlog.c index a0001280503c..2879c4f0ceb7 100644 --- a/arch/powerpc/platforms/pseries/scanlog.c +++ b/arch/powerpc/platforms/pseries/scanlog.c @@ -152,13 +152,12 @@ static int scanlog_release(struct inode * inode, struct file * file) return 0; } -static const struct file_operations scanlog_fops = { - .owner = THIS_MODULE, - .read = scanlog_read, - .write = scanlog_write, - .open = scanlog_open, - .release = scanlog_release, - .llseek = noop_llseek, +static const struct proc_ops scanlog_proc_ops = { + .proc_read = scanlog_read, + .proc_write = scanlog_write, + .proc_open = scanlog_open, + .proc_release = scanlog_release, + .proc_lseek = noop_llseek, }; static int __init scanlog_init(void) @@ -176,7 +175,7 @@ static int __init scanlog_init(void) goto err; ent = proc_create("powerpc/rtas/scan-log-dump", 0400, NULL, - &scanlog_fops); + &scanlog_proc_ops); if (!ent) goto err; return 0; diff --git a/arch/sh/mm/alignment.c b/arch/sh/mm/alignment.c index ec2b25302427..fb517b82a87b 100644 --- a/arch/sh/mm/alignment.c +++ b/arch/sh/mm/alignment.c @@ -152,13 +152,12 @@ static ssize_t alignment_proc_write(struct file *file, return count; } -static const struct file_operations alignment_proc_fops = { - .owner = THIS_MODULE, - .open = alignment_proc_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, - .write = alignment_proc_write, +static const struct proc_ops alignment_proc_ops = { + .proc_open = alignment_proc_open, + .proc_read = seq_read, + .proc_lseek = seq_lseek, + .proc_release = single_release, + .proc_write = alignment_proc_write, }; /* @@ -176,12 +175,12 @@ static int __init alignment_init(void) return -ENOMEM; res = proc_create_data("alignment", S_IWUSR | S_IRUGO, dir, - &alignment_proc_fops, &se_usermode); + &alignment_proc_ops, &se_usermode); if (!res) return -ENOMEM; res = proc_create_data("kernel_alignment", S_IWUSR | S_IRUGO, dir, - &alignment_proc_fops, &se_kernmode_warn); + &alignment_proc_ops, &se_kernmode_warn); if (!res) return -ENOMEM; diff --git a/arch/sparc/kernel/led.c b/arch/sparc/kernel/led.c index a6292f8ed180..bd48575172c3 100644 --- a/arch/sparc/kernel/led.c +++ b/arch/sparc/kernel/led.c @@ -104,13 +104,12 @@ static ssize_t led_proc_write(struct file *file, const char __user *buffer, return count; } -static const struct file_operations led_proc_fops = { - .owner = THIS_MODULE, - .open = led_proc_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, - .write = led_proc_write, +static const struct proc_ops led_proc_ops = { + .proc_open = led_proc_open, + .proc_read = seq_read, + .proc_lseek = seq_lseek, + .proc_release = single_release, + .proc_write = led_proc_write, }; static struct proc_dir_entry *led; @@ -121,7 +120,7 @@ static int __init led_init(void) { timer_setup(&led_blink_timer, led_blink, 0); - led = proc_create("led", 0, NULL, &led_proc_fops); + led = proc_create("led", 0, NULL, &led_proc_ops); if (!led) return -ENOMEM; diff --git a/arch/um/drivers/mconsole_kern.c b/arch/um/drivers/mconsole_kern.c index 0117489e9b30..b80a1d616e4e 100644 --- a/arch/um/drivers/mconsole_kern.c +++ b/arch/um/drivers/mconsole_kern.c @@ -752,10 +752,9 @@ static ssize_t mconsole_proc_write(struct file *file, return count; } -static const struct file_operations mconsole_proc_fops = { - .owner = THIS_MODULE, - .write = mconsole_proc_write, - .llseek = noop_llseek, +static const struct proc_ops mconsole_proc_ops = { + .proc_write = mconsole_proc_write, + .proc_lseek = noop_llseek, }; static int create_proc_mconsole(void) @@ -765,7 +764,7 @@ static int create_proc_mconsole(void) if (notify_socket == NULL) return 0; - ent = proc_create("mconsole", 0200, NULL, &mconsole_proc_fops); + ent = proc_create("mconsole", 0200, NULL, &mconsole_proc_ops); if (ent == NULL) { printk(KERN_INFO "create_proc_mconsole : proc_create failed\n"); return 0; diff --git a/arch/um/kernel/exitcode.c b/arch/um/kernel/exitcode.c index 369fd844e195..43edc2aa57e4 100644 --- a/arch/um/kernel/exitcode.c +++ b/arch/um/kernel/exitcode.c @@ -55,20 +55,19 @@ static ssize_t exitcode_proc_write(struct file *file, return count; } -static const struct file_operations exitcode_proc_fops = { - .owner = THIS_MODULE, - .open = exitcode_proc_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, - .write = exitcode_proc_write, +static const struct proc_ops exitcode_proc_ops = { + .proc_open = exitcode_proc_open, + .proc_read = seq_read, + .proc_lseek = seq_lseek, + .proc_release = single_release, + .proc_write = exitcode_proc_write, }; static int make_proc_exitcode(void) { struct proc_dir_entry *ent; - ent = proc_create("exitcode", 0600, NULL, &exitcode_proc_fops); + ent = proc_create("exitcode", 0600, NULL, &exitcode_proc_ops); if (ent == NULL) { printk(KERN_WARNING "make_proc_exitcode : Failed to register " "/proc/exitcode\n"); diff --git a/arch/um/kernel/process.c b/arch/um/kernel/process.c index 17045e7211bf..56a094182bf5 100644 --- a/arch/um/kernel/process.c +++ b/arch/um/kernel/process.c @@ -348,13 +348,12 @@ static ssize_t sysemu_proc_write(struct file *file, const char __user *buf, return count; } -static const struct file_operations sysemu_proc_fops = { - .owner = THIS_MODULE, - .open = sysemu_proc_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, - .write = sysemu_proc_write, +static const struct proc_ops sysemu_proc_ops = { + .proc_open = sysemu_proc_open, + .proc_read = seq_read, + .proc_lseek = seq_lseek, + .proc_release = single_release, + .proc_write = sysemu_proc_write, }; int __init make_proc_sysemu(void) @@ -363,7 +362,7 @@ int __init make_proc_sysemu(void) if (!sysemu_supported) return 0; - ent = proc_create("sysemu", 0600, NULL, &sysemu_proc_fops); + ent = proc_create("sysemu", 0600, NULL, &sysemu_proc_ops); if (ent == NULL) { diff --git a/arch/x86/kernel/cpu/mtrr/if.c b/arch/x86/kernel/cpu/mtrr/if.c index da532f656a7b..a5c506f6da7f 100644 --- a/arch/x86/kernel/cpu/mtrr/if.c +++ b/arch/x86/kernel/cpu/mtrr/if.c @@ -396,15 +396,16 @@ static int mtrr_open(struct inode *inode, struct file *file) return single_open(file, mtrr_seq_show, NULL); } -static const struct file_operations mtrr_fops = { - .owner = THIS_MODULE, - .open = mtrr_open, - .read = seq_read, - .llseek = seq_lseek, - .write = mtrr_write, - .unlocked_ioctl = mtrr_ioctl, - .compat_ioctl = mtrr_ioctl, - .release = mtrr_close, +static const struct proc_ops mtrr_proc_ops = { + .proc_open = mtrr_open, + .proc_read = seq_read, + .proc_lseek = seq_lseek, + .proc_write = mtrr_write, + .proc_ioctl = mtrr_ioctl, +#ifdef CONFIG_COMPAT + .proc_compat_ioctl = mtrr_ioctl, +#endif + .proc_release = mtrr_close, }; static int __init mtrr_if_init(void) @@ -417,7 +418,7 @@ static int __init mtrr_if_init(void) (!cpu_has(c, X86_FEATURE_CENTAUR_MCR))) return -ENODEV; - proc_create("mtrr", S_IWUSR | S_IRUGO, NULL, &mtrr_fops); + proc_create("mtrr", S_IWUSR | S_IRUGO, NULL, &mtrr_proc_ops); return 0; } arch_initcall(mtrr_if_init); diff --git a/arch/x86/platform/uv/tlb_uv.c b/arch/x86/platform/uv/tlb_uv.c index 5f0a96bf27a1..1fd321f37f1b 100644 --- a/arch/x86/platform/uv/tlb_uv.c +++ b/arch/x86/platform/uv/tlb_uv.c @@ -1668,12 +1668,12 @@ static int tunables_open(struct inode *inode, struct file *file) return 0; } -static const struct file_operations proc_uv_ptc_operations = { - .open = ptc_proc_open, - .read = seq_read, - .write = ptc_proc_write, - .llseek = seq_lseek, - .release = seq_release, +static const struct proc_ops uv_ptc_proc_ops = { + .proc_open = ptc_proc_open, + .proc_read = seq_read, + .proc_write = ptc_proc_write, + .proc_lseek = seq_lseek, + .proc_release = seq_release, }; static const struct file_operations tunables_fops = { @@ -1691,7 +1691,7 @@ static int __init uv_ptc_init(void) return 0; proc_uv_ptc = proc_create(UV_PTC_BASENAME, 0444, NULL, - &proc_uv_ptc_operations); + &uv_ptc_proc_ops); if (!proc_uv_ptc) { pr_err("unable to create %s proc entry\n", UV_PTC_BASENAME); diff --git a/arch/xtensa/platforms/iss/simdisk.c b/arch/xtensa/platforms/iss/simdisk.c index f9cd45860bee..833109880165 100644 --- a/arch/xtensa/platforms/iss/simdisk.c +++ b/arch/xtensa/platforms/iss/simdisk.c @@ -251,10 +251,10 @@ out_free: return err; } -static const struct file_operations fops = { - .read = proc_read_simdisk, - .write = proc_write_simdisk, - .llseek = default_llseek, +static const struct proc_ops simdisk_proc_ops = { + .proc_read = proc_read_simdisk, + .proc_write = proc_write_simdisk, + .proc_lseek = default_llseek, }; static int __init simdisk_setup(struct simdisk *dev, int which, @@ -290,7 +290,7 @@ static int __init simdisk_setup(struct simdisk *dev, int which, set_capacity(dev->gd, 0); add_disk(dev->gd); - dev->procfile = proc_create_data(tmp, 0644, procdir, &fops, dev); + dev->procfile = proc_create_data(tmp, 0644, procdir, &simdisk_proc_ops, dev); return 0; out_alloc_disk: diff --git a/drivers/acpi/battery.c b/drivers/acpi/battery.c index 15cc7d5a6185..111a407dcc77 100644 --- a/drivers/acpi/battery.c +++ b/drivers/acpi/battery.c @@ -1202,13 +1202,12 @@ static int acpi_battery_alarm_proc_open(struct inode *inode, struct file *file) return single_open(file, acpi_battery_alarm_proc_show, PDE_DATA(inode)); } -static const struct file_operations acpi_battery_alarm_fops = { - .owner = THIS_MODULE, - .open = acpi_battery_alarm_proc_open, - .read = seq_read, - .write = acpi_battery_write_alarm, - .llseek = seq_lseek, - .release = single_release, +static const struct proc_ops acpi_battery_alarm_proc_ops = { + .proc_open = acpi_battery_alarm_proc_open, + .proc_read = seq_read, + .proc_write = acpi_battery_write_alarm, + .proc_lseek = seq_lseek, + .proc_release = single_release, }; static int acpi_battery_add_fs(struct acpi_device *device) @@ -1228,7 +1227,7 @@ static int acpi_battery_add_fs(struct acpi_device *device) acpi_battery_state_proc_show, acpi_driver_data(device))) return -ENODEV; if (!proc_create_data("alarm", S_IFREG | S_IRUGO | S_IWUSR, - acpi_device_dir(device), &acpi_battery_alarm_fops, + acpi_device_dir(device), &acpi_battery_alarm_proc_ops, acpi_driver_data(device))) return -ENODEV; return 0; diff --git a/drivers/acpi/proc.c b/drivers/acpi/proc.c index 652f19e6c541..0e62ef265ce4 100644 --- a/drivers/acpi/proc.c +++ b/drivers/acpi/proc.c @@ -136,18 +136,17 @@ acpi_system_wakeup_device_open_fs(struct inode *inode, struct file *file) PDE_DATA(inode)); } -static const struct file_operations acpi_system_wakeup_device_fops = { - .owner = THIS_MODULE, - .open = acpi_system_wakeup_device_open_fs, - .read = seq_read, - .write = acpi_system_write_wakeup_device, - .llseek = seq_lseek, - .release = single_release, +static const struct proc_ops acpi_system_wakeup_device_proc_ops = { + .proc_open = acpi_system_wakeup_device_open_fs, + .proc_read = seq_read, + .proc_write = acpi_system_write_wakeup_device, + .proc_lseek = seq_lseek, + .proc_release = single_release, }; void __init acpi_sleep_proc_init(void) { /* 'wakeup device' [R/W] */ proc_create("wakeup", S_IFREG | S_IRUGO | S_IWUSR, - acpi_root_dir, &acpi_system_wakeup_device_fops); + acpi_root_dir, &acpi_system_wakeup_device_proc_ops); } diff --git a/drivers/hwmon/dell-smm-hwmon.c b/drivers/hwmon/dell-smm-hwmon.c index 17583bf8c2dc..d4c83009d625 100644 --- a/drivers/hwmon/dell-smm-hwmon.c +++ b/drivers/hwmon/dell-smm-hwmon.c @@ -595,19 +595,18 @@ static int i8k_open_fs(struct inode *inode, struct file *file) return single_open(file, i8k_proc_show, NULL); } -static const struct file_operations i8k_fops = { - .owner = THIS_MODULE, - .open = i8k_open_fs, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, - .unlocked_ioctl = i8k_ioctl, +static const struct proc_ops i8k_proc_ops = { + .proc_open = i8k_open_fs, + .proc_read = seq_read, + .proc_lseek = seq_lseek, + .proc_release = single_release, + .proc_ioctl = i8k_ioctl, }; static void __init i8k_init_procfs(void) { /* Register the proc entry */ - proc_create("i8k", 0, NULL, &i8k_fops); + proc_create("i8k", 0, NULL, &i8k_proc_ops); } static void __exit i8k_exit_procfs(void) diff --git a/drivers/ide/ide-proc.c b/drivers/ide/ide-proc.c index e73016cbd406..15c17f3781ee 100644 --- a/drivers/ide/ide-proc.c +++ b/drivers/ide/ide-proc.c @@ -381,13 +381,12 @@ parse_error: return -EINVAL; } -static const struct file_operations ide_settings_proc_fops = { - .owner = THIS_MODULE, - .open = ide_settings_proc_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, - .write = ide_settings_proc_write, +static const struct proc_ops ide_settings_proc_ops = { + .proc_open = ide_settings_proc_open, + .proc_read = seq_read, + .proc_lseek = seq_lseek, + .proc_release = single_release, + .proc_write = ide_settings_proc_write, }; int ide_capacity_proc_show(struct seq_file *m, void *v) @@ -546,7 +545,7 @@ void ide_proc_port_register_devices(ide_hwif_t *hwif) if (drive->proc) { ide_add_proc_entries(drive->proc, generic_drive_entries, drive); proc_create_data("settings", S_IFREG|S_IRUSR|S_IWUSR, - drive->proc, &ide_settings_proc_fops, + drive->proc, &ide_settings_proc_ops, drive); } sprintf(name, "ide%d/%s", (drive->name[2]-'a')/2, drive->name); @@ -615,7 +614,7 @@ static int ide_drivers_show(struct seq_file *s, void *p) return 0; } -DEFINE_SHOW_ATTRIBUTE(ide_drivers); +DEFINE_PROC_SHOW_ATTRIBUTE(ide_drivers); void proc_ide_create(void) { @@ -624,7 +623,7 @@ void proc_ide_create(void) if (!proc_ide_root) return; - proc_create("drivers", 0, proc_ide_root, &ide_drivers_fops); + proc_create("drivers", 0, proc_ide_root, &ide_drivers_proc_ops); } void proc_ide_destroy(void) diff --git a/drivers/input/input.c b/drivers/input/input.c index ee6c3234df36..fce43e62dd45 100644 --- a/drivers/input/input.c +++ b/drivers/input/input.c @@ -1216,13 +1216,12 @@ static int input_proc_devices_open(struct inode *inode, struct file *file) return seq_open(file, &input_devices_seq_ops); } -static const struct file_operations input_devices_fileops = { - .owner = THIS_MODULE, - .open = input_proc_devices_open, - .poll = input_proc_devices_poll, - .read = seq_read, - .llseek = seq_lseek, - .release = seq_release, +static const struct proc_ops input_devices_proc_ops = { + .proc_open = input_proc_devices_open, + .proc_poll = input_proc_devices_poll, + .proc_read = seq_read, + .proc_lseek = seq_lseek, + .proc_release = seq_release, }; static void *input_handlers_seq_start(struct seq_file *seq, loff_t *pos) @@ -1280,12 +1279,11 @@ static int input_proc_handlers_open(struct inode *inode, struct file *file) return seq_open(file, &input_handlers_seq_ops); } -static const struct file_operations input_handlers_fileops = { - .owner = THIS_MODULE, - .open = input_proc_handlers_open, - .read = seq_read, - .llseek = seq_lseek, - .release = seq_release, +static const struct proc_ops input_handlers_proc_ops = { + .proc_open = input_proc_handlers_open, + .proc_read = seq_read, + .proc_lseek = seq_lseek, + .proc_release = seq_release, }; static int __init input_proc_init(void) @@ -1297,12 +1295,12 @@ static int __init input_proc_init(void) return -ENOMEM; entry = proc_create("devices", 0, proc_bus_input_dir, - &input_devices_fileops); + &input_devices_proc_ops); if (!entry) goto fail1; entry = proc_create("handlers", 0, proc_bus_input_dir, - &input_handlers_fileops); + &input_handlers_proc_ops); if (!entry) goto fail2; diff --git a/drivers/isdn/capi/kcapi_proc.c b/drivers/isdn/capi/kcapi_proc.c index eadbe59b3753..b5ed4ea145cb 100644 --- a/drivers/isdn/capi/kcapi_proc.c +++ b/drivers/isdn/capi/kcapi_proc.c @@ -199,8 +199,8 @@ static ssize_t empty_read(struct file *file, char __user *buf, return 0; } -static const struct file_operations empty_fops = { - .read = empty_read, +static const struct proc_ops empty_proc_ops = { + .proc_read = empty_read, }; // --------------------------------------------------------------------------- @@ -214,7 +214,7 @@ kcapi_proc_init(void) proc_create_seq("capi/contrstats", 0, NULL, &seq_contrstats_ops); proc_create_seq("capi/applications", 0, NULL, &seq_applications_ops); proc_create_seq("capi/applstats", 0, NULL, &seq_applstats_ops); - proc_create("capi/driver", 0, NULL, &empty_fops); + proc_create("capi/driver", 0, NULL, &empty_proc_ops); } void diff --git a/drivers/macintosh/via-pmu.c b/drivers/macintosh/via-pmu.c index 21d532a78fa4..d38fb78a3b23 100644 --- a/drivers/macintosh/via-pmu.c +++ b/drivers/macintosh/via-pmu.c @@ -212,7 +212,7 @@ static int pmu_info_proc_show(struct seq_file *m, void *v); static int pmu_irqstats_proc_show(struct seq_file *m, void *v); static int pmu_battery_proc_show(struct seq_file *m, void *v); static void pmu_pass_intr(unsigned char *data, int len); -static const struct file_operations pmu_options_proc_fops; +static const struct proc_ops pmu_options_proc_ops; #ifdef CONFIG_ADB const struct adb_driver via_pmu_driver = { @@ -573,7 +573,7 @@ static int __init via_pmu_dev_init(void) proc_pmu_irqstats = proc_create_single("interrupts", 0, proc_pmu_root, pmu_irqstats_proc_show); proc_pmu_options = proc_create("options", 0600, proc_pmu_root, - &pmu_options_proc_fops); + &pmu_options_proc_ops); } return 0; } @@ -974,13 +974,12 @@ static ssize_t pmu_options_proc_write(struct file *file, return fcount; } -static const struct file_operations pmu_options_proc_fops = { - .owner = THIS_MODULE, - .open = pmu_options_proc_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, - .write = pmu_options_proc_write, +static const struct proc_ops pmu_options_proc_ops = { + .proc_open = pmu_options_proc_open, + .proc_read = seq_read, + .proc_lseek = seq_lseek, + .proc_release = single_release, + .proc_write = pmu_options_proc_write, }; #ifdef CONFIG_ADB diff --git a/drivers/md/md.c b/drivers/md/md.c index 4824d50526fa..469f551863be 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -8279,13 +8279,12 @@ static __poll_t mdstat_poll(struct file *filp, poll_table *wait) return mask; } -static const struct file_operations md_seq_fops = { - .owner = THIS_MODULE, - .open = md_seq_open, - .read = seq_read, - .llseek = seq_lseek, - .release = seq_release, - .poll = mdstat_poll, +static const struct proc_ops mdstat_proc_ops = { + .proc_open = md_seq_open, + .proc_read = seq_read, + .proc_lseek = seq_lseek, + .proc_release = seq_release, + .proc_poll = mdstat_poll, }; int register_md_personality(struct md_personality *p) @@ -9454,7 +9453,7 @@ static void md_geninit(void) { pr_debug("md: sizeof(mdp_super_t) = %d\n", (int)sizeof(mdp_super_t)); - proc_create("mdstat", S_IRUGO, NULL, &md_seq_fops); + proc_create("mdstat", S_IRUGO, NULL, &mdstat_proc_ops); } static int __init md_init(void) diff --git a/drivers/misc/sgi-gru/gruprocfs.c b/drivers/misc/sgi-gru/gruprocfs.c index 2817f4751306..97b8b38ab47d 100644 --- a/drivers/misc/sgi-gru/gruprocfs.c +++ b/drivers/misc/sgi-gru/gruprocfs.c @@ -255,28 +255,28 @@ static int options_open(struct inode *inode, struct file *file) } /* *INDENT-OFF* */ -static const struct file_operations statistics_fops = { - .open = statistics_open, - .read = seq_read, - .write = statistics_write, - .llseek = seq_lseek, - .release = single_release, +static const struct proc_ops statistics_proc_ops = { + .proc_open = statistics_open, + .proc_read = seq_read, + .proc_write = statistics_write, + .proc_lseek = seq_lseek, + .proc_release = single_release, }; -static const struct file_operations mcs_statistics_fops = { - .open = mcs_statistics_open, - .read = seq_read, - .write = mcs_statistics_write, - .llseek = seq_lseek, - .release = single_release, +static const struct proc_ops mcs_statistics_proc_ops = { + .proc_open = mcs_statistics_open, + .proc_read = seq_read, + .proc_write = mcs_statistics_write, + .proc_lseek = seq_lseek, + .proc_release = single_release, }; -static const struct file_operations options_fops = { - .open = options_open, - .read = seq_read, - .write = options_write, - .llseek = seq_lseek, - .release = single_release, +static const struct proc_ops options_proc_ops = { + .proc_open = options_open, + .proc_read = seq_read, + .proc_write = options_write, + .proc_lseek = seq_lseek, + .proc_release = single_release, }; static struct proc_dir_entry *proc_gru __read_mostly; @@ -286,11 +286,11 @@ int gru_proc_init(void) proc_gru = proc_mkdir("sgi_uv/gru", NULL); if (!proc_gru) return -1; - if (!proc_create("statistics", 0644, proc_gru, &statistics_fops)) + if (!proc_create("statistics", 0644, proc_gru, &statistics_proc_ops)) goto err; - if (!proc_create("mcs_statistics", 0644, proc_gru, &mcs_statistics_fops)) + if (!proc_create("mcs_statistics", 0644, proc_gru, &mcs_statistics_proc_ops)) goto err; - if (!proc_create("debug_options", 0644, proc_gru, &options_fops)) + if (!proc_create("debug_options", 0644, proc_gru, &options_proc_ops)) goto err; if (!proc_create_seq("cch_status", 0444, proc_gru, &cch_seq_ops)) goto err; diff --git a/drivers/net/wireless/cisco/airo.c b/drivers/net/wireless/cisco/airo.c index c4c8f1b62e1e..8363f91df7ea 100644 --- a/drivers/net/wireless/cisco/airo.c +++ b/drivers/net/wireless/cisco/airo.c @@ -4420,73 +4420,65 @@ static int proc_BSSList_open( struct inode *inode, struct file *file ); static int proc_config_open( struct inode *inode, struct file *file ); static int proc_wepkey_open( struct inode *inode, struct file *file ); -static const struct file_operations proc_statsdelta_ops = { - .owner = THIS_MODULE, - .read = proc_read, - .open = proc_statsdelta_open, - .release = proc_close, - .llseek = default_llseek, +static const struct proc_ops proc_statsdelta_ops = { + .proc_read = proc_read, + .proc_open = proc_statsdelta_open, + .proc_release = proc_close, + .proc_lseek = default_llseek, }; -static const struct file_operations proc_stats_ops = { - .owner = THIS_MODULE, - .read = proc_read, - .open = proc_stats_open, - .release = proc_close, - .llseek = default_llseek, +static const struct proc_ops proc_stats_ops = { + .proc_read = proc_read, + .proc_open = proc_stats_open, + .proc_release = proc_close, + .proc_lseek = default_llseek, }; -static const struct file_operations proc_status_ops = { - .owner = THIS_MODULE, - .read = proc_read, - .open = proc_status_open, - .release = proc_close, - .llseek = default_llseek, +static const struct proc_ops proc_status_ops = { + .proc_read = proc_read, + .proc_open = proc_status_open, + .proc_release = proc_close, + .proc_lseek = default_llseek, }; -static const struct file_operations proc_SSID_ops = { - .owner = THIS_MODULE, - .read = proc_read, - .write = proc_write, - .open = proc_SSID_open, - .release = proc_close, - .llseek = default_llseek, +static const struct proc_ops proc_SSID_ops = { + .proc_read = proc_read, + .proc_write = proc_write, + .proc_open = proc_SSID_open, + .proc_release = proc_close, + .proc_lseek = default_llseek, }; -static const struct file_operations proc_BSSList_ops = { - .owner = THIS_MODULE, - .read = proc_read, - .write = proc_write, - .open = proc_BSSList_open, - .release = proc_close, - .llseek = default_llseek, +static const struct proc_ops proc_BSSList_ops = { + .proc_read = proc_read, + .proc_write = proc_write, + .proc_open = proc_BSSList_open, + .proc_release = proc_close, + .proc_lseek = default_llseek, }; -static const struct file_operations proc_APList_ops = { - .owner = THIS_MODULE, - .read = proc_read, - .write = proc_write, - .open = proc_APList_open, - .release = proc_close, - .llseek = default_llseek, +static const struct proc_ops proc_APList_ops = { + .proc_read = proc_read, + .proc_write = proc_write, + .proc_open = proc_APList_open, + .proc_release = proc_close, + .proc_lseek = default_llseek, }; -static const struct file_operations proc_config_ops = { - .owner = THIS_MODULE, - .read = proc_read, - .write = proc_write, - .open = proc_config_open, - .release = proc_close, - .llseek = default_llseek, +static const struct proc_ops proc_config_ops = { + .proc_read = proc_read, + .proc_write = proc_write, + .proc_open = proc_config_open, + .proc_release = proc_close, + .proc_lseek = default_llseek, }; -static const struct file_operations proc_wepkey_ops = { - .owner = THIS_MODULE, - .read = proc_read, - .write = proc_write, - .open = proc_wepkey_open, - .release = proc_close, - .llseek = default_llseek, +static const struct proc_ops proc_wepkey_ops = { + .proc_read = proc_read, + .proc_write = proc_write, + .proc_open = proc_wepkey_open, + .proc_release = proc_close, + .proc_lseek = default_llseek, }; static struct proc_dir_entry *airo_entry; diff --git a/drivers/net/wireless/intel/ipw2x00/libipw_module.c b/drivers/net/wireless/intel/ipw2x00/libipw_module.c index 436b819aeb36..43bab92a4148 100644 --- a/drivers/net/wireless/intel/ipw2x00/libipw_module.c +++ b/drivers/net/wireless/intel/ipw2x00/libipw_module.c @@ -240,13 +240,12 @@ static ssize_t debug_level_proc_write(struct file *file, return strnlen(buf, len); } -static const struct file_operations debug_level_proc_fops = { - .owner = THIS_MODULE, - .open = debug_level_proc_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, - .write = debug_level_proc_write, +static const struct proc_ops debug_level_proc_ops = { + .proc_open = debug_level_proc_open, + .proc_read = seq_read, + .proc_lseek = seq_lseek, + .proc_release = single_release, + .proc_write = debug_level_proc_write, }; #endif /* CONFIG_LIBIPW_DEBUG */ @@ -263,7 +262,7 @@ static int __init libipw_init(void) return -EIO; } e = proc_create("debug_level", 0644, libipw_proc, - &debug_level_proc_fops); + &debug_level_proc_ops); if (!e) { remove_proc_entry(DRV_PROCNAME, init_net.proc_net); libipw_proc = NULL; diff --git a/drivers/net/wireless/intersil/hostap/hostap_hw.c b/drivers/net/wireless/intersil/hostap/hostap_hw.c index e323e9a5999f..58212c532c90 100644 --- a/drivers/net/wireless/intersil/hostap/hostap_hw.c +++ b/drivers/net/wireless/intersil/hostap/hostap_hw.c @@ -126,7 +126,7 @@ static void prism2_check_sta_fw_version(local_info_t *local); #ifdef PRISM2_DOWNLOAD_SUPPORT /* hostap_download.c */ -static const struct file_operations prism2_download_aux_dump_proc_fops; +static const struct proc_ops prism2_download_aux_dump_proc_ops; static u8 * prism2_read_pda(struct net_device *dev); static int prism2_download(local_info_t *local, struct prism2_download_param *param); @@ -3094,7 +3094,7 @@ prism2_init_local_data(struct prism2_helper_functions *funcs, int card_idx, local->func->reset_port = prism2_reset_port; local->func->schedule_reset = prism2_schedule_reset; #ifdef PRISM2_DOWNLOAD_SUPPORT - local->func->read_aux_fops = &prism2_download_aux_dump_proc_fops; + local->func->read_aux_proc_ops = &prism2_download_aux_dump_proc_ops; local->func->download = prism2_download; #endif /* PRISM2_DOWNLOAD_SUPPORT */ local->func->tx = prism2_tx_80211; diff --git a/drivers/net/wireless/intersil/hostap/hostap_proc.c b/drivers/net/wireless/intersil/hostap/hostap_proc.c index 6151d8db5924..a2ee4693eaed 100644 --- a/drivers/net/wireless/intersil/hostap/hostap_proc.c +++ b/drivers/net/wireless/intersil/hostap/hostap_proc.c @@ -211,9 +211,9 @@ static ssize_t prism2_pda_proc_read(struct file *file, char __user *buf, return count; } -static const struct file_operations prism2_pda_proc_fops = { - .read = prism2_pda_proc_read, - .llseek = generic_file_llseek, +static const struct proc_ops prism2_pda_proc_ops = { + .proc_read = prism2_pda_proc_read, + .proc_lseek = generic_file_llseek, }; @@ -223,8 +223,8 @@ static ssize_t prism2_aux_dump_proc_no_read(struct file *file, char __user *buf, return 0; } -static const struct file_operations prism2_aux_dump_proc_fops = { - .read = prism2_aux_dump_proc_no_read, +static const struct proc_ops prism2_aux_dump_proc_ops = { + .proc_read = prism2_aux_dump_proc_no_read, }; @@ -379,9 +379,9 @@ void hostap_init_proc(local_info_t *local) proc_create_seq_data("wds", 0, local->proc, &prism2_wds_proc_seqops, local); proc_create_data("pda", 0, local->proc, - &prism2_pda_proc_fops, local); + &prism2_pda_proc_ops, local); proc_create_data("aux_dump", 0, local->proc, - local->func->read_aux_fops ?: &prism2_aux_dump_proc_fops, + local->func->read_aux_proc_ops ?: &prism2_aux_dump_proc_ops, local); proc_create_seq_data("bss_list", 0, local->proc, &prism2_bss_list_proc_seqops, local); diff --git a/drivers/net/wireless/intersil/hostap/hostap_wlan.h b/drivers/net/wireless/intersil/hostap/hostap_wlan.h index a8c4c1a8b29d..487883fbb58c 100644 --- a/drivers/net/wireless/intersil/hostap/hostap_wlan.h +++ b/drivers/net/wireless/intersil/hostap/hostap_wlan.h @@ -599,7 +599,7 @@ struct prism2_helper_functions { struct prism2_download_param *param); int (*tx)(struct sk_buff *skb, struct net_device *dev); int (*set_tim)(struct net_device *dev, int aid, int set); - const struct file_operations *read_aux_fops; + const struct proc_ops *read_aux_proc_ops; int need_tx_headroom; /* number of bytes of headroom needed before * IEEE 802.11 header */ diff --git a/drivers/net/wireless/ray_cs.c b/drivers/net/wireless/ray_cs.c index cf372684b681..c1d542bfa530 100644 --- a/drivers/net/wireless/ray_cs.c +++ b/drivers/net/wireless/ray_cs.c @@ -2717,10 +2717,9 @@ static ssize_t ray_cs_essid_proc_write(struct file *file, return count; } -static const struct file_operations ray_cs_essid_proc_fops = { - .owner = THIS_MODULE, - .write = ray_cs_essid_proc_write, - .llseek = noop_llseek, +static const struct proc_ops ray_cs_essid_proc_ops = { + .proc_write = ray_cs_essid_proc_write, + .proc_lseek = noop_llseek, }; static ssize_t int_proc_write(struct file *file, const char __user *buffer, @@ -2751,10 +2750,9 @@ static ssize_t int_proc_write(struct file *file, const char __user *buffer, return count; } -static const struct file_operations int_proc_fops = { - .owner = THIS_MODULE, - .write = int_proc_write, - .llseek = noop_llseek, +static const struct proc_ops int_proc_ops = { + .proc_write = int_proc_write, + .proc_lseek = noop_llseek, }; #endif @@ -2790,10 +2788,10 @@ static int __init init_ray_cs(void) proc_mkdir("driver/ray_cs", NULL); proc_create_single("driver/ray_cs/ray_cs", 0, NULL, ray_cs_proc_show); - proc_create("driver/ray_cs/essid", 0200, NULL, &ray_cs_essid_proc_fops); - proc_create_data("driver/ray_cs/net_type", 0200, NULL, &int_proc_fops, + proc_create("driver/ray_cs/essid", 0200, NULL, &ray_cs_essid_proc_ops); + proc_create_data("driver/ray_cs/net_type", 0200, NULL, &int_proc_ops, &net_type); - proc_create_data("driver/ray_cs/translate", 0200, NULL, &int_proc_fops, + proc_create_data("driver/ray_cs/translate", 0200, NULL, &int_proc_ops, &translate); #endif if (translate != 0) diff --git a/drivers/parisc/led.c b/drivers/parisc/led.c index 73e37bb877a4..36c6613f7a36 100644 --- a/drivers/parisc/led.c +++ b/drivers/parisc/led.c @@ -230,13 +230,12 @@ parse_error: return -EINVAL; } -static const struct file_operations led_proc_fops = { - .owner = THIS_MODULE, - .open = led_proc_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, - .write = led_proc_write, +static const struct proc_ops led_proc_ops = { + .proc_open = led_proc_open, + .proc_read = seq_read, + .proc_lseek = seq_lseek, + .proc_release = single_release, + .proc_write = led_proc_write, }; static int __init led_create_procfs(void) @@ -252,14 +251,14 @@ static int __init led_create_procfs(void) if (!lcd_no_led_support) { ent = proc_create_data("led", S_IRUGO|S_IWUSR, proc_pdc_root, - &led_proc_fops, (void *)LED_NOLCD); /* LED */ + &led_proc_ops, (void *)LED_NOLCD); /* LED */ if (!ent) return -1; } if (led_type == LED_HASLCD) { ent = proc_create_data("lcd", S_IRUGO|S_IWUSR, proc_pdc_root, - &led_proc_fops, (void *)LED_HASLCD); /* LCD */ + &led_proc_ops, (void *)LED_HASLCD); /* LCD */ if (!ent) return -1; } diff --git a/drivers/pci/proc.c b/drivers/pci/proc.c index 6ef74bf5013f..bd2b691fa7a3 100644 --- a/drivers/pci/proc.c +++ b/drivers/pci/proc.c @@ -306,19 +306,20 @@ static int proc_bus_pci_release(struct inode *inode, struct file *file) } #endif /* HAVE_PCI_MMAP */ -static const struct file_operations proc_bus_pci_operations = { - .owner = THIS_MODULE, - .llseek = proc_bus_pci_lseek, - .read = proc_bus_pci_read, - .write = proc_bus_pci_write, - .unlocked_ioctl = proc_bus_pci_ioctl, - .compat_ioctl = proc_bus_pci_ioctl, +static const struct proc_ops proc_bus_pci_ops = { + .proc_lseek = proc_bus_pci_lseek, + .proc_read = proc_bus_pci_read, + .proc_write = proc_bus_pci_write, + .proc_ioctl = proc_bus_pci_ioctl, +#ifdef CONFIG_COMPAT + .proc_compat_ioctl = proc_bus_pci_ioctl, +#endif #ifdef HAVE_PCI_MMAP - .open = proc_bus_pci_open, - .release = proc_bus_pci_release, - .mmap = proc_bus_pci_mmap, + .proc_open = proc_bus_pci_open, + .proc_release = proc_bus_pci_release, + .proc_mmap = proc_bus_pci_mmap, #ifdef HAVE_ARCH_PCI_GET_UNMAPPED_AREA - .get_unmapped_area = get_pci_unmapped_area, + .proc_get_unmapped_area = get_pci_unmapped_area, #endif /* HAVE_ARCH_PCI_GET_UNMAPPED_AREA */ #endif /* HAVE_PCI_MMAP */ }; @@ -424,7 +425,7 @@ int pci_proc_attach_device(struct pci_dev *dev) sprintf(name, "%02x.%x", PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn)); e = proc_create_data(name, S_IFREG | S_IRUGO | S_IWUSR, bus->procdir, - &proc_bus_pci_operations, dev); + &proc_bus_pci_ops, dev); if (!e) return -ENOMEM; proc_set_size(e, dev->cfg_size); diff --git a/drivers/platform/x86/thinkpad_acpi.c b/drivers/platform/x86/thinkpad_acpi.c index da794dcfdd92..8eaadbaf8ffa 100644 --- a/drivers/platform/x86/thinkpad_acpi.c +++ b/drivers/platform/x86/thinkpad_acpi.c @@ -907,13 +907,12 @@ static ssize_t dispatch_proc_write(struct file *file, return ret; } -static const struct file_operations dispatch_proc_fops = { - .owner = THIS_MODULE, - .open = dispatch_proc_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, - .write = dispatch_proc_write, +static const struct proc_ops dispatch_proc_ops = { + .proc_open = dispatch_proc_open, + .proc_read = seq_read, + .proc_lseek = seq_lseek, + .proc_release = single_release, + .proc_write = dispatch_proc_write, }; static char *next_cmd(char **cmds) @@ -9984,7 +9983,7 @@ static int __init ibm_init(struct ibm_init_struct *iibm) if (ibm->write) mode |= S_IWUSR; entry = proc_create_data(ibm->name, mode, proc_dir, - &dispatch_proc_fops, ibm); + &dispatch_proc_ops, ibm); if (!entry) { pr_err("unable to create proc entry %s\n", ibm->name); ret = -ENODEV; diff --git a/drivers/platform/x86/toshiba_acpi.c b/drivers/platform/x86/toshiba_acpi.c index a1e6569427c3..808944546739 100644 --- a/drivers/platform/x86/toshiba_acpi.c +++ b/drivers/platform/x86/toshiba_acpi.c @@ -1432,13 +1432,12 @@ static ssize_t lcd_proc_write(struct file *file, const char __user *buf, return count; } -static const struct file_operations lcd_proc_fops = { - .owner = THIS_MODULE, - .open = lcd_proc_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, - .write = lcd_proc_write, +static const struct proc_ops lcd_proc_ops = { + .proc_open = lcd_proc_open, + .proc_read = seq_read, + .proc_lseek = seq_lseek, + .proc_release = single_release, + .proc_write = lcd_proc_write, }; /* Video-Out */ @@ -1539,13 +1538,12 @@ static ssize_t video_proc_write(struct file *file, const char __user *buf, return ret ? -EIO : count; } -static const struct file_operations video_proc_fops = { - .owner = THIS_MODULE, - .open = video_proc_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, - .write = video_proc_write, +static const struct proc_ops video_proc_ops = { + .proc_open = video_proc_open, + .proc_read = seq_read, + .proc_lseek = seq_lseek, + .proc_release = single_release, + .proc_write = video_proc_write, }; /* Fan status */ @@ -1617,13 +1615,12 @@ static ssize_t fan_proc_write(struct file *file, const char __user *buf, return count; } -static const struct file_operations fan_proc_fops = { - .owner = THIS_MODULE, - .open = fan_proc_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, - .write = fan_proc_write, +static const struct proc_ops fan_proc_ops = { + .proc_open = fan_proc_open, + .proc_read = seq_read, + .proc_lseek = seq_lseek, + .proc_release = single_release, + .proc_write = fan_proc_write, }; static int keys_proc_show(struct seq_file *m, void *v) @@ -1662,13 +1659,12 @@ static ssize_t keys_proc_write(struct file *file, const char __user *buf, return count; } -static const struct file_operations keys_proc_fops = { - .owner = THIS_MODULE, - .open = keys_proc_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, - .write = keys_proc_write, +static const struct proc_ops keys_proc_ops = { + .proc_open = keys_proc_open, + .proc_read = seq_read, + .proc_lseek = seq_lseek, + .proc_release = single_release, + .proc_write = keys_proc_write, }; static int __maybe_unused version_proc_show(struct seq_file *m, void *v) @@ -1688,16 +1684,16 @@ static void create_toshiba_proc_entries(struct toshiba_acpi_dev *dev) { if (dev->backlight_dev) proc_create_data("lcd", S_IRUGO | S_IWUSR, toshiba_proc_dir, - &lcd_proc_fops, dev); + &lcd_proc_ops, dev); if (dev->video_supported) proc_create_data("video", S_IRUGO | S_IWUSR, toshiba_proc_dir, - &video_proc_fops, dev); + &video_proc_ops, dev); if (dev->fan_supported) proc_create_data("fan", S_IRUGO | S_IWUSR, toshiba_proc_dir, - &fan_proc_fops, dev); + &fan_proc_ops, dev); if (dev->hotkey_dev) proc_create_data("keys", S_IRUGO | S_IWUSR, toshiba_proc_dir, - &keys_proc_fops, dev); + &keys_proc_ops, dev); proc_create_single_data("version", S_IRUGO, toshiba_proc_dir, version_proc_show, dev); } diff --git a/drivers/pnp/isapnp/proc.c b/drivers/pnp/isapnp/proc.c index 36820979bd1c..785a796430fa 100644 --- a/drivers/pnp/isapnp/proc.c +++ b/drivers/pnp/isapnp/proc.c @@ -49,10 +49,9 @@ static ssize_t isapnp_proc_bus_read(struct file *file, char __user * buf, return nbytes; } -static const struct file_operations isapnp_proc_bus_file_operations = { - .owner = THIS_MODULE, - .llseek = isapnp_proc_bus_lseek, - .read = isapnp_proc_bus_read, +static const struct proc_ops isapnp_proc_bus_proc_ops = { + .proc_lseek = isapnp_proc_bus_lseek, + .proc_read = isapnp_proc_bus_read, }; static int isapnp_proc_attach_device(struct pnp_dev *dev) @@ -69,7 +68,7 @@ static int isapnp_proc_attach_device(struct pnp_dev *dev) } sprintf(name, "%02x", dev->number); e = dev->procent = proc_create_data(name, S_IFREG | S_IRUGO, de, - &isapnp_proc_bus_file_operations, dev); + &isapnp_proc_bus_proc_ops, dev); if (!e) return -ENOMEM; proc_set_size(e, 256); diff --git a/drivers/pnp/pnpbios/proc.c b/drivers/pnp/pnpbios/proc.c index fe1c8f5d9af0..a806830e3a40 100644 --- a/drivers/pnp/pnpbios/proc.c +++ b/drivers/pnp/pnpbios/proc.c @@ -210,13 +210,12 @@ out: return ret; } -static const struct file_operations pnpbios_proc_fops = { - .owner = THIS_MODULE, - .open = pnpbios_proc_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, - .write = pnpbios_proc_write, +static const struct proc_ops pnpbios_proc_ops = { + .proc_open = pnpbios_proc_open, + .proc_read = seq_read, + .proc_lseek = seq_lseek, + .proc_release = single_release, + .proc_write = pnpbios_proc_write, }; int pnpbios_interface_attach_device(struct pnp_bios_node *node) @@ -228,13 +227,13 @@ int pnpbios_interface_attach_device(struct pnp_bios_node *node) if (!proc_pnp) return -EIO; if (!pnpbios_dont_use_current_config) { - proc_create_data(name, 0644, proc_pnp, &pnpbios_proc_fops, + proc_create_data(name, 0644, proc_pnp, &pnpbios_proc_ops, (void *)(long)(node->handle)); } if (!proc_pnp_boot) return -EIO; - if (proc_create_data(name, 0644, proc_pnp_boot, &pnpbios_proc_fops, + if (proc_create_data(name, 0644, proc_pnp_boot, &pnpbios_proc_ops, (void *)(long)(node->handle + 0x100))) return 0; return -EIO; diff --git a/drivers/s390/block/dasd_proc.c b/drivers/s390/block/dasd_proc.c index 8d4d69ea5baf..62a859ea67f8 100644 --- a/drivers/s390/block/dasd_proc.c +++ b/drivers/s390/block/dasd_proc.c @@ -320,13 +320,12 @@ out_error: #endif /* CONFIG_DASD_PROFILE */ } -static const struct file_operations dasd_stats_proc_fops = { - .owner = THIS_MODULE, - .open = dasd_stats_proc_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, - .write = dasd_stats_proc_write, +static const struct proc_ops dasd_stats_proc_ops = { + .proc_open = dasd_stats_proc_open, + .proc_read = seq_read, + .proc_lseek = seq_lseek, + .proc_release = single_release, + .proc_write = dasd_stats_proc_write, }; /* @@ -347,7 +346,7 @@ dasd_proc_init(void) dasd_statistics_entry = proc_create("statistics", S_IFREG | S_IRUGO | S_IWUSR, dasd_proc_root_entry, - &dasd_stats_proc_fops); + &dasd_stats_proc_ops); if (!dasd_statistics_entry) goto out_nostatistics; return 0; diff --git a/drivers/s390/cio/blacklist.c b/drivers/s390/cio/blacklist.c index 2a3f874a21d5..da642e811f7f 100644 --- a/drivers/s390/cio/blacklist.c +++ b/drivers/s390/cio/blacklist.c @@ -398,12 +398,12 @@ cio_ignore_proc_open(struct inode *inode, struct file *file) sizeof(struct ccwdev_iter)); } -static const struct file_operations cio_ignore_proc_fops = { - .open = cio_ignore_proc_open, - .read = seq_read, - .llseek = seq_lseek, - .release = seq_release_private, - .write = cio_ignore_write, +static const struct proc_ops cio_ignore_proc_ops = { + .proc_open = cio_ignore_proc_open, + .proc_read = seq_read, + .proc_lseek = seq_lseek, + .proc_release = seq_release_private, + .proc_write = cio_ignore_write, }; static int @@ -412,7 +412,7 @@ cio_ignore_proc_init (void) struct proc_dir_entry *entry; entry = proc_create("cio_ignore", S_IFREG | S_IRUGO | S_IWUSR, NULL, - &cio_ignore_proc_fops); + &cio_ignore_proc_ops); if (!entry) return -ENOENT; return 0; diff --git a/drivers/s390/cio/css.c b/drivers/s390/cio/css.c index 831850435c23..94edbb33d0d1 100644 --- a/drivers/s390/cio/css.c +++ b/drivers/s390/cio/css.c @@ -1372,18 +1372,17 @@ static ssize_t cio_settle_write(struct file *file, const char __user *buf, return ret ? ret : count; } -static const struct file_operations cio_settle_proc_fops = { - .open = nonseekable_open, - .write = cio_settle_write, - .llseek = no_llseek, +static const struct proc_ops cio_settle_proc_ops = { + .proc_open = nonseekable_open, + .proc_write = cio_settle_write, + .proc_lseek = no_llseek, }; static int __init cio_settle_init(void) { struct proc_dir_entry *entry; - entry = proc_create("cio_settle", S_IWUSR, NULL, - &cio_settle_proc_fops); + entry = proc_create("cio_settle", S_IWUSR, NULL, &cio_settle_proc_ops); if (!entry) return -ENOMEM; return 0; diff --git a/drivers/scsi/esas2r/esas2r_main.c b/drivers/scsi/esas2r/esas2r_main.c index 80c5a235d193..7b49e2e9fcde 100644 --- a/drivers/scsi/esas2r/esas2r_main.c +++ b/drivers/scsi/esas2r/esas2r_main.c @@ -617,6 +617,13 @@ static const struct file_operations esas2r_proc_fops = { .unlocked_ioctl = esas2r_proc_ioctl, }; +static const struct proc_ops esas2r_proc_ops = { + .proc_ioctl = esas2r_proc_ioctl, +#ifdef CONFIG_COMPAT + .proc_compat_ioctl = compat_ptr_ioctl, +#endif +}; + static struct Scsi_Host *esas2r_proc_host; static int esas2r_proc_major; @@ -728,7 +735,7 @@ const char *esas2r_info(struct Scsi_Host *sh) pde = proc_create(ATTONODE_NAME, 0, sh->hostt->proc_dir, - &esas2r_proc_fops); + &esas2r_proc_ops); if (!pde) { esas2r_log_dev(ESAS2R_LOG_WARN, diff --git a/drivers/scsi/scsi_devinfo.c b/drivers/scsi/scsi_devinfo.c index df14597752ec..eed31021e788 100644 --- a/drivers/scsi/scsi_devinfo.c +++ b/drivers/scsi/scsi_devinfo.c @@ -736,13 +736,12 @@ out: return err; } -static const struct file_operations scsi_devinfo_proc_fops = { - .owner = THIS_MODULE, - .open = proc_scsi_devinfo_open, - .read = seq_read, - .write = proc_scsi_devinfo_write, - .llseek = seq_lseek, - .release = seq_release, +static const struct proc_ops scsi_devinfo_proc_ops = { + .proc_open = proc_scsi_devinfo_open, + .proc_read = seq_read, + .proc_write = proc_scsi_devinfo_write, + .proc_lseek = seq_lseek, + .proc_release = seq_release, }; #endif /* CONFIG_SCSI_PROC_FS */ @@ -867,7 +866,7 @@ int __init scsi_init_devinfo(void) } #ifdef CONFIG_SCSI_PROC_FS - p = proc_create("scsi/device_info", 0, NULL, &scsi_devinfo_proc_fops); + p = proc_create("scsi/device_info", 0, NULL, &scsi_devinfo_proc_ops); if (!p) { error = -ENOMEM; goto out; diff --git a/drivers/scsi/scsi_proc.c b/drivers/scsi/scsi_proc.c index 5b313226f11c..d6982d355739 100644 --- a/drivers/scsi/scsi_proc.c +++ b/drivers/scsi/scsi_proc.c @@ -83,12 +83,12 @@ static int proc_scsi_host_open(struct inode *inode, struct file *file) 4 * PAGE_SIZE); } -static const struct file_operations proc_scsi_fops = { - .open = proc_scsi_host_open, - .release = single_release, - .read = seq_read, - .llseek = seq_lseek, - .write = proc_scsi_host_write +static const struct proc_ops proc_scsi_ops = { + .proc_open = proc_scsi_host_open, + .proc_release = single_release, + .proc_read = seq_read, + .proc_lseek = seq_lseek, + .proc_write = proc_scsi_host_write }; /** @@ -146,7 +146,7 @@ void scsi_proc_host_add(struct Scsi_Host *shost) sprintf(name,"%d", shost->host_no); p = proc_create_data(name, S_IRUGO | S_IWUSR, - sht->proc_dir, &proc_scsi_fops, shost); + sht->proc_dir, &proc_scsi_ops, shost); if (!p) printk(KERN_ERR "%s: Failed to register host %d in" "%s\n", __func__, shost->host_no, @@ -436,13 +436,12 @@ static int proc_scsi_open(struct inode *inode, struct file *file) return seq_open(file, &scsi_seq_ops); } -static const struct file_operations proc_scsi_operations = { - .owner = THIS_MODULE, - .open = proc_scsi_open, - .read = seq_read, - .write = proc_scsi_write, - .llseek = seq_lseek, - .release = seq_release, +static const struct proc_ops scsi_scsi_proc_ops = { + .proc_open = proc_scsi_open, + .proc_read = seq_read, + .proc_write = proc_scsi_write, + .proc_lseek = seq_lseek, + .proc_release = seq_release, }; /** @@ -456,7 +455,7 @@ int __init scsi_init_procfs(void) if (!proc_scsi) goto err1; - pde = proc_create("scsi/scsi", 0, NULL, &proc_scsi_operations); + pde = proc_create("scsi/scsi", 0, NULL, &scsi_scsi_proc_ops); if (!pde) goto err2; diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c index bafeaf7b9ad8..4e6af592f018 100644 --- a/drivers/scsi/sg.c +++ b/drivers/scsi/sg.c @@ -2322,25 +2322,23 @@ static int sg_proc_seq_show_int(struct seq_file *s, void *v); static int sg_proc_single_open_adio(struct inode *inode, struct file *file); static ssize_t sg_proc_write_adio(struct file *filp, const char __user *buffer, size_t count, loff_t *off); -static const struct file_operations adio_fops = { - .owner = THIS_MODULE, - .open = sg_proc_single_open_adio, - .read = seq_read, - .llseek = seq_lseek, - .write = sg_proc_write_adio, - .release = single_release, +static const struct proc_ops adio_proc_ops = { + .proc_open = sg_proc_single_open_adio, + .proc_read = seq_read, + .proc_lseek = seq_lseek, + .proc_write = sg_proc_write_adio, + .proc_release = single_release, }; static int sg_proc_single_open_dressz(struct inode *inode, struct file *file); static ssize_t sg_proc_write_dressz(struct file *filp, const char __user *buffer, size_t count, loff_t *off); -static const struct file_operations dressz_fops = { - .owner = THIS_MODULE, - .open = sg_proc_single_open_dressz, - .read = seq_read, - .llseek = seq_lseek, - .write = sg_proc_write_dressz, - .release = single_release, +static const struct proc_ops dressz_proc_ops = { + .proc_open = sg_proc_single_open_dressz, + .proc_read = seq_read, + .proc_lseek = seq_lseek, + .proc_write = sg_proc_write_dressz, + .proc_release = single_release, }; static int sg_proc_seq_show_version(struct seq_file *s, void *v); @@ -2381,9 +2379,9 @@ sg_proc_init(void) if (!p) return 1; - proc_create("allow_dio", S_IRUGO | S_IWUSR, p, &adio_fops); + proc_create("allow_dio", S_IRUGO | S_IWUSR, p, &adio_proc_ops); proc_create_seq("debug", S_IRUGO, p, &debug_seq_ops); - proc_create("def_reserved_size", S_IRUGO | S_IWUSR, p, &dressz_fops); + proc_create("def_reserved_size", S_IRUGO | S_IWUSR, p, &dressz_proc_ops); proc_create_single("device_hdr", S_IRUGO, p, sg_proc_seq_show_devhdr); proc_create_seq("devices", S_IRUGO, p, &dev_seq_ops); proc_create_seq("device_strs", S_IRUGO, p, &devstrs_seq_ops); diff --git a/drivers/staging/rtl8192u/ieee80211/ieee80211_module.c b/drivers/staging/rtl8192u/ieee80211/ieee80211_module.c index 4a6c3f674431..aa9dab8a4ae8 100644 --- a/drivers/staging/rtl8192u/ieee80211/ieee80211_module.c +++ b/drivers/staging/rtl8192u/ieee80211/ieee80211_module.c @@ -264,12 +264,12 @@ static int open_debug_level(struct inode *inode, struct file *file) return single_open(file, show_debug_level, NULL); } -static const struct file_operations fops = { - .open = open_debug_level, - .read = seq_read, - .llseek = seq_lseek, - .write = write_debug_level, - .release = single_release, +static const struct proc_ops debug_level_proc_ops = { + .proc_open = open_debug_level, + .proc_read = seq_read, + .proc_lseek = seq_lseek, + .proc_write = write_debug_level, + .proc_release = single_release, }; int __init ieee80211_debug_init(void) @@ -284,7 +284,7 @@ int __init ieee80211_debug_init(void) " proc directory\n"); return -EIO; } - e = proc_create("debug_level", 0644, ieee80211_proc, &fops); + e = proc_create("debug_level", 0644, ieee80211_proc, &debug_level_proc_ops); if (!e) { remove_proc_entry(DRV_NAME, init_net.proc_net); ieee80211_proc = NULL; diff --git a/drivers/tty/sysrq.c b/drivers/tty/sysrq.c index 1d4f317a0e42..f724962a5906 100644 --- a/drivers/tty/sysrq.c +++ b/drivers/tty/sysrq.c @@ -1101,15 +1101,15 @@ static ssize_t write_sysrq_trigger(struct file *file, const char __user *buf, return count; } -static const struct file_operations proc_sysrq_trigger_operations = { - .write = write_sysrq_trigger, - .llseek = noop_llseek, +static const struct proc_ops sysrq_trigger_proc_ops = { + .proc_write = write_sysrq_trigger, + .proc_lseek = noop_llseek, }; static void sysrq_init_procfs(void) { if (!proc_create("sysrq-trigger", S_IWUSR, NULL, - &proc_sysrq_trigger_operations)) + &sysrq_trigger_proc_ops)) pr_err("Failed to register proc interface\n"); } diff --git a/drivers/usb/gadget/function/rndis.c b/drivers/usb/gadget/function/rndis.c index 04c142c13075..64de9f1b874c 100644 --- a/drivers/usb/gadget/function/rndis.c +++ b/drivers/usb/gadget/function/rndis.c @@ -72,7 +72,7 @@ static rndis_resp_t *rndis_add_response(struct rndis_params *params, #ifdef CONFIG_USB_GADGET_DEBUG_FILES -static const struct file_operations rndis_proc_fops; +static const struct proc_ops rndis_proc_ops; #endif /* CONFIG_USB_GADGET_DEBUG_FILES */ @@ -902,7 +902,7 @@ struct rndis_params *rndis_register(void (*resp_avail)(void *v), void *v) sprintf(name, NAME_TEMPLATE, i); proc_entry = proc_create_data(name, 0660, NULL, - &rndis_proc_fops, params); + &rndis_proc_ops, params); if (!proc_entry) { kfree(params); rndis_put_nr(i); @@ -1164,13 +1164,12 @@ static int rndis_proc_open(struct inode *inode, struct file *file) return single_open(file, rndis_proc_show, PDE_DATA(inode)); } -static const struct file_operations rndis_proc_fops = { - .owner = THIS_MODULE, - .open = rndis_proc_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, - .write = rndis_proc_write, +static const struct proc_ops rndis_proc_ops = { + .proc_open = rndis_proc_open, + .proc_read = seq_read, + .proc_lseek = seq_lseek, + .proc_release = single_release, + .proc_write = rndis_proc_write, }; #define NAME_TEMPLATE "driver/rndis-%03d" diff --git a/drivers/video/fbdev/via/viafbdev.c b/drivers/video/fbdev/via/viafbdev.c index f815f98190bc..852673c40a2f 100644 --- a/drivers/video/fbdev/via/viafbdev.c +++ b/drivers/video/fbdev/via/viafbdev.c @@ -1173,13 +1173,12 @@ static ssize_t viafb_dvp0_proc_write(struct file *file, return count; } -static const struct file_operations viafb_dvp0_proc_fops = { - .owner = THIS_MODULE, - .open = viafb_dvp0_proc_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, - .write = viafb_dvp0_proc_write, +static const struct proc_ops viafb_dvp0_proc_ops = { + .proc_open = viafb_dvp0_proc_open, + .proc_read = seq_read, + .proc_lseek = seq_lseek, + .proc_release = single_release, + .proc_write = viafb_dvp0_proc_write, }; static int viafb_dvp1_proc_show(struct seq_file *m, void *v) @@ -1238,13 +1237,12 @@ static ssize_t viafb_dvp1_proc_write(struct file *file, return count; } -static const struct file_operations viafb_dvp1_proc_fops = { - .owner = THIS_MODULE, - .open = viafb_dvp1_proc_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, - .write = viafb_dvp1_proc_write, +static const struct proc_ops viafb_dvp1_proc_ops = { + .proc_open = viafb_dvp1_proc_open, + .proc_read = seq_read, + .proc_lseek = seq_lseek, + .proc_release = single_release, + .proc_write = viafb_dvp1_proc_write, }; static int viafb_dfph_proc_show(struct seq_file *m, void *v) @@ -1273,13 +1271,12 @@ static ssize_t viafb_dfph_proc_write(struct file *file, return count; } -static const struct file_operations viafb_dfph_proc_fops = { - .owner = THIS_MODULE, - .open = viafb_dfph_proc_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, - .write = viafb_dfph_proc_write, +static const struct proc_ops viafb_dfph_proc_ops = { + .proc_open = viafb_dfph_proc_open, + .proc_read = seq_read, + .proc_lseek = seq_lseek, + .proc_release = single_release, + .proc_write = viafb_dfph_proc_write, }; static int viafb_dfpl_proc_show(struct seq_file *m, void *v) @@ -1308,13 +1305,12 @@ static ssize_t viafb_dfpl_proc_write(struct file *file, return count; } -static const struct file_operations viafb_dfpl_proc_fops = { - .owner = THIS_MODULE, - .open = viafb_dfpl_proc_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, - .write = viafb_dfpl_proc_write, +static const struct proc_ops viafb_dfpl_proc_ops = { + .proc_open = viafb_dfpl_proc_open, + .proc_read = seq_read, + .proc_lseek = seq_lseek, + .proc_release = single_release, + .proc_write = viafb_dfpl_proc_write, }; static int viafb_vt1636_proc_show(struct seq_file *m, void *v) @@ -1444,13 +1440,12 @@ static ssize_t viafb_vt1636_proc_write(struct file *file, return count; } -static const struct file_operations viafb_vt1636_proc_fops = { - .owner = THIS_MODULE, - .open = viafb_vt1636_proc_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, - .write = viafb_vt1636_proc_write, +static const struct proc_ops viafb_vt1636_proc_ops = { + .proc_open = viafb_vt1636_proc_open, + .proc_read = seq_read, + .proc_lseek = seq_lseek, + .proc_release = single_release, + .proc_write = viafb_vt1636_proc_write, }; #endif /* CONFIG_FB_VIA_DIRECT_PROCFS */ @@ -1522,13 +1517,12 @@ static ssize_t viafb_iga1_odev_proc_write(struct file *file, return res; } -static const struct file_operations viafb_iga1_odev_proc_fops = { - .owner = THIS_MODULE, - .open = viafb_iga1_odev_proc_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, - .write = viafb_iga1_odev_proc_write, +static const struct proc_ops viafb_iga1_odev_proc_ops = { + .proc_open = viafb_iga1_odev_proc_open, + .proc_read = seq_read, + .proc_lseek = seq_lseek, + .proc_release = single_release, + .proc_write = viafb_iga1_odev_proc_write, }; static int viafb_iga2_odev_proc_show(struct seq_file *m, void *v) @@ -1562,13 +1556,12 @@ static ssize_t viafb_iga2_odev_proc_write(struct file *file, return res; } -static const struct file_operations viafb_iga2_odev_proc_fops = { - .owner = THIS_MODULE, - .open = viafb_iga2_odev_proc_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, - .write = viafb_iga2_odev_proc_write, +static const struct proc_ops viafb_iga2_odev_proc_ops = { + .proc_open = viafb_iga2_odev_proc_open, + .proc_read = seq_read, + .proc_lseek = seq_lseek, + .proc_release = single_release, + .proc_write = viafb_iga2_odev_proc_write, }; #define IS_VT1636(lvds_chip) ((lvds_chip).lvds_chip_name == VT1636_LVDS) @@ -1580,14 +1573,14 @@ static void viafb_init_proc(struct viafb_shared *shared) shared->proc_entry = viafb_entry; if (viafb_entry) { #ifdef CONFIG_FB_VIA_DIRECT_PROCFS - proc_create("dvp0", 0, viafb_entry, &viafb_dvp0_proc_fops); - proc_create("dvp1", 0, viafb_entry, &viafb_dvp1_proc_fops); - proc_create("dfph", 0, viafb_entry, &viafb_dfph_proc_fops); - proc_create("dfpl", 0, viafb_entry, &viafb_dfpl_proc_fops); + proc_create("dvp0", 0, viafb_entry, &viafb_dvp0_proc_ops); + proc_create("dvp1", 0, viafb_entry, &viafb_dvp1_proc_ops); + proc_create("dfph", 0, viafb_entry, &viafb_dfph_proc_ops); + proc_create("dfpl", 0, viafb_entry, &viafb_dfpl_proc_ops); if (IS_VT1636(shared->chip_info.lvds_chip_info) || IS_VT1636(shared->chip_info.lvds_chip_info2)) proc_create("vt1636", 0, viafb_entry, - &viafb_vt1636_proc_fops); + &viafb_vt1636_proc_ops); #endif /* CONFIG_FB_VIA_DIRECT_PROCFS */ proc_create_single("supported_output_devices", 0, viafb_entry, @@ -1595,11 +1588,11 @@ static void viafb_init_proc(struct viafb_shared *shared) iga1_entry = proc_mkdir("iga1", viafb_entry); shared->iga1_proc_entry = iga1_entry; proc_create("output_devices", 0, iga1_entry, - &viafb_iga1_odev_proc_fops); + &viafb_iga1_odev_proc_ops); iga2_entry = proc_mkdir("iga2", viafb_entry); shared->iga2_proc_entry = iga2_entry; proc_create("output_devices", 0, iga2_entry, - &viafb_iga2_odev_proc_fops); + &viafb_iga2_odev_proc_ops); } } static void viafb_remove_proc(struct viafb_shared *shared) diff --git a/drivers/zorro/proc.c b/drivers/zorro/proc.c index 2e4ca4dc0960..1c9ae08225d8 100644 --- a/drivers/zorro/proc.c +++ b/drivers/zorro/proc.c @@ -56,10 +56,9 @@ proc_bus_zorro_read(struct file *file, char __user *buf, size_t nbytes, loff_t * return nbytes; } -static const struct file_operations proc_bus_zorro_operations = { - .owner = THIS_MODULE, - .llseek = proc_bus_zorro_lseek, - .read = proc_bus_zorro_read, +static const struct proc_ops bus_zorro_proc_ops = { + .proc_lseek = proc_bus_zorro_lseek, + .proc_read = proc_bus_zorro_read, }; static void * zorro_seq_start(struct seq_file *m, loff_t *pos) @@ -105,7 +104,7 @@ static int __init zorro_proc_attach_device(unsigned int slot) sprintf(name, "%02x", slot); entry = proc_create_data(name, 0, proc_bus_zorro_dir, - &proc_bus_zorro_operations, + &bus_zorro_proc_ops, &zorro_autocon[slot]); if (!entry) return -ENOMEM; diff --git a/fs/cifs/cifs_debug.c b/fs/cifs/cifs_debug.c index 19f6e592b941..276e4b5ea8e0 100644 --- a/fs/cifs/cifs_debug.c +++ b/fs/cifs/cifs_debug.c @@ -611,12 +611,12 @@ static int cifs_stats_proc_open(struct inode *inode, struct file *file) return single_open(file, cifs_stats_proc_show, NULL); } -static const struct file_operations cifs_stats_proc_fops = { - .open = cifs_stats_proc_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, - .write = cifs_stats_proc_write, +static const struct proc_ops cifs_stats_proc_ops = { + .proc_open = cifs_stats_proc_open, + .proc_read = seq_read, + .proc_lseek = seq_lseek, + .proc_release = single_release, + .proc_write = cifs_stats_proc_write, }; #ifdef CONFIG_CIFS_SMB_DIRECT @@ -640,12 +640,12 @@ static int name##_open(struct inode *inode, struct file *file) \ return single_open(file, name##_proc_show, NULL); \ } \ \ -static const struct file_operations cifs_##name##_proc_fops = { \ - .open = name##_open, \ - .read = seq_read, \ - .llseek = seq_lseek, \ - .release = single_release, \ - .write = name##_write, \ +static const struct proc_ops cifs_##name##_proc_fops = { \ + .proc_open = name##_open, \ + .proc_read = seq_read, \ + .proc_lseek = seq_lseek, \ + .proc_release = single_release, \ + .proc_write = name##_write, \ } PROC_FILE_DEFINE(rdma_readwrite_threshold); @@ -659,11 +659,11 @@ PROC_FILE_DEFINE(smbd_receive_credit_max); #endif static struct proc_dir_entry *proc_fs_cifs; -static const struct file_operations cifsFYI_proc_fops; -static const struct file_operations cifs_lookup_cache_proc_fops; -static const struct file_operations traceSMB_proc_fops; -static const struct file_operations cifs_security_flags_proc_fops; -static const struct file_operations cifs_linux_ext_proc_fops; +static const struct proc_ops cifsFYI_proc_ops; +static const struct proc_ops cifs_lookup_cache_proc_ops; +static const struct proc_ops traceSMB_proc_ops; +static const struct proc_ops cifs_security_flags_proc_ops; +static const struct proc_ops cifs_linux_ext_proc_ops; void cifs_proc_init(void) @@ -678,18 +678,18 @@ cifs_proc_init(void) proc_create_single("open_files", 0400, proc_fs_cifs, cifs_debug_files_proc_show); - proc_create("Stats", 0644, proc_fs_cifs, &cifs_stats_proc_fops); - proc_create("cifsFYI", 0644, proc_fs_cifs, &cifsFYI_proc_fops); - proc_create("traceSMB", 0644, proc_fs_cifs, &traceSMB_proc_fops); + proc_create("Stats", 0644, proc_fs_cifs, &cifs_stats_proc_ops); + proc_create("cifsFYI", 0644, proc_fs_cifs, &cifsFYI_proc_ops); + proc_create("traceSMB", 0644, proc_fs_cifs, &traceSMB_proc_ops); proc_create("LinuxExtensionsEnabled", 0644, proc_fs_cifs, - &cifs_linux_ext_proc_fops); + &cifs_linux_ext_proc_ops); proc_create("SecurityFlags", 0644, proc_fs_cifs, - &cifs_security_flags_proc_fops); + &cifs_security_flags_proc_ops); proc_create("LookupCacheEnabled", 0644, proc_fs_cifs, - &cifs_lookup_cache_proc_fops); + &cifs_lookup_cache_proc_ops); #ifdef CONFIG_CIFS_DFS_UPCALL - proc_create("dfscache", 0644, proc_fs_cifs, &dfscache_proc_fops); + proc_create("dfscache", 0644, proc_fs_cifs, &dfscache_proc_ops); #endif #ifdef CONFIG_CIFS_SMB_DIRECT @@ -774,12 +774,12 @@ static ssize_t cifsFYI_proc_write(struct file *file, const char __user *buffer, return count; } -static const struct file_operations cifsFYI_proc_fops = { - .open = cifsFYI_proc_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, - .write = cifsFYI_proc_write, +static const struct proc_ops cifsFYI_proc_ops = { + .proc_open = cifsFYI_proc_open, + .proc_read = seq_read, + .proc_lseek = seq_lseek, + .proc_release = single_release, + .proc_write = cifsFYI_proc_write, }; static int cifs_linux_ext_proc_show(struct seq_file *m, void *v) @@ -805,12 +805,12 @@ static ssize_t cifs_linux_ext_proc_write(struct file *file, return count; } -static const struct file_operations cifs_linux_ext_proc_fops = { - .open = cifs_linux_ext_proc_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, - .write = cifs_linux_ext_proc_write, +static const struct proc_ops cifs_linux_ext_proc_ops = { + .proc_open = cifs_linux_ext_proc_open, + .proc_read = seq_read, + .proc_lseek = seq_lseek, + .proc_release = single_release, + .proc_write = cifs_linux_ext_proc_write, }; static int cifs_lookup_cache_proc_show(struct seq_file *m, void *v) @@ -836,12 +836,12 @@ static ssize_t cifs_lookup_cache_proc_write(struct file *file, return count; } -static const struct file_operations cifs_lookup_cache_proc_fops = { - .open = cifs_lookup_cache_proc_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, - .write = cifs_lookup_cache_proc_write, +static const struct proc_ops cifs_lookup_cache_proc_ops = { + .proc_open = cifs_lookup_cache_proc_open, + .proc_read = seq_read, + .proc_lseek = seq_lseek, + .proc_release = single_release, + .proc_write = cifs_lookup_cache_proc_write, }; static int traceSMB_proc_show(struct seq_file *m, void *v) @@ -867,12 +867,12 @@ static ssize_t traceSMB_proc_write(struct file *file, const char __user *buffer, return count; } -static const struct file_operations traceSMB_proc_fops = { - .open = traceSMB_proc_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, - .write = traceSMB_proc_write, +static const struct proc_ops traceSMB_proc_ops = { + .proc_open = traceSMB_proc_open, + .proc_read = seq_read, + .proc_lseek = seq_lseek, + .proc_release = single_release, + .proc_write = traceSMB_proc_write, }; static int cifs_security_flags_proc_show(struct seq_file *m, void *v) @@ -978,12 +978,12 @@ static ssize_t cifs_security_flags_proc_write(struct file *file, return count; } -static const struct file_operations cifs_security_flags_proc_fops = { - .open = cifs_security_flags_proc_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, - .write = cifs_security_flags_proc_write, +static const struct proc_ops cifs_security_flags_proc_ops = { + .proc_open = cifs_security_flags_proc_open, + .proc_read = seq_read, + .proc_lseek = seq_lseek, + .proc_release = single_release, + .proc_write = cifs_security_flags_proc_write, }; #else inline void cifs_proc_init(void) diff --git a/fs/cifs/dfs_cache.c b/fs/cifs/dfs_cache.c index 9a384d1e27b4..43c1b43a07ec 100644 --- a/fs/cifs/dfs_cache.c +++ b/fs/cifs/dfs_cache.c @@ -8,6 +8,7 @@ #include #include #include +#include #include #include #include "cifsglob.h" @@ -211,12 +212,12 @@ static int dfscache_proc_open(struct inode *inode, struct file *file) return single_open(file, dfscache_proc_show, NULL); } -const struct file_operations dfscache_proc_fops = { - .open = dfscache_proc_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, - .write = dfscache_proc_write, +const struct proc_ops dfscache_proc_ops = { + .proc_open = dfscache_proc_open, + .proc_read = seq_read, + .proc_lseek = seq_lseek, + .proc_release = single_release, + .proc_write = dfscache_proc_write, }; #ifdef CONFIG_CIFS_DEBUG2 diff --git a/fs/cifs/dfs_cache.h b/fs/cifs/dfs_cache.h index 76c732943f5f..99ee44f8ad07 100644 --- a/fs/cifs/dfs_cache.h +++ b/fs/cifs/dfs_cache.h @@ -24,7 +24,7 @@ struct dfs_cache_tgt_iterator { extern int dfs_cache_init(void); extern void dfs_cache_destroy(void); -extern const struct file_operations dfscache_proc_fops; +extern const struct proc_ops dfscache_proc_ops; extern int dfs_cache_find(const unsigned int xid, struct cifs_ses *ses, const struct nls_table *nls_codepage, int remap, diff --git a/fs/fscache/internal.h b/fs/fscache/internal.h index 9616af3768e1..08e91efbce53 100644 --- a/fs/fscache/internal.h +++ b/fs/fscache/internal.h @@ -111,7 +111,7 @@ extern void fscache_enqueue_object(struct fscache_object *); * object-list.c */ #ifdef CONFIG_FSCACHE_OBJECT_LIST -extern const struct file_operations fscache_objlist_fops; +extern const struct proc_ops fscache_objlist_proc_ops; extern void fscache_objlist_add(struct fscache_object *); extern void fscache_objlist_remove(struct fscache_object *); diff --git a/fs/fscache/object-list.c b/fs/fscache/object-list.c index 72ebfe578f40..e106a1a1600d 100644 --- a/fs/fscache/object-list.c +++ b/fs/fscache/object-list.c @@ -7,6 +7,7 @@ #define FSCACHE_DEBUG_LEVEL COOKIE #include +#include #include #include #include @@ -405,9 +406,9 @@ static int fscache_objlist_release(struct inode *inode, struct file *file) return seq_release(inode, file); } -const struct file_operations fscache_objlist_fops = { - .open = fscache_objlist_open, - .read = seq_read, - .llseek = seq_lseek, - .release = fscache_objlist_release, +const struct proc_ops fscache_objlist_proc_ops = { + .proc_open = fscache_objlist_open, + .proc_read = seq_read, + .proc_lseek = seq_lseek, + .proc_release = fscache_objlist_release, }; diff --git a/fs/fscache/proc.c b/fs/fscache/proc.c index 5523446e2952..90a7bc22f7e1 100644 --- a/fs/fscache/proc.c +++ b/fs/fscache/proc.c @@ -35,7 +35,7 @@ int __init fscache_proc_init(void) #ifdef CONFIG_FSCACHE_OBJECT_LIST if (!proc_create("fs/fscache/objects", S_IFREG | 0444, NULL, - &fscache_objlist_fops)) + &fscache_objlist_proc_ops)) goto error_objects; #endif diff --git a/fs/jbd2/journal.c b/fs/jbd2/journal.c index 60bf8ff78913..eb8ca446d1ab 100644 --- a/fs/jbd2/journal.c +++ b/fs/jbd2/journal.c @@ -1074,12 +1074,11 @@ static int jbd2_seq_info_release(struct inode *inode, struct file *file) return seq_release(inode, file); } -static const struct file_operations jbd2_seq_info_fops = { - .owner = THIS_MODULE, - .open = jbd2_seq_info_open, - .read = seq_read, - .llseek = seq_lseek, - .release = jbd2_seq_info_release, +static const struct proc_ops jbd2_info_proc_ops = { + .proc_open = jbd2_seq_info_open, + .proc_read = seq_read, + .proc_lseek = seq_lseek, + .proc_release = jbd2_seq_info_release, }; static struct proc_dir_entry *proc_jbd2_stats; @@ -1089,7 +1088,7 @@ static void jbd2_stats_proc_init(journal_t *journal) journal->j_proc_entry = proc_mkdir(journal->j_devname, proc_jbd2_stats); if (journal->j_proc_entry) { proc_create_data("info", S_IRUGO, journal->j_proc_entry, - &jbd2_seq_info_fops, journal); + &jbd2_info_proc_ops, journal); } } diff --git a/fs/jfs/jfs_debug.c b/fs/jfs/jfs_debug.c index 888cdd685a1e..44b62b3c322e 100644 --- a/fs/jfs/jfs_debug.c +++ b/fs/jfs/jfs_debug.c @@ -43,12 +43,12 @@ static ssize_t jfs_loglevel_proc_write(struct file *file, return count; } -static const struct file_operations jfs_loglevel_proc_fops = { - .open = jfs_loglevel_proc_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, - .write = jfs_loglevel_proc_write, +static const struct proc_ops jfs_loglevel_proc_ops = { + .proc_open = jfs_loglevel_proc_open, + .proc_read = seq_read, + .proc_lseek = seq_lseek, + .proc_release = single_release, + .proc_write = jfs_loglevel_proc_write, }; #endif @@ -68,7 +68,7 @@ void jfs_proc_init(void) #endif #ifdef CONFIG_JFS_DEBUG proc_create_single("TxAnchor", 0, base, jfs_txanchor_proc_show); - proc_create("loglevel", 0, base, &jfs_loglevel_proc_fops); + proc_create("loglevel", 0, base, &jfs_loglevel_proc_ops); #endif } diff --git a/fs/lockd/procfs.c b/fs/lockd/procfs.c index ca9228a56d65..a01f08c8c2f3 100644 --- a/fs/lockd/procfs.c +++ b/fs/lockd/procfs.c @@ -60,11 +60,11 @@ nlm_end_grace_read(struct file *file, char __user *buf, size_t size, return simple_read_from_buffer(buf, size, pos, resp, sizeof(resp)); } -static const struct file_operations lockd_end_grace_operations = { - .write = nlm_end_grace_write, - .read = nlm_end_grace_read, - .llseek = default_llseek, - .release = simple_transaction_release, +static const struct proc_ops lockd_end_grace_proc_ops = { + .proc_write = nlm_end_grace_write, + .proc_read = nlm_end_grace_read, + .proc_lseek = default_llseek, + .proc_release = simple_transaction_release, }; int __init @@ -76,7 +76,7 @@ lockd_create_procfs(void) if (!entry) return -ENOMEM; entry = proc_create("nlm_end_grace", S_IRUGO|S_IWUSR, entry, - &lockd_end_grace_operations); + &lockd_end_grace_proc_ops); if (!entry) { remove_proc_entry("fs/lockd", NULL); return -ENOMEM; diff --git a/fs/nfsd/nfsctl.c b/fs/nfsd/nfsctl.c index 11b42c523f04..7eb919f1b13f 100644 --- a/fs/nfsd/nfsctl.c +++ b/fs/nfsd/nfsctl.c @@ -157,11 +157,11 @@ static int exports_proc_open(struct inode *inode, struct file *file) return exports_net_open(current->nsproxy->net_ns, file); } -static const struct file_operations exports_proc_operations = { - .open = exports_proc_open, - .read = seq_read, - .llseek = seq_lseek, - .release = seq_release, +static const struct proc_ops exports_proc_ops = { + .proc_open = exports_proc_open, + .proc_read = seq_read, + .proc_lseek = seq_lseek, + .proc_release = seq_release, }; static int exports_nfsd_open(struct inode *inode, struct file *file) @@ -1431,8 +1431,7 @@ static int create_proc_exports_entry(void) entry = proc_mkdir("fs/nfs", NULL); if (!entry) return -ENOMEM; - entry = proc_create("exports", 0, entry, - &exports_proc_operations); + entry = proc_create("exports", 0, entry, &exports_proc_ops); if (!entry) { remove_proc_entry("fs/nfs", NULL); return -ENOMEM; diff --git a/fs/nfsd/stats.c b/fs/nfsd/stats.c index 9bce3b913189..b1bc582b0493 100644 --- a/fs/nfsd/stats.c +++ b/fs/nfsd/stats.c @@ -84,17 +84,17 @@ static int nfsd_proc_open(struct inode *inode, struct file *file) return single_open(file, nfsd_proc_show, NULL); } -static const struct file_operations nfsd_proc_fops = { - .open = nfsd_proc_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, +static const struct proc_ops nfsd_proc_ops = { + .proc_open = nfsd_proc_open, + .proc_read = seq_read, + .proc_lseek = seq_lseek, + .proc_release = single_release, }; void nfsd_stat_init(void) { - svc_proc_register(&init_net, &nfsd_svcstats, &nfsd_proc_fops); + svc_proc_register(&init_net, &nfsd_svcstats, &nfsd_proc_ops); } void diff --git a/fs/proc/cpuinfo.c b/fs/proc/cpuinfo.c index 96f1087e372c..c1dea9b8222e 100644 --- a/fs/proc/cpuinfo.c +++ b/fs/proc/cpuinfo.c @@ -16,16 +16,16 @@ static int cpuinfo_open(struct inode *inode, struct file *file) return seq_open(file, &cpuinfo_op); } -static const struct file_operations proc_cpuinfo_operations = { - .open = cpuinfo_open, - .read = seq_read, - .llseek = seq_lseek, - .release = seq_release, +static const struct proc_ops cpuinfo_proc_ops = { + .proc_open = cpuinfo_open, + .proc_read = seq_read, + .proc_lseek = seq_lseek, + .proc_release = seq_release, }; static int __init proc_cpuinfo_init(void) { - proc_create("cpuinfo", 0, NULL, &proc_cpuinfo_operations); + proc_create("cpuinfo", 0, NULL, &cpuinfo_proc_ops); return 0; } fs_initcall(proc_cpuinfo_init); diff --git a/fs/proc/kcore.c b/fs/proc/kcore.c index e2ed8e08cc7a..8ba492d44e68 100644 --- a/fs/proc/kcore.c +++ b/fs/proc/kcore.c @@ -574,11 +574,11 @@ static int release_kcore(struct inode *inode, struct file *file) return 0; } -static const struct file_operations proc_kcore_operations = { - .read = read_kcore, - .open = open_kcore, - .release = release_kcore, - .llseek = default_llseek, +static const struct proc_ops kcore_proc_ops = { + .proc_read = read_kcore, + .proc_open = open_kcore, + .proc_release = release_kcore, + .proc_lseek = default_llseek, }; /* just remember that we have to update kcore */ @@ -637,8 +637,7 @@ static void __init add_modules_range(void) static int __init proc_kcore_init(void) { - proc_root_kcore = proc_create("kcore", S_IRUSR, NULL, - &proc_kcore_operations); + proc_root_kcore = proc_create("kcore", S_IRUSR, NULL, &kcore_proc_ops); if (!proc_root_kcore) { pr_err("couldn't create /proc/kcore\n"); return 0; /* Always returns 0. */ diff --git a/fs/proc/kmsg.c b/fs/proc/kmsg.c index 4f4a2abb225e..ec1b7d2fb773 100644 --- a/fs/proc/kmsg.c +++ b/fs/proc/kmsg.c @@ -49,17 +49,17 @@ static __poll_t kmsg_poll(struct file *file, poll_table *wait) } -static const struct file_operations proc_kmsg_operations = { - .read = kmsg_read, - .poll = kmsg_poll, - .open = kmsg_open, - .release = kmsg_release, - .llseek = generic_file_llseek, +static const struct proc_ops kmsg_proc_ops = { + .proc_read = kmsg_read, + .proc_poll = kmsg_poll, + .proc_open = kmsg_open, + .proc_release = kmsg_release, + .proc_lseek = generic_file_llseek, }; static int __init proc_kmsg_init(void) { - proc_create("kmsg", S_IRUSR, NULL, &proc_kmsg_operations); + proc_create("kmsg", S_IRUSR, NULL, &kmsg_proc_ops); return 0; } fs_initcall(proc_kmsg_init); diff --git a/fs/proc/page.c b/fs/proc/page.c index 7a84f6fcfa68..f909243d4a66 100644 --- a/fs/proc/page.c +++ b/fs/proc/page.c @@ -89,9 +89,9 @@ static ssize_t kpagecount_read(struct file *file, char __user *buf, return ret; } -static const struct file_operations proc_kpagecount_operations = { - .llseek = mem_lseek, - .read = kpagecount_read, +static const struct proc_ops kpagecount_proc_ops = { + .proc_lseek = mem_lseek, + .proc_read = kpagecount_read, }; /* /proc/kpageflags - an array exposing page flags @@ -263,9 +263,9 @@ static ssize_t kpageflags_read(struct file *file, char __user *buf, return ret; } -static const struct file_operations proc_kpageflags_operations = { - .llseek = mem_lseek, - .read = kpageflags_read, +static const struct proc_ops kpageflags_proc_ops = { + .proc_lseek = mem_lseek, + .proc_read = kpageflags_read, }; #ifdef CONFIG_MEMCG @@ -317,18 +317,18 @@ static ssize_t kpagecgroup_read(struct file *file, char __user *buf, return ret; } -static const struct file_operations proc_kpagecgroup_operations = { - .llseek = mem_lseek, - .read = kpagecgroup_read, +static const struct proc_ops kpagecgroup_proc_ops = { + .proc_lseek = mem_lseek, + .proc_read = kpagecgroup_read, }; #endif /* CONFIG_MEMCG */ static int __init proc_page_init(void) { - proc_create("kpagecount", S_IRUSR, NULL, &proc_kpagecount_operations); - proc_create("kpageflags", S_IRUSR, NULL, &proc_kpageflags_operations); + proc_create("kpagecount", S_IRUSR, NULL, &kpagecount_proc_ops); + proc_create("kpageflags", S_IRUSR, NULL, &kpageflags_proc_ops); #ifdef CONFIG_MEMCG - proc_create("kpagecgroup", S_IRUSR, NULL, &proc_kpagecgroup_operations); + proc_create("kpagecgroup", S_IRUSR, NULL, &kpagecgroup_proc_ops); #endif return 0; } diff --git a/fs/proc/stat.c b/fs/proc/stat.c index fd931d3e77be..0449edf460f5 100644 --- a/fs/proc/stat.c +++ b/fs/proc/stat.c @@ -223,16 +223,16 @@ static int stat_open(struct inode *inode, struct file *file) return single_open_size(file, show_stat, NULL, size); } -static const struct file_operations proc_stat_operations = { - .open = stat_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, +static const struct proc_ops stat_proc_ops = { + .proc_open = stat_open, + .proc_read = seq_read, + .proc_lseek = seq_lseek, + .proc_release = single_release, }; static int __init proc_stat_init(void) { - proc_create("stat", 0, NULL, &proc_stat_operations); + proc_create("stat", 0, NULL, &stat_proc_ops); return 0; } fs_initcall(proc_stat_init); diff --git a/fs/proc/vmcore.c b/fs/proc/vmcore.c index 7b13988796e1..7dc800cce354 100644 --- a/fs/proc/vmcore.c +++ b/fs/proc/vmcore.c @@ -667,10 +667,10 @@ static int mmap_vmcore(struct file *file, struct vm_area_struct *vma) } #endif -static const struct file_operations proc_vmcore_operations = { - .read = read_vmcore, - .llseek = default_llseek, - .mmap = mmap_vmcore, +static const struct proc_ops vmcore_proc_ops = { + .proc_read = read_vmcore, + .proc_lseek = default_llseek, + .proc_mmap = mmap_vmcore, }; static struct vmcore* __init get_new_element(void) @@ -1555,7 +1555,7 @@ static int __init vmcore_init(void) elfcorehdr_free(elfcorehdr_addr); elfcorehdr_addr = ELFCORE_ADDR_ERR; - proc_vmcore = proc_create("vmcore", S_IRUSR, NULL, &proc_vmcore_operations); + proc_vmcore = proc_create("vmcore", S_IRUSR, NULL, &vmcore_proc_ops); if (proc_vmcore) proc_vmcore->size = vmcore_size; return 0; diff --git a/include/linux/seq_file.h b/include/linux/seq_file.h index 5998e1f4ff06..770c2bf3aa43 100644 --- a/include/linux/seq_file.h +++ b/include/linux/seq_file.h @@ -160,6 +160,19 @@ static const struct file_operations __name ## _fops = { \ .release = single_release, \ } +#define DEFINE_PROC_SHOW_ATTRIBUTE(__name) \ +static int __name ## _open(struct inode *inode, struct file *file) \ +{ \ + return single_open(file, __name ## _show, inode->i_private); \ +} \ + \ +static const struct proc_ops __name ## _proc_ops = { \ + .proc_open = __name ## _open, \ + .proc_read = seq_read, \ + .proc_lseek = seq_lseek, \ + .proc_release = single_release, \ +} + static inline struct user_namespace *seq_user_ns(struct seq_file *seq) { #ifdef CONFIG_USER_NS diff --git a/include/linux/sunrpc/stats.h b/include/linux/sunrpc/stats.h index 84b92b4ad1c0..d94d4f410507 100644 --- a/include/linux/sunrpc/stats.h +++ b/include/linux/sunrpc/stats.h @@ -63,7 +63,7 @@ struct proc_dir_entry * rpc_proc_register(struct net *,struct rpc_stat *); void rpc_proc_unregister(struct net *,const char *); void rpc_proc_zero(const struct rpc_program *); struct proc_dir_entry * svc_proc_register(struct net *, struct svc_stat *, - const struct file_operations *); + const struct proc_ops *); void svc_proc_unregister(struct net *, const char *); void svc_seq_show(struct seq_file *, @@ -75,7 +75,7 @@ static inline void rpc_proc_unregister(struct net *net, const char *p) {} static inline void rpc_proc_zero(const struct rpc_program *p) {} static inline struct proc_dir_entry *svc_proc_register(struct net *net, struct svc_stat *s, - const struct file_operations *f) { return NULL; } + const struct proc_ops *proc_ops) { return NULL; } static inline void svc_proc_unregister(struct net *net, const char *p) {} static inline void svc_seq_show(struct seq_file *seq, diff --git a/ipc/util.c b/ipc/util.c index 915eacb9c059..fe61df53775a 100644 --- a/ipc/util.c +++ b/ipc/util.c @@ -126,7 +126,7 @@ void ipc_init_ids(struct ipc_ids *ids) } #ifdef CONFIG_PROC_FS -static const struct file_operations sysvipc_proc_fops; +static const struct proc_ops sysvipc_proc_ops; /** * ipc_init_proc_interface - create a proc interface for sysipc types using a seq_file interface. * @path: Path in procfs @@ -151,7 +151,7 @@ void __init ipc_init_proc_interface(const char *path, const char *header, pde = proc_create_data(path, S_IRUGO, /* world readable */ NULL, /* parent dir */ - &sysvipc_proc_fops, + &sysvipc_proc_ops, iface); if (!pde) kfree(iface); @@ -884,10 +884,10 @@ static int sysvipc_proc_release(struct inode *inode, struct file *file) return seq_release_private(inode, file); } -static const struct file_operations sysvipc_proc_fops = { - .open = sysvipc_proc_open, - .read = seq_read, - .llseek = seq_lseek, - .release = sysvipc_proc_release, +static const struct proc_ops sysvipc_proc_ops = { + .proc_open = sysvipc_proc_open, + .proc_read = seq_read, + .proc_lseek = seq_lseek, + .proc_release = sysvipc_proc_release, }; #endif /* CONFIG_PROC_FS */ diff --git a/kernel/configs.c b/kernel/configs.c index c09ea4c995e1..a28c79c5f713 100644 --- a/kernel/configs.c +++ b/kernel/configs.c @@ -47,10 +47,9 @@ ikconfig_read_current(struct file *file, char __user *buf, &kernel_config_data); } -static const struct file_operations ikconfig_file_ops = { - .owner = THIS_MODULE, - .read = ikconfig_read_current, - .llseek = default_llseek, +static const struct proc_ops config_gz_proc_ops = { + .proc_read = ikconfig_read_current, + .proc_lseek = default_llseek, }; static int __init ikconfig_init(void) @@ -59,7 +58,7 @@ static int __init ikconfig_init(void) /* create the current config file */ entry = proc_create("config.gz", S_IFREG | S_IRUGO, NULL, - &ikconfig_file_ops); + &config_gz_proc_ops); if (!entry) return -ENOMEM; diff --git a/kernel/irq/proc.c b/kernel/irq/proc.c index cfc4f088a0e7..9e5783d98033 100644 --- a/kernel/irq/proc.c +++ b/kernel/irq/proc.c @@ -176,20 +176,20 @@ static int irq_affinity_list_proc_open(struct inode *inode, struct file *file) return single_open(file, irq_affinity_list_proc_show, PDE_DATA(inode)); } -static const struct file_operations irq_affinity_proc_fops = { - .open = irq_affinity_proc_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, - .write = irq_affinity_proc_write, +static const struct proc_ops irq_affinity_proc_ops = { + .proc_open = irq_affinity_proc_open, + .proc_read = seq_read, + .proc_lseek = seq_lseek, + .proc_release = single_release, + .proc_write = irq_affinity_proc_write, }; -static const struct file_operations irq_affinity_list_proc_fops = { - .open = irq_affinity_list_proc_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, - .write = irq_affinity_list_proc_write, +static const struct proc_ops irq_affinity_list_proc_ops = { + .proc_open = irq_affinity_list_proc_open, + .proc_read = seq_read, + .proc_lseek = seq_lseek, + .proc_release = single_release, + .proc_write = irq_affinity_list_proc_write, }; #ifdef CONFIG_GENERIC_IRQ_EFFECTIVE_AFF_MASK @@ -246,12 +246,12 @@ static int default_affinity_open(struct inode *inode, struct file *file) return single_open(file, default_affinity_show, PDE_DATA(inode)); } -static const struct file_operations default_affinity_proc_fops = { - .open = default_affinity_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, - .write = default_affinity_write, +static const struct proc_ops default_affinity_proc_ops = { + .proc_open = default_affinity_open, + .proc_read = seq_read, + .proc_lseek = seq_lseek, + .proc_release = single_release, + .proc_write = default_affinity_write, }; static int irq_node_proc_show(struct seq_file *m, void *v) @@ -342,7 +342,7 @@ void register_irq_proc(unsigned int irq, struct irq_desc *desc) #ifdef CONFIG_SMP /* create /proc/irq//smp_affinity */ proc_create_data("smp_affinity", 0644, desc->dir, - &irq_affinity_proc_fops, irqp); + &irq_affinity_proc_ops, irqp); /* create /proc/irq//affinity_hint */ proc_create_single_data("affinity_hint", 0444, desc->dir, @@ -350,7 +350,7 @@ void register_irq_proc(unsigned int irq, struct irq_desc *desc) /* create /proc/irq//smp_affinity_list */ proc_create_data("smp_affinity_list", 0644, desc->dir, - &irq_affinity_list_proc_fops, irqp); + &irq_affinity_list_proc_ops, irqp); proc_create_single_data("node", 0444, desc->dir, irq_node_proc_show, irqp); @@ -401,7 +401,7 @@ static void register_default_affinity_proc(void) { #ifdef CONFIG_SMP proc_create("irq/default_smp_affinity", 0644, NULL, - &default_affinity_proc_fops); + &default_affinity_proc_ops); #endif } diff --git a/kernel/kallsyms.c b/kernel/kallsyms.c index 136ce049c4ad..d812b90f4c86 100644 --- a/kernel/kallsyms.c +++ b/kernel/kallsyms.c @@ -698,16 +698,16 @@ const char *kdb_walk_kallsyms(loff_t *pos) } #endif /* CONFIG_KGDB_KDB */ -static const struct file_operations kallsyms_operations = { - .open = kallsyms_open, - .read = seq_read, - .llseek = seq_lseek, - .release = seq_release_private, +static const struct proc_ops kallsyms_proc_ops = { + .proc_open = kallsyms_open, + .proc_read = seq_read, + .proc_lseek = seq_lseek, + .proc_release = seq_release_private, }; static int __init kallsyms_init(void) { - proc_create("kallsyms", 0444, NULL, &kallsyms_operations); + proc_create("kallsyms", 0444, NULL, &kallsyms_proc_ops); return 0; } device_initcall(kallsyms_init); diff --git a/kernel/latencytop.c b/kernel/latencytop.c index e3acead004e6..8d1c15832e55 100644 --- a/kernel/latencytop.c +++ b/kernel/latencytop.c @@ -255,17 +255,17 @@ static int lstats_open(struct inode *inode, struct file *filp) return single_open(filp, lstats_show, NULL); } -static const struct file_operations lstats_fops = { - .open = lstats_open, - .read = seq_read, - .write = lstats_write, - .llseek = seq_lseek, - .release = single_release, +static const struct proc_ops lstats_proc_ops = { + .proc_open = lstats_open, + .proc_read = seq_read, + .proc_write = lstats_write, + .proc_lseek = seq_lseek, + .proc_release = single_release, }; static int __init init_lstats_procfs(void) { - proc_create("latency_stats", 0644, NULL, &lstats_fops); + proc_create("latency_stats", 0644, NULL, &lstats_proc_ops); return 0; } diff --git a/kernel/locking/lockdep_proc.c b/kernel/locking/lockdep_proc.c index 9bb6d2497b04..231684cfc5ae 100644 --- a/kernel/locking/lockdep_proc.c +++ b/kernel/locking/lockdep_proc.c @@ -643,12 +643,12 @@ static int lock_stat_release(struct inode *inode, struct file *file) return seq_release(inode, file); } -static const struct file_operations proc_lock_stat_operations = { - .open = lock_stat_open, - .write = lock_stat_write, - .read = seq_read, - .llseek = seq_lseek, - .release = lock_stat_release, +static const struct proc_ops lock_stat_proc_ops = { + .proc_open = lock_stat_open, + .proc_write = lock_stat_write, + .proc_read = seq_read, + .proc_lseek = seq_lseek, + .proc_release = lock_stat_release, }; #endif /* CONFIG_LOCK_STAT */ @@ -660,8 +660,7 @@ static int __init lockdep_proc_init(void) #endif proc_create_single("lockdep_stats", S_IRUSR, NULL, lockdep_stats_show); #ifdef CONFIG_LOCK_STAT - proc_create("lock_stat", S_IRUSR | S_IWUSR, NULL, - &proc_lock_stat_operations); + proc_create("lock_stat", S_IRUSR | S_IWUSR, NULL, &lock_stat_proc_ops); #endif return 0; diff --git a/kernel/module.c b/kernel/module.c index 90ec5ab60255..33569a01d6e1 100644 --- a/kernel/module.c +++ b/kernel/module.c @@ -4354,16 +4354,16 @@ static int modules_open(struct inode *inode, struct file *file) return err; } -static const struct file_operations proc_modules_operations = { - .open = modules_open, - .read = seq_read, - .llseek = seq_lseek, - .release = seq_release, +static const struct proc_ops modules_proc_ops = { + .proc_open = modules_open, + .proc_read = seq_read, + .proc_lseek = seq_lseek, + .proc_release = seq_release, }; static int __init proc_modules_init(void) { - proc_create("modules", 0, NULL, &proc_modules_operations); + proc_create("modules", 0, NULL, &modules_proc_ops); return 0; } module_init(proc_modules_init); diff --git a/kernel/profile.c b/kernel/profile.c index 4b144b02ca5d..6f69a4195d56 100644 --- a/kernel/profile.c +++ b/kernel/profile.c @@ -442,18 +442,18 @@ static ssize_t prof_cpu_mask_proc_write(struct file *file, return err; } -static const struct file_operations prof_cpu_mask_proc_fops = { - .open = prof_cpu_mask_proc_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, - .write = prof_cpu_mask_proc_write, +static const struct proc_ops prof_cpu_mask_proc_ops = { + .proc_open = prof_cpu_mask_proc_open, + .proc_read = seq_read, + .proc_lseek = seq_lseek, + .proc_release = single_release, + .proc_write = prof_cpu_mask_proc_write, }; void create_prof_cpu_mask(void) { /* create /proc/irq/prof_cpu_mask */ - proc_create("irq/prof_cpu_mask", 0600, NULL, &prof_cpu_mask_proc_fops); + proc_create("irq/prof_cpu_mask", 0600, NULL, &prof_cpu_mask_proc_ops); } /* @@ -517,10 +517,10 @@ static ssize_t write_profile(struct file *file, const char __user *buf, return count; } -static const struct file_operations proc_profile_operations = { - .read = read_profile, - .write = write_profile, - .llseek = default_llseek, +static const struct proc_ops profile_proc_ops = { + .proc_read = read_profile, + .proc_write = write_profile, + .proc_lseek = default_llseek, }; int __ref create_proc_profile(void) @@ -548,7 +548,7 @@ int __ref create_proc_profile(void) err = 0; #endif entry = proc_create("profile", S_IWUSR | S_IRUGO, - NULL, &proc_profile_operations); + NULL, &profile_proc_ops); if (!entry) goto err_state_onl; proc_set_size(entry, (1 + prof_len) * sizeof(atomic_t)); diff --git a/kernel/sched/psi.c b/kernel/sched/psi.c index db7b50bba3f1..ac4bd0ca11cc 100644 --- a/kernel/sched/psi.c +++ b/kernel/sched/psi.c @@ -1251,40 +1251,40 @@ static int psi_fop_release(struct inode *inode, struct file *file) return single_release(inode, file); } -static const struct file_operations psi_io_fops = { - .open = psi_io_open, - .read = seq_read, - .llseek = seq_lseek, - .write = psi_io_write, - .poll = psi_fop_poll, - .release = psi_fop_release, +static const struct proc_ops psi_io_proc_ops = { + .proc_open = psi_io_open, + .proc_read = seq_read, + .proc_lseek = seq_lseek, + .proc_write = psi_io_write, + .proc_poll = psi_fop_poll, + .proc_release = psi_fop_release, }; -static const struct file_operations psi_memory_fops = { - .open = psi_memory_open, - .read = seq_read, - .llseek = seq_lseek, - .write = psi_memory_write, - .poll = psi_fop_poll, - .release = psi_fop_release, +static const struct proc_ops psi_memory_proc_ops = { + .proc_open = psi_memory_open, + .proc_read = seq_read, + .proc_lseek = seq_lseek, + .proc_write = psi_memory_write, + .proc_poll = psi_fop_poll, + .proc_release = psi_fop_release, }; -static const struct file_operations psi_cpu_fops = { - .open = psi_cpu_open, - .read = seq_read, - .llseek = seq_lseek, - .write = psi_cpu_write, - .poll = psi_fop_poll, - .release = psi_fop_release, +static const struct proc_ops psi_cpu_proc_ops = { + .proc_open = psi_cpu_open, + .proc_read = seq_read, + .proc_lseek = seq_lseek, + .proc_write = psi_cpu_write, + .proc_poll = psi_fop_poll, + .proc_release = psi_fop_release, }; static int __init psi_proc_init(void) { if (psi_enable) { proc_mkdir("pressure", NULL); - proc_create("pressure/io", 0, NULL, &psi_io_fops); - proc_create("pressure/memory", 0, NULL, &psi_memory_fops); - proc_create("pressure/cpu", 0, NULL, &psi_cpu_fops); + proc_create("pressure/io", 0, NULL, &psi_io_proc_ops); + proc_create("pressure/memory", 0, NULL, &psi_memory_proc_ops); + proc_create("pressure/cpu", 0, NULL, &psi_cpu_proc_ops); } return 0; } diff --git a/mm/slab_common.c b/mm/slab_common.c index 0c63c0d3dd38..1907cb2903c7 100644 --- a/mm/slab_common.c +++ b/mm/slab_common.c @@ -1580,18 +1580,17 @@ static int slabinfo_open(struct inode *inode, struct file *file) return seq_open(file, &slabinfo_op); } -static const struct file_operations proc_slabinfo_operations = { - .open = slabinfo_open, - .read = seq_read, - .write = slabinfo_write, - .llseek = seq_lseek, - .release = seq_release, +static const struct proc_ops slabinfo_proc_ops = { + .proc_open = slabinfo_open, + .proc_read = seq_read, + .proc_write = slabinfo_write, + .proc_lseek = seq_lseek, + .proc_release = seq_release, }; static int __init slab_proc_init(void) { - proc_create("slabinfo", SLABINFO_RIGHTS, NULL, - &proc_slabinfo_operations); + proc_create("slabinfo", SLABINFO_RIGHTS, NULL, &slabinfo_proc_ops); return 0; } module_init(slab_proc_init); diff --git a/mm/swapfile.c b/mm/swapfile.c index 6febae9ad3cd..2c33ff456ed5 100644 --- a/mm/swapfile.c +++ b/mm/swapfile.c @@ -2796,17 +2796,17 @@ static int swaps_open(struct inode *inode, struct file *file) return 0; } -static const struct file_operations proc_swaps_operations = { - .open = swaps_open, - .read = seq_read, - .llseek = seq_lseek, - .release = seq_release, - .poll = swaps_poll, +static const struct proc_ops swaps_proc_ops = { + .proc_open = swaps_open, + .proc_read = seq_read, + .proc_lseek = seq_lseek, + .proc_release = seq_release, + .proc_poll = swaps_poll, }; static int __init procswaps_init(void) { - proc_create("swaps", 0, NULL, &proc_swaps_operations); + proc_create("swaps", 0, NULL, &swaps_proc_ops); return 0; } __initcall(procswaps_init); diff --git a/net/atm/mpoa_proc.c b/net/atm/mpoa_proc.c index 46d6cd9a36ae..829db9eba0cb 100644 --- a/net/atm/mpoa_proc.c +++ b/net/atm/mpoa_proc.c @@ -53,15 +53,12 @@ static ssize_t proc_mpc_write(struct file *file, const char __user *buff, static int parse_qos(const char *buff); -/* - * Define allowed FILE OPERATIONS - */ -static const struct file_operations mpc_file_operations = { - .open = proc_mpc_open, - .read = seq_read, - .llseek = seq_lseek, - .write = proc_mpc_write, - .release = seq_release, +static const struct proc_ops mpc_proc_ops = { + .proc_open = proc_mpc_open, + .proc_read = seq_read, + .proc_lseek = seq_lseek, + .proc_write = proc_mpc_write, + .proc_release = seq_release, }; /* @@ -290,7 +287,7 @@ int mpc_proc_init(void) { struct proc_dir_entry *p; - p = proc_create(STAT_FILE_NAME, 0, atm_proc_root, &mpc_file_operations); + p = proc_create(STAT_FILE_NAME, 0, atm_proc_root, &mpc_proc_ops); if (!p) { pr_err("Unable to initialize /proc/atm/%s\n", STAT_FILE_NAME); return -ENOMEM; diff --git a/net/atm/proc.c b/net/atm/proc.c index c31896707313..4369ffa3302a 100644 --- a/net/atm/proc.c +++ b/net/atm/proc.c @@ -36,9 +36,9 @@ static ssize_t proc_dev_atm_read(struct file *file, char __user *buf, size_t count, loff_t *pos); -static const struct file_operations proc_atm_dev_ops = { - .read = proc_dev_atm_read, - .llseek = noop_llseek, +static const struct proc_ops atm_dev_proc_ops = { + .proc_read = proc_dev_atm_read, + .proc_lseek = noop_llseek, }; static void add_stats(struct seq_file *seq, const char *aal, @@ -359,7 +359,7 @@ int atm_proc_dev_register(struct atm_dev *dev) goto err_out; dev->proc_entry = proc_create_data(dev->proc_name, 0, atm_proc_root, - &proc_atm_dev_ops, dev); + &atm_dev_proc_ops, dev); if (!dev->proc_entry) goto err_free_name; return 0; diff --git a/net/core/pktgen.c b/net/core/pktgen.c index 294bfcf0ce0e..acc849df60b5 100644 --- a/net/core/pktgen.c +++ b/net/core/pktgen.c @@ -535,12 +535,12 @@ static int pgctrl_open(struct inode *inode, struct file *file) return single_open(file, pgctrl_show, PDE_DATA(inode)); } -static const struct file_operations pktgen_fops = { - .open = pgctrl_open, - .read = seq_read, - .llseek = seq_lseek, - .write = pgctrl_write, - .release = single_release, +static const struct proc_ops pktgen_proc_ops = { + .proc_open = pgctrl_open, + .proc_read = seq_read, + .proc_lseek = seq_lseek, + .proc_write = pgctrl_write, + .proc_release = single_release, }; static int pktgen_if_show(struct seq_file *seq, void *v) @@ -1707,12 +1707,12 @@ static int pktgen_if_open(struct inode *inode, struct file *file) return single_open(file, pktgen_if_show, PDE_DATA(inode)); } -static const struct file_operations pktgen_if_fops = { - .open = pktgen_if_open, - .read = seq_read, - .llseek = seq_lseek, - .write = pktgen_if_write, - .release = single_release, +static const struct proc_ops pktgen_if_proc_ops = { + .proc_open = pktgen_if_open, + .proc_read = seq_read, + .proc_lseek = seq_lseek, + .proc_write = pktgen_if_write, + .proc_release = single_release, }; static int pktgen_thread_show(struct seq_file *seq, void *v) @@ -1844,12 +1844,12 @@ static int pktgen_thread_open(struct inode *inode, struct file *file) return single_open(file, pktgen_thread_show, PDE_DATA(inode)); } -static const struct file_operations pktgen_thread_fops = { - .open = pktgen_thread_open, - .read = seq_read, - .llseek = seq_lseek, - .write = pktgen_thread_write, - .release = single_release, +static const struct proc_ops pktgen_thread_proc_ops = { + .proc_open = pktgen_thread_open, + .proc_read = seq_read, + .proc_lseek = seq_lseek, + .proc_write = pktgen_thread_write, + .proc_release = single_release, }; /* Think find or remove for NN */ @@ -1926,7 +1926,7 @@ static void pktgen_change_name(const struct pktgen_net *pn, struct net_device *d pkt_dev->entry = proc_create_data(dev->name, 0600, pn->proc_dir, - &pktgen_if_fops, + &pktgen_if_proc_ops, pkt_dev); if (!pkt_dev->entry) pr_err("can't move proc entry for '%s'\n", @@ -3638,7 +3638,7 @@ static int pktgen_add_device(struct pktgen_thread *t, const char *ifname) pkt_dev->clone_skb = pg_clone_skb_d; pkt_dev->entry = proc_create_data(ifname, 0600, t->net->proc_dir, - &pktgen_if_fops, pkt_dev); + &pktgen_if_proc_ops, pkt_dev); if (!pkt_dev->entry) { pr_err("cannot create %s/%s procfs entry\n", PG_PROC_DIR, ifname); @@ -3708,7 +3708,7 @@ static int __net_init pktgen_create_thread(int cpu, struct pktgen_net *pn) t->tsk = p; pe = proc_create_data(t->tsk->comm, 0600, pn->proc_dir, - &pktgen_thread_fops, t); + &pktgen_thread_proc_ops, t); if (!pe) { pr_err("cannot create %s/%s procfs entry\n", PG_PROC_DIR, t->tsk->comm); @@ -3793,7 +3793,7 @@ static int __net_init pg_net_init(struct net *net) pr_warn("cannot create /proc/net/%s\n", PG_PROC_DIR); return -ENODEV; } - pe = proc_create(PGCTRL, 0600, pn->proc_dir, &pktgen_fops); + pe = proc_create(PGCTRL, 0600, pn->proc_dir, &pktgen_proc_ops); if (pe == NULL) { pr_err("cannot create %s procfs entry\n", PGCTRL); ret = -EINVAL; diff --git a/net/ipv4/ipconfig.c b/net/ipv4/ipconfig.c index f35308ff84c3..4438f6b12335 100644 --- a/net/ipv4/ipconfig.c +++ b/net/ipv4/ipconfig.c @@ -1334,7 +1334,7 @@ static int __init ipconfig_proc_net_init(void) /* Create a new file under /proc/net/ipconfig */ static int ipconfig_proc_net_create(const char *name, - const struct file_operations *fops) + const struct proc_ops *proc_ops) { char *pname; struct proc_dir_entry *p; @@ -1346,7 +1346,7 @@ static int ipconfig_proc_net_create(const char *name, if (!pname) return -ENOMEM; - p = proc_create(pname, 0444, init_net.proc_net, fops); + p = proc_create(pname, 0444, init_net.proc_net, proc_ops); kfree(pname); if (!p) return -ENOMEM; @@ -1355,7 +1355,7 @@ static int ipconfig_proc_net_create(const char *name, } /* Write NTP server IP addresses to /proc/net/ipconfig/ntp_servers */ -static int ntp_servers_seq_show(struct seq_file *seq, void *v) +static int ntp_servers_show(struct seq_file *seq, void *v) { int i; @@ -1365,7 +1365,7 @@ static int ntp_servers_seq_show(struct seq_file *seq, void *v) } return 0; } -DEFINE_SHOW_ATTRIBUTE(ntp_servers_seq); +DEFINE_PROC_SHOW_ATTRIBUTE(ntp_servers); #endif /* CONFIG_PROC_FS */ /* @@ -1456,7 +1456,7 @@ static int __init ip_auto_config(void) proc_create_single("pnp", 0444, init_net.proc_net, pnp_seq_show); if (ipconfig_proc_net_init() == 0) - ipconfig_proc_net_create("ntp_servers", &ntp_servers_seq_fops); + ipconfig_proc_net_create("ntp_servers", &ntp_servers_proc_ops); #endif /* CONFIG_PROC_FS */ if (!ic_enable) diff --git a/net/ipv4/netfilter/ipt_CLUSTERIP.c b/net/ipv4/netfilter/ipt_CLUSTERIP.c index 6bdb1ab8af61..f8755a4ae9d4 100644 --- a/net/ipv4/netfilter/ipt_CLUSTERIP.c +++ b/net/ipv4/netfilter/ipt_CLUSTERIP.c @@ -58,7 +58,7 @@ struct clusterip_config { }; #ifdef CONFIG_PROC_FS -static const struct file_operations clusterip_proc_fops; +static const struct proc_ops clusterip_proc_ops; #endif struct clusterip_net { @@ -280,7 +280,7 @@ clusterip_config_init(struct net *net, const struct ipt_clusterip_tgt_info *i, mutex_lock(&cn->mutex); c->pde = proc_create_data(buffer, 0600, cn->procdir, - &clusterip_proc_fops, c); + &clusterip_proc_ops, c); mutex_unlock(&cn->mutex); if (!c->pde) { err = -ENOMEM; @@ -804,12 +804,12 @@ static ssize_t clusterip_proc_write(struct file *file, const char __user *input, return size; } -static const struct file_operations clusterip_proc_fops = { - .open = clusterip_proc_open, - .read = seq_read, - .write = clusterip_proc_write, - .llseek = seq_lseek, - .release = clusterip_proc_release, +static const struct proc_ops clusterip_proc_ops = { + .proc_open = clusterip_proc_open, + .proc_read = seq_read, + .proc_write = clusterip_proc_write, + .proc_lseek = seq_lseek, + .proc_release = clusterip_proc_release, }; #endif /* CONFIG_PROC_FS */ diff --git a/net/ipv4/route.c b/net/ipv4/route.c index d5c57b3f77d5..ebe7060d0fc9 100644 --- a/net/ipv4/route.c +++ b/net/ipv4/route.c @@ -237,11 +237,11 @@ static int rt_cache_seq_open(struct inode *inode, struct file *file) return seq_open(file, &rt_cache_seq_ops); } -static const struct file_operations rt_cache_seq_fops = { - .open = rt_cache_seq_open, - .read = seq_read, - .llseek = seq_lseek, - .release = seq_release, +static const struct proc_ops rt_cache_proc_ops = { + .proc_open = rt_cache_seq_open, + .proc_read = seq_read, + .proc_lseek = seq_lseek, + .proc_release = seq_release, }; @@ -328,11 +328,11 @@ static int rt_cpu_seq_open(struct inode *inode, struct file *file) return seq_open(file, &rt_cpu_seq_ops); } -static const struct file_operations rt_cpu_seq_fops = { - .open = rt_cpu_seq_open, - .read = seq_read, - .llseek = seq_lseek, - .release = seq_release, +static const struct proc_ops rt_cpu_proc_ops = { + .proc_open = rt_cpu_seq_open, + .proc_read = seq_read, + .proc_lseek = seq_lseek, + .proc_release = seq_release, }; #ifdef CONFIG_IP_ROUTE_CLASSID @@ -366,12 +366,12 @@ static int __net_init ip_rt_do_proc_init(struct net *net) struct proc_dir_entry *pde; pde = proc_create("rt_cache", 0444, net->proc_net, - &rt_cache_seq_fops); + &rt_cache_proc_ops); if (!pde) goto err1; pde = proc_create("rt_cache", 0444, - net->proc_net_stat, &rt_cpu_seq_fops); + net->proc_net_stat, &rt_cpu_proc_ops); if (!pde) goto err2; diff --git a/net/netfilter/xt_recent.c b/net/netfilter/xt_recent.c index 781e0b482189..0a9708004e20 100644 --- a/net/netfilter/xt_recent.c +++ b/net/netfilter/xt_recent.c @@ -103,7 +103,7 @@ static DEFINE_SPINLOCK(recent_lock); static DEFINE_MUTEX(recent_mutex); #ifdef CONFIG_PROC_FS -static const struct file_operations recent_mt_fops; +static const struct proc_ops recent_mt_proc_ops; #endif static u_int32_t hash_rnd __read_mostly; @@ -405,7 +405,7 @@ static int recent_mt_check(const struct xt_mtchk_param *par, goto out; } pde = proc_create_data(t->name, ip_list_perms, recent_net->xt_recent, - &recent_mt_fops, t); + &recent_mt_proc_ops, t); if (pde == NULL) { recent_table_free(t); ret = -ENOMEM; @@ -616,13 +616,12 @@ recent_mt_proc_write(struct file *file, const char __user *input, return size + 1; } -static const struct file_operations recent_mt_fops = { - .open = recent_seq_open, - .read = seq_read, - .write = recent_mt_proc_write, - .release = seq_release_private, - .owner = THIS_MODULE, - .llseek = seq_lseek, +static const struct proc_ops recent_mt_proc_ops = { + .proc_open = recent_seq_open, + .proc_read = seq_read, + .proc_write = recent_mt_proc_write, + .proc_release = seq_release_private, + .proc_lseek = seq_lseek, }; static int __net_init recent_proc_net_init(struct net *net) diff --git a/net/sunrpc/auth_gss/svcauth_gss.c b/net/sunrpc/auth_gss/svcauth_gss.c index 311181720d79..7511a68aadf0 100644 --- a/net/sunrpc/auth_gss/svcauth_gss.c +++ b/net/sunrpc/auth_gss/svcauth_gss.c @@ -1428,10 +1428,10 @@ static ssize_t read_gssp(struct file *file, char __user *buf, return len; } -static const struct file_operations use_gss_proxy_ops = { - .open = nonseekable_open, - .write = write_gssp, - .read = read_gssp, +static const struct proc_ops use_gss_proxy_proc_ops = { + .proc_open = nonseekable_open, + .proc_write = write_gssp, + .proc_read = read_gssp, }; static int create_use_gss_proxy_proc_entry(struct net *net) @@ -1442,7 +1442,7 @@ static int create_use_gss_proxy_proc_entry(struct net *net) sn->use_gss_proxy = -1; *p = proc_create_data("use-gss-proxy", S_IFREG | 0600, sn->proc_net_rpc, - &use_gss_proxy_ops, net); + &use_gss_proxy_proc_ops, net); if (!*p) return -ENOMEM; init_gssp_clnt(sn); diff --git a/net/sunrpc/cache.c b/net/sunrpc/cache.c index d996bf872a7c..375914c7a7b1 100644 --- a/net/sunrpc/cache.c +++ b/net/sunrpc/cache.c @@ -1571,15 +1571,14 @@ static int cache_release_procfs(struct inode *inode, struct file *filp) return cache_release(inode, filp, cd); } -static const struct file_operations cache_file_operations_procfs = { - .owner = THIS_MODULE, - .llseek = no_llseek, - .read = cache_read_procfs, - .write = cache_write_procfs, - .poll = cache_poll_procfs, - .unlocked_ioctl = cache_ioctl_procfs, /* for FIONREAD */ - .open = cache_open_procfs, - .release = cache_release_procfs, +static const struct proc_ops cache_channel_proc_ops = { + .proc_lseek = no_llseek, + .proc_read = cache_read_procfs, + .proc_write = cache_write_procfs, + .proc_poll = cache_poll_procfs, + .proc_ioctl = cache_ioctl_procfs, /* for FIONREAD */ + .proc_open = cache_open_procfs, + .proc_release = cache_release_procfs, }; static int content_open_procfs(struct inode *inode, struct file *filp) @@ -1596,11 +1595,11 @@ static int content_release_procfs(struct inode *inode, struct file *filp) return content_release(inode, filp, cd); } -static const struct file_operations content_file_operations_procfs = { - .open = content_open_procfs, - .read = seq_read, - .llseek = seq_lseek, - .release = content_release_procfs, +static const struct proc_ops content_proc_ops = { + .proc_open = content_open_procfs, + .proc_read = seq_read, + .proc_lseek = seq_lseek, + .proc_release = content_release_procfs, }; static int open_flush_procfs(struct inode *inode, struct file *filp) @@ -1634,12 +1633,12 @@ static ssize_t write_flush_procfs(struct file *filp, return write_flush(filp, buf, count, ppos, cd); } -static const struct file_operations cache_flush_operations_procfs = { - .open = open_flush_procfs, - .read = read_flush_procfs, - .write = write_flush_procfs, - .release = release_flush_procfs, - .llseek = no_llseek, +static const struct proc_ops cache_flush_proc_ops = { + .proc_open = open_flush_procfs, + .proc_read = read_flush_procfs, + .proc_write = write_flush_procfs, + .proc_release = release_flush_procfs, + .proc_lseek = no_llseek, }; static void remove_cache_proc_entries(struct cache_detail *cd) @@ -1662,19 +1661,19 @@ static int create_cache_proc_entries(struct cache_detail *cd, struct net *net) goto out_nomem; p = proc_create_data("flush", S_IFREG | 0600, - cd->procfs, &cache_flush_operations_procfs, cd); + cd->procfs, &cache_flush_proc_ops, cd); if (p == NULL) goto out_nomem; if (cd->cache_request || cd->cache_parse) { p = proc_create_data("channel", S_IFREG | 0600, cd->procfs, - &cache_file_operations_procfs, cd); + &cache_channel_proc_ops, cd); if (p == NULL) goto out_nomem; } if (cd->cache_show) { p = proc_create_data("content", S_IFREG | 0400, cd->procfs, - &content_file_operations_procfs, cd); + &content_proc_ops, cd); if (p == NULL) goto out_nomem; } diff --git a/net/sunrpc/stats.c b/net/sunrpc/stats.c index 7c74197c2ecf..c964b48eaaba 100644 --- a/net/sunrpc/stats.c +++ b/net/sunrpc/stats.c @@ -69,12 +69,11 @@ static int rpc_proc_open(struct inode *inode, struct file *file) return single_open(file, rpc_proc_show, PDE_DATA(inode)); } -static const struct file_operations rpc_proc_fops = { - .owner = THIS_MODULE, - .open = rpc_proc_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, +static const struct proc_ops rpc_proc_ops = { + .proc_open = rpc_proc_open, + .proc_read = seq_read, + .proc_lseek = seq_lseek, + .proc_release = single_release, }; /* @@ -281,19 +280,19 @@ EXPORT_SYMBOL_GPL(rpc_clnt_show_stats); */ static inline struct proc_dir_entry * do_register(struct net *net, const char *name, void *data, - const struct file_operations *fops) + const struct proc_ops *proc_ops) { struct sunrpc_net *sn; dprintk("RPC: registering /proc/net/rpc/%s\n", name); sn = net_generic(net, sunrpc_net_id); - return proc_create_data(name, 0, sn->proc_net_rpc, fops, data); + return proc_create_data(name, 0, sn->proc_net_rpc, proc_ops, data); } struct proc_dir_entry * rpc_proc_register(struct net *net, struct rpc_stat *statp) { - return do_register(net, statp->program->name, statp, &rpc_proc_fops); + return do_register(net, statp->program->name, statp, &rpc_proc_ops); } EXPORT_SYMBOL_GPL(rpc_proc_register); @@ -308,9 +307,9 @@ rpc_proc_unregister(struct net *net, const char *name) EXPORT_SYMBOL_GPL(rpc_proc_unregister); struct proc_dir_entry * -svc_proc_register(struct net *net, struct svc_stat *statp, const struct file_operations *fops) +svc_proc_register(struct net *net, struct svc_stat *statp, const struct proc_ops *proc_ops) { - return do_register(net, statp->program->pg_name, statp, fops); + return do_register(net, statp->program->pg_name, statp, proc_ops); } EXPORT_SYMBOL_GPL(svc_proc_register); diff --git a/samples/kfifo/bytestream-example.c b/samples/kfifo/bytestream-example.c index 9ca3e4400c98..c406f03ee551 100644 --- a/samples/kfifo/bytestream-example.c +++ b/samples/kfifo/bytestream-example.c @@ -142,11 +142,10 @@ static ssize_t fifo_read(struct file *file, char __user *buf, return ret ? ret : copied; } -static const struct file_operations fifo_fops = { - .owner = THIS_MODULE, - .read = fifo_read, - .write = fifo_write, - .llseek = noop_llseek, +static const struct proc_ops fifo_proc_ops = { + .proc_read = fifo_read, + .proc_write = fifo_write, + .proc_lseek = noop_llseek, }; static int __init example_init(void) @@ -169,7 +168,7 @@ static int __init example_init(void) return -EIO; } - if (proc_create(PROC_FIFO, 0, NULL, &fifo_fops) == NULL) { + if (proc_create(PROC_FIFO, 0, NULL, &fifo_proc_ops) == NULL) { #ifdef DYNAMIC kfifo_free(&test); #endif diff --git a/samples/kfifo/inttype-example.c b/samples/kfifo/inttype-example.c index 6cdeb72f83f1..78977fc4a23f 100644 --- a/samples/kfifo/inttype-example.c +++ b/samples/kfifo/inttype-example.c @@ -135,11 +135,10 @@ static ssize_t fifo_read(struct file *file, char __user *buf, return ret ? ret : copied; } -static const struct file_operations fifo_fops = { - .owner = THIS_MODULE, - .read = fifo_read, - .write = fifo_write, - .llseek = noop_llseek, +static const struct proc_ops fifo_proc_ops = { + .proc_read = fifo_read, + .proc_write = fifo_write, + .proc_lseek = noop_llseek, }; static int __init example_init(void) @@ -160,7 +159,7 @@ static int __init example_init(void) return -EIO; } - if (proc_create(PROC_FIFO, 0, NULL, &fifo_fops) == NULL) { + if (proc_create(PROC_FIFO, 0, NULL, &fifo_proc_ops) == NULL) { #ifdef DYNAMIC kfifo_free(&test); #endif diff --git a/samples/kfifo/record-example.c b/samples/kfifo/record-example.c index 79ae8bb04120..c507998a2617 100644 --- a/samples/kfifo/record-example.c +++ b/samples/kfifo/record-example.c @@ -149,11 +149,10 @@ static ssize_t fifo_read(struct file *file, char __user *buf, return ret ? ret : copied; } -static const struct file_operations fifo_fops = { - .owner = THIS_MODULE, - .read = fifo_read, - .write = fifo_write, - .llseek = noop_llseek, +static const struct proc_ops fifo_proc_ops = { + .proc_read = fifo_read, + .proc_write = fifo_write, + .proc_lseek = noop_llseek, }; static int __init example_init(void) @@ -176,7 +175,7 @@ static int __init example_init(void) return -EIO; } - if (proc_create(PROC_FIFO, 0, NULL, &fifo_fops) == NULL) { + if (proc_create(PROC_FIFO, 0, NULL, &fifo_proc_ops) == NULL) { #ifdef DYNAMIC kfifo_free(&test); #endif diff --git a/sound/core/info.c b/sound/core/info.c index 6801d8160866..ca87ae4c30ba 100644 --- a/sound/core/info.c +++ b/sound/core/info.c @@ -282,17 +282,16 @@ static int snd_info_entry_release(struct inode *inode, struct file *file) return 0; } -static const struct file_operations snd_info_entry_operations = -{ - .owner = THIS_MODULE, - .llseek = snd_info_entry_llseek, - .read = snd_info_entry_read, - .write = snd_info_entry_write, - .poll = snd_info_entry_poll, - .unlocked_ioctl = snd_info_entry_ioctl, - .mmap = snd_info_entry_mmap, - .open = snd_info_entry_open, - .release = snd_info_entry_release, +static const struct proc_ops snd_info_entry_operations = +{ + .proc_lseek = snd_info_entry_llseek, + .proc_read = snd_info_entry_read, + .proc_write = snd_info_entry_write, + .proc_poll = snd_info_entry_poll, + .proc_ioctl = snd_info_entry_ioctl, + .proc_mmap = snd_info_entry_mmap, + .proc_open = snd_info_entry_open, + .proc_release = snd_info_entry_release, }; /* @@ -421,14 +420,13 @@ static int snd_info_text_entry_release(struct inode *inode, struct file *file) return 0; } -static const struct file_operations snd_info_text_entry_ops = +static const struct proc_ops snd_info_text_entry_ops = { - .owner = THIS_MODULE, - .open = snd_info_text_entry_open, - .release = snd_info_text_entry_release, - .write = snd_info_text_entry_write, - .llseek = seq_lseek, - .read = seq_read, + .proc_open = snd_info_text_entry_open, + .proc_release = snd_info_text_entry_release, + .proc_write = snd_info_text_entry_write, + .proc_lseek = seq_lseek, + .proc_read = seq_read, }; static struct snd_info_entry *create_subdir(struct module *mod, @@ -810,7 +808,7 @@ static int __snd_info_register(struct snd_info_entry *entry) return -ENOMEM; } } else { - const struct file_operations *ops; + const struct proc_ops *ops; if (entry->content == SNDRV_INFO_CONTENT_DATA) ops = &snd_info_entry_operations; else -- cgit v1.2.3 From c154703bc8dd2231ae81aafef5589b795b2b7e09 Mon Sep 17 00:00:00 2001 From: Christophe JAILLET Date: Sat, 18 Apr 2020 21:18:07 -0700 Subject: Input: tca6416-keypad - fix a typo in MODULE_DESCRIPTION This should be 'tca6416', not 'tca6146' Signed-off-by: Christophe JAILLET Link: https://lore.kernel.org/r/20200413152329.4435-1-christophe.jaillet@wanadoo.fr Signed-off-by: Dmitry Torokhov --- drivers/input/keyboard/tca6416-keypad.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/input') diff --git a/drivers/input/keyboard/tca6416-keypad.c b/drivers/input/keyboard/tca6416-keypad.c index 2a14769de637..d2fe258774c6 100644 --- a/drivers/input/keyboard/tca6416-keypad.c +++ b/drivers/input/keyboard/tca6416-keypad.c @@ -374,5 +374,5 @@ static void __exit tca6416_keypad_exit(void) module_exit(tca6416_keypad_exit); MODULE_AUTHOR("Sriramakrishnan "); -MODULE_DESCRIPTION("Keypad driver over tca6146 IO expander"); +MODULE_DESCRIPTION("Keypad driver over tca6416 IO expander"); MODULE_LICENSE("GPL"); -- cgit v1.2.3 From ec4ba6c35b1bd748de50044e36040136f378b9b6 Mon Sep 17 00:00:00 2001 From: Christophe JAILLET Date: Sat, 18 Apr 2020 21:27:25 -0700 Subject: Input: spear-keyboard - fix a typo in a module name in Kconfig A 'y' is missing in spear-keyboard. Signed-off-by: Christophe JAILLET Link: https://lore.kernel.org/r/20200412095711.9107-1-christophe.jaillet@wanadoo.fr Signed-off-by: Dmitry Torokhov --- drivers/input/keyboard/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/input') diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig index 4706ff09f0e8..f6c356e579c5 100644 --- a/drivers/input/keyboard/Kconfig +++ b/drivers/input/keyboard/Kconfig @@ -691,7 +691,7 @@ config KEYBOARD_SPEAR Say Y here if you want to use the SPEAR keyboard. To compile this driver as a module, choose M here: the - module will be called spear-keboard. + module will be called spear-keyboard. config KEYBOARD_TC3589X tristate "TC3589X Keypad support" -- cgit v1.2.3 From 81b4d1d22ca0d0162360d3536b0eb3f6d5bfcf88 Mon Sep 17 00:00:00 2001 From: Kenny Levinsen Date: Sat, 18 Apr 2020 21:26:50 -0700 Subject: Input: evdev - use keyed wakeups Some processes, such as systemd, are only polling for EPOLLERR|EPOLLHUP. As evdev uses unkeyed wakeups, such a poll receives many spurious wakeups from uninteresting events. Use keyed wakeups to allow the wakeup target to more efficiently discard these uninteresting events. Signed-off-by: Kenny Levinsen Link: https://lore.kernel.org/r/20200410233557.3892-1-kl@kl.wtf Signed-off-by: Dmitry Torokhov --- drivers/input/evdev.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'drivers/input') diff --git a/drivers/input/evdev.c b/drivers/input/evdev.c index d7dd6fcf2db0..f54d3d31f61d 100644 --- a/drivers/input/evdev.c +++ b/drivers/input/evdev.c @@ -282,7 +282,8 @@ static void evdev_pass_values(struct evdev_client *client, spin_unlock(&client->buffer_lock); if (wakeup) - wake_up_interruptible(&evdev->wait); + wake_up_interruptible_poll(&evdev->wait, + EPOLLIN | EPOLLOUT | EPOLLRDNORM | EPOLLWRNORM); } /* @@ -443,7 +444,7 @@ static void evdev_hangup(struct evdev *evdev) kill_fasync(&client->fasync, SIGIO, POLL_HUP); spin_unlock(&evdev->client_lock); - wake_up_interruptible(&evdev->wait); + wake_up_interruptible_poll(&evdev->wait, EPOLLHUP | EPOLLERR); } static int evdev_release(struct inode *inode, struct file *file) @@ -958,7 +959,7 @@ static int evdev_revoke(struct evdev *evdev, struct evdev_client *client, client->revoked = true; evdev_ungrab(evdev, client); input_flush_device(&evdev->handle, file); - wake_up_interruptible(&evdev->wait); + wake_up_interruptible_poll(&evdev->wait, EPOLLHUP | EPOLLERR); return 0; } -- cgit v1.2.3 From 4ea8391e3556ad08ff0ea8fb282f9a550b8a3333 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Sat, 18 Apr 2020 13:40:09 -0700 Subject: Input: delete unused GP2AP002A00F driver There is now an IIO driver for GP2AP002A00F and GP2AP002S00F in drivers/iio/light/gp2ap002.c. Delete this driver, it is unused in the kernel tree and new users can make use of the IIO driver. Signed-off-by: Linus Walleij Link: https://lore.kernel.org/r/20200417203059.8151-1-linus.walleij@linaro.org Signed-off-by: Dmitry Torokhov --- drivers/input/misc/Kconfig | 11 -- drivers/input/misc/Makefile | 1 - drivers/input/misc/gp2ap002a00f.c | 281 ------------------------------------- include/linux/input/gp2ap002a00f.h | 23 --- 4 files changed, 316 deletions(-) delete mode 100644 drivers/input/misc/gp2ap002a00f.c delete mode 100644 include/linux/input/gp2ap002a00f.h (limited to 'drivers/input') diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig index 7e2e658d551c..293e55fb7a4e 100644 --- a/drivers/input/misc/Kconfig +++ b/drivers/input/misc/Kconfig @@ -265,17 +265,6 @@ config INPUT_APANEL To compile this driver as a module, choose M here: the module will be called apanel. -config INPUT_GP2A - tristate "Sharp GP2AP002A00F I2C Proximity/Opto sensor driver" - depends on I2C - depends on GPIOLIB || COMPILE_TEST - help - Say Y here if you have a Sharp GP2AP002A00F proximity/als combo-chip - hooked to an I2C bus. - - To compile this driver as a module, choose M here: the - module will be called gp2ap002a00f. - config INPUT_GPIO_BEEPER tristate "Generic GPIO Beeper support" depends on GPIOLIB || COMPILE_TEST diff --git a/drivers/input/misc/Makefile b/drivers/input/misc/Makefile index 8fd187f314bd..1db1815ce803 100644 --- a/drivers/input/misc/Makefile +++ b/drivers/input/misc/Makefile @@ -33,7 +33,6 @@ obj-$(CONFIG_INPUT_E3X0_BUTTON) += e3x0-button.o obj-$(CONFIG_INPUT_DRV260X_HAPTICS) += drv260x.o obj-$(CONFIG_INPUT_DRV2665_HAPTICS) += drv2665.o obj-$(CONFIG_INPUT_DRV2667_HAPTICS) += drv2667.o -obj-$(CONFIG_INPUT_GP2A) += gp2ap002a00f.o obj-$(CONFIG_INPUT_GPIO_BEEPER) += gpio-beeper.o obj-$(CONFIG_INPUT_GPIO_DECODER) += gpio_decoder.o obj-$(CONFIG_INPUT_GPIO_VIBRA) += gpio-vibra.o diff --git a/drivers/input/misc/gp2ap002a00f.c b/drivers/input/misc/gp2ap002a00f.c deleted file mode 100644 index 90abda8eea67..000000000000 --- a/drivers/input/misc/gp2ap002a00f.c +++ /dev/null @@ -1,281 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * Copyright (C) 2011 Sony Ericsson Mobile Communications Inc. - * - * Author: Courtney Cavin - * Prepared for up-stream by: Oskar Andero - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -struct gp2a_data { - struct input_dev *input; - const struct gp2a_platform_data *pdata; - struct i2c_client *i2c_client; -}; - -enum gp2a_addr { - GP2A_ADDR_PROX = 0x0, - GP2A_ADDR_GAIN = 0x1, - GP2A_ADDR_HYS = 0x2, - GP2A_ADDR_CYCLE = 0x3, - GP2A_ADDR_OPMOD = 0x4, - GP2A_ADDR_CON = 0x6 -}; - -enum gp2a_controls { - /* Software Shutdown control: 0 = shutdown, 1 = normal operation */ - GP2A_CTRL_SSD = 0x01 -}; - -static int gp2a_report(struct gp2a_data *dt) -{ - int vo = gpio_get_value(dt->pdata->vout_gpio); - - input_report_switch(dt->input, SW_FRONT_PROXIMITY, !vo); - input_sync(dt->input); - - return 0; -} - -static irqreturn_t gp2a_irq(int irq, void *handle) -{ - struct gp2a_data *dt = handle; - - gp2a_report(dt); - - return IRQ_HANDLED; -} - -static int gp2a_enable(struct gp2a_data *dt) -{ - return i2c_smbus_write_byte_data(dt->i2c_client, GP2A_ADDR_OPMOD, - GP2A_CTRL_SSD); -} - -static int gp2a_disable(struct gp2a_data *dt) -{ - return i2c_smbus_write_byte_data(dt->i2c_client, GP2A_ADDR_OPMOD, - 0x00); -} - -static int gp2a_device_open(struct input_dev *dev) -{ - struct gp2a_data *dt = input_get_drvdata(dev); - int error; - - error = gp2a_enable(dt); - if (error < 0) { - dev_err(&dt->i2c_client->dev, - "unable to activate, err %d\n", error); - return error; - } - - gp2a_report(dt); - - return 0; -} - -static void gp2a_device_close(struct input_dev *dev) -{ - struct gp2a_data *dt = input_get_drvdata(dev); - int error; - - error = gp2a_disable(dt); - if (error < 0) - dev_err(&dt->i2c_client->dev, - "unable to deactivate, err %d\n", error); -} - -static int gp2a_initialize(struct gp2a_data *dt) -{ - int error; - - error = i2c_smbus_write_byte_data(dt->i2c_client, GP2A_ADDR_GAIN, - 0x08); - if (error < 0) - return error; - - error = i2c_smbus_write_byte_data(dt->i2c_client, GP2A_ADDR_HYS, - 0xc2); - if (error < 0) - return error; - - error = i2c_smbus_write_byte_data(dt->i2c_client, GP2A_ADDR_CYCLE, - 0x04); - if (error < 0) - return error; - - error = gp2a_disable(dt); - - return error; -} - -static int gp2a_probe(struct i2c_client *client, - const struct i2c_device_id *id) -{ - const struct gp2a_platform_data *pdata = dev_get_platdata(&client->dev); - struct gp2a_data *dt; - int error; - - if (!pdata) - return -EINVAL; - - if (pdata->hw_setup) { - error = pdata->hw_setup(client); - if (error < 0) - return error; - } - - error = gpio_request_one(pdata->vout_gpio, GPIOF_IN, GP2A_I2C_NAME); - if (error) - goto err_hw_shutdown; - - dt = kzalloc(sizeof(struct gp2a_data), GFP_KERNEL); - if (!dt) { - error = -ENOMEM; - goto err_free_gpio; - } - - dt->pdata = pdata; - dt->i2c_client = client; - - error = gp2a_initialize(dt); - if (error < 0) - goto err_free_mem; - - dt->input = input_allocate_device(); - if (!dt->input) { - error = -ENOMEM; - goto err_free_mem; - } - - input_set_drvdata(dt->input, dt); - - dt->input->open = gp2a_device_open; - dt->input->close = gp2a_device_close; - dt->input->name = GP2A_I2C_NAME; - dt->input->id.bustype = BUS_I2C; - dt->input->dev.parent = &client->dev; - - input_set_capability(dt->input, EV_SW, SW_FRONT_PROXIMITY); - - error = request_threaded_irq(client->irq, NULL, gp2a_irq, - IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING | - IRQF_ONESHOT, - GP2A_I2C_NAME, dt); - if (error) { - dev_err(&client->dev, "irq request failed\n"); - goto err_free_input_dev; - } - - error = input_register_device(dt->input); - if (error) { - dev_err(&client->dev, "device registration failed\n"); - goto err_free_irq; - } - - device_init_wakeup(&client->dev, pdata->wakeup); - i2c_set_clientdata(client, dt); - - return 0; - -err_free_irq: - free_irq(client->irq, dt); -err_free_input_dev: - input_free_device(dt->input); -err_free_mem: - kfree(dt); -err_free_gpio: - gpio_free(pdata->vout_gpio); -err_hw_shutdown: - if (pdata->hw_shutdown) - pdata->hw_shutdown(client); - return error; -} - -static int gp2a_remove(struct i2c_client *client) -{ - struct gp2a_data *dt = i2c_get_clientdata(client); - const struct gp2a_platform_data *pdata = dt->pdata; - - free_irq(client->irq, dt); - - input_unregister_device(dt->input); - kfree(dt); - - gpio_free(pdata->vout_gpio); - - if (pdata->hw_shutdown) - pdata->hw_shutdown(client); - - return 0; -} - -static int __maybe_unused gp2a_suspend(struct device *dev) -{ - struct i2c_client *client = to_i2c_client(dev); - struct gp2a_data *dt = i2c_get_clientdata(client); - int retval = 0; - - if (device_may_wakeup(&client->dev)) { - enable_irq_wake(client->irq); - } else { - mutex_lock(&dt->input->mutex); - if (dt->input->users) - retval = gp2a_disable(dt); - mutex_unlock(&dt->input->mutex); - } - - return retval; -} - -static int __maybe_unused gp2a_resume(struct device *dev) -{ - struct i2c_client *client = to_i2c_client(dev); - struct gp2a_data *dt = i2c_get_clientdata(client); - int retval = 0; - - if (device_may_wakeup(&client->dev)) { - disable_irq_wake(client->irq); - } else { - mutex_lock(&dt->input->mutex); - if (dt->input->users) - retval = gp2a_enable(dt); - mutex_unlock(&dt->input->mutex); - } - - return retval; -} - -static SIMPLE_DEV_PM_OPS(gp2a_pm, gp2a_suspend, gp2a_resume); - -static const struct i2c_device_id gp2a_i2c_id[] = { - { GP2A_I2C_NAME, 0 }, - { } -}; -MODULE_DEVICE_TABLE(i2c, gp2a_i2c_id); - -static struct i2c_driver gp2a_i2c_driver = { - .driver = { - .name = GP2A_I2C_NAME, - .pm = &gp2a_pm, - }, - .probe = gp2a_probe, - .remove = gp2a_remove, - .id_table = gp2a_i2c_id, -}; - -module_i2c_driver(gp2a_i2c_driver); - -MODULE_AUTHOR("Courtney Cavin "); -MODULE_DESCRIPTION("Sharp GP2AP002A00F I2C Proximity/Opto sensor driver"); -MODULE_LICENSE("GPL v2"); diff --git a/include/linux/input/gp2ap002a00f.h b/include/linux/input/gp2ap002a00f.h deleted file mode 100644 index 3614a13a8297..000000000000 --- a/include/linux/input/gp2ap002a00f.h +++ /dev/null @@ -1,23 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -#ifndef _GP2AP002A00F_H_ -#define _GP2AP002A00F_H_ - -#include - -#define GP2A_I2C_NAME "gp2ap002a00f" - -/** - * struct gp2a_platform_data - Sharp gp2ap002a00f proximity platform data - * @vout_gpio: The gpio connected to the object detected pin (VOUT) - * @wakeup: Set to true if the proximity can wake the device from suspend - * @hw_setup: Callback for setting up hardware such as gpios and vregs - * @hw_shutdown: Callback for properly shutting down hardware - */ -struct gp2a_platform_data { - int vout_gpio; - bool wakeup; - int (*hw_setup)(struct i2c_client *client); - int (*hw_shutdown)(struct i2c_client *client); -}; - -#endif -- cgit v1.2.3 From 7842087b0196d674ed877d768de8f2a34d7fdc53 Mon Sep 17 00:00:00 2001 From: Stephan Gerhold Date: Sat, 25 Apr 2020 13:06:31 -0700 Subject: Input: mms114 - add extra compatible for mms345l MMS345L is another first generation touch screen from Melfas, which uses mostly the same registers as MMS152. However, there is some garbage printed during initialization. Apparently MMS345L does not have the MMS152_COMPAT_GROUP register that is read+printed during initialization. TSP FW Rev: bootloader 0x6 / core 0x26 / config 0x26, Compat group: \x06 On earlier kernel versions the compat group was actually printed as an ASCII control character, seems like it gets escaped now. But we probably shouldn't print something from a random register. Add a separate "melfas,mms345l" compatible that avoids reading from the MMS152_COMPAT_GROUP register. This might also help in case there is some other device-specific quirk in the future. Signed-off-by: Stephan Gerhold Reviewed-by: Andi Shyti Link: https://lore.kernel.org/r/20200423102431.2715-1-stephan@gerhold.net Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/mms114.c | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) (limited to 'drivers/input') diff --git a/drivers/input/touchscreen/mms114.c b/drivers/input/touchscreen/mms114.c index 69c6d559eeb0..b3dda1722bae 100644 --- a/drivers/input/touchscreen/mms114.c +++ b/drivers/input/touchscreen/mms114.c @@ -54,6 +54,7 @@ enum mms_type { TYPE_MMS114 = 114, TYPE_MMS152 = 152, + TYPE_MMS345L = 345, }; struct mms114_data { @@ -250,6 +251,15 @@ static int mms114_get_version(struct mms114_data *data) int error; switch (data->type) { + case TYPE_MMS345L: + error = __mms114_read_reg(data, MMS152_FW_REV, 3, buf); + if (error) + return error; + + dev_info(dev, "TSP FW Rev: bootloader 0x%x / core 0x%x / config 0x%x\n", + buf[0], buf[1], buf[2]); + break; + case TYPE_MMS152: error = __mms114_read_reg(data, MMS152_FW_REV, 3, buf); if (error) @@ -287,8 +297,8 @@ static int mms114_setup_regs(struct mms114_data *data) if (error < 0) return error; - /* MMS152 has no configuration or power on registers */ - if (data->type == TYPE_MMS152) + /* Only MMS114 has configuration and power on registers */ + if (data->type != TYPE_MMS114) return 0; error = mms114_set_active(data, true); @@ -599,6 +609,9 @@ static const struct of_device_id mms114_dt_match[] = { }, { .compatible = "melfas,mms152", .data = (void *)TYPE_MMS152, + }, { + .compatible = "melfas,mms345l", + .data = (void *)TYPE_MMS345L, }, { } }; -- cgit v1.2.3 From 6052abf8ff783a14dcd2416be2c029ebeba9ad98 Mon Sep 17 00:00:00 2001 From: Rajat Jain Date: Mon, 27 Apr 2020 17:50:45 -0700 Subject: Input: i8042 - attach fwnode to serio i8042 kbd device Attach the firmware node to the serio i8042 kbd device so that device properties can be passed from the firmware. Signed-off-by: Rajat Jain Link: https://lore.kernel.org/r/20200427210259.91330-1-rajatja@google.com Signed-off-by: Dmitry Torokhov --- drivers/input/serio/i8042-x86ia64io.h | 1 + drivers/input/serio/i8042.c | 3 +++ 2 files changed, 4 insertions(+) (limited to 'drivers/input') diff --git a/drivers/input/serio/i8042-x86ia64io.h b/drivers/input/serio/i8042-x86ia64io.h index 08e919dbeb5d..d0c39426ca2c 100644 --- a/drivers/input/serio/i8042-x86ia64io.h +++ b/drivers/input/serio/i8042-x86ia64io.h @@ -938,6 +938,7 @@ static int i8042_pnp_kbd_probe(struct pnp_dev *dev, const struct pnp_device_id * } i8042_pnp_id_to_string(dev->id, i8042_kbd_firmware_id, sizeof(i8042_kbd_firmware_id)); + i8042_kbd_fwnode = dev_fwnode(&dev->dev); /* Keyboard ports are always supposed to be wakeup-enabled */ device_set_wakeup_enable(&dev->dev, true); diff --git a/drivers/input/serio/i8042.c b/drivers/input/serio/i8042.c index 20ff2bed3917..0dddf273afd9 100644 --- a/drivers/input/serio/i8042.c +++ b/drivers/input/serio/i8042.c @@ -21,6 +21,7 @@ #include #include #include +#include #include @@ -124,6 +125,7 @@ MODULE_PARM_DESC(unmask_kbd_data, "Unconditional enable (may reveal sensitive da static bool i8042_bypass_aux_irq_test; static char i8042_kbd_firmware_id[128]; static char i8042_aux_firmware_id[128]; +static struct fwnode_handle *i8042_kbd_fwnode; #include "i8042.h" @@ -1335,6 +1337,7 @@ static int __init i8042_create_kbd_port(void) strlcpy(serio->phys, I8042_KBD_PHYS_DESC, sizeof(serio->phys)); strlcpy(serio->firmware_id, i8042_kbd_firmware_id, sizeof(serio->firmware_id)); + set_primary_fwnode(&serio->dev, i8042_kbd_fwnode); port->serio = serio; port->irq = I8042_KBD_IRQ; -- cgit v1.2.3 From 8f7b057abe283a4505747ea8275751479442de53 Mon Sep 17 00:00:00 2001 From: Rajat Jain Date: Mon, 27 Apr 2020 17:51:15 -0700 Subject: Input: atkbd - expose function row physical map to userspace Certain keyboards have their top-row keys intended for actions such as "Browser back", "Browser Refresh", "Fullscreen" etc as their primary mode, thus they will send scan codes for those actions. Further, they don't have a dedicated "Fn" key so don't have the capability to generate function key codes (e.g. F1, F2 etc..). However in this case, if userspace still wants to "synthesize" those function keys using the top row action keys, it needs to know the physical position of the top row keys. (Essentially a mapping between usage codes and a physical location in the top row). This patch enhances the atkbd driver to receive such a mapping from the firmware / device tree, and expose it to userspace in the form of a function-row-physmap attribute. The attribute would be a space separated ordered list of physical codes, for the keys in the function row, in left-to-right order. The attribute will only be present if the kernel knows about such mapping, otherwise the attribute shall not be visible. Signed-off-by: Rajat Jain Link: https://lore.kernel.org/r/20200427210259.91330-2-rajatja@google.com Signed-off-by: Dmitry Torokhov --- drivers/input/keyboard/atkbd.c | 56 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 56 insertions(+) (limited to 'drivers/input') diff --git a/drivers/input/keyboard/atkbd.c b/drivers/input/keyboard/atkbd.c index 7e3eae54c192..358e91f8888f 100644 --- a/drivers/input/keyboard/atkbd.c +++ b/drivers/input/keyboard/atkbd.c @@ -24,6 +24,7 @@ #include #include #include +#include #define DRIVER_DESC "AT and PS/2 keyboard driver" @@ -63,6 +64,8 @@ static bool atkbd_terminal; module_param_named(terminal, atkbd_terminal, bool, 0); MODULE_PARM_DESC(terminal, "Enable break codes on an IBM Terminal keyboard connected via AT/PS2"); +#define MAX_FUNCTION_ROW_KEYS 24 + /* * Scancode to keycode tables. These are just the default setting, and * are loadable via a userland utility. @@ -230,6 +233,9 @@ struct atkbd { /* Serializes reconnect(), attr->set() and event work */ struct mutex mutex; + + u32 function_row_physmap[MAX_FUNCTION_ROW_KEYS]; + int num_function_row_keys; }; /* @@ -283,6 +289,7 @@ static struct device_attribute atkbd_attr_##_name = \ __ATTR(_name, S_IRUGO, atkbd_do_show_##_name, NULL); ATKBD_DEFINE_RO_ATTR(err_count); +ATKBD_DEFINE_RO_ATTR(function_row_physmap); static struct attribute *atkbd_attributes[] = { &atkbd_attr_extra.attr, @@ -292,11 +299,42 @@ static struct attribute *atkbd_attributes[] = { &atkbd_attr_softrepeat.attr, &atkbd_attr_softraw.attr, &atkbd_attr_err_count.attr, + &atkbd_attr_function_row_physmap.attr, NULL }; +static ssize_t atkbd_show_function_row_physmap(struct atkbd *atkbd, char *buf) +{ + ssize_t size = 0; + int i; + + if (!atkbd->num_function_row_keys) + return 0; + + for (i = 0; i < atkbd->num_function_row_keys; i++) + size += scnprintf(buf + size, PAGE_SIZE - size, "%02X ", + atkbd->function_row_physmap[i]); + size += scnprintf(buf + size, PAGE_SIZE - size, "\n"); + return size; +} + +static umode_t atkbd_attr_is_visible(struct kobject *kobj, + struct attribute *attr, int i) +{ + struct device *dev = container_of(kobj, struct device, kobj); + struct serio *serio = to_serio_port(dev); + struct atkbd *atkbd = serio_get_drvdata(serio); + + if (attr == &atkbd_attr_function_row_physmap.attr && + !atkbd->num_function_row_keys) + return 0; + + return attr->mode; +} + static struct attribute_group atkbd_attribute_group = { .attrs = atkbd_attributes, + .is_visible = atkbd_attr_is_visible, }; static const unsigned int xl_table[] = { @@ -1121,6 +1159,22 @@ static void atkbd_set_device_attrs(struct atkbd *atkbd) } } +static void atkbd_parse_fwnode_data(struct serio *serio) +{ + struct atkbd *atkbd = serio_get_drvdata(serio); + struct device *dev = &serio->dev; + int n; + + /* Parse "function-row-physmap" property */ + n = device_property_count_u32(dev, "function-row-physmap"); + if (n > 0 && n <= MAX_FUNCTION_ROW_KEYS && + !device_property_read_u32_array(dev, "function-row-physmap", + atkbd->function_row_physmap, n)) { + atkbd->num_function_row_keys = n; + dev_dbg(dev, "FW reported %d function-row key locations\n", n); + } +} + /* * atkbd_connect() is called when the serio module finds an interface * that isn't handled yet by an appropriate device driver. We check if @@ -1184,6 +1238,8 @@ static int atkbd_connect(struct serio *serio, struct serio_driver *drv) atkbd->id = 0xab00; } + atkbd_parse_fwnode_data(serio); + atkbd_set_keycode_table(atkbd); atkbd_set_device_attrs(atkbd); -- cgit v1.2.3 From 9d17ad2369dcc9beda0785cf5960222dbdd6c9df Mon Sep 17 00:00:00 2001 From: Rajat Jain Date: Mon, 27 Apr 2020 17:53:46 -0700 Subject: Input: atkbd - receive and use physcode->keycode mapping from FW Allow the firmware to specify the mapping between the scan code and the linux keycode. This takes the form of a "linux,keymap" property which is an array of u32 values, each value specifying mapping for a key. Signed-off-by: Rajat Jain Link: https://lore.kernel.org/r/20200427210259.91330-3-rajatja@google.com Signed-off-by: Dmitry Torokhov --- drivers/input/keyboard/atkbd.c | 41 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 40 insertions(+), 1 deletion(-) (limited to 'drivers/input') diff --git a/drivers/input/keyboard/atkbd.c b/drivers/input/keyboard/atkbd.c index 358e91f8888f..6ec28265771d 100644 --- a/drivers/input/keyboard/atkbd.c +++ b/drivers/input/keyboard/atkbd.c @@ -66,6 +66,9 @@ MODULE_PARM_DESC(terminal, "Enable break codes on an IBM Terminal keyboard conne #define MAX_FUNCTION_ROW_KEYS 24 +#define SCANCODE(keymap) ((keymap >> 16) & 0xFFFF) +#define KEYCODE(keymap) (keymap & 0xFFFF) + /* * Scancode to keycode tables. These are just the default setting, and * are loadable via a userland utility. @@ -1032,6 +1035,39 @@ static unsigned int atkbd_oqo_01plus_scancode_fixup(struct atkbd *atkbd, return code; } +static int atkbd_get_keymap_from_fwnode(struct atkbd *atkbd) +{ + struct device *dev = &atkbd->ps2dev.serio->dev; + int i, n; + u32 *ptr; + u16 scancode, keycode; + + /* Parse "linux,keymap" property */ + n = device_property_count_u32(dev, "linux,keymap"); + if (n <= 0 || n > ATKBD_KEYMAP_SIZE) + return -ENXIO; + + ptr = kcalloc(n, sizeof(u32), GFP_KERNEL); + if (!ptr) + return -ENOMEM; + + if (device_property_read_u32_array(dev, "linux,keymap", ptr, n)) { + dev_err(dev, "problem parsing FW keymap property\n"); + kfree(ptr); + return -EINVAL; + } + + memset(atkbd->keycode, 0, sizeof(atkbd->keycode)); + for (i = 0; i < n; i++) { + scancode = SCANCODE(ptr[i]); + keycode = KEYCODE(ptr[i]); + atkbd->keycode[scancode] = keycode; + } + + kfree(ptr); + return 0; +} + /* * atkbd_set_keycode_table() initializes keyboard's keycode table * according to the selected scancode set @@ -1039,13 +1075,16 @@ static unsigned int atkbd_oqo_01plus_scancode_fixup(struct atkbd *atkbd, static void atkbd_set_keycode_table(struct atkbd *atkbd) { + struct device *dev = &atkbd->ps2dev.serio->dev; unsigned int scancode; int i, j; memset(atkbd->keycode, 0, sizeof(atkbd->keycode)); bitmap_zero(atkbd->force_release_mask, ATKBD_KEYMAP_SIZE); - if (atkbd->translated) { + if (!atkbd_get_keymap_from_fwnode(atkbd)) { + dev_dbg(dev, "Using FW keymap\n"); + } else if (atkbd->translated) { for (i = 0; i < 128; i++) { scancode = atkbd_unxlate_table[i]; atkbd->keycode[i] = atkbd_set2_keycode[scancode]; -- cgit v1.2.3 From 255cdaf73412de13608fb776101402dca68bed2b Mon Sep 17 00:00:00 2001 From: Marco Felsch Date: Sat, 9 May 2020 14:34:35 -0700 Subject: Input: edt-ft5x06 - fix get_default register write access Since commit b6eba86030bf ("Input: edt-ft5x06 - add offset support for ev-ft5726") offset-x and offset-y is supported. Devices using those offset parameters don't support the offset parameter so we need to add the NO_REGISTER check for edt_ft5x06_ts_get_defaults(). Fixes: b6eba86030bf ("Input: edt-ft5x06 - add offset support for ev-ft5726") Signed-off-by: Marco Felsch Link: https://lore.kernel.org/r/20200227112819.16754-2-m.felsch@pengutronix.de Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/edt-ft5x06.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) (limited to 'drivers/input') diff --git a/drivers/input/touchscreen/edt-ft5x06.c b/drivers/input/touchscreen/edt-ft5x06.c index d2587724c52a..9b8450794a8a 100644 --- a/drivers/input/touchscreen/edt-ft5x06.c +++ b/drivers/input/touchscreen/edt-ft5x06.c @@ -938,19 +938,25 @@ static void edt_ft5x06_ts_get_defaults(struct device *dev, error = device_property_read_u32(dev, "offset", &val); if (!error) { - edt_ft5x06_register_write(tsdata, reg_addr->reg_offset, val); + if (reg_addr->reg_offset != NO_REGISTER) + edt_ft5x06_register_write(tsdata, + reg_addr->reg_offset, val); tsdata->offset = val; } error = device_property_read_u32(dev, "offset-x", &val); if (!error) { - edt_ft5x06_register_write(tsdata, reg_addr->reg_offset_x, val); + if (reg_addr->reg_offset_x != NO_REGISTER) + edt_ft5x06_register_write(tsdata, + reg_addr->reg_offset_x, val); tsdata->offset_x = val; } error = device_property_read_u32(dev, "offset-y", &val); if (!error) { - edt_ft5x06_register_write(tsdata, reg_addr->reg_offset_y, val); + if (reg_addr->reg_offset_y != NO_REGISTER) + edt_ft5x06_register_write(tsdata, + reg_addr->reg_offset_y, val); tsdata->offset_y = val; } } -- cgit v1.2.3 From f4ee52f3ad8c9210030a9fe48bbb74dbc7c9f90e Mon Sep 17 00:00:00 2001 From: Marco Felsch Date: Sat, 9 May 2020 12:05:36 -0700 Subject: Input: edt-ft5x06 - move parameter restore into helper We need to restore the parameters if we switch between the factory/work mode and during the resume process if we switched off the power-supply. Therefore refactor edt_ft5x06_work_mode() and move the "restore the parameters" into a helper routine so we can reuse it later. Signed-off-by: Marco Felsch Link: https://lore.kernel.org/r/20200227112819.16754-3-m.felsch@pengutronix.de Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/edt-ft5x06.c | 43 +++++++++++++++++++--------------- 1 file changed, 24 insertions(+), 19 deletions(-) (limited to 'drivers/input') diff --git a/drivers/input/touchscreen/edt-ft5x06.c b/drivers/input/touchscreen/edt-ft5x06.c index 9b8450794a8a..bb9107093796 100644 --- a/drivers/input/touchscreen/edt-ft5x06.c +++ b/drivers/input/touchscreen/edt-ft5x06.c @@ -527,6 +527,29 @@ static const struct attribute_group edt_ft5x06_attr_group = { .attrs = edt_ft5x06_attrs, }; +static void edt_ft5x06_restore_reg_parameters(struct edt_ft5x06_ts_data *tsdata) +{ + struct edt_reg_addr *reg_addr = &tsdata->reg_addr; + + edt_ft5x06_register_write(tsdata, reg_addr->reg_threshold, + tsdata->threshold); + edt_ft5x06_register_write(tsdata, reg_addr->reg_gain, + tsdata->gain); + if (reg_addr->reg_offset != NO_REGISTER) + edt_ft5x06_register_write(tsdata, reg_addr->reg_offset, + tsdata->offset); + if (reg_addr->reg_offset_x != NO_REGISTER) + edt_ft5x06_register_write(tsdata, reg_addr->reg_offset_x, + tsdata->offset_x); + if (reg_addr->reg_offset_y != NO_REGISTER) + edt_ft5x06_register_write(tsdata, reg_addr->reg_offset_y, + tsdata->offset_y); + if (reg_addr->reg_report_rate != NO_REGISTER) + edt_ft5x06_register_write(tsdata, reg_addr->reg_report_rate, + tsdata->report_rate); + +} + #ifdef CONFIG_DEBUG_FS static int edt_ft5x06_factory_mode(struct edt_ft5x06_ts_data *tsdata) { @@ -592,7 +615,6 @@ static int edt_ft5x06_work_mode(struct edt_ft5x06_ts_data *tsdata) { struct i2c_client *client = tsdata->client; int retries = EDT_SWITCH_MODE_RETRIES; - struct edt_reg_addr *reg_addr = &tsdata->reg_addr; int ret; int error; @@ -624,24 +646,7 @@ static int edt_ft5x06_work_mode(struct edt_ft5x06_ts_data *tsdata) kfree(tsdata->raw_buffer); tsdata->raw_buffer = NULL; - /* restore parameters */ - edt_ft5x06_register_write(tsdata, reg_addr->reg_threshold, - tsdata->threshold); - edt_ft5x06_register_write(tsdata, reg_addr->reg_gain, - tsdata->gain); - if (reg_addr->reg_offset != NO_REGISTER) - edt_ft5x06_register_write(tsdata, reg_addr->reg_offset, - tsdata->offset); - if (reg_addr->reg_offset_x != NO_REGISTER) - edt_ft5x06_register_write(tsdata, reg_addr->reg_offset_x, - tsdata->offset_x); - if (reg_addr->reg_offset_y != NO_REGISTER) - edt_ft5x06_register_write(tsdata, reg_addr->reg_offset_y, - tsdata->offset_y); - if (reg_addr->reg_report_rate != NO_REGISTER) - edt_ft5x06_register_write(tsdata, reg_addr->reg_report_rate, - tsdata->report_rate); - + edt_ft5x06_restore_reg_parameters(tsdata); enable_irq(client->irq); return 0; -- cgit v1.2.3 From 21d1611a83f8aa3907ca653b5851dd01951d4da6 Mon Sep 17 00:00:00 2001 From: Marco Felsch Date: Sat, 9 May 2020 12:10:40 -0700 Subject: Input: edt-ft5x06 - improve power management operations It is possible to bring the device into a deep sleep state. To exit this state the reset or wakeup pin must be toggeled as documented in [1]. Because of the poor documentation I used the several downstream kernels [2] and other applications notes [3] to indentify the related registers. Furthermore I added the support to disable the device completely which is obviously the most effective power-saving mechanism. This mechanism needs the reset pin to ensure the power-up/down sequence. We can't apply any of these power-saving mechanism if both pins are missing (not connected) or if it is a wakeup device. [1] https://www.newhavendisplay.com/appnotes/datasheets/touchpanel/FT5x26.pdf https://www.newhavendisplay.com/appnotes/datasheets/touchpanel/FT5x06.pdf [2] https://github.com/linux-sunxi/linux-sunxi/blob/sunxi-3.4/drivers/input/touchscreen/ft5x_ts.c https://github.com/Pablito2020/focaltech-touch-driver/blob/master/ft5336_driver.c [3] https://www.newhavendisplay.com/appnotes/datasheets/touchpanel/FT5x16_registers.pdf Signed-off-by: Marco Felsch Link: https://lore.kernel.org/r/20200227112819.16754-4-m.felsch@pengutronix.de Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/edt-ft5x06.c | 142 ++++++++++++++++++++++++++++++--- 1 file changed, 132 insertions(+), 10 deletions(-) (limited to 'drivers/input') diff --git a/drivers/input/touchscreen/edt-ft5x06.c b/drivers/input/touchscreen/edt-ft5x06.c index bb9107093796..d423bd6bfeda 100644 --- a/drivers/input/touchscreen/edt-ft5x06.c +++ b/drivers/input/touchscreen/edt-ft5x06.c @@ -38,6 +38,9 @@ #define WORK_REGISTER_NUM_X 0x33 #define WORK_REGISTER_NUM_Y 0x34 +#define PMOD_REGISTER_ACTIVE 0x00 +#define PMOD_REGISTER_HIBERNATE 0x03 + #define M09_REGISTER_THRESHOLD 0x80 #define M09_REGISTER_GAIN 0x92 #define M09_REGISTER_OFFSET 0x93 @@ -53,6 +56,7 @@ #define WORK_REGISTER_OPMODE 0x3c #define FACTORY_REGISTER_OPMODE 0x01 +#define PMOD_REGISTER_OPMODE 0xa5 #define TOUCH_EVENT_DOWN 0x00 #define TOUCH_EVENT_UP 0x01 @@ -65,6 +69,12 @@ #define EDT_RAW_DATA_RETRIES 100 #define EDT_RAW_DATA_DELAY 1000 /* usec */ +enum edt_pmode { + EDT_PMODE_NOT_SUPPORTED, + EDT_PMODE_HIBERNATE, + EDT_PMODE_POWEROFF, +}; + enum edt_ver { EDT_M06, EDT_M09, @@ -103,6 +113,7 @@ struct edt_ft5x06_ts_data { struct mutex mutex; bool factory_mode; + enum edt_pmode suspend_mode; int threshold; int gain; int offset; @@ -767,9 +778,8 @@ static const struct file_operations debugfs_raw_data_fops = { .read = edt_ft5x06_debugfs_raw_data_read, }; -static void -edt_ft5x06_ts_prepare_debugfs(struct edt_ft5x06_ts_data *tsdata, - const char *debugfs_name) +static void edt_ft5x06_ts_prepare_debugfs(struct edt_ft5x06_ts_data *tsdata, + const char *debugfs_name) { tsdata->debug_dir = debugfs_create_dir(debugfs_name, NULL); @@ -782,8 +792,7 @@ edt_ft5x06_ts_prepare_debugfs(struct edt_ft5x06_ts_data *tsdata, tsdata->debug_dir, tsdata, &debugfs_raw_data_fops); } -static void -edt_ft5x06_ts_teardown_debugfs(struct edt_ft5x06_ts_data *tsdata) +static void edt_ft5x06_ts_teardown_debugfs(struct edt_ft5x06_ts_data *tsdata) { debugfs_remove_recursive(tsdata->debug_dir); kfree(tsdata->raw_buffer); @@ -791,14 +800,17 @@ edt_ft5x06_ts_teardown_debugfs(struct edt_ft5x06_ts_data *tsdata) #else -static inline void -edt_ft5x06_ts_prepare_debugfs(struct edt_ft5x06_ts_data *tsdata, - const char *debugfs_name) +static int edt_ft5x06_factory_mode(struct edt_ft5x06_ts_data *tsdata) { + return -ENOSYS; } -static inline void -edt_ft5x06_ts_teardown_debugfs(struct edt_ft5x06_ts_data *tsdata) +static void edt_ft5x06_ts_prepare_debugfs(struct edt_ft5x06_ts_data *tsdata, + const char *debugfs_name) +{ +} + +static void edt_ft5x06_ts_teardown_debugfs(struct edt_ft5x06_ts_data *tsdata) { } @@ -1125,6 +1137,19 @@ static int edt_ft5x06_ts_probe(struct i2c_client *client, return error; } + /* + * Check which sleep modes we can support. Power-off requieres the + * reset-pin to ensure correct power-down/power-up behaviour. Start with + * the EDT_PMODE_POWEROFF test since this is the deepest possible sleep + * mode. + */ + if (tsdata->reset_gpio) + tsdata->suspend_mode = EDT_PMODE_POWEROFF; + else if (tsdata->wake_gpio) + tsdata->suspend_mode = EDT_PMODE_HIBERNATE; + else + tsdata->suspend_mode = EDT_PMODE_NOT_SUPPORTED; + if (tsdata->wake_gpio) { usleep_range(5000, 6000); gpiod_set_value_cansleep(tsdata->wake_gpio, 1); @@ -1238,6 +1263,102 @@ static int edt_ft5x06_ts_remove(struct i2c_client *client) return 0; } +static int __maybe_unused edt_ft5x06_ts_suspend(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct edt_ft5x06_ts_data *tsdata = i2c_get_clientdata(client); + struct gpio_desc *reset_gpio = tsdata->reset_gpio; + int ret; + + if (device_may_wakeup(dev)) + return 0; + + if (tsdata->suspend_mode == EDT_PMODE_NOT_SUPPORTED) + return 0; + + /* Enter hibernate mode. */ + ret = edt_ft5x06_register_write(tsdata, PMOD_REGISTER_OPMODE, + PMOD_REGISTER_HIBERNATE); + if (ret) + dev_warn(dev, "Failed to set hibernate mode\n"); + + if (tsdata->suspend_mode == EDT_PMODE_HIBERNATE) + return 0; + + /* + * Power-off according the datasheet. Cut the power may leaf the irq + * line in an undefined state depending on the host pull resistor + * settings. Disable the irq to avoid adjusting each host till the + * device is back in a full functional state. + */ + disable_irq(tsdata->client->irq); + + gpiod_set_value_cansleep(reset_gpio, 1); + usleep_range(1000, 2000); + + ret = regulator_disable(tsdata->vcc); + if (ret) + dev_warn(dev, "Failed to disable vcc\n"); + + return 0; +} + +static int __maybe_unused edt_ft5x06_ts_resume(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct edt_ft5x06_ts_data *tsdata = i2c_get_clientdata(client); + int ret = 0; + + if (device_may_wakeup(dev)) + return 0; + + if (tsdata->suspend_mode == EDT_PMODE_NOT_SUPPORTED) + return 0; + + if (tsdata->suspend_mode == EDT_PMODE_POWEROFF) { + struct gpio_desc *reset_gpio = tsdata->reset_gpio; + + /* + * We can't check if the regulator is a dummy or a real + * regulator. So we need to specify the 5ms reset time (T_rst) + * here instead of the 100us T_rtp time. We also need to wait + * 300ms in case it was a real supply and the power was cutted + * of. Toggle the reset pin is also a way to exit the hibernate + * mode. + */ + gpiod_set_value_cansleep(reset_gpio, 1); + usleep_range(5000, 6000); + + ret = regulator_enable(tsdata->vcc); + if (ret) { + dev_err(dev, "Failed to enable vcc\n"); + return ret; + } + + usleep_range(1000, 2000); + gpiod_set_value_cansleep(reset_gpio, 0); + msleep(300); + + edt_ft5x06_restore_reg_parameters(tsdata); + enable_irq(tsdata->client->irq); + + if (tsdata->factory_mode) + ret = edt_ft5x06_factory_mode(tsdata); + } else { + struct gpio_desc *wake_gpio = tsdata->wake_gpio; + + gpiod_set_value_cansleep(wake_gpio, 0); + usleep_range(5000, 6000); + gpiod_set_value_cansleep(wake_gpio, 1); + } + + + return ret; +} + +static SIMPLE_DEV_PM_OPS(edt_ft5x06_ts_pm_ops, + edt_ft5x06_ts_suspend, edt_ft5x06_ts_resume); + static const struct edt_i2c_chip_data edt_ft5x06_data = { .max_support_points = 5, }; @@ -1276,6 +1397,7 @@ static struct i2c_driver edt_ft5x06_ts_driver = { .driver = { .name = "edt_ft5x06", .of_match_table = edt_ft5x06_of_match, + .pm = &edt_ft5x06_ts_pm_ops, }, .id_table = edt_ft5x06_ts_id, .probe = edt_ft5x06_ts_probe, -- cgit v1.2.3 From 0f58daaacca9fdc078eadfcfaa19e467b264cb28 Mon Sep 17 00:00:00 2001 From: Ahmad Fatoum Date: Sat, 9 May 2020 14:27:23 -0700 Subject: Input: edt-ft5x06 - prefer asynchronous probe Probing the device takes a while, because we sleep for 300 ms after a reset; allow asynchronous probing so this can happen in the background while other devices are being probed. Signed-off-by: Ahmad Fatoum Signed-off-by: Marco Felsch Link: https://lore.kernel.org/r/20200227112819.16754-5-m.felsch@pengutronix.de Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/edt-ft5x06.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/input') diff --git a/drivers/input/touchscreen/edt-ft5x06.c b/drivers/input/touchscreen/edt-ft5x06.c index d423bd6bfeda..3a4f18d3450d 100644 --- a/drivers/input/touchscreen/edt-ft5x06.c +++ b/drivers/input/touchscreen/edt-ft5x06.c @@ -1398,6 +1398,7 @@ static struct i2c_driver edt_ft5x06_ts_driver = { .name = "edt_ft5x06", .of_match_table = edt_ft5x06_of_match, .pm = &edt_ft5x06_ts_pm_ops, + .probe_type = PROBE_PREFER_ASYNCHRONOUS, }, .id_table = edt_ft5x06_ts_id, .probe = edt_ft5x06_ts_probe, -- cgit v1.2.3 From 3eb66d9f97f386262adbba9ce752ec80b85246ed Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Sat, 9 May 2020 22:18:18 -0700 Subject: Input: add driver for the Cypress CY8CTMA140 touchscreen This adds a new driver for the Cypress CY8CTMA140 touchscreen. This driver is inspired by out-of-tree code for the Samsung GT-S7710 mobile phone. I have tried to compare the structure and behaviour of this touchscreen to the existing CYTTSP and CYTTSP4 generics and it seems pretty different. It is also different in character from the cy8ctmg110_ts.c. It appears to rather be vaguely related to the Melfas MMS114 driver, yet distinctly different. Dmitry Torokhov rewrote the key scanning code during the submission process so the driver is a joint work. Signed-off-by: Linus Walleij Link: https://lore.kernel.org/r/20200506123435.187432-2-linus.walleij@linaro.org Signed-off-by: Dmitry Torokhov --- MAINTAINERS | 6 + drivers/input/touchscreen/Kconfig | 12 ++ drivers/input/touchscreen/Makefile | 1 + drivers/input/touchscreen/cy8ctma140.c | 353 +++++++++++++++++++++++++++++++++ 4 files changed, 372 insertions(+) create mode 100644 drivers/input/touchscreen/cy8ctma140.c (limited to 'drivers/input') diff --git a/MAINTAINERS b/MAINTAINERS index 8982c6e013b3..faa5bfe8ece0 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -4578,6 +4578,12 @@ T: git git://linuxtv.org/anttip/media_tree.git S: Maintained F: drivers/media/common/cypress_firmware* +CYPRESS CY8CTMA140 TOUCHSCREEN DRIVER +M: Linus Walleij +L: linux-input@vger.kernel.org +S: Maintained +F: drivers/input/touchscreen/cy8ctma140.c + CYTTSP TOUCHSCREEN DRIVER M: Ferruh Yigit L: linux-input@vger.kernel.org diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig index c071f7c407b6..35c867b2d9a7 100644 --- a/drivers/input/touchscreen/Kconfig +++ b/drivers/input/touchscreen/Kconfig @@ -201,6 +201,18 @@ config TOUCHSCREEN_CHIPONE_ICN8505 To compile this driver as a module, choose M here: the module will be called chipone_icn8505. +config TOUCHSCREEN_CY8CTMA140 + tristate "cy8ctma140 touchscreen" + depends on I2C + help + Say Y here if you have a Cypress CY8CTMA140 capacitive + touchscreen also just known as "TMA140" + + If unsure, say N. + + To compile this driver as a module, choose M here: the + module will be called cy8ctma140. + config TOUCHSCREEN_CY8CTMG110 tristate "cy8ctmg110 touchscreen" depends on I2C diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile index 94c6162409b3..30d1e1b42492 100644 --- a/drivers/input/touchscreen/Makefile +++ b/drivers/input/touchscreen/Makefile @@ -22,6 +22,7 @@ obj-$(CONFIG_TOUCHSCREEN_BU21013) += bu21013_ts.o obj-$(CONFIG_TOUCHSCREEN_BU21029) += bu21029_ts.o obj-$(CONFIG_TOUCHSCREEN_CHIPONE_ICN8318) += chipone_icn8318.o obj-$(CONFIG_TOUCHSCREEN_CHIPONE_ICN8505) += chipone_icn8505.o +obj-$(CONFIG_TOUCHSCREEN_CY8CTMA140) += cy8ctma140.o obj-$(CONFIG_TOUCHSCREEN_CY8CTMG110) += cy8ctmg110_ts.o obj-$(CONFIG_TOUCHSCREEN_CYTTSP_CORE) += cyttsp_core.o obj-$(CONFIG_TOUCHSCREEN_CYTTSP_I2C) += cyttsp_i2c.o cyttsp_i2c_common.o diff --git a/drivers/input/touchscreen/cy8ctma140.c b/drivers/input/touchscreen/cy8ctma140.c new file mode 100644 index 000000000000..a9be29139cbf --- /dev/null +++ b/drivers/input/touchscreen/cy8ctma140.c @@ -0,0 +1,353 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Driver for Cypress CY8CTMA140 (TMA140) touchscreen + * (C) 2020 Linus Walleij + * (C) 2007 Cypress + * (C) 2007 Google, Inc. + * + * Inspired by the tma140_skomer.c driver in the Samsung GT-S7710 code + * drop. The GT-S7710 is codenamed "Skomer", the code also indicates + * that the same touchscreen was used in a product called "Lucas". + * + * The code drop for GT-S7710 also contains a firmware downloader and + * 15 (!) versions of the firmware drop from Cypress. But here we assume + * the firmware got downloaded to the touchscreen flash successfully and + * just use it to read the fingers. The shipped vendor driver does the + * same. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define CY8CTMA140_NAME "cy8ctma140" + +#define CY8CTMA140_MAX_FINGERS 4 + +#define CY8CTMA140_GET_FINGERS 0x00 +#define CY8CTMA140_GET_FW_INFO 0x19 + +/* This message also fits some bytes for touchkeys, if used */ +#define CY8CTMA140_PACKET_SIZE 31 + +#define CY8CTMA140_INVALID_BUFFER_BIT 5 + +struct cy8ctma140 { + struct input_dev *input; + struct touchscreen_properties props; + struct device *dev; + struct i2c_client *client; + struct regulator_bulk_data regulators[2]; + u8 prev_fingers; + u8 prev_f1id; + u8 prev_f2id; +}; + +static void cy8ctma140_report(struct cy8ctma140 *ts, u8 *data, int n_fingers) +{ + static const u8 contact_offsets[] = { 0x03, 0x09, 0x10, 0x16 }; + u8 *buf; + u16 x, y; + u8 w; + u8 id; + int slot; + int i; + + for (i = 0; i < n_fingers; i++) { + buf = &data[contact_offsets[i]]; + + /* + * Odd contacts have contact ID in the lower nibble of + * the preceding byte, whereas even contacts have it in + * the upper nibble of the following byte. + */ + id = i % 2 ? buf[-1] & 0x0f : buf[5] >> 4; + slot = input_mt_get_slot_by_key(ts->input, id); + if (slot < 0) + continue; + + x = get_unaligned_be16(buf); + y = get_unaligned_be16(buf + 2); + w = buf[4]; + + dev_dbg(ts->dev, "finger %d: ID %02x (%d, %d) w: %d\n", + slot, id, x, y, w); + + input_mt_slot(ts->input, slot); + input_mt_report_slot_state(ts->input, MT_TOOL_FINGER, true); + touchscreen_report_pos(ts->input, &ts->props, x, y, true); + input_report_abs(ts->input, ABS_MT_TOUCH_MAJOR, w); + } + + input_mt_sync_frame(ts->input); + input_sync(ts->input); +} + +static irqreturn_t cy8ctma140_irq_thread(int irq, void *d) +{ + struct cy8ctma140 *ts = d; + u8 cmdbuf[] = { CY8CTMA140_GET_FINGERS }; + u8 buf[CY8CTMA140_PACKET_SIZE]; + struct i2c_msg msg[] = { + { + .addr = ts->client->addr, + .flags = 0, + .len = sizeof(cmdbuf), + .buf = cmdbuf, + }, { + .addr = ts->client->addr, + .flags = I2C_M_RD, + .len = sizeof(buf), + .buf = buf, + }, + }; + u8 n_fingers; + int ret; + + ret = i2c_transfer(ts->client->adapter, msg, ARRAY_SIZE(msg)); + if (ret != ARRAY_SIZE(msg)) { + if (ret < 0) + dev_err(ts->dev, "error reading message: %d\n", ret); + else + dev_err(ts->dev, "wrong number of messages\n"); + goto out; + } + + if (buf[1] & BIT(CY8CTMA140_INVALID_BUFFER_BIT)) { + dev_dbg(ts->dev, "invalid event\n"); + goto out; + } + + n_fingers = buf[2] & 0x0f; + if (n_fingers > CY8CTMA140_MAX_FINGERS) { + dev_err(ts->dev, "unexpected number of fingers: %d\n", + n_fingers); + goto out; + } + + cy8ctma140_report(ts, buf, n_fingers); + +out: + return IRQ_HANDLED; +} + +static int cy8ctma140_init(struct cy8ctma140 *ts) +{ + u8 addr[1]; + u8 buf[5]; + int ret; + + addr[0] = CY8CTMA140_GET_FW_INFO; + ret = i2c_master_send(ts->client, addr, 1); + if (ret < 0) { + dev_err(ts->dev, "error sending FW info message\n"); + return ret; + } + ret = i2c_master_recv(ts->client, buf, 5); + if (ret < 0) { + dev_err(ts->dev, "error receiving FW info message\n"); + return ret; + } + if (ret != 5) { + dev_err(ts->dev, "got only %d bytes\n", ret); + return -EIO; + } + + dev_dbg(ts->dev, "vendor %c%c, HW ID %.2d, FW ver %.4d\n", + buf[0], buf[1], buf[3], buf[4]); + + return 0; +} + +static int cy8ctma140_power_up(struct cy8ctma140 *ts) +{ + int error; + + error = regulator_bulk_enable(ARRAY_SIZE(ts->regulators), + ts->regulators); + if (error) { + dev_err(ts->dev, "failed to enable regulators\n"); + return error; + } + + msleep(250); + + return 0; +} + +static void cy8ctma140_power_down(struct cy8ctma140 *ts) +{ + regulator_bulk_disable(ARRAY_SIZE(ts->regulators), + ts->regulators); +} + +/* Called from the registered devm action */ +static void cy8ctma140_power_off_action(void *d) +{ + struct cy8ctma140 *ts = d; + + cy8ctma140_power_down(ts); +} + +static int cy8ctma140_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct cy8ctma140 *ts; + struct input_dev *input; + struct device *dev = &client->dev; + int error; + + ts = devm_kzalloc(dev, sizeof(*ts), GFP_KERNEL); + if (!ts) + return -ENOMEM; + + input = devm_input_allocate_device(dev); + if (!input) + return -ENOMEM; + + ts->dev = dev; + ts->client = client; + ts->input = input; + + input_set_capability(input, EV_ABS, ABS_MT_POSITION_X); + input_set_capability(input, EV_ABS, ABS_MT_POSITION_Y); + /* One byte for width 0..255 so this is the limit */ + input_set_abs_params(input, ABS_MT_TOUCH_MAJOR, 0, 255, 0, 0); + /* + * This sets up event max/min capabilities and fuzz. + * Some DT properties are compulsory so we do not need + * to provide defaults for X/Y max or pressure max. + * + * We just initialize a very simple MT touchscreen here, + * some devices use the capability of this touchscreen to + * provide touchkeys, and in that case this needs to be + * extended to handle touchkey input. + * + * The firmware takes care of finger tracking and dropping + * invalid ranges. + */ + touchscreen_parse_properties(input, true, &ts->props); + input_abs_set_fuzz(input, ABS_MT_POSITION_X, 0); + input_abs_set_fuzz(input, ABS_MT_POSITION_Y, 0); + + error = input_mt_init_slots(input, CY8CTMA140_MAX_FINGERS, + INPUT_MT_DIRECT | INPUT_MT_DROP_UNUSED); + if (error) + return error; + + input->name = CY8CTMA140_NAME; + input->id.bustype = BUS_I2C; + input_set_drvdata(input, ts); + + /* + * VCPIN is the analog voltage supply + * VDD is the digital voltage supply + * since the voltage range of VDD overlaps that of VCPIN, + * many designs to just supply both with a single voltage + * source of ~3.3 V. + */ + ts->regulators[0].supply = "vcpin"; + ts->regulators[1].supply = "vdd"; + error = devm_regulator_bulk_get(dev, ARRAY_SIZE(ts->regulators), + ts->regulators); + if (error) { + if (error != -EPROBE_DEFER) + dev_err(dev, "Failed to get regulators %d\n", + error); + return error; + } + + error = cy8ctma140_power_up(ts); + if (error) + return error; + + error = devm_add_action_or_reset(dev, cy8ctma140_power_off_action, ts); + if (error) { + dev_err(dev, "failed to install power off handler\n"); + return error; + } + + error = devm_request_threaded_irq(dev, client->irq, + NULL, cy8ctma140_irq_thread, + IRQF_ONESHOT, CY8CTMA140_NAME, ts); + if (error) { + dev_err(dev, "irq %d busy? error %d\n", client->irq, error); + return error; + } + + error = cy8ctma140_init(ts); + if (error) + return error; + + error = input_register_device(input); + if (error) + return error; + + i2c_set_clientdata(client, ts); + + return 0; +} + +static int __maybe_unused cy8ctma140_suspend(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct cy8ctma140 *ts = i2c_get_clientdata(client); + + if (!device_may_wakeup(&client->dev)) + cy8ctma140_power_down(ts); + + return 0; +} + +static int __maybe_unused cy8ctma140_resume(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct cy8ctma140 *ts = i2c_get_clientdata(client); + int error; + + if (!device_may_wakeup(&client->dev)) { + error = cy8ctma140_power_up(ts); + if (error) + return error; + } + + return 0; +} + +static SIMPLE_DEV_PM_OPS(cy8ctma140_pm, cy8ctma140_suspend, cy8ctma140_resume); + +static const struct i2c_device_id cy8ctma140_idtable[] = { + { CY8CTMA140_NAME, 0 }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(i2c, cy8ctma140_idtable); + +static const struct of_device_id cy8ctma140_of_match[] = { + { .compatible = "cypress,cy8ctma140", }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(of, cy8ctma140_of_match); + +static struct i2c_driver cy8ctma140_driver = { + .driver = { + .name = CY8CTMA140_NAME, + .pm = &cy8ctma140_pm, + .of_match_table = cy8ctma140_of_match, + }, + .id_table = cy8ctma140_idtable, + .probe = cy8ctma140_probe, +}; +module_i2c_driver(cy8ctma140_driver); + +MODULE_AUTHOR("Linus Walleij "); +MODULE_DESCRIPTION("CY8CTMA140 TouchScreen Driver"); +MODULE_LICENSE("GPL v2"); -- cgit v1.2.3 From 5fc70e350edd30fb22d2f9b4e6d680c5471890ff Mon Sep 17 00:00:00 2001 From: Jiada Wang Date: Mon, 11 May 2020 13:12:13 -0700 Subject: Input: introduce input_mt_report_slot_inactive() input_mt_report_slot_state() ignores "tool" argument when the slot is closed, which has caused a bit of confusion. Let's introduce input_mt_report_slot_inactive() to report inactive slot state. Suggested-by: Dmitry Torokhov Signed-off-by: Jiada Wang Link: https://lore.kernel.org/r/20200508055656.96389-2-jiada_wang@mentor.com Signed-off-by: Dmitry Torokhov --- drivers/hid/hid-alps.c | 3 +-- drivers/hid/hid-multitouch.c | 6 ++---- drivers/input/misc/xen-kbdfront.c | 2 +- drivers/input/mouse/elan_i2c_core.c | 2 +- drivers/input/touchscreen/atmel_mxt_ts.c | 7 +++---- drivers/input/touchscreen/cyttsp4_core.c | 5 ++--- drivers/input/touchscreen/cyttsp_core.c | 2 +- drivers/input/touchscreen/melfas_mip4.c | 4 ++-- drivers/input/touchscreen/mms114.c | 2 +- drivers/input/touchscreen/raspberrypi-ts.c | 2 +- drivers/input/touchscreen/stmfts.c | 2 +- include/linux/input/mt.h | 5 +++++ 12 files changed, 21 insertions(+), 21 deletions(-) (limited to 'drivers/input') diff --git a/drivers/hid/hid-alps.c b/drivers/hid/hid-alps.c index fa704153cb00..28588f74425e 100644 --- a/drivers/hid/hid-alps.c +++ b/drivers/hid/hid-alps.c @@ -387,8 +387,7 @@ static int u1_raw_event(struct alps_dev *hdata, u8 *data, int size) input_report_abs(hdata->input, ABS_MT_PRESSURE, z); } else { - input_mt_report_slot_state(hdata->input, - MT_TOOL_FINGER, 0); + input_mt_report_slot_inactive(hdata->input); } } diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c index 362805ddf377..e2ce790ff4a4 100644 --- a/drivers/hid/hid-multitouch.c +++ b/drivers/hid/hid-multitouch.c @@ -896,7 +896,7 @@ static void mt_release_pending_palms(struct mt_device *td, clear_bit(slotnum, app->pending_palm_slots); input_mt_slot(input, slotnum); - input_mt_report_slot_state(input, MT_TOOL_PALM, false); + input_mt_report_slot_inactive(input); need_sync = true; } @@ -1640,9 +1640,7 @@ static void mt_release_contacts(struct hid_device *hid) if (mt) { for (i = 0; i < mt->num_slots; i++) { input_mt_slot(input_dev, i); - input_mt_report_slot_state(input_dev, - MT_TOOL_FINGER, - false); + input_mt_report_slot_inactive(input_dev); } input_mt_sync_frame(input_dev); input_sync(input_dev); diff --git a/drivers/input/misc/xen-kbdfront.c b/drivers/input/misc/xen-kbdfront.c index 24bc5c5d876f..a1bba722b234 100644 --- a/drivers/input/misc/xen-kbdfront.c +++ b/drivers/input/misc/xen-kbdfront.c @@ -146,7 +146,7 @@ static void xenkbd_handle_mt_event(struct xenkbd_info *info, break; case XENKBD_MT_EV_UP: - input_mt_report_slot_state(info->mtouch, MT_TOOL_FINGER, false); + input_mt_report_slot_inactive(info->mtouch); break; case XENKBD_MT_EV_SYN: diff --git a/drivers/input/mouse/elan_i2c_core.c b/drivers/input/mouse/elan_i2c_core.c index 8719da540383..3f9354baac4b 100644 --- a/drivers/input/mouse/elan_i2c_core.c +++ b/drivers/input/mouse/elan_i2c_core.c @@ -938,7 +938,7 @@ static void elan_report_contact(struct elan_tp_data *data, input_report_abs(input, ABS_MT_TOUCH_MINOR, minor); } else { input_mt_slot(input, contact_num); - input_mt_report_slot_state(input, MT_TOOL_FINGER, false); + input_mt_report_slot_inactive(input); } } diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c index ae60442efda0..a2189739e30f 100644 --- a/drivers/input/touchscreen/atmel_mxt_ts.c +++ b/drivers/input/touchscreen/atmel_mxt_ts.c @@ -822,8 +822,7 @@ static void mxt_proc_t9_message(struct mxt_data *data, u8 *message) * have happened. */ if (status & MXT_T9_RELEASE) { - input_mt_report_slot_state(input_dev, - MT_TOOL_FINGER, 0); + input_mt_report_slot_inactive(input_dev); mxt_input_sync(data); } @@ -839,7 +838,7 @@ static void mxt_proc_t9_message(struct mxt_data *data, u8 *message) input_report_abs(input_dev, ABS_MT_TOUCH_MAJOR, area); } else { /* Touch no longer active, close out slot */ - input_mt_report_slot_state(input_dev, MT_TOOL_FINGER, 0); + input_mt_report_slot_inactive(input_dev); } data->update_input = true; @@ -947,7 +946,7 @@ static void mxt_proc_t100_message(struct mxt_data *data, u8 *message) dev_dbg(dev, "[%u] release\n", id); /* close out slot */ - input_mt_report_slot_state(input_dev, 0, 0); + input_mt_report_slot_inactive(input_dev); } data->update_input = true; diff --git a/drivers/input/touchscreen/cyttsp4_core.c b/drivers/input/touchscreen/cyttsp4_core.c index 6bcffc930384..02a73d9a4def 100644 --- a/drivers/input/touchscreen/cyttsp4_core.c +++ b/drivers/input/touchscreen/cyttsp4_core.c @@ -744,8 +744,7 @@ static void cyttsp4_report_slot_liftoff(struct cyttsp4_mt_data *md, for (t = 0; t < max_slots; t++) { input_mt_slot(md->input, t); - input_mt_report_slot_state(md->input, - MT_TOOL_FINGER, false); + input_mt_report_slot_inactive(md->input); } } @@ -845,7 +844,7 @@ static void cyttsp4_final_sync(struct input_dev *input, int max_slots, int *ids) if (ids[t]) continue; input_mt_slot(input, t); - input_mt_report_slot_state(input, MT_TOOL_FINGER, false); + input_mt_report_slot_inactive(input); } input_sync(input); diff --git a/drivers/input/touchscreen/cyttsp_core.c b/drivers/input/touchscreen/cyttsp_core.c index 3f5d463dbeed..697aa2c158f7 100644 --- a/drivers/input/touchscreen/cyttsp_core.c +++ b/drivers/input/touchscreen/cyttsp_core.c @@ -340,7 +340,7 @@ static void cyttsp_report_tchdata(struct cyttsp *ts) continue; input_mt_slot(input, i); - input_mt_report_slot_state(input, MT_TOOL_FINGER, false); + input_mt_report_slot_inactive(input); } input_sync(input); diff --git a/drivers/input/touchscreen/melfas_mip4.c b/drivers/input/touchscreen/melfas_mip4.c index 247c3aaba2d8..f67efdd040b2 100644 --- a/drivers/input/touchscreen/melfas_mip4.c +++ b/drivers/input/touchscreen/melfas_mip4.c @@ -391,7 +391,7 @@ static void mip4_clear_input(struct mip4_ts *ts) /* Screen */ for (i = 0; i < MIP4_MAX_FINGERS; i++) { input_mt_slot(ts->input, i); - input_mt_report_slot_state(ts->input, MT_TOOL_FINGER, 0); + input_mt_report_slot_inactive(ts->input); } /* Keys */ @@ -534,7 +534,7 @@ static void mip4_report_touch(struct mip4_ts *ts, u8 *packet) } else { /* Release event */ input_mt_slot(ts->input, id); - input_mt_report_slot_state(ts->input, MT_TOOL_FINGER, 0); + input_mt_report_slot_inactive(ts->input); } input_mt_sync_frame(ts->input); diff --git a/drivers/input/touchscreen/mms114.c b/drivers/input/touchscreen/mms114.c index b3dda1722bae..d5e2d2a139a2 100644 --- a/drivers/input/touchscreen/mms114.c +++ b/drivers/input/touchscreen/mms114.c @@ -559,7 +559,7 @@ static int __maybe_unused mms114_suspend(struct device *dev) /* Release all touch */ for (id = 0; id < MMS114_MAX_TOUCH; id++) { input_mt_slot(input_dev, id); - input_mt_report_slot_state(input_dev, MT_TOOL_FINGER, false); + input_mt_report_slot_inactive(input_dev); } input_mt_report_pointer_emulation(input_dev, true); diff --git a/drivers/input/touchscreen/raspberrypi-ts.c b/drivers/input/touchscreen/raspberrypi-ts.c index 0e2e08f3f433..ef6aaed217cf 100644 --- a/drivers/input/touchscreen/raspberrypi-ts.c +++ b/drivers/input/touchscreen/raspberrypi-ts.c @@ -100,7 +100,7 @@ static void rpi_ts_poll(struct input_dev *input) released_ids = ts->known_ids & ~modified_ids; for_each_set_bit(i, &released_ids, RPI_TS_MAX_SUPPORTED_POINTS) { input_mt_slot(input, i); - input_mt_report_slot_state(input, MT_TOOL_FINGER, 0); + input_mt_report_slot_inactive(input); modified_ids &= ~(BIT(i)); } ts->known_ids = modified_ids; diff --git a/drivers/input/touchscreen/stmfts.c b/drivers/input/touchscreen/stmfts.c index b6f95f20f924..b54cc64e4ea6 100644 --- a/drivers/input/touchscreen/stmfts.c +++ b/drivers/input/touchscreen/stmfts.c @@ -198,7 +198,7 @@ static void stmfts_report_contact_release(struct stmfts_data *sdata, u8 slot_id = (event[0] & STMFTS_MASK_TOUCH_ID) >> 4; input_mt_slot(sdata->input, slot_id); - input_mt_report_slot_state(sdata->input, MT_TOOL_FINGER, false); + input_mt_report_slot_inactive(sdata->input); input_sync(sdata->input); } diff --git a/include/linux/input/mt.h b/include/linux/input/mt.h index 9e409bb13642..3b8580bd33c1 100644 --- a/include/linux/input/mt.h +++ b/include/linux/input/mt.h @@ -100,6 +100,11 @@ static inline bool input_is_mt_axis(int axis) bool input_mt_report_slot_state(struct input_dev *dev, unsigned int tool_type, bool active); +static inline void input_mt_report_slot_inactive(struct input_dev *dev) +{ + input_mt_report_slot_state(dev, 0, false); +} + void input_mt_report_finger_count(struct input_dev *dev, int count); void input_mt_report_pointer_emulation(struct input_dev *dev, bool use_count); void input_mt_drop_unused(struct input_dev *dev); -- cgit v1.2.3 From cf520c64301204afa8272a94cc2e1495a425446a Mon Sep 17 00:00:00 2001 From: Johnny Chuang Date: Tue, 12 May 2020 14:44:39 -0700 Subject: Input: elants_i2c - provide an attribute to show calibration count There is an non-touch case by non-calibration after update firmware. Elan could know calibrate or not by calibration count. The value of '0xffff' means we didn't calibrate after update firmware. If calibrate success, it will plus one and change to '0x0000'. Signed-off-by: Johnny Chuang Link: https://lore.kernel.org/r/1588754932-5902-1-git-send-email-johnny.chuang.emc@gmail.com Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/elants_i2c.c | 28 +++++++++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) (limited to 'drivers/input') diff --git a/drivers/input/touchscreen/elants_i2c.c b/drivers/input/touchscreen/elants_i2c.c index 14c577c16b16..6e962b54fea3 100644 --- a/drivers/input/touchscreen/elants_i2c.c +++ b/drivers/input/touchscreen/elants_i2c.c @@ -87,6 +87,7 @@ /* FW read command, 0x53 0x?? 0x0, 0x01 */ #define E_ELAN_INFO_FW_VER 0x00 #define E_ELAN_INFO_BC_VER 0x10 +#define E_ELAN_INFO_REK 0xE0 #define E_ELAN_INFO_TEST_VER 0xE0 #define E_ELAN_INFO_FW_ID 0xF0 #define E_INFO_OSR 0xD6 @@ -1010,7 +1011,7 @@ out: */ static ssize_t calibrate_store(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) + const char *buf, size_t count) { struct i2c_client *client = to_i2c_client(dev); struct elants_data *ts = i2c_get_clientdata(client); @@ -1056,8 +1057,32 @@ static ssize_t show_iap_mode(struct device *dev, "Normal" : "Recovery"); } +static ssize_t show_calibration_count(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct i2c_client *client = to_i2c_client(dev); + const u8 cmd[] = { CMD_HEADER_READ, E_ELAN_INFO_REK, 0x00, 0x01 }; + u8 resp[HEADER_SIZE]; + u16 rek_count; + int error; + + error = elants_i2c_execute_command(client, cmd, sizeof(cmd), + resp, sizeof(resp)); + if (error) { + dev_err(&client->dev, + "read ReK status error=%d, buf=%*phC\n", + error, (int)sizeof(resp), resp); + return sprintf(buf, "%d\n", error); + } + + rek_count = get_unaligned_be16(&resp[2]); + + return sprintf(buf, "0x%04x\n", rek_count); +} + static DEVICE_ATTR_WO(calibrate); static DEVICE_ATTR(iap_mode, S_IRUGO, show_iap_mode, NULL); +static DEVICE_ATTR(calibration_count, S_IRUGO, show_calibration_count, NULL); static DEVICE_ATTR(update_fw, S_IWUSR, NULL, write_update_fw); struct elants_version_attribute { @@ -1113,6 +1138,7 @@ static struct attribute *elants_attributes[] = { &dev_attr_calibrate.attr, &dev_attr_update_fw.attr, &dev_attr_iap_mode.attr, + &dev_attr_calibration_count.attr, &elants_ver_attr_fw_version.dattr.attr, &elants_ver_attr_hw_version.dattr.attr, -- cgit v1.2.3 From 2ecf9487a7c86e033bab007d63d61f2ec2ca093f Mon Sep 17 00:00:00 2001 From: Brian Masney Date: Tue, 12 May 2020 20:03:31 -0700 Subject: Input: remove msm-vibrator driver The address referenced by this driver is within the Qualcomm Clock namespace so let's drop the msm-vibrator bindings so that a more generic solution can be used instead. No one is currently using driver so this won't affect any users. Signed-off-by: Brian Masney Link: https://lore.kernel.org/r/20200513013140.69935-3-masneyb@onstation.org Signed-off-by: Dmitry Torokhov --- drivers/input/misc/Kconfig | 10 -- drivers/input/misc/Makefile | 1 - drivers/input/misc/msm-vibrator.c | 281 -------------------------------------- 3 files changed, 292 deletions(-) delete mode 100644 drivers/input/misc/msm-vibrator.c (limited to 'drivers/input') diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig index 293e55fb7a4e..315b14d59ad7 100644 --- a/drivers/input/misc/Kconfig +++ b/drivers/input/misc/Kconfig @@ -117,16 +117,6 @@ config INPUT_E3X0_BUTTON To compile this driver as a module, choose M here: the module will be called e3x0_button. -config INPUT_MSM_VIBRATOR - tristate "Qualcomm MSM vibrator driver" - select INPUT_FF_MEMLESS - help - Support for the vibrator that is found on various Qualcomm MSM - SOCs. - - To compile this driver as a module, choose M here: the module - will be called msm_vibrator. - config INPUT_PCSPKR tristate "PC Speaker support" depends on PCSPKR_PLATFORM diff --git a/drivers/input/misc/Makefile b/drivers/input/misc/Makefile index 1db1815ce803..546766f29aca 100644 --- a/drivers/input/misc/Makefile +++ b/drivers/input/misc/Makefile @@ -49,7 +49,6 @@ obj-$(CONFIG_INPUT_MAX8925_ONKEY) += max8925_onkey.o obj-$(CONFIG_INPUT_MAX8997_HAPTIC) += max8997_haptic.o obj-$(CONFIG_INPUT_MC13783_PWRBUTTON) += mc13783-pwrbutton.o obj-$(CONFIG_INPUT_MMA8450) += mma8450.o -obj-$(CONFIG_INPUT_MSM_VIBRATOR) += msm-vibrator.o obj-$(CONFIG_INPUT_PALMAS_PWRBUTTON) += palmas-pwrbutton.o obj-$(CONFIG_INPUT_PCAP) += pcap_keys.o obj-$(CONFIG_INPUT_PCF50633_PMU) += pcf50633-input.o diff --git a/drivers/input/misc/msm-vibrator.c b/drivers/input/misc/msm-vibrator.c deleted file mode 100644 index b60f1aaee705..000000000000 --- a/drivers/input/misc/msm-vibrator.c +++ /dev/null @@ -1,281 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0+ -/* - * Qualcomm MSM vibrator driver - * - * Copyright (c) 2018 Brian Masney - * - * Based on qcom,pwm-vibrator.c from: - * Copyright (c) 2018 Jonathan Marek - * - * Based on msm_pwm_vibrator.c from downstream Android sources: - * Copyright (C) 2009-2014 LGE, Inc. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define REG_CMD_RCGR 0x00 -#define REG_CFG_RCGR 0x04 -#define REG_M 0x08 -#define REG_N 0x0C -#define REG_D 0x10 -#define REG_CBCR 0x24 -#define MMSS_CC_M_DEFAULT 1 - -struct msm_vibrator { - struct input_dev *input; - struct mutex mutex; - struct work_struct worker; - void __iomem *base; - struct regulator *vcc; - struct clk *clk; - struct gpio_desc *enable_gpio; - u16 magnitude; - bool enabled; -}; - -static void msm_vibrator_write(struct msm_vibrator *vibrator, int offset, - u32 value) -{ - writel(value, vibrator->base + offset); -} - -static int msm_vibrator_start(struct msm_vibrator *vibrator) -{ - int d_reg_val, ret = 0; - - mutex_lock(&vibrator->mutex); - - if (!vibrator->enabled) { - ret = clk_set_rate(vibrator->clk, 24000); - if (ret) { - dev_err(&vibrator->input->dev, - "Failed to set clock rate: %d\n", ret); - goto unlock; - } - - ret = clk_prepare_enable(vibrator->clk); - if (ret) { - dev_err(&vibrator->input->dev, - "Failed to enable clock: %d\n", ret); - goto unlock; - } - - ret = regulator_enable(vibrator->vcc); - if (ret) { - dev_err(&vibrator->input->dev, - "Failed to enable regulator: %d\n", ret); - clk_disable(vibrator->clk); - goto unlock; - } - - gpiod_set_value_cansleep(vibrator->enable_gpio, 1); - - vibrator->enabled = true; - } - - d_reg_val = 127 - ((126 * vibrator->magnitude) / 0xffff); - msm_vibrator_write(vibrator, REG_CFG_RCGR, - (2 << 12) | /* dual edge mode */ - (0 << 8) | /* cxo */ - (7 << 0)); - msm_vibrator_write(vibrator, REG_M, 1); - msm_vibrator_write(vibrator, REG_N, 128); - msm_vibrator_write(vibrator, REG_D, d_reg_val); - msm_vibrator_write(vibrator, REG_CMD_RCGR, 1); - msm_vibrator_write(vibrator, REG_CBCR, 1); - -unlock: - mutex_unlock(&vibrator->mutex); - - return ret; -} - -static void msm_vibrator_stop(struct msm_vibrator *vibrator) -{ - mutex_lock(&vibrator->mutex); - - if (vibrator->enabled) { - gpiod_set_value_cansleep(vibrator->enable_gpio, 0); - regulator_disable(vibrator->vcc); - clk_disable(vibrator->clk); - vibrator->enabled = false; - } - - mutex_unlock(&vibrator->mutex); -} - -static void msm_vibrator_worker(struct work_struct *work) -{ - struct msm_vibrator *vibrator = container_of(work, - struct msm_vibrator, - worker); - - if (vibrator->magnitude) - msm_vibrator_start(vibrator); - else - msm_vibrator_stop(vibrator); -} - -static int msm_vibrator_play_effect(struct input_dev *dev, void *data, - struct ff_effect *effect) -{ - struct msm_vibrator *vibrator = input_get_drvdata(dev); - - mutex_lock(&vibrator->mutex); - - if (effect->u.rumble.strong_magnitude > 0) - vibrator->magnitude = effect->u.rumble.strong_magnitude; - else - vibrator->magnitude = effect->u.rumble.weak_magnitude; - - mutex_unlock(&vibrator->mutex); - - schedule_work(&vibrator->worker); - - return 0; -} - -static void msm_vibrator_close(struct input_dev *input) -{ - struct msm_vibrator *vibrator = input_get_drvdata(input); - - cancel_work_sync(&vibrator->worker); - msm_vibrator_stop(vibrator); -} - -static int msm_vibrator_probe(struct platform_device *pdev) -{ - struct msm_vibrator *vibrator; - struct resource *res; - int ret; - - vibrator = devm_kzalloc(&pdev->dev, sizeof(*vibrator), GFP_KERNEL); - if (!vibrator) - return -ENOMEM; - - vibrator->input = devm_input_allocate_device(&pdev->dev); - if (!vibrator->input) - return -ENOMEM; - - vibrator->vcc = devm_regulator_get(&pdev->dev, "vcc"); - if (IS_ERR(vibrator->vcc)) { - if (PTR_ERR(vibrator->vcc) != -EPROBE_DEFER) - dev_err(&pdev->dev, "Failed to get regulator: %ld\n", - PTR_ERR(vibrator->vcc)); - return PTR_ERR(vibrator->vcc); - } - - vibrator->enable_gpio = devm_gpiod_get(&pdev->dev, "enable", - GPIOD_OUT_LOW); - if (IS_ERR(vibrator->enable_gpio)) { - if (PTR_ERR(vibrator->enable_gpio) != -EPROBE_DEFER) - dev_err(&pdev->dev, "Failed to get enable gpio: %ld\n", - PTR_ERR(vibrator->enable_gpio)); - return PTR_ERR(vibrator->enable_gpio); - } - - vibrator->clk = devm_clk_get(&pdev->dev, "pwm"); - if (IS_ERR(vibrator->clk)) { - if (PTR_ERR(vibrator->clk) != -EPROBE_DEFER) - dev_err(&pdev->dev, "Failed to lookup pwm clock: %ld\n", - PTR_ERR(vibrator->clk)); - return PTR_ERR(vibrator->clk); - } - - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!res) { - dev_err(&pdev->dev, "Failed to get platform resource\n"); - return -ENODEV; - } - - vibrator->base = devm_ioremap(&pdev->dev, res->start, - resource_size(res)); - if (!vibrator->base) { - dev_err(&pdev->dev, "Failed to iomap resource.\n"); - return -ENOMEM; - } - - vibrator->enabled = false; - mutex_init(&vibrator->mutex); - INIT_WORK(&vibrator->worker, msm_vibrator_worker); - - vibrator->input->name = "msm-vibrator"; - vibrator->input->id.bustype = BUS_HOST; - vibrator->input->close = msm_vibrator_close; - - input_set_drvdata(vibrator->input, vibrator); - input_set_capability(vibrator->input, EV_FF, FF_RUMBLE); - - ret = input_ff_create_memless(vibrator->input, NULL, - msm_vibrator_play_effect); - if (ret) { - dev_err(&pdev->dev, "Failed to create ff memless: %d", ret); - return ret; - } - - ret = input_register_device(vibrator->input); - if (ret) { - dev_err(&pdev->dev, "Failed to register input device: %d", ret); - return ret; - } - - platform_set_drvdata(pdev, vibrator); - - return 0; -} - -static int __maybe_unused msm_vibrator_suspend(struct device *dev) -{ - struct platform_device *pdev = to_platform_device(dev); - struct msm_vibrator *vibrator = platform_get_drvdata(pdev); - - cancel_work_sync(&vibrator->worker); - - if (vibrator->enabled) - msm_vibrator_stop(vibrator); - - return 0; -} - -static int __maybe_unused msm_vibrator_resume(struct device *dev) -{ - struct platform_device *pdev = to_platform_device(dev); - struct msm_vibrator *vibrator = platform_get_drvdata(pdev); - - if (vibrator->enabled) - msm_vibrator_start(vibrator); - - return 0; -} - -static SIMPLE_DEV_PM_OPS(msm_vibrator_pm_ops, msm_vibrator_suspend, - msm_vibrator_resume); - -static const struct of_device_id msm_vibrator_of_match[] = { - { .compatible = "qcom,msm8226-vibrator" }, - { .compatible = "qcom,msm8974-vibrator" }, - {}, -}; -MODULE_DEVICE_TABLE(of, msm_vibrator_of_match); - -static struct platform_driver msm_vibrator_driver = { - .probe = msm_vibrator_probe, - .driver = { - .name = "msm-vibrator", - .pm = &msm_vibrator_pm_ops, - .of_match_table = of_match_ptr(msm_vibrator_of_match), - }, -}; -module_platform_driver(msm_vibrator_driver); - -MODULE_AUTHOR("Brian Masney "); -MODULE_DESCRIPTION("Qualcomm MSM vibrator driver"); -MODULE_LICENSE("GPL"); -- cgit v1.2.3 From 768062fd1284529212daffd360314e9aa93abb62 Mon Sep 17 00:00:00 2001 From: Anson Huang Date: Wed, 13 May 2020 10:15:49 -0700 Subject: Input: imx_sc_key - use devm_add_action_or_reset() to handle all cleanups Use devm_add_action_or_reset() to handle all cleanups of failure in .probe and .remove, then .remove callback can be dropped. Signed-off-by: Anson Huang Link: https://lore.kernel.org/r/1584082751-17047-1-git-send-email-Anson.Huang@nxp.com Signed-off-by: Dmitry Torokhov --- drivers/input/keyboard/imx_sc_key.c | 33 +++++++++++++++------------------ 1 file changed, 15 insertions(+), 18 deletions(-) (limited to 'drivers/input') diff --git a/drivers/input/keyboard/imx_sc_key.c b/drivers/input/keyboard/imx_sc_key.c index 9f809aeb785c..d18839f1f4f6 100644 --- a/drivers/input/keyboard/imx_sc_key.c +++ b/drivers/input/keyboard/imx_sc_key.c @@ -99,6 +99,15 @@ static void imx_sc_check_for_events(struct work_struct *work) msecs_to_jiffies(REPEAT_INTERVAL)); } +static void imx_sc_key_action(void *data) +{ + struct imx_key_drv_data *priv = data; + + imx_scu_irq_group_enable(SC_IRQ_GROUP_WAKE, SC_IRQ_BUTTON, false); + imx_scu_irq_unregister_notifier(&priv->key_notifier); + cancel_delayed_work_sync(&priv->check_work); +} + static int imx_sc_key_probe(struct platform_device *pdev) { struct imx_key_drv_data *priv; @@ -149,27 +158,16 @@ static int imx_sc_key_probe(struct platform_device *pdev) return error; } + error = devm_add_action_or_reset(&pdev->dev, imx_sc_key_action, &priv); + if (error) + return error; + priv->key_notifier.notifier_call = imx_sc_key_notify; error = imx_scu_irq_register_notifier(&priv->key_notifier); - if (error) { - imx_scu_irq_group_enable(SC_IRQ_GROUP_WAKE, SC_IRQ_BUTTON, - false); + if (error) dev_err(&pdev->dev, "failed to register scu notifier\n"); - return error; - } - - return 0; -} - -static int imx_sc_key_remove(struct platform_device *pdev) -{ - struct imx_key_drv_data *priv = platform_get_drvdata(pdev); - - imx_scu_irq_group_enable(SC_IRQ_GROUP_WAKE, SC_IRQ_BUTTON, false); - imx_scu_irq_unregister_notifier(&priv->key_notifier); - cancel_delayed_work_sync(&priv->check_work); - return 0; + return error; } static const struct of_device_id imx_sc_key_ids[] = { @@ -184,7 +182,6 @@ static struct platform_driver imx_sc_key_driver = { .of_match_table = imx_sc_key_ids, }, .probe = imx_sc_key_probe, - .remove = imx_sc_key_remove, }; module_platform_driver(imx_sc_key_driver); -- cgit v1.2.3 From 04e49867fad1f4a0739862bb15133f96ace1d190 Mon Sep 17 00:00:00 2001 From: Jeff LaBundy Date: Sun, 17 May 2020 17:42:22 -0700 Subject: Input: add support for Azoteq IQS269A This patch adds support for the Azoteq IQS269A capacitive touch controller. Signed-off-by: Jeff LaBundy Link: https://lore.kernel.org/r/1588352982-5117-2-git-send-email-jeff@labundy.com Signed-off-by: Dmitry Torokhov --- drivers/input/misc/Kconfig | 10 + drivers/input/misc/Makefile | 1 + drivers/input/misc/iqs269a.c | 1833 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 1844 insertions(+) create mode 100644 drivers/input/misc/iqs269a.c (limited to 'drivers/input') diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig index 315b14d59ad7..943cf69b5b73 100644 --- a/drivers/input/misc/Kconfig +++ b/drivers/input/misc/Kconfig @@ -718,6 +718,16 @@ config INPUT_IMS_PCU To compile this driver as a module, choose M here: the module will be called ims_pcu. +config INPUT_IQS269A + tristate "Azoteq IQS269A capacitive touch controller" + select REGMAP_I2C + help + Say Y to enable support for the Azoteq IQS269A capacitive + touch controller. + + To compile this driver as a module, choose M here: the + module will be called iqs269a. + config INPUT_CMA3000 tristate "VTI CMA3000 Tri-axis accelerometer" help diff --git a/drivers/input/misc/Makefile b/drivers/input/misc/Makefile index 546766f29aca..a48e5f2d859d 100644 --- a/drivers/input/misc/Makefile +++ b/drivers/input/misc/Makefile @@ -39,6 +39,7 @@ obj-$(CONFIG_INPUT_GPIO_VIBRA) += gpio-vibra.o obj-$(CONFIG_INPUT_HISI_POWERKEY) += hisi_powerkey.o obj-$(CONFIG_HP_SDC_RTC) += hp_sdc_rtc.o obj-$(CONFIG_INPUT_IMS_PCU) += ims-pcu.o +obj-$(CONFIG_INPUT_IQS269A) += iqs269a.o obj-$(CONFIG_INPUT_IXP4XX_BEEPER) += ixp4xx-beeper.o obj-$(CONFIG_INPUT_KEYSPAN_REMOTE) += keyspan_remote.o obj-$(CONFIG_INPUT_KXTJ9) += kxtj9.o diff --git a/drivers/input/misc/iqs269a.c b/drivers/input/misc/iqs269a.c new file mode 100644 index 000000000000..6699eb160a0f --- /dev/null +++ b/drivers/input/misc/iqs269a.c @@ -0,0 +1,1833 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Azoteq IQS269A Capacitive Touch Controller + * + * Copyright (C) 2020 Jeff LaBundy + * + * This driver registers up to 3 input devices: one representing capacitive or + * inductive keys as well as Hall-effect switches, and one for each of the two + * axial sliders presented by the device. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define IQS269_VER_INFO 0x00 +#define IQS269_VER_INFO_PROD_NUM 0x4F + +#define IQS269_SYS_FLAGS 0x02 +#define IQS269_SYS_FLAGS_SHOW_RESET BIT(15) +#define IQS269_SYS_FLAGS_PWR_MODE_MASK GENMASK(12, 11) +#define IQS269_SYS_FLAGS_PWR_MODE_SHIFT 11 +#define IQS269_SYS_FLAGS_IN_ATI BIT(10) + +#define IQS269_CHx_COUNTS 0x08 + +#define IQS269_SLIDER_X 0x30 + +#define IQS269_CAL_DATA_A 0x35 +#define IQS269_CAL_DATA_A_HALL_BIN_L_MASK GENMASK(15, 12) +#define IQS269_CAL_DATA_A_HALL_BIN_L_SHIFT 12 +#define IQS269_CAL_DATA_A_HALL_BIN_R_MASK GENMASK(11, 8) +#define IQS269_CAL_DATA_A_HALL_BIN_R_SHIFT 8 + +#define IQS269_SYS_SETTINGS 0x80 +#define IQS269_SYS_SETTINGS_CLK_DIV BIT(15) +#define IQS269_SYS_SETTINGS_ULP_AUTO BIT(14) +#define IQS269_SYS_SETTINGS_DIS_AUTO BIT(13) +#define IQS269_SYS_SETTINGS_PWR_MODE_MASK GENMASK(12, 11) +#define IQS269_SYS_SETTINGS_PWR_MODE_SHIFT 11 +#define IQS269_SYS_SETTINGS_PWR_MODE_MAX 3 +#define IQS269_SYS_SETTINGS_ULP_UPDATE_MASK GENMASK(10, 8) +#define IQS269_SYS_SETTINGS_ULP_UPDATE_SHIFT 8 +#define IQS269_SYS_SETTINGS_ULP_UPDATE_MAX 7 +#define IQS269_SYS_SETTINGS_RESEED_OFFSET BIT(6) +#define IQS269_SYS_SETTINGS_EVENT_MODE BIT(5) +#define IQS269_SYS_SETTINGS_EVENT_MODE_LP BIT(4) +#define IQS269_SYS_SETTINGS_REDO_ATI BIT(2) +#define IQS269_SYS_SETTINGS_ACK_RESET BIT(0) + +#define IQS269_FILT_STR_LP_LTA_MASK GENMASK(7, 6) +#define IQS269_FILT_STR_LP_LTA_SHIFT 6 +#define IQS269_FILT_STR_LP_CNT_MASK GENMASK(5, 4) +#define IQS269_FILT_STR_LP_CNT_SHIFT 4 +#define IQS269_FILT_STR_NP_LTA_MASK GENMASK(3, 2) +#define IQS269_FILT_STR_NP_LTA_SHIFT 2 +#define IQS269_FILT_STR_NP_CNT_MASK GENMASK(1, 0) +#define IQS269_FILT_STR_MAX 3 + +#define IQS269_EVENT_MASK_SYS BIT(6) +#define IQS269_EVENT_MASK_DEEP BIT(2) +#define IQS269_EVENT_MASK_TOUCH BIT(1) +#define IQS269_EVENT_MASK_PROX BIT(0) + +#define IQS269_RATE_NP_MS_MAX 255 +#define IQS269_RATE_LP_MS_MAX 255 +#define IQS269_RATE_ULP_MS_MAX 4080 +#define IQS269_TIMEOUT_PWR_MS_MAX 130560 +#define IQS269_TIMEOUT_LTA_MS_MAX 130560 + +#define IQS269_MISC_A_ATI_BAND_DISABLE BIT(15) +#define IQS269_MISC_A_ATI_LP_ONLY BIT(14) +#define IQS269_MISC_A_ATI_BAND_TIGHTEN BIT(13) +#define IQS269_MISC_A_FILT_DISABLE BIT(12) +#define IQS269_MISC_A_GPIO3_SELECT_MASK GENMASK(10, 8) +#define IQS269_MISC_A_GPIO3_SELECT_SHIFT 8 +#define IQS269_MISC_A_DUAL_DIR BIT(6) +#define IQS269_MISC_A_TX_FREQ_MASK GENMASK(5, 4) +#define IQS269_MISC_A_TX_FREQ_SHIFT 4 +#define IQS269_MISC_A_TX_FREQ_MAX 3 +#define IQS269_MISC_A_GLOBAL_CAP_SIZE BIT(0) + +#define IQS269_MISC_B_RESEED_UI_SEL_MASK GENMASK(7, 6) +#define IQS269_MISC_B_RESEED_UI_SEL_SHIFT 6 +#define IQS269_MISC_B_RESEED_UI_SEL_MAX 3 +#define IQS269_MISC_B_TRACKING_UI_ENABLE BIT(4) +#define IQS269_MISC_B_FILT_STR_SLIDER GENMASK(1, 0) + +#define IQS269_CHx_SETTINGS 0x8C + +#define IQS269_CHx_ENG_A_MEAS_CAP_SIZE BIT(15) +#define IQS269_CHx_ENG_A_RX_GND_INACTIVE BIT(13) +#define IQS269_CHx_ENG_A_LOCAL_CAP_SIZE BIT(12) +#define IQS269_CHx_ENG_A_ATI_MODE_MASK GENMASK(9, 8) +#define IQS269_CHx_ENG_A_ATI_MODE_SHIFT 8 +#define IQS269_CHx_ENG_A_ATI_MODE_MAX 3 +#define IQS269_CHx_ENG_A_INV_LOGIC BIT(7) +#define IQS269_CHx_ENG_A_PROJ_BIAS_MASK GENMASK(6, 5) +#define IQS269_CHx_ENG_A_PROJ_BIAS_SHIFT 5 +#define IQS269_CHx_ENG_A_PROJ_BIAS_MAX 3 +#define IQS269_CHx_ENG_A_SENSE_MODE_MASK GENMASK(3, 0) +#define IQS269_CHx_ENG_A_SENSE_MODE_MAX 15 + +#define IQS269_CHx_ENG_B_LOCAL_CAP_ENABLE BIT(13) +#define IQS269_CHx_ENG_B_SENSE_FREQ_MASK GENMASK(10, 9) +#define IQS269_CHx_ENG_B_SENSE_FREQ_SHIFT 9 +#define IQS269_CHx_ENG_B_SENSE_FREQ_MAX 3 +#define IQS269_CHx_ENG_B_STATIC_ENABLE BIT(8) +#define IQS269_CHx_ENG_B_ATI_BASE_MASK GENMASK(7, 6) +#define IQS269_CHx_ENG_B_ATI_BASE_75 0x00 +#define IQS269_CHx_ENG_B_ATI_BASE_100 0x40 +#define IQS269_CHx_ENG_B_ATI_BASE_150 0x80 +#define IQS269_CHx_ENG_B_ATI_BASE_200 0xC0 +#define IQS269_CHx_ENG_B_ATI_TARGET_MASK GENMASK(5, 0) +#define IQS269_CHx_ENG_B_ATI_TARGET_MAX 2016 + +#define IQS269_CHx_WEIGHT_MAX 255 +#define IQS269_CHx_THRESH_MAX 255 +#define IQS269_CHx_HYST_DEEP_MASK GENMASK(7, 4) +#define IQS269_CHx_HYST_DEEP_SHIFT 4 +#define IQS269_CHx_HYST_TOUCH_MASK GENMASK(3, 0) +#define IQS269_CHx_HYST_MAX 15 + +#define IQS269_CHx_HALL_INACTIVE 6 +#define IQS269_CHx_HALL_ACTIVE 7 + +#define IQS269_HALL_PAD_R BIT(0) +#define IQS269_HALL_PAD_L BIT(1) +#define IQS269_HALL_PAD_INV BIT(6) + +#define IQS269_HALL_UI 0xF5 +#define IQS269_HALL_UI_ENABLE BIT(15) + +#define IQS269_MAX_REG 0xFF + +#define IQS269_NUM_CH 8 +#define IQS269_NUM_SL 2 + +#define IQS269_ATI_POLL_SLEEP_US (iqs269->delay_mult * 10000) +#define IQS269_ATI_POLL_TIMEOUT_US (iqs269->delay_mult * 500000) +#define IQS269_ATI_STABLE_DELAY_MS (iqs269->delay_mult * 150) + +#define IQS269_PWR_MODE_POLL_SLEEP_US IQS269_ATI_POLL_SLEEP_US +#define IQS269_PWR_MODE_POLL_TIMEOUT_US IQS269_ATI_POLL_TIMEOUT_US + +#define iqs269_irq_wait() usleep_range(100, 150) + +enum iqs269_local_cap_size { + IQS269_LOCAL_CAP_SIZE_0, + IQS269_LOCAL_CAP_SIZE_GLOBAL_ONLY, + IQS269_LOCAL_CAP_SIZE_GLOBAL_0pF5, +}; + +enum iqs269_st_offs { + IQS269_ST_OFFS_PROX, + IQS269_ST_OFFS_DIR, + IQS269_ST_OFFS_TOUCH, + IQS269_ST_OFFS_DEEP, +}; + +enum iqs269_th_offs { + IQS269_TH_OFFS_PROX, + IQS269_TH_OFFS_TOUCH, + IQS269_TH_OFFS_DEEP, +}; + +enum iqs269_event_id { + IQS269_EVENT_PROX_DN, + IQS269_EVENT_PROX_UP, + IQS269_EVENT_TOUCH_DN, + IQS269_EVENT_TOUCH_UP, + IQS269_EVENT_DEEP_DN, + IQS269_EVENT_DEEP_UP, +}; + +struct iqs269_switch_desc { + unsigned int code; + bool enabled; +}; + +struct iqs269_event_desc { + const char *name; + enum iqs269_st_offs st_offs; + enum iqs269_th_offs th_offs; + bool dir_up; + u8 mask; +}; + +static const struct iqs269_event_desc iqs269_events[] = { + [IQS269_EVENT_PROX_DN] = { + .name = "event-prox", + .st_offs = IQS269_ST_OFFS_PROX, + .th_offs = IQS269_TH_OFFS_PROX, + .mask = IQS269_EVENT_MASK_PROX, + }, + [IQS269_EVENT_PROX_UP] = { + .name = "event-prox-alt", + .st_offs = IQS269_ST_OFFS_PROX, + .th_offs = IQS269_TH_OFFS_PROX, + .dir_up = true, + .mask = IQS269_EVENT_MASK_PROX, + }, + [IQS269_EVENT_TOUCH_DN] = { + .name = "event-touch", + .st_offs = IQS269_ST_OFFS_TOUCH, + .th_offs = IQS269_TH_OFFS_TOUCH, + .mask = IQS269_EVENT_MASK_TOUCH, + }, + [IQS269_EVENT_TOUCH_UP] = { + .name = "event-touch-alt", + .st_offs = IQS269_ST_OFFS_TOUCH, + .th_offs = IQS269_TH_OFFS_TOUCH, + .dir_up = true, + .mask = IQS269_EVENT_MASK_TOUCH, + }, + [IQS269_EVENT_DEEP_DN] = { + .name = "event-deep", + .st_offs = IQS269_ST_OFFS_DEEP, + .th_offs = IQS269_TH_OFFS_DEEP, + .mask = IQS269_EVENT_MASK_DEEP, + }, + [IQS269_EVENT_DEEP_UP] = { + .name = "event-deep-alt", + .st_offs = IQS269_ST_OFFS_DEEP, + .th_offs = IQS269_TH_OFFS_DEEP, + .dir_up = true, + .mask = IQS269_EVENT_MASK_DEEP, + }, +}; + +struct iqs269_ver_info { + u8 prod_num; + u8 sw_num; + u8 hw_num; + u8 padding; +} __packed; + +struct iqs269_sys_reg { + __be16 general; + u8 active; + u8 filter; + u8 reseed; + u8 event_mask; + u8 rate_np; + u8 rate_lp; + u8 rate_ulp; + u8 timeout_pwr; + u8 timeout_rdy; + u8 timeout_lta; + __be16 misc_a; + __be16 misc_b; + u8 blocking; + u8 padding; + u8 slider_select[IQS269_NUM_SL]; + u8 timeout_tap; + u8 timeout_swipe; + u8 thresh_swipe; + u8 redo_ati; +} __packed; + +struct iqs269_ch_reg { + u8 rx_enable; + u8 tx_enable; + __be16 engine_a; + __be16 engine_b; + __be16 ati_comp; + u8 thresh[3]; + u8 hyst; + u8 assoc_select; + u8 assoc_weight; +} __packed; + +struct iqs269_flags { + __be16 system; + u8 gesture; + u8 padding; + u8 states[4]; +} __packed; + +struct iqs269_private { + struct i2c_client *client; + struct regmap *regmap; + struct mutex lock; + struct iqs269_switch_desc switches[ARRAY_SIZE(iqs269_events)]; + struct iqs269_ch_reg ch_reg[IQS269_NUM_CH]; + struct iqs269_sys_reg sys_reg; + struct input_dev *keypad; + struct input_dev *slider[IQS269_NUM_SL]; + unsigned int keycode[ARRAY_SIZE(iqs269_events) * IQS269_NUM_CH]; + unsigned int suspend_mode; + unsigned int delay_mult; + unsigned int ch_num; + bool hall_enable; + bool ati_current; +}; + +static int iqs269_ati_mode_set(struct iqs269_private *iqs269, + unsigned int ch_num, unsigned int mode) +{ + u16 engine_a; + + if (ch_num >= IQS269_NUM_CH) + return -EINVAL; + + if (mode > IQS269_CHx_ENG_A_ATI_MODE_MAX) + return -EINVAL; + + mutex_lock(&iqs269->lock); + + engine_a = be16_to_cpu(iqs269->ch_reg[ch_num].engine_a); + + engine_a &= ~IQS269_CHx_ENG_A_ATI_MODE_MASK; + engine_a |= (mode << IQS269_CHx_ENG_A_ATI_MODE_SHIFT); + + iqs269->ch_reg[ch_num].engine_a = cpu_to_be16(engine_a); + iqs269->ati_current = false; + + mutex_unlock(&iqs269->lock); + + return 0; +} + +static int iqs269_ati_mode_get(struct iqs269_private *iqs269, + unsigned int ch_num, unsigned int *mode) +{ + u16 engine_a; + + if (ch_num >= IQS269_NUM_CH) + return -EINVAL; + + mutex_lock(&iqs269->lock); + engine_a = be16_to_cpu(iqs269->ch_reg[ch_num].engine_a); + mutex_unlock(&iqs269->lock); + + engine_a &= IQS269_CHx_ENG_A_ATI_MODE_MASK; + *mode = (engine_a >> IQS269_CHx_ENG_A_ATI_MODE_SHIFT); + + return 0; +} + +static int iqs269_ati_base_set(struct iqs269_private *iqs269, + unsigned int ch_num, unsigned int base) +{ + u16 engine_b; + + if (ch_num >= IQS269_NUM_CH) + return -EINVAL; + + switch (base) { + case 75: + base = IQS269_CHx_ENG_B_ATI_BASE_75; + break; + + case 100: + base = IQS269_CHx_ENG_B_ATI_BASE_100; + break; + + case 150: + base = IQS269_CHx_ENG_B_ATI_BASE_150; + break; + + case 200: + base = IQS269_CHx_ENG_B_ATI_BASE_200; + break; + + default: + return -EINVAL; + } + + mutex_lock(&iqs269->lock); + + engine_b = be16_to_cpu(iqs269->ch_reg[ch_num].engine_b); + + engine_b &= ~IQS269_CHx_ENG_B_ATI_BASE_MASK; + engine_b |= base; + + iqs269->ch_reg[ch_num].engine_b = cpu_to_be16(engine_b); + iqs269->ati_current = false; + + mutex_unlock(&iqs269->lock); + + return 0; +} + +static int iqs269_ati_base_get(struct iqs269_private *iqs269, + unsigned int ch_num, unsigned int *base) +{ + u16 engine_b; + + if (ch_num >= IQS269_NUM_CH) + return -EINVAL; + + mutex_lock(&iqs269->lock); + engine_b = be16_to_cpu(iqs269->ch_reg[ch_num].engine_b); + mutex_unlock(&iqs269->lock); + + switch (engine_b & IQS269_CHx_ENG_B_ATI_BASE_MASK) { + case IQS269_CHx_ENG_B_ATI_BASE_75: + *base = 75; + return 0; + + case IQS269_CHx_ENG_B_ATI_BASE_100: + *base = 100; + return 0; + + case IQS269_CHx_ENG_B_ATI_BASE_150: + *base = 150; + return 0; + + case IQS269_CHx_ENG_B_ATI_BASE_200: + *base = 200; + return 0; + + default: + return -EINVAL; + } +} + +static int iqs269_ati_target_set(struct iqs269_private *iqs269, + unsigned int ch_num, unsigned int target) +{ + u16 engine_b; + + if (ch_num >= IQS269_NUM_CH) + return -EINVAL; + + if (target > IQS269_CHx_ENG_B_ATI_TARGET_MAX) + return -EINVAL; + + mutex_lock(&iqs269->lock); + + engine_b = be16_to_cpu(iqs269->ch_reg[ch_num].engine_b); + + engine_b &= ~IQS269_CHx_ENG_B_ATI_TARGET_MASK; + engine_b |= target / 32; + + iqs269->ch_reg[ch_num].engine_b = cpu_to_be16(engine_b); + iqs269->ati_current = false; + + mutex_unlock(&iqs269->lock); + + return 0; +} + +static int iqs269_ati_target_get(struct iqs269_private *iqs269, + unsigned int ch_num, unsigned int *target) +{ + u16 engine_b; + + if (ch_num >= IQS269_NUM_CH) + return -EINVAL; + + mutex_lock(&iqs269->lock); + engine_b = be16_to_cpu(iqs269->ch_reg[ch_num].engine_b); + mutex_unlock(&iqs269->lock); + + *target = (engine_b & IQS269_CHx_ENG_B_ATI_TARGET_MASK) * 32; + + return 0; +} + +static int iqs269_parse_mask(const struct fwnode_handle *fwnode, + const char *propname, u8 *mask) +{ + unsigned int val[IQS269_NUM_CH]; + int count, error, i; + + count = fwnode_property_count_u32(fwnode, propname); + if (count < 0) + return 0; + + if (count > IQS269_NUM_CH) + return -EINVAL; + + error = fwnode_property_read_u32_array(fwnode, propname, val, count); + if (error) + return error; + + *mask = 0; + + for (i = 0; i < count; i++) { + if (val[i] >= IQS269_NUM_CH) + return -EINVAL; + + *mask |= BIT(val[i]); + } + + return 0; +} + +static int iqs269_parse_chan(struct iqs269_private *iqs269, + const struct fwnode_handle *ch_node) +{ + struct i2c_client *client = iqs269->client; + struct fwnode_handle *ev_node; + struct iqs269_ch_reg *ch_reg; + u16 engine_a, engine_b; + unsigned int reg, val; + int error, i; + + error = fwnode_property_read_u32(ch_node, "reg", ®); + if (error) { + dev_err(&client->dev, "Failed to read channel number: %d\n", + error); + return error; + } else if (reg >= IQS269_NUM_CH) { + dev_err(&client->dev, "Invalid channel number: %u\n", reg); + return -EINVAL; + } + + iqs269->sys_reg.active |= BIT(reg); + if (!fwnode_property_present(ch_node, "azoteq,reseed-disable")) + iqs269->sys_reg.reseed |= BIT(reg); + + if (fwnode_property_present(ch_node, "azoteq,blocking-enable")) + iqs269->sys_reg.blocking |= BIT(reg); + + if (fwnode_property_present(ch_node, "azoteq,slider0-select")) + iqs269->sys_reg.slider_select[0] |= BIT(reg); + + if (fwnode_property_present(ch_node, "azoteq,slider1-select")) + iqs269->sys_reg.slider_select[1] |= BIT(reg); + + ch_reg = &iqs269->ch_reg[reg]; + + error = regmap_raw_read(iqs269->regmap, + IQS269_CHx_SETTINGS + reg * sizeof(*ch_reg) / 2, + ch_reg, sizeof(*ch_reg)); + if (error) + return error; + + error = iqs269_parse_mask(ch_node, "azoteq,rx-enable", + &ch_reg->rx_enable); + if (error) { + dev_err(&client->dev, "Invalid channel %u RX enable mask: %d\n", + reg, error); + return error; + } + + error = iqs269_parse_mask(ch_node, "azoteq,tx-enable", + &ch_reg->tx_enable); + if (error) { + dev_err(&client->dev, "Invalid channel %u TX enable mask: %d\n", + reg, error); + return error; + } + + engine_a = be16_to_cpu(ch_reg->engine_a); + engine_b = be16_to_cpu(ch_reg->engine_b); + + engine_a |= IQS269_CHx_ENG_A_MEAS_CAP_SIZE; + if (fwnode_property_present(ch_node, "azoteq,meas-cap-decrease")) + engine_a &= ~IQS269_CHx_ENG_A_MEAS_CAP_SIZE; + + engine_a |= IQS269_CHx_ENG_A_RX_GND_INACTIVE; + if (fwnode_property_present(ch_node, "azoteq,rx-float-inactive")) + engine_a &= ~IQS269_CHx_ENG_A_RX_GND_INACTIVE; + + engine_a &= ~IQS269_CHx_ENG_A_LOCAL_CAP_SIZE; + engine_b &= ~IQS269_CHx_ENG_B_LOCAL_CAP_ENABLE; + if (!fwnode_property_read_u32(ch_node, "azoteq,local-cap-size", &val)) { + switch (val) { + case IQS269_LOCAL_CAP_SIZE_0: + break; + + case IQS269_LOCAL_CAP_SIZE_GLOBAL_0pF5: + engine_a |= IQS269_CHx_ENG_A_LOCAL_CAP_SIZE; + + /* fall through */ + + case IQS269_LOCAL_CAP_SIZE_GLOBAL_ONLY: + engine_b |= IQS269_CHx_ENG_B_LOCAL_CAP_ENABLE; + break; + + default: + dev_err(&client->dev, + "Invalid channel %u local cap. size: %u\n", reg, + val); + return -EINVAL; + } + } + + engine_a &= ~IQS269_CHx_ENG_A_INV_LOGIC; + if (fwnode_property_present(ch_node, "azoteq,invert-enable")) + engine_a |= IQS269_CHx_ENG_A_INV_LOGIC; + + if (!fwnode_property_read_u32(ch_node, "azoteq,proj-bias", &val)) { + if (val > IQS269_CHx_ENG_A_PROJ_BIAS_MAX) { + dev_err(&client->dev, + "Invalid channel %u bias current: %u\n", reg, + val); + return -EINVAL; + } + + engine_a &= ~IQS269_CHx_ENG_A_PROJ_BIAS_MASK; + engine_a |= (val << IQS269_CHx_ENG_A_PROJ_BIAS_SHIFT); + } + + if (!fwnode_property_read_u32(ch_node, "azoteq,sense-mode", &val)) { + if (val > IQS269_CHx_ENG_A_SENSE_MODE_MAX) { + dev_err(&client->dev, + "Invalid channel %u sensing mode: %u\n", reg, + val); + return -EINVAL; + } + + engine_a &= ~IQS269_CHx_ENG_A_SENSE_MODE_MASK; + engine_a |= val; + } + + if (!fwnode_property_read_u32(ch_node, "azoteq,sense-freq", &val)) { + if (val > IQS269_CHx_ENG_B_SENSE_FREQ_MAX) { + dev_err(&client->dev, + "Invalid channel %u sensing frequency: %u\n", + reg, val); + return -EINVAL; + } + + engine_b &= ~IQS269_CHx_ENG_B_SENSE_FREQ_MASK; + engine_b |= (val << IQS269_CHx_ENG_B_SENSE_FREQ_SHIFT); + } + + engine_b &= ~IQS269_CHx_ENG_B_STATIC_ENABLE; + if (fwnode_property_present(ch_node, "azoteq,static-enable")) + engine_b |= IQS269_CHx_ENG_B_STATIC_ENABLE; + + ch_reg->engine_a = cpu_to_be16(engine_a); + ch_reg->engine_b = cpu_to_be16(engine_b); + + if (!fwnode_property_read_u32(ch_node, "azoteq,ati-mode", &val)) { + error = iqs269_ati_mode_set(iqs269, reg, val); + if (error) { + dev_err(&client->dev, + "Invalid channel %u ATI mode: %u\n", reg, val); + return error; + } + } + + if (!fwnode_property_read_u32(ch_node, "azoteq,ati-base", &val)) { + error = iqs269_ati_base_set(iqs269, reg, val); + if (error) { + dev_err(&client->dev, + "Invalid channel %u ATI base: %u\n", reg, val); + return error; + } + } + + if (!fwnode_property_read_u32(ch_node, "azoteq,ati-target", &val)) { + error = iqs269_ati_target_set(iqs269, reg, val); + if (error) { + dev_err(&client->dev, + "Invalid channel %u ATI target: %u\n", reg, + val); + return error; + } + } + + error = iqs269_parse_mask(ch_node, "azoteq,assoc-select", + &ch_reg->assoc_select); + if (error) { + dev_err(&client->dev, "Invalid channel %u association: %d\n", + reg, error); + return error; + } + + if (!fwnode_property_read_u32(ch_node, "azoteq,assoc-weight", &val)) { + if (val > IQS269_CHx_WEIGHT_MAX) { + dev_err(&client->dev, + "Invalid channel %u associated weight: %u\n", + reg, val); + return -EINVAL; + } + + ch_reg->assoc_weight = val; + } + + for (i = 0; i < ARRAY_SIZE(iqs269_events); i++) { + ev_node = fwnode_get_named_child_node(ch_node, + iqs269_events[i].name); + if (!ev_node) + continue; + + if (!fwnode_property_read_u32(ev_node, "azoteq,thresh", &val)) { + if (val > IQS269_CHx_THRESH_MAX) { + dev_err(&client->dev, + "Invalid channel %u threshold: %u\n", + reg, val); + return -EINVAL; + } + + ch_reg->thresh[iqs269_events[i].th_offs] = val; + } + + if (!fwnode_property_read_u32(ev_node, "azoteq,hyst", &val)) { + u8 *hyst = &ch_reg->hyst; + + if (val > IQS269_CHx_HYST_MAX) { + dev_err(&client->dev, + "Invalid channel %u hysteresis: %u\n", + reg, val); + return -EINVAL; + } + + if (i == IQS269_EVENT_DEEP_DN || + i == IQS269_EVENT_DEEP_UP) { + *hyst &= ~IQS269_CHx_HYST_DEEP_MASK; + *hyst |= (val << IQS269_CHx_HYST_DEEP_SHIFT); + } else if (i == IQS269_EVENT_TOUCH_DN || + i == IQS269_EVENT_TOUCH_UP) { + *hyst &= ~IQS269_CHx_HYST_TOUCH_MASK; + *hyst |= val; + } + } + + if (fwnode_property_read_u32(ev_node, "linux,code", &val)) + continue; + + switch (reg) { + case IQS269_CHx_HALL_ACTIVE: + if (iqs269->hall_enable) { + iqs269->switches[i].code = val; + iqs269->switches[i].enabled = true; + } + + /* fall through */ + + case IQS269_CHx_HALL_INACTIVE: + if (iqs269->hall_enable) + break; + + /* fall through */ + + default: + iqs269->keycode[i * IQS269_NUM_CH + reg] = val; + } + + iqs269->sys_reg.event_mask &= ~iqs269_events[i].mask; + } + + return 0; +} + +static int iqs269_parse_prop(struct iqs269_private *iqs269) +{ + struct iqs269_sys_reg *sys_reg = &iqs269->sys_reg; + struct i2c_client *client = iqs269->client; + struct fwnode_handle *ch_node; + u16 general, misc_a, misc_b; + unsigned int val; + int error; + + iqs269->hall_enable = device_property_present(&client->dev, + "azoteq,hall-enable"); + + if (!device_property_read_u32(&client->dev, "azoteq,suspend-mode", + &val)) { + if (val > IQS269_SYS_SETTINGS_PWR_MODE_MAX) { + dev_err(&client->dev, "Invalid suspend mode: %u\n", + val); + return -EINVAL; + } + + iqs269->suspend_mode = val; + } + + error = regmap_raw_read(iqs269->regmap, IQS269_SYS_SETTINGS, sys_reg, + sizeof(*sys_reg)); + if (error) + return error; + + if (!device_property_read_u32(&client->dev, "azoteq,filt-str-lp-lta", + &val)) { + if (val > IQS269_FILT_STR_MAX) { + dev_err(&client->dev, "Invalid filter strength: %u\n", + val); + return -EINVAL; + } + + sys_reg->filter &= ~IQS269_FILT_STR_LP_LTA_MASK; + sys_reg->filter |= (val << IQS269_FILT_STR_LP_LTA_SHIFT); + } + + if (!device_property_read_u32(&client->dev, "azoteq,filt-str-lp-cnt", + &val)) { + if (val > IQS269_FILT_STR_MAX) { + dev_err(&client->dev, "Invalid filter strength: %u\n", + val); + return -EINVAL; + } + + sys_reg->filter &= ~IQS269_FILT_STR_LP_CNT_MASK; + sys_reg->filter |= (val << IQS269_FILT_STR_LP_CNT_SHIFT); + } + + if (!device_property_read_u32(&client->dev, "azoteq,filt-str-np-lta", + &val)) { + if (val > IQS269_FILT_STR_MAX) { + dev_err(&client->dev, "Invalid filter strength: %u\n", + val); + return -EINVAL; + } + + sys_reg->filter &= ~IQS269_FILT_STR_NP_LTA_MASK; + sys_reg->filter |= (val << IQS269_FILT_STR_NP_LTA_SHIFT); + } + + if (!device_property_read_u32(&client->dev, "azoteq,filt-str-np-cnt", + &val)) { + if (val > IQS269_FILT_STR_MAX) { + dev_err(&client->dev, "Invalid filter strength: %u\n", + val); + return -EINVAL; + } + + sys_reg->filter &= ~IQS269_FILT_STR_NP_CNT_MASK; + sys_reg->filter |= val; + } + + if (!device_property_read_u32(&client->dev, "azoteq,rate-np-ms", + &val)) { + if (val > IQS269_RATE_NP_MS_MAX) { + dev_err(&client->dev, "Invalid report rate: %u\n", val); + return -EINVAL; + } + + sys_reg->rate_np = val; + } + + if (!device_property_read_u32(&client->dev, "azoteq,rate-lp-ms", + &val)) { + if (val > IQS269_RATE_LP_MS_MAX) { + dev_err(&client->dev, "Invalid report rate: %u\n", val); + return -EINVAL; + } + + sys_reg->rate_lp = val; + } + + if (!device_property_read_u32(&client->dev, "azoteq,rate-ulp-ms", + &val)) { + if (val > IQS269_RATE_ULP_MS_MAX) { + dev_err(&client->dev, "Invalid report rate: %u\n", val); + return -EINVAL; + } + + sys_reg->rate_ulp = val / 16; + } + + if (!device_property_read_u32(&client->dev, "azoteq,timeout-pwr-ms", + &val)) { + if (val > IQS269_TIMEOUT_PWR_MS_MAX) { + dev_err(&client->dev, "Invalid timeout: %u\n", val); + return -EINVAL; + } + + sys_reg->timeout_pwr = val / 512; + } + + if (!device_property_read_u32(&client->dev, "azoteq,timeout-lta-ms", + &val)) { + if (val > IQS269_TIMEOUT_LTA_MS_MAX) { + dev_err(&client->dev, "Invalid timeout: %u\n", val); + return -EINVAL; + } + + sys_reg->timeout_lta = val / 512; + } + + misc_a = be16_to_cpu(sys_reg->misc_a); + misc_b = be16_to_cpu(sys_reg->misc_b); + + misc_a &= ~IQS269_MISC_A_ATI_BAND_DISABLE; + if (device_property_present(&client->dev, "azoteq,ati-band-disable")) + misc_a |= IQS269_MISC_A_ATI_BAND_DISABLE; + + misc_a &= ~IQS269_MISC_A_ATI_LP_ONLY; + if (device_property_present(&client->dev, "azoteq,ati-lp-only")) + misc_a |= IQS269_MISC_A_ATI_LP_ONLY; + + misc_a &= ~IQS269_MISC_A_ATI_BAND_TIGHTEN; + if (device_property_present(&client->dev, "azoteq,ati-band-tighten")) + misc_a |= IQS269_MISC_A_ATI_BAND_TIGHTEN; + + misc_a &= ~IQS269_MISC_A_FILT_DISABLE; + if (device_property_present(&client->dev, "azoteq,filt-disable")) + misc_a |= IQS269_MISC_A_FILT_DISABLE; + + if (!device_property_read_u32(&client->dev, "azoteq,gpio3-select", + &val)) { + if (val >= IQS269_NUM_CH) { + dev_err(&client->dev, "Invalid GPIO3 selection: %u\n", + val); + return -EINVAL; + } + + misc_a &= ~IQS269_MISC_A_GPIO3_SELECT_MASK; + misc_a |= (val << IQS269_MISC_A_GPIO3_SELECT_SHIFT); + } + + misc_a &= ~IQS269_MISC_A_DUAL_DIR; + if (device_property_present(&client->dev, "azoteq,dual-direction")) + misc_a |= IQS269_MISC_A_DUAL_DIR; + + if (!device_property_read_u32(&client->dev, "azoteq,tx-freq", &val)) { + if (val > IQS269_MISC_A_TX_FREQ_MAX) { + dev_err(&client->dev, + "Invalid excitation frequency: %u\n", val); + return -EINVAL; + } + + misc_a &= ~IQS269_MISC_A_TX_FREQ_MASK; + misc_a |= (val << IQS269_MISC_A_TX_FREQ_SHIFT); + } + + misc_a &= ~IQS269_MISC_A_GLOBAL_CAP_SIZE; + if (device_property_present(&client->dev, "azoteq,global-cap-increase")) + misc_a |= IQS269_MISC_A_GLOBAL_CAP_SIZE; + + if (!device_property_read_u32(&client->dev, "azoteq,reseed-select", + &val)) { + if (val > IQS269_MISC_B_RESEED_UI_SEL_MAX) { + dev_err(&client->dev, "Invalid reseed selection: %u\n", + val); + return -EINVAL; + } + + misc_b &= ~IQS269_MISC_B_RESEED_UI_SEL_MASK; + misc_b |= (val << IQS269_MISC_B_RESEED_UI_SEL_SHIFT); + } + + misc_b &= ~IQS269_MISC_B_TRACKING_UI_ENABLE; + if (device_property_present(&client->dev, "azoteq,tracking-enable")) + misc_b |= IQS269_MISC_B_TRACKING_UI_ENABLE; + + if (!device_property_read_u32(&client->dev, "azoteq,filt-str-slider", + &val)) { + if (val > IQS269_FILT_STR_MAX) { + dev_err(&client->dev, "Invalid filter strength: %u\n", + val); + return -EINVAL; + } + + misc_b &= ~IQS269_MISC_B_FILT_STR_SLIDER; + misc_b |= val; + } + + sys_reg->misc_a = cpu_to_be16(misc_a); + sys_reg->misc_b = cpu_to_be16(misc_b); + + sys_reg->active = 0; + sys_reg->reseed = 0; + + sys_reg->blocking = 0; + + sys_reg->slider_select[0] = 0; + sys_reg->slider_select[1] = 0; + + sys_reg->event_mask = ~((u8)IQS269_EVENT_MASK_SYS); + + device_for_each_child_node(&client->dev, ch_node) { + error = iqs269_parse_chan(iqs269, ch_node); + if (error) { + fwnode_handle_put(ch_node); + return error; + } + } + + /* + * Volunteer all active channels to participate in ATI when REDO-ATI is + * manually triggered. + */ + sys_reg->redo_ati = sys_reg->active; + + general = be16_to_cpu(sys_reg->general); + + if (device_property_present(&client->dev, "azoteq,clk-div")) { + general |= IQS269_SYS_SETTINGS_CLK_DIV; + iqs269->delay_mult = 4; + } else { + general &= ~IQS269_SYS_SETTINGS_CLK_DIV; + iqs269->delay_mult = 1; + } + + /* + * Configure the device to automatically switch between normal and low- + * power modes as a function of sensing activity. Ultra-low-power mode, + * if enabled, is reserved for suspend. + */ + general &= ~IQS269_SYS_SETTINGS_ULP_AUTO; + general &= ~IQS269_SYS_SETTINGS_DIS_AUTO; + general &= ~IQS269_SYS_SETTINGS_PWR_MODE_MASK; + + if (!device_property_read_u32(&client->dev, "azoteq,ulp-update", + &val)) { + if (val > IQS269_SYS_SETTINGS_ULP_UPDATE_MAX) { + dev_err(&client->dev, "Invalid update rate: %u\n", val); + return -EINVAL; + } + + general &= ~IQS269_SYS_SETTINGS_ULP_UPDATE_MASK; + general |= (val << IQS269_SYS_SETTINGS_ULP_UPDATE_SHIFT); + } + + general &= ~IQS269_SYS_SETTINGS_RESEED_OFFSET; + if (device_property_present(&client->dev, "azoteq,reseed-offset")) + general |= IQS269_SYS_SETTINGS_RESEED_OFFSET; + + general |= IQS269_SYS_SETTINGS_EVENT_MODE; + + /* + * As per the datasheet, enable streaming during normal-power mode if + * either slider is in use. In that case, the device returns to event + * mode during low-power mode. + */ + if (sys_reg->slider_select[0] || sys_reg->slider_select[1]) + general |= IQS269_SYS_SETTINGS_EVENT_MODE_LP; + + general |= IQS269_SYS_SETTINGS_REDO_ATI; + general |= IQS269_SYS_SETTINGS_ACK_RESET; + + sys_reg->general = cpu_to_be16(general); + + return 0; +} + +static int iqs269_dev_init(struct iqs269_private *iqs269) +{ + struct iqs269_sys_reg *sys_reg = &iqs269->sys_reg; + struct iqs269_ch_reg *ch_reg; + unsigned int val; + int error, i; + + mutex_lock(&iqs269->lock); + + error = regmap_update_bits(iqs269->regmap, IQS269_HALL_UI, + IQS269_HALL_UI_ENABLE, + iqs269->hall_enable ? ~0 : 0); + if (error) + goto err_mutex; + + for (i = 0; i < IQS269_NUM_CH; i++) { + if (!(sys_reg->active & BIT(i))) + continue; + + ch_reg = &iqs269->ch_reg[i]; + + error = regmap_raw_write(iqs269->regmap, + IQS269_CHx_SETTINGS + i * + sizeof(*ch_reg) / 2, ch_reg, + sizeof(*ch_reg)); + if (error) + goto err_mutex; + } + + /* + * The REDO-ATI and ATI channel selection fields must be written in the + * same block write, so every field between registers 0x80 through 0x8B + * (inclusive) must be written as well. + */ + error = regmap_raw_write(iqs269->regmap, IQS269_SYS_SETTINGS, sys_reg, + sizeof(*sys_reg)); + if (error) + goto err_mutex; + + error = regmap_read_poll_timeout(iqs269->regmap, IQS269_SYS_FLAGS, val, + !(val & IQS269_SYS_FLAGS_IN_ATI), + IQS269_ATI_POLL_SLEEP_US, + IQS269_ATI_POLL_TIMEOUT_US); + if (error) + goto err_mutex; + + msleep(IQS269_ATI_STABLE_DELAY_MS); + iqs269->ati_current = true; + +err_mutex: + mutex_unlock(&iqs269->lock); + + return error; +} + +static int iqs269_input_init(struct iqs269_private *iqs269) +{ + struct i2c_client *client = iqs269->client; + struct iqs269_flags flags; + unsigned int sw_code, keycode; + int error, i, j; + u8 dir_mask, state; + + iqs269->keypad = devm_input_allocate_device(&client->dev); + if (!iqs269->keypad) + return -ENOMEM; + + iqs269->keypad->keycodemax = ARRAY_SIZE(iqs269->keycode); + iqs269->keypad->keycode = iqs269->keycode; + iqs269->keypad->keycodesize = sizeof(*iqs269->keycode); + + iqs269->keypad->name = "iqs269a_keypad"; + iqs269->keypad->id.bustype = BUS_I2C; + + if (iqs269->hall_enable) { + error = regmap_raw_read(iqs269->regmap, IQS269_SYS_FLAGS, + &flags, sizeof(flags)); + if (error) { + dev_err(&client->dev, + "Failed to read initial status: %d\n", error); + return error; + } + } + + for (i = 0; i < ARRAY_SIZE(iqs269_events); i++) { + dir_mask = flags.states[IQS269_ST_OFFS_DIR]; + if (!iqs269_events[i].dir_up) + dir_mask = ~dir_mask; + + state = flags.states[iqs269_events[i].st_offs] & dir_mask; + + sw_code = iqs269->switches[i].code; + + for (j = 0; j < IQS269_NUM_CH; j++) { + keycode = iqs269->keycode[i * IQS269_NUM_CH + j]; + + /* + * Hall-effect sensing repurposes a pair of dedicated + * channels, only one of which reports events. + */ + switch (j) { + case IQS269_CHx_HALL_ACTIVE: + if (iqs269->hall_enable && + iqs269->switches[i].enabled) { + input_set_capability(iqs269->keypad, + EV_SW, sw_code); + input_report_switch(iqs269->keypad, + sw_code, + state & BIT(j)); + } + + /* fall through */ + + case IQS269_CHx_HALL_INACTIVE: + if (iqs269->hall_enable) + continue; + + /* fall through */ + + default: + if (keycode != KEY_RESERVED) + input_set_capability(iqs269->keypad, + EV_KEY, keycode); + } + } + } + + input_sync(iqs269->keypad); + + error = input_register_device(iqs269->keypad); + if (error) { + dev_err(&client->dev, "Failed to register keypad: %d\n", error); + return error; + } + + for (i = 0; i < IQS269_NUM_SL; i++) { + if (!iqs269->sys_reg.slider_select[i]) + continue; + + iqs269->slider[i] = devm_input_allocate_device(&client->dev); + if (!iqs269->slider[i]) + return -ENOMEM; + + iqs269->slider[i]->name = i ? "iqs269a_slider_1" + : "iqs269a_slider_0"; + iqs269->slider[i]->id.bustype = BUS_I2C; + + input_set_capability(iqs269->slider[i], EV_KEY, BTN_TOUCH); + input_set_abs_params(iqs269->slider[i], ABS_X, 0, 255, 0, 0); + + error = input_register_device(iqs269->slider[i]); + if (error) { + dev_err(&client->dev, + "Failed to register slider %d: %d\n", i, error); + return error; + } + } + + return 0; +} + +static int iqs269_report(struct iqs269_private *iqs269) +{ + struct i2c_client *client = iqs269->client; + struct iqs269_flags flags; + unsigned int sw_code, keycode; + int error, i, j; + u8 slider_x[IQS269_NUM_SL]; + u8 dir_mask, state; + + error = regmap_raw_read(iqs269->regmap, IQS269_SYS_FLAGS, &flags, + sizeof(flags)); + if (error) { + dev_err(&client->dev, "Failed to read device status: %d\n", + error); + return error; + } + + /* + * The device resets itself if its own watchdog bites, which can happen + * in the event of an I2C communication error. In this case, the device + * asserts a SHOW_RESET interrupt and all registers must be restored. + */ + if (be16_to_cpu(flags.system) & IQS269_SYS_FLAGS_SHOW_RESET) { + dev_err(&client->dev, "Unexpected device reset\n"); + + error = iqs269_dev_init(iqs269); + if (error) + dev_err(&client->dev, + "Failed to re-initialize device: %d\n", error); + + return error; + } + + error = regmap_raw_read(iqs269->regmap, IQS269_SLIDER_X, slider_x, + sizeof(slider_x)); + if (error) { + dev_err(&client->dev, "Failed to read slider position: %d\n", + error); + return error; + } + + for (i = 0; i < IQS269_NUM_SL; i++) { + if (!iqs269->sys_reg.slider_select[i]) + continue; + + /* + * Report BTN_TOUCH if any channel that participates in the + * slider is in a state of touch. + */ + if (flags.states[IQS269_ST_OFFS_TOUCH] & + iqs269->sys_reg.slider_select[i]) { + input_report_key(iqs269->slider[i], BTN_TOUCH, 1); + input_report_abs(iqs269->slider[i], ABS_X, slider_x[i]); + } else { + input_report_key(iqs269->slider[i], BTN_TOUCH, 0); + } + + input_sync(iqs269->slider[i]); + } + + for (i = 0; i < ARRAY_SIZE(iqs269_events); i++) { + dir_mask = flags.states[IQS269_ST_OFFS_DIR]; + if (!iqs269_events[i].dir_up) + dir_mask = ~dir_mask; + + state = flags.states[iqs269_events[i].st_offs] & dir_mask; + + sw_code = iqs269->switches[i].code; + + for (j = 0; j < IQS269_NUM_CH; j++) { + keycode = iqs269->keycode[i * IQS269_NUM_CH + j]; + + switch (j) { + case IQS269_CHx_HALL_ACTIVE: + if (iqs269->hall_enable && + iqs269->switches[i].enabled) + input_report_switch(iqs269->keypad, + sw_code, + state & BIT(j)); + + /* fall through */ + + case IQS269_CHx_HALL_INACTIVE: + if (iqs269->hall_enable) + continue; + + /* fall through */ + + default: + input_report_key(iqs269->keypad, keycode, + state & BIT(j)); + } + } + } + + input_sync(iqs269->keypad); + + return 0; +} + +static irqreturn_t iqs269_irq(int irq, void *context) +{ + struct iqs269_private *iqs269 = context; + + if (iqs269_report(iqs269)) + return IRQ_NONE; + + /* + * The device does not deassert its interrupt (RDY) pin until shortly + * after receiving an I2C stop condition; the following delay ensures + * the interrupt handler does not return before this time. + */ + iqs269_irq_wait(); + + return IRQ_HANDLED; +} + +static ssize_t counts_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct iqs269_private *iqs269 = dev_get_drvdata(dev); + struct i2c_client *client = iqs269->client; + __le16 counts; + int error; + + if (!iqs269->ati_current || iqs269->hall_enable) + return -EPERM; + + /* + * Unsolicited I2C communication prompts the device to assert its RDY + * pin, so disable the interrupt line until the operation is finished + * and RDY has been deasserted. + */ + disable_irq(client->irq); + + error = regmap_raw_read(iqs269->regmap, + IQS269_CHx_COUNTS + iqs269->ch_num * 2, + &counts, sizeof(counts)); + + iqs269_irq_wait(); + enable_irq(client->irq); + + if (error) + return error; + + return scnprintf(buf, PAGE_SIZE, "%u\n", le16_to_cpu(counts)); +} + +static ssize_t hall_bin_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct iqs269_private *iqs269 = dev_get_drvdata(dev); + struct i2c_client *client = iqs269->client; + unsigned int val; + int error; + + disable_irq(client->irq); + + error = regmap_read(iqs269->regmap, IQS269_CAL_DATA_A, &val); + + iqs269_irq_wait(); + enable_irq(client->irq); + + if (error) + return error; + + switch (iqs269->ch_reg[IQS269_CHx_HALL_ACTIVE].rx_enable & + iqs269->ch_reg[IQS269_CHx_HALL_INACTIVE].rx_enable) { + case IQS269_HALL_PAD_R: + val &= IQS269_CAL_DATA_A_HALL_BIN_R_MASK; + val >>= IQS269_CAL_DATA_A_HALL_BIN_R_SHIFT; + break; + + case IQS269_HALL_PAD_L: + val &= IQS269_CAL_DATA_A_HALL_BIN_L_MASK; + val >>= IQS269_CAL_DATA_A_HALL_BIN_L_SHIFT; + break; + + default: + return -EINVAL; + } + + return scnprintf(buf, PAGE_SIZE, "%u\n", val); +} + +static ssize_t hall_enable_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct iqs269_private *iqs269 = dev_get_drvdata(dev); + + return scnprintf(buf, PAGE_SIZE, "%u\n", iqs269->hall_enable); +} + +static ssize_t hall_enable_store(struct device *dev, + struct device_attribute *attr, const char *buf, + size_t count) +{ + struct iqs269_private *iqs269 = dev_get_drvdata(dev); + unsigned int val; + int error; + + error = kstrtouint(buf, 10, &val); + if (error) + return error; + + mutex_lock(&iqs269->lock); + + iqs269->hall_enable = val; + iqs269->ati_current = false; + + mutex_unlock(&iqs269->lock); + + return count; +} + +static ssize_t ch_number_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct iqs269_private *iqs269 = dev_get_drvdata(dev); + + return scnprintf(buf, PAGE_SIZE, "%u\n", iqs269->ch_num); +} + +static ssize_t ch_number_store(struct device *dev, + struct device_attribute *attr, const char *buf, + size_t count) +{ + struct iqs269_private *iqs269 = dev_get_drvdata(dev); + unsigned int val; + int error; + + error = kstrtouint(buf, 10, &val); + if (error) + return error; + + if (val >= IQS269_NUM_CH) + return -EINVAL; + + iqs269->ch_num = val; + + return count; +} + +static ssize_t rx_enable_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct iqs269_private *iqs269 = dev_get_drvdata(dev); + + return scnprintf(buf, PAGE_SIZE, "%u\n", + iqs269->ch_reg[iqs269->ch_num].rx_enable); +} + +static ssize_t rx_enable_store(struct device *dev, + struct device_attribute *attr, const char *buf, + size_t count) +{ + struct iqs269_private *iqs269 = dev_get_drvdata(dev); + unsigned int val; + int error; + + error = kstrtouint(buf, 10, &val); + if (error) + return error; + + if (val > 0xFF) + return -EINVAL; + + mutex_lock(&iqs269->lock); + + iqs269->ch_reg[iqs269->ch_num].rx_enable = val; + iqs269->ati_current = false; + + mutex_unlock(&iqs269->lock); + + return count; +} + +static ssize_t ati_mode_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct iqs269_private *iqs269 = dev_get_drvdata(dev); + unsigned int val; + int error; + + error = iqs269_ati_mode_get(iqs269, iqs269->ch_num, &val); + if (error) + return error; + + return scnprintf(buf, PAGE_SIZE, "%u\n", val); +} + +static ssize_t ati_mode_store(struct device *dev, + struct device_attribute *attr, const char *buf, + size_t count) +{ + struct iqs269_private *iqs269 = dev_get_drvdata(dev); + unsigned int val; + int error; + + error = kstrtouint(buf, 10, &val); + if (error) + return error; + + error = iqs269_ati_mode_set(iqs269, iqs269->ch_num, val); + if (error) + return error; + + return count; +} + +static ssize_t ati_base_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct iqs269_private *iqs269 = dev_get_drvdata(dev); + unsigned int val; + int error; + + error = iqs269_ati_base_get(iqs269, iqs269->ch_num, &val); + if (error) + return error; + + return scnprintf(buf, PAGE_SIZE, "%u\n", val); +} + +static ssize_t ati_base_store(struct device *dev, + struct device_attribute *attr, const char *buf, + size_t count) +{ + struct iqs269_private *iqs269 = dev_get_drvdata(dev); + unsigned int val; + int error; + + error = kstrtouint(buf, 10, &val); + if (error) + return error; + + error = iqs269_ati_base_set(iqs269, iqs269->ch_num, val); + if (error) + return error; + + return count; +} + +static ssize_t ati_target_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct iqs269_private *iqs269 = dev_get_drvdata(dev); + unsigned int val; + int error; + + error = iqs269_ati_target_get(iqs269, iqs269->ch_num, &val); + if (error) + return error; + + return scnprintf(buf, PAGE_SIZE, "%u\n", val); +} + +static ssize_t ati_target_store(struct device *dev, + struct device_attribute *attr, const char *buf, + size_t count) +{ + struct iqs269_private *iqs269 = dev_get_drvdata(dev); + unsigned int val; + int error; + + error = kstrtouint(buf, 10, &val); + if (error) + return error; + + error = iqs269_ati_target_set(iqs269, iqs269->ch_num, val); + if (error) + return error; + + return count; +} + +static ssize_t ati_trigger_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct iqs269_private *iqs269 = dev_get_drvdata(dev); + + return scnprintf(buf, PAGE_SIZE, "%u\n", iqs269->ati_current); +} + +static ssize_t ati_trigger_store(struct device *dev, + struct device_attribute *attr, const char *buf, + size_t count) +{ + struct iqs269_private *iqs269 = dev_get_drvdata(dev); + struct i2c_client *client = iqs269->client; + unsigned int val; + int error; + + error = kstrtouint(buf, 10, &val); + if (error) + return error; + + if (!val) + return count; + + disable_irq(client->irq); + + error = iqs269_dev_init(iqs269); + + iqs269_irq_wait(); + enable_irq(client->irq); + + if (error) + return error; + + return count; +} + +static DEVICE_ATTR_RO(counts); +static DEVICE_ATTR_RO(hall_bin); +static DEVICE_ATTR_RW(hall_enable); +static DEVICE_ATTR_RW(ch_number); +static DEVICE_ATTR_RW(rx_enable); +static DEVICE_ATTR_RW(ati_mode); +static DEVICE_ATTR_RW(ati_base); +static DEVICE_ATTR_RW(ati_target); +static DEVICE_ATTR_RW(ati_trigger); + +static struct attribute *iqs269_attrs[] = { + &dev_attr_counts.attr, + &dev_attr_hall_bin.attr, + &dev_attr_hall_enable.attr, + &dev_attr_ch_number.attr, + &dev_attr_rx_enable.attr, + &dev_attr_ati_mode.attr, + &dev_attr_ati_base.attr, + &dev_attr_ati_target.attr, + &dev_attr_ati_trigger.attr, + NULL, +}; + +static const struct attribute_group iqs269_attr_group = { + .attrs = iqs269_attrs, +}; + +static const struct regmap_config iqs269_regmap_config = { + .reg_bits = 8, + .val_bits = 16, + .max_register = IQS269_MAX_REG, +}; + +static int iqs269_probe(struct i2c_client *client) +{ + struct iqs269_ver_info ver_info; + struct iqs269_private *iqs269; + int error; + + iqs269 = devm_kzalloc(&client->dev, sizeof(*iqs269), GFP_KERNEL); + if (!iqs269) + return -ENOMEM; + + i2c_set_clientdata(client, iqs269); + iqs269->client = client; + + iqs269->regmap = devm_regmap_init_i2c(client, &iqs269_regmap_config); + if (IS_ERR(iqs269->regmap)) { + error = PTR_ERR(iqs269->regmap); + dev_err(&client->dev, "Failed to initialize register map: %d\n", + error); + return error; + } + + mutex_init(&iqs269->lock); + + error = regmap_raw_read(iqs269->regmap, IQS269_VER_INFO, &ver_info, + sizeof(ver_info)); + if (error) + return error; + + if (ver_info.prod_num != IQS269_VER_INFO_PROD_NUM) { + dev_err(&client->dev, "Unrecognized product number: 0x%02X\n", + ver_info.prod_num); + return -EINVAL; + } + + error = iqs269_parse_prop(iqs269); + if (error) + return error; + + error = iqs269_dev_init(iqs269); + if (error) { + dev_err(&client->dev, "Failed to initialize device: %d\n", + error); + return error; + } + + error = iqs269_input_init(iqs269); + if (error) + return error; + + error = devm_request_threaded_irq(&client->dev, client->irq, + NULL, iqs269_irq, IRQF_ONESHOT, + client->name, iqs269); + if (error) { + dev_err(&client->dev, "Failed to request IRQ: %d\n", error); + return error; + } + + error = devm_device_add_group(&client->dev, &iqs269_attr_group); + if (error) + dev_err(&client->dev, "Failed to add attributes: %d\n", error); + + return error; +} + +static int __maybe_unused iqs269_suspend(struct device *dev) +{ + struct iqs269_private *iqs269 = dev_get_drvdata(dev); + struct i2c_client *client = iqs269->client; + unsigned int val; + int error; + + if (!iqs269->suspend_mode) + return 0; + + disable_irq(client->irq); + + /* + * Automatic power mode switching must be disabled before the device is + * forced into any particular power mode. In this case, the device will + * transition into normal-power mode. + */ + error = regmap_update_bits(iqs269->regmap, IQS269_SYS_SETTINGS, + IQS269_SYS_SETTINGS_DIS_AUTO, ~0); + if (error) + goto err_irq; + + /* + * The following check ensures the device has completed its transition + * into normal-power mode before a manual mode switch is performed. + */ + error = regmap_read_poll_timeout(iqs269->regmap, IQS269_SYS_FLAGS, val, + !(val & IQS269_SYS_FLAGS_PWR_MODE_MASK), + IQS269_PWR_MODE_POLL_SLEEP_US, + IQS269_PWR_MODE_POLL_TIMEOUT_US); + if (error) + goto err_irq; + + error = regmap_update_bits(iqs269->regmap, IQS269_SYS_SETTINGS, + IQS269_SYS_SETTINGS_PWR_MODE_MASK, + iqs269->suspend_mode << + IQS269_SYS_SETTINGS_PWR_MODE_SHIFT); + if (error) + goto err_irq; + + /* + * This last check ensures the device has completed its transition into + * the desired power mode to prevent any spurious interrupts from being + * triggered after iqs269_suspend has already returned. + */ + error = regmap_read_poll_timeout(iqs269->regmap, IQS269_SYS_FLAGS, val, + (val & IQS269_SYS_FLAGS_PWR_MODE_MASK) + == (iqs269->suspend_mode << + IQS269_SYS_FLAGS_PWR_MODE_SHIFT), + IQS269_PWR_MODE_POLL_SLEEP_US, + IQS269_PWR_MODE_POLL_TIMEOUT_US); + +err_irq: + iqs269_irq_wait(); + enable_irq(client->irq); + + return error; +} + +static int __maybe_unused iqs269_resume(struct device *dev) +{ + struct iqs269_private *iqs269 = dev_get_drvdata(dev); + struct i2c_client *client = iqs269->client; + unsigned int val; + int error; + + if (!iqs269->suspend_mode) + return 0; + + disable_irq(client->irq); + + error = regmap_update_bits(iqs269->regmap, IQS269_SYS_SETTINGS, + IQS269_SYS_SETTINGS_PWR_MODE_MASK, 0); + if (error) + goto err_irq; + + /* + * This check ensures the device has returned to normal-power mode + * before automatic power mode switching is re-enabled. + */ + error = regmap_read_poll_timeout(iqs269->regmap, IQS269_SYS_FLAGS, val, + !(val & IQS269_SYS_FLAGS_PWR_MODE_MASK), + IQS269_PWR_MODE_POLL_SLEEP_US, + IQS269_PWR_MODE_POLL_TIMEOUT_US); + if (error) + goto err_irq; + + error = regmap_update_bits(iqs269->regmap, IQS269_SYS_SETTINGS, + IQS269_SYS_SETTINGS_DIS_AUTO, 0); + if (error) + goto err_irq; + + /* + * This step reports any events that may have been "swallowed" as a + * result of polling PWR_MODE (which automatically acknowledges any + * pending interrupts). + */ + error = iqs269_report(iqs269); + +err_irq: + iqs269_irq_wait(); + enable_irq(client->irq); + + return error; +} + +static SIMPLE_DEV_PM_OPS(iqs269_pm, iqs269_suspend, iqs269_resume); + +static const struct of_device_id iqs269_of_match[] = { + { .compatible = "azoteq,iqs269a" }, + { } +}; +MODULE_DEVICE_TABLE(of, iqs269_of_match); + +static struct i2c_driver iqs269_i2c_driver = { + .driver = { + .name = "iqs269a", + .of_match_table = iqs269_of_match, + .pm = &iqs269_pm, + }, + .probe_new = iqs269_probe, +}; +module_i2c_driver(iqs269_i2c_driver); + +MODULE_AUTHOR("Jeff LaBundy "); +MODULE_DESCRIPTION("Azoteq IQS269A Capacitive Touch Controller"); +MODULE_LICENSE("GPL"); -- cgit v1.2.3 From 6def17b12ba3d30196d4f35a5cf1edf38f791d1d Mon Sep 17 00:00:00 2001 From: Michał Mirosław Date: Sun, 17 May 2020 20:38:43 -0700 Subject: Input: elants - remove unused axes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Driver only ever reports MT events and input_mt_init_slots() sets up emulated axes already. Clear the capabilities not generated directly and move MT axes setup, so they are visible by input_mt_init_slots(). Signed-off-by: Michał Mirosław Reviewed-by: Dmitry Osipenko Tested-by: Dmitry Osipenko Link: https://lore.kernel.org/r/d5eee8cd305adb144a11264d70da94f7b6570366.1587923061.git.mirq-linux@rere.qmqm.pl Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/elants_i2c.c | 26 ++++++++------------------ 1 file changed, 8 insertions(+), 18 deletions(-) (limited to 'drivers/input') diff --git a/drivers/input/touchscreen/elants_i2c.c b/drivers/input/touchscreen/elants_i2c.c index 0c4bbd2eb3a2..3abfa3f7db38 100644 --- a/drivers/input/touchscreen/elants_i2c.c +++ b/drivers/input/touchscreen/elants_i2c.c @@ -1316,25 +1316,7 @@ static int elants_i2c_probe(struct i2c_client *client, ts->input->name = "Elan Touchscreen"; ts->input->id.bustype = BUS_I2C; - __set_bit(BTN_TOUCH, ts->input->keybit); - __set_bit(EV_ABS, ts->input->evbit); - __set_bit(EV_KEY, ts->input->evbit); - - /* Single touch input params setup */ - input_set_abs_params(ts->input, ABS_X, 0, ts->x_max, 0, 0); - input_set_abs_params(ts->input, ABS_Y, 0, ts->y_max, 0, 0); - input_set_abs_params(ts->input, ABS_PRESSURE, 0, 255, 0, 0); - input_abs_set_res(ts->input, ABS_X, ts->x_res); - input_abs_set_res(ts->input, ABS_Y, ts->y_res); - /* Multitouch input params setup */ - error = input_mt_init_slots(ts->input, MAX_CONTACT_NUM, - INPUT_MT_DIRECT | INPUT_MT_DROP_UNUSED); - if (error) { - dev_err(&client->dev, - "failed to initialize MT slots: %d\n", error); - return error; - } input_set_abs_params(ts->input, ABS_MT_POSITION_X, 0, ts->x_max, 0, 0); input_set_abs_params(ts->input, ABS_MT_POSITION_Y, 0, ts->y_max, 0, 0); @@ -1346,6 +1328,14 @@ static int elants_i2c_probe(struct i2c_client *client, input_abs_set_res(ts->input, ABS_MT_POSITION_Y, ts->y_res); input_abs_set_res(ts->input, ABS_MT_TOUCH_MAJOR, 1); + error = input_mt_init_slots(ts->input, MAX_CONTACT_NUM, + INPUT_MT_DIRECT | INPUT_MT_DROP_UNUSED); + if (error) { + dev_err(&client->dev, + "failed to initialize MT slots: %d\n", error); + return error; + } + error = input_register_device(ts->input); if (error) { dev_err(&client->dev, -- cgit v1.2.3 From 68334dbab13bc5d637fdf1aa2ccfe7e1932b2af1 Mon Sep 17 00:00:00 2001 From: Michał Mirosław Date: Sun, 17 May 2020 20:39:40 -0700 Subject: Input: elants - override touchscreen info with DT properties MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Allow overriding of information from hardware and support additional common DT properties like axis inversion. This is required for eg. Nexus 7 and TF300T where the programmed values in firmware differ from reality. Signed-off-by: Dmitry Osipenko [moved "prop" before DMA buffer] Signed-off-by: Michał Mirosław Link: https://lore.kernel.org/r/49ea996878264f7c8bde25204e4ddf4b1e85ae71.1587923061.git.mirq-linux@rere.qmqm.pl Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/elants_i2c.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'drivers/input') diff --git a/drivers/input/touchscreen/elants_i2c.c b/drivers/input/touchscreen/elants_i2c.c index 3abfa3f7db38..ccaef4031556 100644 --- a/drivers/input/touchscreen/elants_i2c.c +++ b/drivers/input/touchscreen/elants_i2c.c @@ -33,6 +33,7 @@ #include #include #include +#include #include #include #include @@ -137,6 +138,7 @@ struct elants_data { unsigned int y_res; unsigned int x_max; unsigned int y_max; + struct touchscreen_properties prop; enum elants_state state; enum elants_iap_mode iap_mode; @@ -876,8 +878,7 @@ static void elants_i2c_mt_event(struct elants_data *ts, u8 *buf) input_mt_slot(input, i); input_mt_report_slot_state(input, tool_type, true); - input_event(input, EV_ABS, ABS_MT_POSITION_X, x); - input_event(input, EV_ABS, ABS_MT_POSITION_Y, y); + touchscreen_report_pos(input, &ts->prop, x, y, true); input_event(input, EV_ABS, ABS_MT_PRESSURE, p); input_event(input, EV_ABS, ABS_MT_TOUCH_MAJOR, w); @@ -1328,6 +1329,8 @@ static int elants_i2c_probe(struct i2c_client *client, input_abs_set_res(ts->input, ABS_MT_POSITION_Y, ts->y_res); input_abs_set_res(ts->input, ABS_MT_TOUCH_MAJOR, 1); + touchscreen_parse_properties(ts->input, true, &ts->prop); + error = input_mt_init_slots(ts->input, MAX_CONTACT_NUM, INPUT_MT_DIRECT | INPUT_MT_DROP_UNUSED); if (error) { -- cgit v1.2.3 From 918e2844d940da7c624262a7aa327615d3eb5abd Mon Sep 17 00:00:00 2001 From: Michał Mirosław Date: Sun, 17 May 2020 20:41:05 -0700 Subject: Input: elants - refactor elants_i2c_execute_command() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Apply some DRY-ing to elants_i2c_execute_command() callers. This pulls polling and error printk()s into a single function. Signed-off-by: Michał Mirosław Link: https://lore.kernel.org/r/6c576f688b385235c65b461410a917080d27e825.1587923061.git.mirq-linux@rere.qmqm.pl Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/elants_i2c.c | 200 ++++++++++++++++----------------- 1 file changed, 99 insertions(+), 101 deletions(-) (limited to 'drivers/input') diff --git a/drivers/input/touchscreen/elants_i2c.c b/drivers/input/touchscreen/elants_i2c.c index ccaef4031556..233cb1085bbd 100644 --- a/drivers/input/touchscreen/elants_i2c.c +++ b/drivers/input/touchscreen/elants_i2c.c @@ -192,7 +192,8 @@ static int elants_i2c_read(struct i2c_client *client, void *data, size_t size) static int elants_i2c_execute_command(struct i2c_client *client, const u8 *cmd, size_t cmd_size, - u8 *resp, size_t resp_size) + u8 *resp, size_t resp_size, + int retries, const char *cmd_name) { struct i2c_msg msgs[2]; int ret; @@ -212,30 +213,55 @@ static int elants_i2c_execute_command(struct i2c_client *client, break; default: - dev_err(&client->dev, "%s: invalid command %*ph\n", - __func__, (int)cmd_size, cmd); + dev_err(&client->dev, "(%s): invalid command: %*ph\n", + cmd_name, (int)cmd_size, cmd); return -EINVAL; } - msgs[0].addr = client->addr; - msgs[0].flags = client->flags & I2C_M_TEN; - msgs[0].len = cmd_size; - msgs[0].buf = (u8 *)cmd; + for (;;) { + msgs[0].addr = client->addr; + msgs[0].flags = client->flags & I2C_M_TEN; + msgs[0].len = cmd_size; + msgs[0].buf = (u8 *)cmd; + + msgs[1].addr = client->addr; + msgs[1].flags = (client->flags & I2C_M_TEN) | I2C_M_RD; + msgs[1].flags |= I2C_M_RD; + msgs[1].len = resp_size; + msgs[1].buf = resp; + + ret = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs)); + if (ret < 0) { + if (--retries > 0) { + dev_dbg(&client->dev, + "(%s) I2C transfer failed: %pe (retrying)\n", + cmd_name, ERR_PTR(ret)); + continue; + } - msgs[1].addr = client->addr; - msgs[1].flags = client->flags & I2C_M_TEN; - msgs[1].flags |= I2C_M_RD; - msgs[1].len = resp_size; - msgs[1].buf = resp; + dev_err(&client->dev, + "(%s) I2C transfer failed: %pe\n", + cmd_name, ERR_PTR(ret)); + return ret; + } - ret = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs)); - if (ret < 0) - return ret; + if (ret != ARRAY_SIZE(msgs) || + resp[FW_HDR_TYPE] != expected_response) { + if (--retries > 0) { + dev_dbg(&client->dev, + "(%s) unexpected response: %*ph (retrying)\n", + cmd_name, ret, resp); + continue; + } - if (ret != ARRAY_SIZE(msgs) || resp[FW_HDR_TYPE] != expected_response) - return -EIO; + dev_err(&client->dev, + "(%s) unexpected response: %*ph\n", + cmd_name, ret, resp); + return -EIO; + } - return 0; + return 0; + } } static int elants_i2c_calibrate(struct elants_data *ts) @@ -308,27 +334,21 @@ static u16 elants_i2c_parse_version(u8 *buf) static int elants_i2c_query_hw_version(struct elants_data *ts) { struct i2c_client *client = ts->client; - int error, retry_cnt; + int retry_cnt = MAX_RETRIES; const u8 cmd[] = { CMD_HEADER_READ, E_ELAN_INFO_FW_ID, 0x00, 0x01 }; u8 resp[HEADER_SIZE]; + int error; - for (retry_cnt = 0; retry_cnt < MAX_RETRIES; retry_cnt++) { + while (retry_cnt--) { error = elants_i2c_execute_command(client, cmd, sizeof(cmd), - resp, sizeof(resp)); - if (!error) { - ts->hw_version = elants_i2c_parse_version(resp); - if (ts->hw_version != 0xffff) - return 0; - } - - dev_dbg(&client->dev, "read fw id error=%d, buf=%*phC\n", - error, (int)sizeof(resp), resp); - } + resp, sizeof(resp), 1, + "read fw id"); + if (error) + return error; - if (error) { - dev_err(&client->dev, - "Failed to read fw id: %d\n", error); - return error; + ts->hw_version = elants_i2c_parse_version(resp); + if (ts->hw_version != 0xffff) + return 0; } dev_err(&client->dev, "Invalid fw id: %#04x\n", ts->hw_version); @@ -339,26 +359,27 @@ static int elants_i2c_query_hw_version(struct elants_data *ts) static int elants_i2c_query_fw_version(struct elants_data *ts) { struct i2c_client *client = ts->client; - int error, retry_cnt; + int retry_cnt = MAX_RETRIES; const u8 cmd[] = { CMD_HEADER_READ, E_ELAN_INFO_FW_VER, 0x00, 0x01 }; u8 resp[HEADER_SIZE]; + int error; - for (retry_cnt = 0; retry_cnt < MAX_RETRIES; retry_cnt++) { + while (retry_cnt--) { error = elants_i2c_execute_command(client, cmd, sizeof(cmd), - resp, sizeof(resp)); - if (!error) { - ts->fw_version = elants_i2c_parse_version(resp); - if (ts->fw_version != 0x0000 && - ts->fw_version != 0xffff) - return 0; - } + resp, sizeof(resp), 1, + "read fw version"); + if (error) + return error; + + ts->fw_version = elants_i2c_parse_version(resp); + if (ts->fw_version != 0x0000 && ts->fw_version != 0xffff) + return 0; - dev_dbg(&client->dev, "read fw version error=%d, buf=%*phC\n", - error, (int)sizeof(resp), resp); + dev_dbg(&client->dev, "(read fw version) resp %*phC\n", + (int)sizeof(resp), resp); } - dev_err(&client->dev, - "Failed to read fw version or fw version is invalid\n"); + dev_err(&client->dev, "Invalid fw ver: %#04x\n", ts->fw_version); return -EINVAL; } @@ -366,30 +387,24 @@ static int elants_i2c_query_fw_version(struct elants_data *ts) static int elants_i2c_query_test_version(struct elants_data *ts) { struct i2c_client *client = ts->client; - int error, retry_cnt; + int error; u16 version; const u8 cmd[] = { CMD_HEADER_READ, E_ELAN_INFO_TEST_VER, 0x00, 0x01 }; u8 resp[HEADER_SIZE]; - for (retry_cnt = 0; retry_cnt < MAX_RETRIES; retry_cnt++) { - error = elants_i2c_execute_command(client, cmd, sizeof(cmd), - resp, sizeof(resp)); - if (!error) { - version = elants_i2c_parse_version(resp); - ts->test_version = version >> 8; - ts->solution_version = version & 0xff; - - return 0; - } - - dev_dbg(&client->dev, - "read test version error rc=%d, buf=%*phC\n", - error, (int)sizeof(resp), resp); + error = elants_i2c_execute_command(client, cmd, sizeof(cmd), + resp, sizeof(resp), MAX_RETRIES, + "read test version"); + if (error) { + dev_err(&client->dev, "Failed to read test version\n"); + return error; } - dev_err(&client->dev, "Failed to read test version\n"); + version = elants_i2c_parse_version(resp); + ts->test_version = version >> 8; + ts->solution_version = version & 0xff; - return -EINVAL; + return 0; } static int elants_i2c_query_bc_version(struct elants_data *ts) @@ -401,13 +416,10 @@ static int elants_i2c_query_bc_version(struct elants_data *ts) int error; error = elants_i2c_execute_command(client, cmd, sizeof(cmd), - resp, sizeof(resp)); - if (error) { - dev_err(&client->dev, - "read BC version error=%d, buf=%*phC\n", - error, (int)sizeof(resp), resp); + resp, sizeof(resp), 1, + "read BC version"); + if (error) return error; - } version = elants_i2c_parse_version(resp); ts->bc_version = version >> 8; @@ -439,12 +451,10 @@ static int elants_i2c_query_ts_info(struct elants_data *ts) error = elants_i2c_execute_command(client, get_resolution_cmd, sizeof(get_resolution_cmd), - resp, sizeof(resp)); - if (error) { - dev_err(&client->dev, "get resolution command failed: %d\n", - error); + resp, sizeof(resp), 1, + "get resolution"); + if (error) return error; - } rows = resp[2] + resp[6] + resp[10]; cols = resp[3] + resp[7] + resp[11]; @@ -452,36 +462,29 @@ static int elants_i2c_query_ts_info(struct elants_data *ts) /* Process mm_to_pixel information */ error = elants_i2c_execute_command(client, get_osr_cmd, sizeof(get_osr_cmd), - resp, sizeof(resp)); - if (error) { - dev_err(&client->dev, "get osr command failed: %d\n", - error); + resp, sizeof(resp), 1, "get osr"); + if (error) return error; - } osr = resp[3]; error = elants_i2c_execute_command(client, get_physical_scan_cmd, sizeof(get_physical_scan_cmd), - resp, sizeof(resp)); - if (error) { - dev_err(&client->dev, "get physical scan command failed: %d\n", - error); + resp, sizeof(resp), 1, + "get physical scan"); + if (error) return error; - } phy_x = get_unaligned_be16(&resp[2]); error = elants_i2c_execute_command(client, get_physical_drive_cmd, sizeof(get_physical_drive_cmd), - resp, sizeof(resp)); - if (error) { - dev_err(&client->dev, "get physical drive command failed: %d\n", - error); + resp, sizeof(resp), 1, + "get physical drive"); + if (error) return error; - } phy_y = get_unaligned_be16(&resp[2]); @@ -636,11 +639,10 @@ static int elants_i2c_validate_remark_id(struct elants_data *ts, /* Compare TS Remark ID and FW Remark ID */ error = elants_i2c_execute_command(client, cmd, sizeof(cmd), - resp, sizeof(resp)); - if (error) { - dev_err(&client->dev, "failed to query Remark ID: %d\n", error); + resp, sizeof(resp), + 1, "read Remark ID"); + if (error) return error; - } ts_remark_id = get_unaligned_be16(&resp[3]); @@ -1075,16 +1077,12 @@ static ssize_t show_calibration_count(struct device *dev, int error; error = elants_i2c_execute_command(client, cmd, sizeof(cmd), - resp, sizeof(resp)); - if (error) { - dev_err(&client->dev, - "read ReK status error=%d, buf=%*phC\n", - error, (int)sizeof(resp), resp); + resp, sizeof(resp), 1, + "read ReK status"); + if (error) return sprintf(buf, "%d\n", error); - } rek_count = get_unaligned_be16(&resp[2]); - return sprintf(buf, "0x%04x\n", rek_count); } -- cgit v1.2.3 From d0ac7079d5fcaaaf3eb99c197a08ac1b399754f4 Mon Sep 17 00:00:00 2001 From: Jeff LaBundy Date: Mon, 18 May 2020 11:32:18 -0700 Subject: Input: iqs269a - add missing I2C dependency If CONFIG_INPUT_IQS269A is selected yet CONFIG_I2C is not, the build fails. To solve this problem, add I2C as a dependency. Signed-off-by: Jeff LaBundy Reported-by: kbuild test robot Fixes: 04e49867fad1 ("Input: add support for Azoteq IQS269A") Link: https://lore.kernel.org/r/1589809466-22748-1-git-send-email-jeff@labundy.com Signed-off-by: Dmitry Torokhov --- drivers/input/misc/Kconfig | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/input') diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig index 943cf69b5b73..362e8a01980c 100644 --- a/drivers/input/misc/Kconfig +++ b/drivers/input/misc/Kconfig @@ -720,6 +720,7 @@ config INPUT_IMS_PCU config INPUT_IQS269A tristate "Azoteq IQS269A capacitive touch controller" + depends on I2C select REGMAP_I2C help Say Y to enable support for the Azoteq IQS269A capacitive -- cgit v1.2.3