different to that that runs on device open.
For in kernel calls, the device is only exclusively taken when adding
changing the interrupt. Thus it would I think be possible for multiple user
run this function, whilst they all think they have exclusive control. Do we
not want to ensure single access to the device whether in kernel or via the
userspace interface?
To do this I would propose moving
if (test_and_set_bit_lock(RTC_DEV_BUSY, &rtc->flags))
return -EBUSY;
etc into the rtc_class_open and also to add a call to
ops->open here.
Clearly we would also need the corresponding clear_bit_lock and ops->release
calls in rtc_class_close.
Assuming there is no reason that I'm missing behind the inherent
differences in kernel and out of kernel, the only complexity I know of is
that a lot of drivers define an ops->release. The following certainly seem
to work fine with rtc-pxa. Not sure what my webmail will do with the
patch...
Thanks,
Jonathan
[PATCH] rtc: Make in kernel interface behave similarly to character device.
Signed-off-by: Jonathan Cameron <jic23@cam.ac.uk>
---
drivers/rtc/interface.c | 29 ++++++++++++++++++++++-------
1 files changed, 22 insertions(+), 7 deletions(-)
@@ -406,6 +406,7 @@ struct rtc_device *rtc_class_open(char *name)
{
struct device *dev;
struct rtc_device *rtc = NULL;
+ int err;
dev = class_find_device(rtc_class, NULL, name, __rtc_match);
if (dev)
@@ -415,15 +416,35 @@ struct rtc_device *rtc_class_open(char *name)
if (!try_module_get(rtc->owner)) {
put_device(dev);
rtc = NULL;
+ goto exit;
+ }
+ /* Cannot use while the char dev is in use */
+ if (test_and_set_bit_lock(RTC_DEV_BUSY, &rtc->flags)) {
+ put_device(dev);
+ rtc = NULL;
+ goto exit;
+ }
+ err = rtc->ops->open ? rtc->ops->open(rtc->dev.parent) : 0;
+ if (err != 0) {
+ clear_bit_unlock(RTC_DEV_BUSY, &rtc->flags);
+ put_device(dev);
+ rtc = NULL;
+ goto exit;
}
+ spin_lock_irq(&rtc->irq_lock);
+ rtc->irq_data = 0;
+ spin_unlock_irq(&rtc->irq_lock);
}
-
+exit:
return rtc;
}
EXPORT_SYMBOL_GPL(rtc_class_open);
void rtc_class_close(struct rtc_device *rtc)
{
+ if (rtc->ops->release)
+ rtc->ops->release(rtc->dev.parent);
+ clear_bit_unlock(RTC_DEV_BUSY, &rtc->flags);
module_put(rtc->owner);
put_device(&rtc->dev);
} @@ -436,10 +457,6 @@ int rtc_irq_register(struct rtc_device *rtc, struct