RTC: convert mutex to bitfield
RTC code is using mutex to assure exclusive access to /dev/rtc. This is however wrong usage, as it leaves the mutex locked when returning into userspace, which is unacceptable. Convert rtc->char_lock into bit operation. Signed-off-by: Jiri Kosina <jkosina@suse.cz> Acked-by: Alessandro Zummo <a.zummo@towertech.it> Cc: David Brownell <david-b@pacbell.net> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
This commit is contained in:
parent
08b633070a
commit
8853c202b4
3 changed files with 10 additions and 11 deletions
|
@ -293,7 +293,7 @@ int rtc_irq_register(struct rtc_device *rtc, struct rtc_task *task)
|
|||
return -EINVAL;
|
||||
|
||||
/* Cannot register while the char dev is in use */
|
||||
if (!(mutex_trylock(&rtc->char_lock)))
|
||||
if (test_and_set_bit(RTC_DEV_BUSY, &rtc->flags))
|
||||
return -EBUSY;
|
||||
|
||||
spin_lock_irq(&rtc->irq_task_lock);
|
||||
|
@ -303,7 +303,7 @@ int rtc_irq_register(struct rtc_device *rtc, struct rtc_task *task)
|
|||
}
|
||||
spin_unlock_irq(&rtc->irq_task_lock);
|
||||
|
||||
mutex_unlock(&rtc->char_lock);
|
||||
clear_bit(RTC_DEV_BUSY, &rtc->flags);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
|
|
@ -26,10 +26,7 @@ static int rtc_dev_open(struct inode *inode, struct file *file)
|
|||
struct rtc_device, char_dev);
|
||||
const struct rtc_class_ops *ops = rtc->ops;
|
||||
|
||||
/* We keep the lock as long as the device is in use
|
||||
* and return immediately if busy
|
||||
*/
|
||||
if (!(mutex_trylock(&rtc->char_lock)))
|
||||
if (test_and_set_bit(RTC_DEV_BUSY, &rtc->flags))
|
||||
return -EBUSY;
|
||||
|
||||
file->private_data = rtc;
|
||||
|
@ -43,8 +40,8 @@ static int rtc_dev_open(struct inode *inode, struct file *file)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/* something has gone wrong, release the lock */
|
||||
mutex_unlock(&rtc->char_lock);
|
||||
/* something has gone wrong */
|
||||
clear_bit(RTC_DEV_BUSY, &rtc->flags);
|
||||
return err;
|
||||
}
|
||||
|
||||
|
@ -405,7 +402,7 @@ static int rtc_dev_release(struct inode *inode, struct file *file)
|
|||
if (rtc->ops->release)
|
||||
rtc->ops->release(rtc->dev.parent);
|
||||
|
||||
mutex_unlock(&rtc->char_lock);
|
||||
clear_bit(RTC_DEV_BUSY, &rtc->flags);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -440,7 +437,6 @@ void rtc_dev_prepare(struct rtc_device *rtc)
|
|||
|
||||
rtc->dev.devt = MKDEV(MAJOR(rtc_devt), rtc->id);
|
||||
|
||||
mutex_init(&rtc->char_lock);
|
||||
#ifdef CONFIG_RTC_INTF_DEV_UIE_EMUL
|
||||
INIT_WORK(&rtc->uie_task, rtc_uie_task);
|
||||
setup_timer(&rtc->uie_timer, rtc_uie_timer, (unsigned long)rtc);
|
||||
|
|
|
@ -133,6 +133,9 @@ struct rtc_class_ops {
|
|||
#define RTC_DEVICE_NAME_SIZE 20
|
||||
struct rtc_task;
|
||||
|
||||
/* flags */
|
||||
#define RTC_DEV_BUSY 0
|
||||
|
||||
struct rtc_device
|
||||
{
|
||||
struct device dev;
|
||||
|
@ -145,7 +148,7 @@ struct rtc_device
|
|||
struct mutex ops_lock;
|
||||
|
||||
struct cdev char_dev;
|
||||
struct mutex char_lock;
|
||||
unsigned long flags;
|
||||
|
||||
unsigned long irq_data;
|
||||
spinlock_t irq_lock;
|
||||
|
|
Loading…
Reference in a new issue