diff options
Diffstat (limited to 'drivers/char/genrtc.c')
| -rw-r--r-- | drivers/char/genrtc.c | 75 |
1 files changed, 43 insertions, 32 deletions
diff --git a/drivers/char/genrtc.c b/drivers/char/genrtc.c index 31e7c91c2d9..4f943759d37 100644 --- a/drivers/char/genrtc.c +++ b/drivers/char/genrtc.c @@ -52,11 +52,11 @@ #include <linux/init.h> #include <linux/poll.h> #include <linux/proc_fs.h> -#include <linux/smp_lock.h> +#include <linux/seq_file.h> +#include <linux/mutex.h> #include <linux/workqueue.h> #include <asm/uaccess.h> -#include <asm/system.h> #include <asm/rtc.h> /* @@ -66,6 +66,7 @@ * ioctls. */ +static DEFINE_MUTEX(gen_rtc_mutex); static DECLARE_WAIT_QUEUE_HEAD(gen_rtc_wait); /* @@ -262,7 +263,7 @@ static inline int gen_set_rtc_irq_bit(unsigned char bit) #endif } -static int gen_rtc_ioctl(struct inode *inode, struct file *file, +static int gen_rtc_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { struct rtc_time wtime; @@ -332,6 +333,18 @@ static int gen_rtc_ioctl(struct inode *inode, struct file *file, return -EINVAL; } +static long gen_rtc_unlocked_ioctl(struct file *file, unsigned int cmd, + unsigned long arg) +{ + int ret; + + mutex_lock(&gen_rtc_mutex); + ret = gen_rtc_ioctl(file, cmd, arg); + mutex_unlock(&gen_rtc_mutex); + + return ret; +} + /* * We enforce only one user at a time here with the open/close. * Also clear the previous interrupt data on an open, and clean @@ -340,16 +353,16 @@ static int gen_rtc_ioctl(struct inode *inode, struct file *file, static int gen_rtc_open(struct inode *inode, struct file *file) { - lock_kernel(); + mutex_lock(&gen_rtc_mutex); if (gen_rtc_status & RTC_IS_OPEN) { - unlock_kernel(); + mutex_unlock(&gen_rtc_mutex); return -EBUSY; } gen_rtc_status |= RTC_IS_OPEN; gen_rtc_irq_data = 0; irq_active = 0; - unlock_kernel(); + mutex_unlock(&gen_rtc_mutex); return 0; } @@ -374,18 +387,15 @@ static int gen_rtc_release(struct inode *inode, struct file *file) * Info exported via "/proc/driver/rtc". */ -static int gen_rtc_proc_output(char *buf) +static int gen_rtc_proc_show(struct seq_file *m, void *v) { - char *p; struct rtc_time tm; unsigned int flags; struct rtc_pll_info pll; - p = buf; - flags = get_rtc_time(&tm); - p += sprintf(p, + seq_printf(m, "rtc_time\t: %02d:%02d:%02d\n" "rtc_date\t: %04d-%02d-%02d\n" "rtc_epoch\t: %04u\n", @@ -394,23 +404,23 @@ static int gen_rtc_proc_output(char *buf) tm.tm_hour = tm.tm_min = tm.tm_sec = 0; - p += sprintf(p, "alarm\t\t: "); + seq_puts(m, "alarm\t\t: "); if (tm.tm_hour <= 24) - p += sprintf(p, "%02d:", tm.tm_hour); + seq_printf(m, "%02d:", tm.tm_hour); else - p += sprintf(p, "**:"); + seq_puts(m, "**:"); if (tm.tm_min <= 59) - p += sprintf(p, "%02d:", tm.tm_min); + seq_printf(m, "%02d:", tm.tm_min); else - p += sprintf(p, "**:"); + seq_puts(m, "**:"); if (tm.tm_sec <= 59) - p += sprintf(p, "%02d\n", tm.tm_sec); + seq_printf(m, "%02d\n", tm.tm_sec); else - p += sprintf(p, "**\n"); + seq_puts(m, "**\n"); - p += sprintf(p, + seq_printf(m, "DST_enable\t: %s\n" "BCD\t\t: %s\n" "24hr\t\t: %s\n" @@ -430,7 +440,7 @@ static int gen_rtc_proc_output(char *buf) 0L /* freq */, (flags & RTC_BATT_BAD) ? "bad" : "okay"); if (!get_rtc_pll(&pll)) - p += sprintf(p, + seq_printf(m, "PLL adjustment\t: %d\n" "PLL max +ve adjustment\t: %d\n" "PLL max -ve adjustment\t: %d\n" @@ -443,26 +453,26 @@ static int gen_rtc_proc_output(char *buf) pll.pll_posmult, pll.pll_negmult, pll.pll_clock); - return p - buf; + return 0; } -static int gen_rtc_read_proc(char *page, char **start, off_t off, - int count, int *eof, void *data) +static int gen_rtc_proc_open(struct inode *inode, struct file *file) { - int len = gen_rtc_proc_output (page); - if (len <= off+count) *eof = 1; - *start = page + off; - len -= off; - if (len>count) len = count; - if (len<0) len = 0; - return len; + return single_open(file, gen_rtc_proc_show, NULL); } +static const struct file_operations gen_rtc_proc_fops = { + .open = gen_rtc_proc_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + static int __init gen_rtc_proc_init(void) { struct proc_dir_entry *r; - r = create_proc_read_entry("driver/rtc", 0, NULL, gen_rtc_read_proc, NULL); + r = proc_create("driver/rtc", 0, NULL, &gen_rtc_proc_fops); if (!r) return -ENOMEM; return 0; @@ -482,9 +492,10 @@ static const struct file_operations gen_rtc_fops = { .read = gen_rtc_read, .poll = gen_rtc_poll, #endif - .ioctl = gen_rtc_ioctl, + .unlocked_ioctl = gen_rtc_unlocked_ioctl, .open = gen_rtc_open, .release = gen_rtc_release, + .llseek = noop_llseek, }; static struct miscdevice rtc_gen_dev = |
