summaryrefslogtreecommitdiffstats
path: root/drivers/char/pc8736x_gpio.c
AgeCommit message (Collapse)Author
2010-10-15llseek: automatically add .llseek fopArnd Bergmann
All file_operations should get a .llseek operation so we can make nonseekable_open the default for future file operations without a .llseek pointer. The three cases that we can automatically detect are no_llseek, seq_lseek and default_llseek. For cases where we can we can automatically prove that the file offset is always ignored, we use noop_llseek, which maintains the current behavior of not returning an error from a seek. New drivers should normally not use noop_llseek but instead use no_llseek and call nonseekable_open at open time. Existing drivers can be converted to do the same when the maintainer knows for certain that no user code relies on calling seek on the device file. The generated code is often incorrectly indented and right now contains comments that clarify for each added line why a specific variant was chosen. In the version that gets submitted upstream, the comments will be gone and I will manually fix the indentation, because there does not seem to be a way to do that using coccinelle. Some amount of new code is currently sitting in linux-next that should get the same modifications, which I will do at the end of the merge window. Many thanks to Julia Lawall for helping me learn to write a semantic patch that does all this. ===== begin semantic patch ===== // This adds an llseek= method to all file operations, // as a preparation for making no_llseek the default. // // The rules are // - use no_llseek explicitly if we do nonseekable_open // - use seq_lseek for sequential files // - use default_llseek if we know we access f_pos // - use noop_llseek if we know we don't access f_pos, // but we still want to allow users to call lseek // @ open1 exists @ identifier nested_open; @@ nested_open(...) { <+... nonseekable_open(...) ...+> } @ open exists@ identifier open_f; identifier i, f; identifier open1.nested_open; @@ int open_f(struct inode *i, struct file *f) { <+... ( nonseekable_open(...) | nested_open(...) ) ...+> } @ read disable optional_qualifier exists @ identifier read_f; identifier f, p, s, off; type ssize_t, size_t, loff_t; expression E; identifier func; @@ ssize_t read_f(struct file *f, char *p, size_t s, loff_t *off) { <+... ( *off = E | *off += E | func(..., off, ...) | E = *off ) ...+> } @ read_no_fpos disable optional_qualifier exists @ identifier read_f; identifier f, p, s, off; type ssize_t, size_t, loff_t; @@ ssize_t read_f(struct file *f, char *p, size_t s, loff_t *off) { ... when != off } @ write @ identifier write_f; identifier f, p, s, off; type ssize_t, size_t, loff_t; expression E; identifier func; @@ ssize_t write_f(struct file *f, const char *p, size_t s, loff_t *off) { <+... ( *off = E | *off += E | func(..., off, ...) | E = *off ) ...+> } @ write_no_fpos @ identifier write_f; identifier f, p, s, off; type ssize_t, size_t, loff_t; @@ ssize_t write_f(struct file *f, const char *p, size_t s, loff_t *off) { ... when != off } @ fops0 @ identifier fops; @@ struct file_operations fops = { ... }; @ has_llseek depends on fops0 @ identifier fops0.fops; identifier llseek_f; @@ struct file_operations fops = { ... .llseek = llseek_f, ... }; @ has_read depends on fops0 @ identifier fops0.fops; identifier read_f; @@ struct file_operations fops = { ... .read = read_f, ... }; @ has_write depends on fops0 @ identifier fops0.fops; identifier write_f; @@ struct file_operations fops = { ... .write = write_f, ... }; @ has_open depends on fops0 @ identifier fops0.fops; identifier open_f; @@ struct file_operations fops = { ... .open = open_f, ... }; // use no_llseek if we call nonseekable_open //////////////////////////////////////////// @ nonseekable1 depends on !has_llseek && has_open @ identifier fops0.fops; identifier nso ~= "nonseekable_open"; @@ struct file_operations fops = { ... .open = nso, ... +.llseek = no_llseek, /* nonseekable */ }; @ nonseekable2 depends on !has_llseek @ identifier fops0.fops; identifier open.open_f; @@ struct file_operations fops = { ... .open = open_f, ... +.llseek = no_llseek, /* open uses nonseekable */ }; // use seq_lseek for sequential files ///////////////////////////////////// @ seq depends on !has_llseek @ identifier fops0.fops; identifier sr ~= "seq_read"; @@ struct file_operations fops = { ... .read = sr, ... +.llseek = seq_lseek, /* we have seq_read */ }; // use default_llseek if there is a readdir /////////////////////////////////////////// @ fops1 depends on !has_llseek && !nonseekable1 && !nonseekable2 && !seq @ identifier fops0.fops; identifier readdir_e; @@ // any other fop is used that changes pos struct file_operations fops = { ... .readdir = readdir_e, ... +.llseek = default_llseek, /* readdir is present */ }; // use default_llseek if at least one of read/write touches f_pos ///////////////////////////////////////////////////////////////// @ fops2 depends on !fops1 && !has_llseek && !nonseekable1 && !nonseekable2 && !seq @ identifier fops0.fops; identifier read.read_f; @@ // read fops use offset struct file_operations fops = { ... .read = read_f, ... +.llseek = default_llseek, /* read accesses f_pos */ }; @ fops3 depends on !fops1 && !fops2 && !has_llseek && !nonseekable1 && !nonseekable2 && !seq @ identifier fops0.fops; identifier write.write_f; @@ // write fops use offset struct file_operations fops = { ... .write = write_f, ... + .llseek = default_llseek, /* write accesses f_pos */ }; // Use noop_llseek if neither read nor write accesses f_pos /////////////////////////////////////////////////////////// @ fops4 depends on !fops1 && !fops2 && !fops3 && !has_llseek && !nonseekable1 && !nonseekable2 && !seq @ identifier fops0.fops; identifier read_no_fpos.read_f; identifier write_no_fpos.write_f; @@ // write fops use offset struct file_operations fops = { ... .write = write_f, .read = read_f, ... +.llseek = noop_llseek, /* read and write both use no f_pos */ }; @ depends on has_write && !has_read && !fops1 && !fops2 && !has_llseek && !nonseekable1 && !nonseekable2 && !seq @ identifier fops0.fops; identifier write_no_fpos.write_f; @@ struct file_operations fops = { ... .write = write_f, ... +.llseek = noop_llseek, /* write uses no f_pos */ }; @ depends on has_read && !has_write && !fops1 && !fops2 && !has_llseek && !nonseekable1 && !nonseekable2 && !seq @ identifier fops0.fops; identifier read_no_fpos.read_f; @@ struct file_operations fops = { ... .read = read_f, ... +.llseek = noop_llseek, /* read uses no f_pos */ }; @ depends on !has_read && !has_write && !fops1 && !fops2 && !has_llseek && !nonseekable1 && !nonseekable2 && !seq @ identifier fops0.fops; @@ struct file_operations fops = { ... +.llseek = noop_llseek, /* no read or write fn */ }; ===== End semantic patch ===== Signed-off-by: Arnd Bergmann <arnd@arndb.de> Cc: Julia Lawall <julia@diku.dk> Cc: Christoph Hellwig <hch@infradead.org>
2009-10-14drivers: Remove BKL from pc8736x_gpioThomas Gleixner
cycle_kernel_lock() was added during the big BKL pushdown. It should ensure the serializiation against driver init code. In this case there is nothing to serialize. Remove it. Signed-off-by: Thomas Gleixner <tglx@linutronix.de> LKML-Reference: <20091010153350.127093710@linutronix.de> Acked-by: Jim Cromie <jim.cromie@gmail.com>
2008-10-20pc8736x_gpio: add support for PC87365 chipsAndre Haupt
This is only compile tested, because I do not own appropriate hardware. Signed-off-by: Andre Haupt <andre@bitwigglers.org> Cc: Jim Cromie <jim.cromie@gmail.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2008-06-20Add a bunch of cycle_kernel_lock() callsJonathan Corbet
All of the open() functions which don't need the BKL on their face may still depend on its acquisition to serialize opens against driver initialization. So make those functions acquire then release the BKL to be on the safe side. Signed-off-by: Jonathan Corbet <corbet@lwn.net>
2008-06-20Add "no BKL needed" comments to several driversJonathan Corbet
This documents the fact that somebody looked at the relevant open() functions and concluded that, due to their trivial nature, no locking was needed. Signed-off-by: Jonathan Corbet <corbet@lwn.net>
2006-09-29[PATCH] drivers/char/pc8736x_gpio.c: remove unused static functionsAdrian Bunk
drivers/char/pc8736x_gpio.c:192: warning: #pc8736x_gpio_set_high# defined but not used drivers/char/pc8736x_gpio.c:197: warning: #pc8736x_gpio_set_low# defined but not used Signed-off-by: Adrian Bunk <bunk@stusta.de> Acked-by: Jim Cromie <jim.cromie@gmail.com> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
2006-07-31[PATCH] drivers/char/pc8736x_gpio.c: unexport a static structAdrian Bunk
A static struct mustn't be exported. Signed-off-by: Adrian Bunk <bunk@stusta.de> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
2006-07-14[PATCH] gpio: rename exported vtables to better match purposeJim Cromie
- rename EXPORTed gpio vtables from {scx200,pc8736x}_access to _gpio_ops new name is much closer to the vtable-name struct nsc_gpio_ops, should be clearer. Also rename the _fops vtable var to _fileops to better disambiguate it from the gpio vtable. Signed-off-by: Jim Cromie <jim.cromie@gmail.com> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
2006-07-14[PATCH] gpio: drop vtable members .gpio_set_high .gpio_set_low gpio_set is ↵Jim Cromie
enough drops gpio_set_high, gpio_set_low from the nsc_gpio_ops vtable. While we can't drop them from scx200_gpio (or can we?), we dont need them for new users of the exported vtable; gpio_set(1), gpio_set(0) work fine. Signed-off-by: Jim Cromie <jim.cromie@gmail.com> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
2006-07-10[PATCH] pc8736x_gpio: fix re-modprobe errors: fix/finish cdev-initJim Cromie
- Switch from register_chrdev() to (register|alloc)_chrdev_region(). - use a cdev. This was intended for original patchset, but was overlooked. We use a single cdev for all pins (minor device-numbers), as gleaned from cs5535_gpio, and in contrast to whats currently done in scx200_gpio (which I'll fix soon) Signed-off-by: Jim Cromie <jim.cromie@gmail.com> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
2006-07-10[PATCH] pc8736x_gpio: fix re-modprobe errors: undo region reservationJim Cromie
Fix module-init-func by repairing usage of platform_device_del/put in module-exit-func. IOW, it imitates Ingo's 'mishaps' patch, which fixed the module-init-func's undo handling. Also fixes lack of release_region to undo the earlier registration. Also starts to 'use a cdev' which was originally intended (its present in scx200_gpio). Code compiles and runs, exhibits a lesser error than previously. (re-register-chrdev fails) Since I had to add "include <linux/cdev.h>", I went ahead and made 2 tweaks that fell into diff-context-window: - remove include <linux/config.h> everyone's doing it - copyright updates - current date is 'wrong' Signed-off-by: Jim Cromie <jim.cromie@gmail.com> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
2006-07-10[PATCH] pc8736x_gpio: fix re-modprobe errors: define and use constantsJim Cromie
add constant defines - preparatory patch - adds #define CONSTs for max-pin, gpio-addr-range (for reserving region) - fix wrong max-pin check in gpio_open() - add 'Winbond' to module description. NSC sold the product, Winbond has supported us / lm-sensors Signed-off-by: Jim Cromie <jim.cromie@gmail.com> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
2006-07-03[PATCH] make more file_operation structs staticArjan van de Ven
Mark the static struct file_operations in drivers/char as const. Making them const prevents accidental bugs, and moves them to the .rodata section so that they no longer do any false sharing; in addition with the proper debug option they are then protected against corruption.. [akpm@osdl.org: build fix] Signed-off-by: Arjan van de Ven <arjan@linux.intel.com> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
2006-06-30[PATCH] fix platform_device_put/del mishapsIngo Molnar
This fixes drivers/char/pc8736x_gpio.c and drivers/char/scx200_gpio.c to use the platform_device_del/put ops correctly. Signed-off-by: Ingo Molnar <mingo@elte.hu> Cc: Jim Cromie <jim.cromie@gmail.com> Cc: Greg KH <greg@kroah.com> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
2006-06-27[PATCH] gpio-patchset-fixups: include linux/io.hJim Cromie
Hmm. Im somewhat ambivalent about this patch, since with it, driver wont build for vanilla 17 or older. Its also only 1/2 of your suggestion - when I tried it, I was building against vanilla 17, and asm/uaccess.h cause compilation failure. Looking back, Im perplexed as to why linux/io.h didnt cause same failure ?!? use linux/io.h rather than asm/io.h Signed-off-by: Jim Cromie <jim.cromie@gmail.com> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
2006-06-27[PATCH] chardev: GPIO for SCx200 & PC-8736x: replace spinlocks w mutexesJim Cromie
Replace spinlocks guarding gpio config ops with mutexes. This is a me-too patch, and is justifiable insofar as mutexes have stricter semantics and better debugging support, so are preferred where they are applicable. Signed-off-by: Jim Cromie <jim.cromie@gmail.com> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
2006-06-27[PATCH] chardev: GPIO for SCx200 & PC-8736x: fix gpio_current, use shadow regsJim Cromie
Add a working gpio_current() to pc8736x_gpio.c (the previous implementation just threw a dev_warn), and fix gpio_change() to use gpio_current() rather than the incorrect (and temporary) gpio_get(). Initialize shadow-regs so this all works. Signed-off-by: Jim Cromie <jim.cromie@gmail.com> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
2006-06-27[PATCH] chardev: GPIO for SCx200 & PC-8736x: use dev_dbg in common moduleJim Cromie
Use of dev_dbg() and friends is considered good practice. dev_dbg() needs a struct device *devp, but nsc_gpio is only a helper module, so it doesnt have/need its own. To provide devp to the user-modules (scx200 & pc8736x _gpio), we add it to the vtable, and set it during init. Also squeeze nsc_gpio_dump()'s format a little. [ 199.259879] pc8736x_gpio.0: io09: 0x0044 TS OD PUE EDGE LO DEBOUNCE Signed-off-by: Jim Cromie <jim.cromie@gmail.com> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
2006-06-27[PATCH] chardev: GPIO for SCx200 & PC-8736x: add platform_device for use w ↵Jim Cromie
dev_dbg Adds platform-device to (just introduced) driver, and uses it to replace many printks with dev_dbg() etc. This could trivially be merged into previous patch, but this way matches better with the corresponding patch that does the same change to scx200_gpio. Signed-off-by: Jim Cromie <jim.cromie@gmail.com> Cc: Greg KH <greg@kroah.com> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
2006-06-27[PATCH] chardev: GPIO for SCx200 & PC-8736x: add new pc8736x_gpio moduleJim Cromie
Add the brand new pc8736x_gpio driver. This is mostly based upon scx200_gpio.c, but the platform_dev is treated separately, since its fairly big too. Signed-off-by: Jim Cromie <jim.cromie@gmail.com> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>