From 54066a57c584ee8ce767053116fc4943ed1168b5 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Mon, 22 Mar 2010 20:55:11 +0100 Subject: hpet: kill BKL, add compat_ioctl hpet uses the big kernel lock in its ioctl and open functions. Replace this with a private mutex to be sure. Since we're already touching the ioctl function, add the compat_ioctl version as well -- all commands except HPET_INFO are compatible and that one is easy to add. Signed-off-by: Arnd Bergmann Cc: Clemens Ladisch Cc: Bob Picco --- drivers/char/hpet.c | 98 ++++++++++++++++++++++++++++++++++------------------- 1 file changed, 64 insertions(+), 34 deletions(-) (limited to 'drivers') diff --git a/drivers/char/hpet.c b/drivers/char/hpet.c index a0a1829d319..a4eee324eb1 100644 --- a/drivers/char/hpet.c +++ b/drivers/char/hpet.c @@ -30,6 +30,7 @@ #include #include #include +#include #include #include @@ -67,6 +68,7 @@ #define read_counter(MC) readl(MC) #endif +static DEFINE_MUTEX(hpet_mutex); /* replaces BKL */ static u32 hpet_nhpet, hpet_max_freq = HPET_USER_FREQ; /* This clocksource driver currently only works on ia64 */ @@ -250,7 +252,7 @@ static int hpet_open(struct inode *inode, struct file *file) if (file->f_mode & FMODE_WRITE) return -EINVAL; - lock_kernel(); + mutex_lock(&hpet_mutex); spin_lock_irq(&hpet_lock); for (devp = NULL, hpetp = hpets; hpetp && !devp; hpetp = hpetp->hp_next) @@ -264,7 +266,7 @@ static int hpet_open(struct inode *inode, struct file *file) if (!devp) { spin_unlock_irq(&hpet_lock); - unlock_kernel(); + mutex_unlock(&hpet_mutex); return -EBUSY; } @@ -272,7 +274,7 @@ static int hpet_open(struct inode *inode, struct file *file) devp->hd_irqdata = 0; devp->hd_flags |= HPET_OPEN; spin_unlock_irq(&hpet_lock); - unlock_kernel(); + mutex_unlock(&hpet_mutex); hpet_timer_set_irq(devp); @@ -429,22 +431,6 @@ static int hpet_release(struct inode *inode, struct file *file) return 0; } -static int hpet_ioctl_common(struct hpet_dev *, int, unsigned long, int); - -static long hpet_ioctl(struct file *file, unsigned int cmd, - unsigned long arg) -{ - struct hpet_dev *devp; - int ret; - - devp = file->private_data; - lock_kernel(); - ret = hpet_ioctl_common(devp, cmd, arg, 0); - unlock_kernel(); - - return ret; -} - static int hpet_ioctl_ieon(struct hpet_dev *devp) { struct hpet_timer __iomem *timer; @@ -553,7 +539,8 @@ static inline unsigned long hpet_time_div(struct hpets *hpets, } static int -hpet_ioctl_common(struct hpet_dev *devp, int cmd, unsigned long arg, int kernel) +hpet_ioctl_common(struct hpet_dev *devp, int cmd, unsigned long arg, + struct hpet_info *info) { struct hpet_timer __iomem *timer; struct hpet __iomem *hpet; @@ -594,23 +581,15 @@ hpet_ioctl_common(struct hpet_dev *devp, int cmd, unsigned long arg, int kernel) break; case HPET_INFO: { - struct hpet_info info; - if (devp->hd_ireqfreq) - info.hi_ireqfreq = + info->hi_ireqfreq = hpet_time_div(hpetp, devp->hd_ireqfreq); else - info.hi_ireqfreq = 0; - info.hi_flags = + info->hi_ireqfreq = 0; + info->hi_flags = readq(&timer->hpet_config) & Tn_PER_INT_CAP_MASK; - info.hi_hpet = hpetp->hp_which; - info.hi_timer = devp - hpetp->hp_dev; - if (kernel) - memcpy((void *)arg, &info, sizeof(info)); - else - if (copy_to_user((void __user *)arg, &info, - sizeof(info))) - err = -EFAULT; + info->hi_hpet = hpetp->hp_which; + info->hi_timer = devp - hpetp->hp_dev; break; } case HPET_EPI: @@ -636,7 +615,7 @@ hpet_ioctl_common(struct hpet_dev *devp, int cmd, unsigned long arg, int kernel) devp->hd_flags &= ~HPET_PERIODIC; break; case HPET_IRQFREQ: - if (!kernel && (arg > hpet_max_freq) && + if ((arg > hpet_max_freq) && !capable(CAP_SYS_RESOURCE)) { err = -EACCES; break; @@ -653,12 +632,63 @@ hpet_ioctl_common(struct hpet_dev *devp, int cmd, unsigned long arg, int kernel) return err; } +static long +hpet_ioctl(struct file *file, unsigned int cmd, unsigned long arg) +{ + struct hpet_info info; + int err; + + mutex_lock(&hpet_mutex); + err = hpet_ioctl_common(file->private_data, cmd, arg, &info); + mutex_unlock(&hpet_mutex); + + if ((cmd == HPET_INFO) && !err && + (copy_to_user((void __user *)arg, &info, sizeof(info)))) + err = -EFAULT; + + return err; +} + +#ifdef CONFIG_COMPAT +struct compat_hpet_info { + compat_ulong_t hi_ireqfreq; /* Hz */ + compat_ulong_t hi_flags; /* information */ + unsigned short hi_hpet; + unsigned short hi_timer; +}; + +static long +hpet_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg) +{ + struct hpet_info info; + int err; + + mutex_lock(&hpet_mutex); + err = hpet_ioctl_common(file->private_data, cmd, arg, &info); + mutex_unlock(&hpet_mutex); + + if ((cmd == HPET_INFO) && !err) { + struct compat_hpet_info __user *u = compat_ptr(arg); + if (put_user(info.hi_ireqfreq, &u->hi_ireqfreq) || + put_user(info.hi_flags, &u->hi_flags) || + put_user(info.hi_hpet, &u->hi_hpet) || + put_user(info.hi_timer, &u->hi_timer)) + err = -EFAULT; + } + + return err; +} +#endif + static const struct file_operations hpet_fops = { .owner = THIS_MODULE, .llseek = no_llseek, .read = hpet_read, .poll = hpet_poll, .unlocked_ioctl = hpet_ioctl, +#ifdef CONFIG_COMPAT + .compat_ioctl = hpet_compat_ioctl, +#endif .open = hpet_open, .release = hpet_release, .fasync = hpet_fasync, -- cgit v1.2.3 From cfdb00a77ea7d5fb922fd985e5dfbcb36873411b Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Mon, 31 May 2010 22:38:40 +0200 Subject: s390/block: kill the big kernel lock The dasd and dcssblk drivers gained the big kernel lock in the recent pushdown from the block layer, but they don't really need it, so remove the calls without a replacement. Signed-off-by: Arnd Bergmann Cc: Martin Schwidefsky Cc: Heiko Carstens Cc: linux-s390@vger.kernel.org --- drivers/s390/block/dasd.c | 6 ------ drivers/s390/block/dasd_ioctl.c | 17 ++--------------- drivers/s390/block/dcssblk.c | 5 ----- 3 files changed, 2 insertions(+), 26 deletions(-) (limited to 'drivers') diff --git a/drivers/s390/block/dasd.c b/drivers/s390/block/dasd.c index 8373ca0de8e..38e6fa9a201 100644 --- a/drivers/s390/block/dasd.c +++ b/drivers/s390/block/dasd.c @@ -21,7 +21,6 @@ #include #include #include -#include #include #include @@ -2236,7 +2235,6 @@ static int dasd_open(struct block_device *bdev, fmode_t mode) if (!block) return -ENODEV; - lock_kernel(); base = block->base; atomic_inc(&block->open_count); if (test_bit(DASD_FLAG_OFFLINE, &base->flags)) { @@ -2271,14 +2269,12 @@ static int dasd_open(struct block_device *bdev, fmode_t mode) goto out; } - unlock_kernel(); return 0; out: module_put(base->discipline->owner); unlock: atomic_dec(&block->open_count); - unlock_kernel(); return rc; } @@ -2286,10 +2282,8 @@ static int dasd_release(struct gendisk *disk, fmode_t mode) { struct dasd_block *block = disk->private_data; - lock_kernel(); atomic_dec(&block->open_count); module_put(block->base->discipline->owner); - unlock_kernel(); return 0; } diff --git a/drivers/s390/block/dasd_ioctl.c b/drivers/s390/block/dasd_ioctl.c index 1557214944f..26075e95b1b 100644 --- a/drivers/s390/block/dasd_ioctl.c +++ b/drivers/s390/block/dasd_ioctl.c @@ -16,7 +16,6 @@ #include #include #include -#include #include #include #include @@ -370,9 +369,8 @@ static int dasd_ioctl_readall_cmb(struct dasd_block *block, unsigned int cmd, return ret; } -static int -dasd_do_ioctl(struct block_device *bdev, fmode_t mode, - unsigned int cmd, unsigned long arg) +int dasd_ioctl(struct block_device *bdev, fmode_t mode, + unsigned int cmd, unsigned long arg) { struct dasd_block *block = bdev->bd_disk->private_data; void __user *argp; @@ -430,14 +428,3 @@ dasd_do_ioctl(struct block_device *bdev, fmode_t mode, return -EINVAL; } } - -int dasd_ioctl(struct block_device *bdev, fmode_t mode, - unsigned int cmd, unsigned long arg) -{ - int rc; - - lock_kernel(); - rc = dasd_do_ioctl(bdev, mode, cmd, arg); - unlock_kernel(); - return rc; -} diff --git a/drivers/s390/block/dcssblk.c b/drivers/s390/block/dcssblk.c index 2bd72aa34c5..9b43ae94beb 100644 --- a/drivers/s390/block/dcssblk.c +++ b/drivers/s390/block/dcssblk.c @@ -14,7 +14,6 @@ #include #include #include -#include #include #include #include @@ -776,7 +775,6 @@ dcssblk_open(struct block_device *bdev, fmode_t mode) struct dcssblk_dev_info *dev_info; int rc; - lock_kernel(); dev_info = bdev->bd_disk->private_data; if (NULL == dev_info) { rc = -ENODEV; @@ -786,7 +784,6 @@ dcssblk_open(struct block_device *bdev, fmode_t mode) bdev->bd_block_size = 4096; rc = 0; out: - unlock_kernel(); return rc; } @@ -797,7 +794,6 @@ dcssblk_release(struct gendisk *disk, fmode_t mode) struct segment_info *entry; int rc; - lock_kernel(); if (!dev_info) { rc = -ENODEV; goto out; @@ -815,7 +811,6 @@ dcssblk_release(struct gendisk *disk, fmode_t mode) up_write(&dcssblk_devices_sem); rc = 0; out: - unlock_kernel(); return rc; } -- cgit v1.2.3 From 6117d2130c9da5977e975ad9fa607b86d6516a44 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Sat, 5 Jun 2010 13:28:09 +0200 Subject: isapnp: BKL removal Remove BKL use from isapnp_proc_bus_lseek(), like was done for proc_bus_pci_lseek() a long time ago and recently for Zorro by Geert Uytterhoeven. Signed-off-by: Arnd Bergmann Cc: Geert Uytterhoeven Cc: Jaroslav Kysela --- drivers/pnp/isapnp/proc.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/pnp/isapnp/proc.c b/drivers/pnp/isapnp/proc.c index 3f94edab25f..e73ebefdf3e 100644 --- a/drivers/pnp/isapnp/proc.c +++ b/drivers/pnp/isapnp/proc.c @@ -31,8 +31,9 @@ static struct proc_dir_entry *isapnp_proc_bus_dir = NULL; static loff_t isapnp_proc_bus_lseek(struct file *file, loff_t off, int whence) { loff_t new = -1; + struct inode *inode = file->f_path.dentry->d_inode; - lock_kernel(); + mutex_lock(&inode->i_mutex); switch (whence) { case 0: new = off; @@ -44,12 +45,12 @@ static loff_t isapnp_proc_bus_lseek(struct file *file, loff_t off, int whence) new = 256 + off; break; } - if (new < 0 || new > 256) { - unlock_kernel(); - return -EINVAL; - } - unlock_kernel(); - return (file->f_pos = new); + if (new < 0 || new > 256) + new = -EINVAL; + else + file->f_pos = new; + mutex_unlock(&inode->i_mutex); + return new; } static ssize_t isapnp_proc_bus_read(struct file *file, char __user * buf, -- cgit v1.2.3 From c4a047272566b44b44222369d50a307c708c4f74 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Mon, 24 Aug 2009 22:42:56 +0000 Subject: fix rawctl compat ioctls breakage on amd64 and itanic RAW_SETBIND and RAW_GETBIND 32bit versions are fscked in interesting ways. 1) fs/compat_ioctl.c has COMPATIBLE_IOCTL(RAW_SETBIND) followed by HANDLE_IOCTL(RAW_SETBIND, raw_ioctl). The latter is ignored. 2) on amd64 (and itanic) the damn thing is broken - we have int + u64 + u64 and layouts on i386 and amd64 are _not_ the same. raw_ioctl() would work there, but it's never called due to (1). As it is, i386 /sbin/raw definitely doesn't work on amd64 boxen. 3) switching to raw_ioctl() as is would *not* work on e.g. sparc64 and ppc64, which would be rather sad, seeing that normal userland there is 32bit. The thing is, slapping __packed on the struct in question does not DTRT - it eliminates *all* padding. The real solution is to use compat_u64. 4) of course, all that stuff has no business being outside of raw.c in the first place - there should be ->compat_ioctl() for /dev/rawctl instead of messing with compat_ioctl.c. [akpm@linux-foundation.org: coding-style fixes] [arnd@arndb.de: port to 2.6.36] Signed-off-by: Al Viro Signed-off-by: Andrew Morton Signed-off-by: Arnd Bergmann --- drivers/char/raw.c | 243 ++++++++++++++++++++++++++++++----------------------- 1 file changed, 140 insertions(+), 103 deletions(-) (limited to 'drivers') diff --git a/drivers/char/raw.c b/drivers/char/raw.c index b38942f6bf3..24b2b9160aa 100644 --- a/drivers/char/raw.c +++ b/drivers/char/raw.c @@ -19,8 +19,8 @@ #include #include #include -#include #include +#include #include @@ -55,7 +55,6 @@ static int raw_open(struct inode *inode, struct file *filp) return 0; } - lock_kernel(); mutex_lock(&raw_mutex); /* @@ -82,7 +81,6 @@ static int raw_open(struct inode *inode, struct file *filp) bdev->bd_inode->i_mapping; filp->private_data = bdev; mutex_unlock(&raw_mutex); - unlock_kernel(); return 0; out2: @@ -91,7 +89,6 @@ out1: blkdev_put(bdev, filp->f_mode); out: mutex_unlock(&raw_mutex); - unlock_kernel(); return err; } @@ -125,20 +122,84 @@ static long raw_ioctl(struct file *filp, unsigned int command, unsigned long arg) { struct block_device *bdev = filp->private_data; - int ret; + return blkdev_ioctl(bdev, 0, command, arg); +} + +static int bind_set(int number, u64 major, u64 minor) +{ + dev_t dev = MKDEV(major, minor); + struct raw_device_data *rawdev; + int err = 0; - lock_kernel(); - ret = blkdev_ioctl(bdev, 0, command, arg); - unlock_kernel(); + if (number <= 0 || number >= MAX_RAW_MINORS) + return -EINVAL; - return ret; + if (MAJOR(dev) != major || MINOR(dev) != minor) + return -EINVAL; + + rawdev = &raw_devices[number]; + + /* + * This is like making block devices, so demand the + * same capability + */ + if (!capable(CAP_SYS_ADMIN)) + return -EPERM; + + /* + * For now, we don't need to check that the underlying + * block device is present or not: we can do that when + * the raw device is opened. Just check that the + * major/minor numbers make sense. + */ + + if (MAJOR(dev) == 0 && dev != 0) + return -EINVAL; + + mutex_lock(&raw_mutex); + if (rawdev->inuse) { + mutex_unlock(&raw_mutex); + return -EBUSY; + } + if (rawdev->binding) { + bdput(rawdev->binding); + module_put(THIS_MODULE); + } + if (!dev) { + /* unbind */ + rawdev->binding = NULL; + device_destroy(raw_class, MKDEV(RAW_MAJOR, number)); + } else { + rawdev->binding = bdget(dev); + if (rawdev->binding == NULL) { + err = -ENOMEM; + } else { + dev_t raw = MKDEV(RAW_MAJOR, number); + __module_get(THIS_MODULE); + device_destroy(raw_class, raw); + device_create(raw_class, NULL, raw, NULL, + "raw%d", number); + } + } + mutex_unlock(&raw_mutex); + return err; } -static void bind_device(struct raw_config_request *rq) +static int bind_get(int number, dev_t *dev) { - device_destroy(raw_class, MKDEV(RAW_MAJOR, rq->raw_minor)); - device_create(raw_class, NULL, MKDEV(RAW_MAJOR, rq->raw_minor), NULL, - "raw%d", rq->raw_minor); + struct raw_device_data *rawdev; + struct block_device *bdev; + + if (number <= 0 || number >= MAX_RAW_MINORS) + return -EINVAL; + + rawdev = &raw_devices[number]; + + mutex_lock(&raw_mutex); + bdev = rawdev->binding; + *dev = bdev ? bdev->bd_dev : 0; + mutex_unlock(&raw_mutex); + return 0; } /* @@ -149,105 +210,78 @@ static long raw_ctl_ioctl(struct file *filp, unsigned int command, unsigned long arg) { struct raw_config_request rq; - struct raw_device_data *rawdev; - int err = 0; + dev_t dev; + int err; - lock_kernel(); switch (command) { case RAW_SETBIND: + if (copy_from_user(&rq, (void __user *) arg, sizeof(rq))) + return -EFAULT; + + return bind_set(rq.raw_minor, rq.block_major, rq.block_minor); + case RAW_GETBIND: + if (copy_from_user(&rq, (void __user *) arg, sizeof(rq))) + return -EFAULT; - /* First, find out which raw minor we want */ + err = bind_get(rq.raw_minor, &dev); + if (err) + return err; - if (copy_from_user(&rq, (void __user *) arg, sizeof(rq))) { - err = -EFAULT; - goto out; - } + rq.block_major = MAJOR(dev); + rq.block_minor = MINOR(dev); - if (rq.raw_minor <= 0 || rq.raw_minor >= MAX_RAW_MINORS) { - err = -EINVAL; - goto out; - } - rawdev = &raw_devices[rq.raw_minor]; - - if (command == RAW_SETBIND) { - dev_t dev; - - /* - * This is like making block devices, so demand the - * same capability - */ - if (!capable(CAP_SYS_ADMIN)) { - err = -EPERM; - goto out; - } - - /* - * For now, we don't need to check that the underlying - * block device is present or not: we can do that when - * the raw device is opened. Just check that the - * major/minor numbers make sense. - */ - - dev = MKDEV(rq.block_major, rq.block_minor); - if ((rq.block_major == 0 && rq.block_minor != 0) || - MAJOR(dev) != rq.block_major || - MINOR(dev) != rq.block_minor) { - err = -EINVAL; - goto out; - } - - mutex_lock(&raw_mutex); - if (rawdev->inuse) { - mutex_unlock(&raw_mutex); - err = -EBUSY; - goto out; - } - if (rawdev->binding) { - bdput(rawdev->binding); - module_put(THIS_MODULE); - } - if (rq.block_major == 0 && rq.block_minor == 0) { - /* unbind */ - rawdev->binding = NULL; - device_destroy(raw_class, - MKDEV(RAW_MAJOR, rq.raw_minor)); - } else { - rawdev->binding = bdget(dev); - if (rawdev->binding == NULL) - err = -ENOMEM; - else { - __module_get(THIS_MODULE); - bind_device(&rq); - } - } - mutex_unlock(&raw_mutex); - } else { - struct block_device *bdev; - - mutex_lock(&raw_mutex); - bdev = rawdev->binding; - if (bdev) { - rq.block_major = MAJOR(bdev->bd_dev); - rq.block_minor = MINOR(bdev->bd_dev); - } else { - rq.block_major = rq.block_minor = 0; - } - mutex_unlock(&raw_mutex); - if (copy_to_user((void __user *)arg, &rq, sizeof(rq))) { - err = -EFAULT; - goto out; - } - } - break; - default: - err = -EINVAL; - break; + if (copy_to_user((void __user *)arg, &rq, sizeof(rq))) + return -EFAULT; + + return 0; } -out: - unlock_kernel(); - return err; + + return -EINVAL; +} + +#ifdef CONFIG_COMPAT +struct raw32_config_request { + compat_int_t raw_minor; + compat_u64 block_major; + compat_u64 block_minor; +}; + +static long raw_ctl_compat_ioctl(struct file *file, unsigned int cmd, + unsigned long arg) +{ + struct raw32_config_request __user *user_req = compat_ptr(arg); + struct raw32_config_request rq; + dev_t dev; + int err = 0; + + switch (cmd) { + case RAW_SETBIND: + if (copy_from_user(&rq, user_req, sizeof(rq))) + return -EFAULT; + + return bind_set(rq.raw_minor, rq.block_major, rq.block_minor); + + case RAW_GETBIND: + if (copy_from_user(&rq, user_req, sizeof(rq))) + return -EFAULT; + + err = bind_get(rq.raw_minor, &dev); + if (err) + return err; + + rq.block_major = MAJOR(dev); + rq.block_minor = MINOR(dev); + + if (copy_to_user(user_req, &rq, sizeof(rq))) + return -EFAULT; + + return 0; + } + + return -EINVAL; } +#endif static const struct file_operations raw_fops = { .read = do_sync_read, @@ -263,6 +297,9 @@ static const struct file_operations raw_fops = { static const struct file_operations raw_ctl_fops = { .unlocked_ioctl = raw_ctl_ioctl, +#ifdef CONFIG_COMPAT + .compat_ioctl = raw_ctl_compat_ioctl, +#endif .open = raw_open, .owner = THIS_MODULE, }; -- cgit v1.2.3 From efbec1cd042008b49fe3cad45604088c54905a06 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Sat, 11 Sep 2010 19:31:43 +0200 Subject: tlclk: remove big kernel lock This driver already has a global mutex, so let's just use that in the open function instead of the BKL. It may not even be needed there, but this patch should have the smallest impact. Signed-off-by: Arnd Bergmann Cc: Mark Gross --- drivers/char/tlclk.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/char/tlclk.c b/drivers/char/tlclk.c index 80ea6bcfffd..e32cbf0c9a0 100644 --- a/drivers/char/tlclk.c +++ b/drivers/char/tlclk.c @@ -37,7 +37,7 @@ #include #include #include -#include +#include #include #include #include @@ -206,7 +206,7 @@ static int tlclk_open(struct inode *inode, struct file *filp) { int result; - lock_kernel(); + mutex_lock(&tlclk_mutex); if (test_and_set_bit(0, &useflags)) { result = -EBUSY; /* this legacy device is always one per system and it doesn't @@ -229,7 +229,7 @@ static int tlclk_open(struct inode *inode, struct file *filp) inb(TLCLK_REG6); /* Clear interrupt events */ out: - unlock_kernel(); + mutex_unlock(&tlclk_mutex); return result; } -- cgit v1.2.3 From adfedd216d9f0bc3f5bfa8aab42932301d4edc31 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Sat, 11 Sep 2010 19:53:25 +0200 Subject: dvb/bt8xx: kill the big kernel lock The bt8xx driver only uses the big kernel lock in its dst_ca_ioctl function and never to serialize against other code, so we can trivially replace it with a private mutex. Signed-off-by: Arnd Bergmann Cc: linux-media@vger.kernel.org Cc: Mauro Carvalho Chehab --- drivers/media/dvb/bt8xx/dst_ca.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb/bt8xx/dst_ca.c b/drivers/media/dvb/bt8xx/dst_ca.c index cf870516284..d75788b4e22 100644 --- a/drivers/media/dvb/bt8xx/dst_ca.c +++ b/drivers/media/dvb/bt8xx/dst_ca.c @@ -22,7 +22,7 @@ #include #include #include -#include +#include #include #include #include "dvbdev.h" @@ -52,6 +52,7 @@ } while(0) +static DEFINE_MUTEX(dst_ca_mutex); static unsigned int verbose = 5; module_param(verbose, int, 0644); MODULE_PARM_DESC(verbose, "verbose startup messages, default is 1 (yes)"); @@ -564,7 +565,7 @@ static long dst_ca_ioctl(struct file *file, unsigned int cmd, unsigned long ioct void __user *arg = (void __user *)ioctl_arg; int result = 0; - lock_kernel(); + mutex_lock(&dst_ca_mutex); dvbdev = file->private_data; state = (struct dst_state *)dvbdev->priv; p_ca_message = kmalloc(sizeof (struct ca_msg), GFP_KERNEL); @@ -652,7 +653,7 @@ static long dst_ca_ioctl(struct file *file, unsigned int cmd, unsigned long ioct kfree (p_ca_slot_info); kfree (p_ca_caps); - unlock_kernel(); + mutex_unlock(&dst_ca_mutex); return result; } -- cgit v1.2.3 From 72024f1ec5164a70d84dd8cf4458fe4064a6b692 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Sat, 11 Sep 2010 19:56:45 +0200 Subject: dvb-core: kill the big kernel lock The dvb core only uses the big kernel lock in the open and ioctl functions, which means it can be replaced with a dvb specific mutex. Fortunately, all the ioctl functions go through dvb_usercopy, so we can move the serialization in there. Signed-off-by: Arnd Bergmann Cc: Mauro Carvalho Chehab Cc: linux-media@vger.kernel.org --- drivers/media/dvb/dvb-core/dmxdev.c | 17 ++--------------- drivers/media/dvb/dvb-core/dvb_ca_en50221.c | 8 +------- drivers/media/dvb/dvb-core/dvb_net.c | 9 +-------- drivers/media/dvb/dvb-core/dvbdev.c | 17 +++++++---------- 4 files changed, 11 insertions(+), 40 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb/dvb-core/dmxdev.c b/drivers/media/dvb/dvb-core/dmxdev.c index 0042306ea11..2de13b04b09 100644 --- a/drivers/media/dvb/dvb-core/dmxdev.c +++ b/drivers/media/dvb/dvb-core/dmxdev.c @@ -25,7 +25,6 @@ #include #include #include -#include #include #include #include @@ -1088,13 +1087,7 @@ static int dvb_demux_do_ioctl(struct file *file, static long dvb_demux_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { - int ret; - - lock_kernel(); - ret = dvb_usercopy(file, cmd, arg, dvb_demux_do_ioctl); - unlock_kernel(); - - return ret; + return dvb_usercopy(file, cmd, arg, dvb_demux_do_ioctl); } static unsigned int dvb_demux_poll(struct file *file, poll_table *wait) @@ -1186,13 +1179,7 @@ static int dvb_dvr_do_ioctl(struct file *file, static long dvb_dvr_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { - int ret; - - lock_kernel(); - ret = dvb_usercopy(file, cmd, arg, dvb_dvr_do_ioctl); - unlock_kernel(); - - return ret; + return dvb_usercopy(file, cmd, arg, dvb_dvr_do_ioctl); } static unsigned int dvb_dvr_poll(struct file *file, poll_table *wait) diff --git a/drivers/media/dvb/dvb-core/dvb_ca_en50221.c b/drivers/media/dvb/dvb-core/dvb_ca_en50221.c index cb97e6b8543..1723a984a52 100644 --- a/drivers/media/dvb/dvb-core/dvb_ca_en50221.c +++ b/drivers/media/dvb/dvb-core/dvb_ca_en50221.c @@ -1259,13 +1259,7 @@ static int dvb_ca_en50221_io_do_ioctl(struct file *file, static long dvb_ca_en50221_io_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { - int ret; - - lock_kernel(); - ret = dvb_usercopy(file, cmd, arg, dvb_ca_en50221_io_do_ioctl); - unlock_kernel(); - - return ret; + return dvb_usercopy(file, cmd, arg, dvb_ca_en50221_io_do_ioctl); } diff --git a/drivers/media/dvb/dvb-core/dvb_net.c b/drivers/media/dvb/dvb-core/dvb_net.c index 6c3a8a06cca..a08032284cb 100644 --- a/drivers/media/dvb/dvb-core/dvb_net.c +++ b/drivers/media/dvb/dvb-core/dvb_net.c @@ -59,7 +59,6 @@ #include #include #include -#include #include #include #include @@ -1445,13 +1444,7 @@ static int dvb_net_do_ioctl(struct file *file, static long dvb_net_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { - int ret; - - lock_kernel(); - ret = dvb_usercopy(file, cmd, arg, dvb_net_do_ioctl); - unlock_kernel(); - - return ret; + return dvb_usercopy(file, cmd, arg, dvb_net_do_ioctl); } static int dvb_net_close(struct inode *inode, struct file *file) diff --git a/drivers/media/dvb/dvb-core/dvbdev.c b/drivers/media/dvb/dvb-core/dvbdev.c index b915c39d782..28f486edcaf 100644 --- a/drivers/media/dvb/dvb-core/dvbdev.c +++ b/drivers/media/dvb/dvb-core/dvbdev.c @@ -32,9 +32,9 @@ #include #include #include -#include #include "dvbdev.h" +static DEFINE_MUTEX(dvbdev_mutex); static int dvbdev_debug; module_param(dvbdev_debug, int, 0644); @@ -68,7 +68,7 @@ static int dvb_device_open(struct inode *inode, struct file *file) { struct dvb_device *dvbdev; - lock_kernel(); + mutex_lock(&dvbdev_mutex); down_read(&minor_rwsem); dvbdev = dvb_minors[iminor(inode)]; @@ -91,12 +91,12 @@ static int dvb_device_open(struct inode *inode, struct file *file) } fops_put(old_fops); up_read(&minor_rwsem); - unlock_kernel(); + mutex_unlock(&dvbdev_mutex); return err; } fail: up_read(&minor_rwsem); - unlock_kernel(); + mutex_unlock(&dvbdev_mutex); return -ENODEV; } @@ -158,7 +158,6 @@ long dvb_generic_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { struct dvb_device *dvbdev = file->private_data; - int ret; if (!dvbdev) return -ENODEV; @@ -166,11 +165,7 @@ long dvb_generic_ioctl(struct file *file, if (!dvbdev->kernel_ioctl) return -EINVAL; - lock_kernel(); - ret = dvb_usercopy(file, cmd, arg, dvbdev->kernel_ioctl); - unlock_kernel(); - - return ret; + return dvb_usercopy(file, cmd, arg, dvbdev->kernel_ioctl); } EXPORT_SYMBOL(dvb_generic_ioctl); @@ -421,8 +416,10 @@ int dvb_usercopy(struct file *file, } /* call driver */ + mutex_lock(&dvbdev_mutex); if ((err = func(file, cmd, parg)) == -ENOIOCTLCMD) err = -EINVAL; + mutex_unlock(&dvbdev_mutex); if (err < 0) goto out; -- cgit v1.2.3 From 7ff52efdca367d4bfe2449bd3d4a1f8172c5953a Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Mon, 4 Oct 2010 21:24:14 +0200 Subject: dabusb: remove the BKL The dabusb device driver is sufficiently serialized using its own mutex, no need for the big kernel lock here in addition. Signed-off-by: Arnd Bergmann Cc: Mauro Carvalho Chehab --- drivers/media/video/dabusb.c | 18 +++--------------- 1 file changed, 3 insertions(+), 15 deletions(-) (limited to 'drivers') diff --git a/drivers/media/video/dabusb.c b/drivers/media/video/dabusb.c index 5b176bd7afd..f3e25e91366 100644 --- a/drivers/media/video/dabusb.c +++ b/drivers/media/video/dabusb.c @@ -32,7 +32,6 @@ #include #include #include -#include #include #include #include @@ -621,7 +620,6 @@ static int dabusb_open (struct inode *inode, struct file *file) if (devnum < DABUSB_MINOR || devnum >= (DABUSB_MINOR + NRDABUSB)) return -EIO; - lock_kernel(); s = &dabusb[devnum - DABUSB_MINOR]; dbg("dabusb_open"); @@ -630,21 +628,17 @@ static int dabusb_open (struct inode *inode, struct file *file) while (!s->usbdev || s->opened) { mutex_unlock(&s->mutex); - if (file->f_flags & O_NONBLOCK) { + if (file->f_flags & O_NONBLOCK) return -EBUSY; - } msleep_interruptible(500); - if (signal_pending (current)) { - unlock_kernel(); + if (signal_pending (current)) return -EAGAIN; - } mutex_lock(&s->mutex); } if (usb_set_interface (s->usbdev, _DABUSB_IF, 1) < 0) { mutex_unlock(&s->mutex); dev_err(&s->usbdev->dev, "set_interface failed\n"); - unlock_kernel(); return -EINVAL; } s->opened = 1; @@ -654,7 +648,6 @@ static int dabusb_open (struct inode *inode, struct file *file) file->private_data = s; r = nonseekable_open(inode, file); - unlock_kernel(); return r; } @@ -689,17 +682,13 @@ static long dabusb_ioctl (struct file *file, unsigned int cmd, unsigned long arg dbg("dabusb_ioctl"); - lock_kernel(); - if (s->remove_pending) { - unlock_kernel(); + if (s->remove_pending) return -EIO; - } mutex_lock(&s->mutex); if (!s->usbdev) { mutex_unlock(&s->mutex); - unlock_kernel(); return -EIO; } @@ -735,7 +724,6 @@ static long dabusb_ioctl (struct file *file, unsigned int cmd, unsigned long arg break; } mutex_unlock(&s->mutex); - unlock_kernel(); return ret; } -- cgit v1.2.3 From 6de5bd128d381ad88ac6d419a5e597048eb468cf Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Sat, 11 Sep 2010 18:00:57 +0200 Subject: BKL: introduce CONFIG_BKL. With all the patches we have queued in the BKL removal tree, only a few dozen modules are left that actually rely on the BKL, and even there are lots of low-hanging fruit. We need to decide what to do about them, this patch illustrates one of the options: Every user of the BKL is marked as 'depends on BKL' in Kconfig, and the CONFIG_BKL becomes a user-visible option. If it gets disabled, no BKL using module can be built any more and the BKL code itself is compiled out. The one exception is file locking, which is practically always enabled and does a 'select BKL' instead. This effectively forces CONFIG_BKL to be enabled until we have solved the fs/lockd mess and can apply the patch that removes the BKL from fs/locks.c. Signed-off-by: Arnd Bergmann --- drivers/gpu/drm/Kconfig | 5 ++++- drivers/media/Kconfig | 1 + drivers/net/appletalk/Kconfig | 1 + drivers/staging/cx25821/Kconfig | 1 + drivers/staging/easycap/Kconfig | 1 + drivers/staging/go7007/Kconfig | 1 + drivers/staging/usbip/Kconfig | 2 +- 7 files changed, 10 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig index 4cab0c6397e..7af44367262 100644 --- a/drivers/gpu/drm/Kconfig +++ b/drivers/gpu/drm/Kconfig @@ -73,7 +73,8 @@ source "drivers/gpu/drm/radeon/Kconfig" config DRM_I810 tristate "Intel I810" - depends on DRM && AGP && AGP_INTEL + # BKL usage in order to avoid AB-BA deadlocks, may become BROKEN_ON_SMP + depends on DRM && AGP && AGP_INTEL && BKL help Choose this option if you have an Intel I810 graphics card. If M is selected, the module will be called i810. AGP support is required @@ -86,6 +87,8 @@ choice config DRM_I830 tristate "i830 driver" + # BKL usage in order to avoid AB-BA deadlocks, i830 may get removed + depends on BKL help Choose this option if you have a system that has Intel 830M, 845G, 852GM, 855GM or 865G integrated graphics. If M is selected, the diff --git a/drivers/media/Kconfig b/drivers/media/Kconfig index a28541b2b1a..bad2cedb8d9 100644 --- a/drivers/media/Kconfig +++ b/drivers/media/Kconfig @@ -19,6 +19,7 @@ comment "Multimedia core support" config VIDEO_DEV tristate "Video For Linux" + depends on BKL # used in many drivers for ioctl handling, need to kill ---help--- V4L core support for video capture and overlay devices, webcams and AM/FM radio cards. diff --git a/drivers/net/appletalk/Kconfig b/drivers/net/appletalk/Kconfig index 0a0e0cd81a2..20f97e7017c 100644 --- a/drivers/net/appletalk/Kconfig +++ b/drivers/net/appletalk/Kconfig @@ -3,6 +3,7 @@ # config ATALK tristate "Appletalk protocol support" + depends on BKL # waiting to be removed from net/appletalk/ddp.c select LLC ---help--- AppleTalk is the protocol that Apple computers can use to communicate diff --git a/drivers/staging/cx25821/Kconfig b/drivers/staging/cx25821/Kconfig index df7756a95fa..813cb355ac0 100644 --- a/drivers/staging/cx25821/Kconfig +++ b/drivers/staging/cx25821/Kconfig @@ -1,6 +1,7 @@ config VIDEO_CX25821 tristate "Conexant cx25821 support" depends on DVB_CORE && VIDEO_DEV && PCI && I2C && INPUT + depends on BKL # please fix select I2C_ALGOBIT select VIDEO_BTCX select VIDEO_TVEEPROM diff --git a/drivers/staging/easycap/Kconfig b/drivers/staging/easycap/Kconfig index bd96f39f273..9d5fe4ddc30 100644 --- a/drivers/staging/easycap/Kconfig +++ b/drivers/staging/easycap/Kconfig @@ -1,6 +1,7 @@ config EASYCAP tristate "EasyCAP USB ID 05e1:0408 support" depends on USB && VIDEO_DEV + depends on BKL # please fix ---help--- This is an integrated audio/video driver for EasyCAP cards with diff --git a/drivers/staging/go7007/Kconfig b/drivers/staging/go7007/Kconfig index e47f683a323..75fa4680552 100644 --- a/drivers/staging/go7007/Kconfig +++ b/drivers/staging/go7007/Kconfig @@ -1,6 +1,7 @@ config VIDEO_GO7007 tristate "WIS GO7007 MPEG encoder support" depends on VIDEO_DEV && PCI && I2C && INPUT + depends on BKL # please fix depends on SND select VIDEOBUF_DMA_SG select VIDEO_IR diff --git a/drivers/staging/usbip/Kconfig b/drivers/staging/usbip/Kconfig index 2c1d10acb8b..b11ec379b5c 100644 --- a/drivers/staging/usbip/Kconfig +++ b/drivers/staging/usbip/Kconfig @@ -1,6 +1,6 @@ config USB_IP_COMMON tristate "USB IP support (EXPERIMENTAL)" - depends on USB && NET && EXPERIMENTAL + depends on USB && NET && EXPERIMENTAL && BKL default N ---help--- This enables pushing USB packets over IP to allow remote -- cgit v1.2.3