[PATCH] generic rtc and nvram: Push the BKL down
From: Alan Cox
Date: Thu May 22 2008 - 18:11:47 EST
Switch the ioctl handlers to unlocked_ioctl and push lock_kernel into the
driver instead.
Signed-off-by: Alan Cox <alan@xxxxxxxxxx>
diff --git a/drivers/char/generic_nvram.c b/drivers/char/generic_nvram.c
index 2398e86..8886e51 100644
--- a/drivers/char/generic_nvram.c
+++ b/drivers/char/generic_nvram.c
@@ -20,7 +20,8 @@
#include <linux/fcntl.h>
#include <linux/init.h>
#include <linux/smp_lock.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
+#include <linux/smp_lock.h>
#include <asm/nvram.h>
#ifdef CONFIG_PPC_PMAC
#include <asm/machdep.h>
@@ -85,25 +86,33 @@ static ssize_t write_nvram(struct file *file, const char __user *buf,
return p - buf;
}
-static int nvram_ioctl(struct inode *inode, struct file *file,
- unsigned int cmd, unsigned long arg)
+static long nvram_ioctl(struct file *file, unsigned int cmd,
+ unsigned long arg)
{
+ int ret = 0;
switch(cmd) {
#ifdef CONFIG_PPC_PMAC
case OBSOLETE_PMAC_NVRAM_GET_OFFSET:
+ /* FIXME: should be rate limited */
printk(KERN_WARNING "nvram: Using obsolete PMAC_NVRAM_GET_OFFSET ioctl\n");
case IOC_NVRAM_GET_OFFSET: {
int part, offset;
- if (!machine_is(powermac))
- return -EINVAL;
- if (copy_from_user(&part, (void __user*)arg, sizeof(part)) != 0)
- return -EFAULT;
- if (part < pmac_nvram_OF || part > pmac_nvram_NR)
- return -EINVAL;
+ if (!machine_is(powermac)) {
+ ret = -EINVAL;
+ break;
+ }
+ if (copy_from_user(&part, (void __user*)arg, sizeof(part)) != 0) {
+ ret = -EFAULT;
+ break;
+ }
+ if (part < pmac_nvram_OF || part > pmac_nvram_NR) {
+ ret = -EINVAL;
+ break;
+ }
offset = pmac_get_partition(part);
if (copy_to_user((void __user*)arg, &offset, sizeof(offset)) != 0)
- return -EFAULT;
+ ret = -EFAULT;
break;
}
#endif /* CONFIG_PPC_PMAC */
@@ -111,10 +120,10 @@ static int nvram_ioctl(struct inode *inode, struct file *file,
nvram_sync();
break;
default:
- return -EINVAL;
+ ret = -ENOTTY;
}
-
- return 0;
+ unlock_kernel();
+ return ret;
}
const struct file_operations nvram_fops = {
@@ -122,7 +131,7 @@ const struct file_operations nvram_fops = {
.llseek = nvram_llseek,
.read = read_nvram,
.write = write_nvram,
- .ioctl = nvram_ioctl,
+ .unlocked_ioctl = nvram_ioctl,
};
static struct miscdevice nvram_dev = {
diff --git a/drivers/char/genrtc.c b/drivers/char/genrtc.c
index 69f0a29..503c9c5 100644
--- a/drivers/char/genrtc.c
+++ b/drivers/char/genrtc.c
@@ -52,8 +52,9 @@
#include <linux/poll.h>
#include <linux/proc_fs.h>
#include <linux/workqueue.h>
+#include <linux/smp_lock.h>
+#include <linux/uaccess.h>
-#include <asm/uaccess.h>
#include <asm/system.h>
#include <asm/rtc.h>
@@ -260,74 +261,89 @@ static inline int gen_set_rtc_irq_bit(unsigned char bit)
#endif
}
-static int gen_rtc_ioctl(struct inode *inode, struct file *file,
- unsigned int cmd, unsigned long arg)
+static long gen_rtc_ioctl(struct file *file, unsigned int cmd,
+ unsigned long arg)
{
struct rtc_time wtime;
struct rtc_pll_info pll;
void __user *argp = (void __user *)arg;
+ int ret = 0;
+
+ lock_kernel();
switch (cmd) {
case RTC_PLL_GET:
- if (get_rtc_pll(&pll))
- return -EINVAL;
- else
- return copy_to_user(argp, &pll, sizeof pll) ? -EFAULT : 0;
-
+ if (get_rtc_pll(&pll))
+ ret = -EINVAL;
+ else
+ ret = copy_to_user(argp, &pll, sizeof pll)
+ ? -EFAULT : 0;
+ break;
case RTC_PLL_SET:
if (!capable(CAP_SYS_TIME))
- return -EACCES;
- if (copy_from_user(&pll, argp, sizeof(pll)))
- return -EFAULT;
- return set_rtc_pll(&pll);
+ ret = -EACCES;
+ else if (copy_from_user(&pll, argp, sizeof(pll)))
+ ret = -EFAULT;
+ else
+ ret = set_rtc_pll(&pll);
+ break;
case RTC_UIE_OFF: /* disable ints from RTC updates. */
gen_clear_rtc_irq_bit(RTC_UIE);
- return 0;
+ break;
case RTC_UIE_ON: /* enable ints for RTC updates. */
- return gen_set_rtc_irq_bit(RTC_UIE);
+ ret = gen_set_rtc_irq_bit(RTC_UIE);
+ break;
case RTC_RD_TIME: /* Read the time/date from RTC */
/* this doesn't get week-day, who cares */
memset(&wtime, 0, sizeof(wtime));
get_rtc_time(&wtime);
- return copy_to_user(argp, &wtime, sizeof(wtime)) ? -EFAULT : 0;
-
+ ret = copy_to_user(argp, &wtime, sizeof(wtime))
+ ? -EFAULT : 0;
+ break;
case RTC_SET_TIME: /* Set the RTC */
- {
+ {
int year;
unsigned char leap_yr;
- if (!capable(CAP_SYS_TIME))
- return -EACCES;
-
- if (copy_from_user(&wtime, argp, sizeof(wtime)))
- return -EFAULT;
+ if (!capable(CAP_SYS_TIME)) {
+ ret = -EACCES;
+ break;
+ }
+ if (copy_from_user(&wtime, argp, sizeof(wtime))) {
+ ret = -EFAULT;
+ break;
+ }
year = wtime.tm_year + 1900;
leap_yr = ((!(year % 4) && (year % 100)) ||
!(year % 400));
+ ret = -EINVAL;
if ((wtime.tm_mon < 0 || wtime.tm_mon > 11) || (wtime.tm_mday < 1))
- return -EINVAL;
+ break;
if (wtime.tm_mday < 0 || wtime.tm_mday >
(days_in_mo[wtime.tm_mon] + ((wtime.tm_mon == 1) && leap_yr)))
- return -EINVAL;
+ break;
if (wtime.tm_hour < 0 || wtime.tm_hour >= 24 ||
wtime.tm_min < 0 || wtime.tm_min >= 60 ||
wtime.tm_sec < 0 || wtime.tm_sec >= 60)
- return -EINVAL;
+ break;
- return set_rtc_time(&wtime);
- }
+ ret = set_rtc_time(&wtime);
+ break;
}
-
- return -EINVAL;
+ default:
+ ret = -ENOTTY;
+ }
+ unlock_kernel();
+ return ret;
}
/*
@@ -476,7 +492,7 @@ 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_ioctl,
.open = gen_rtc_open,
.release = gen_rtc_release,
};
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/