Archived
14
0
Fork 0

Merge branch 'timer-fixes-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip

* 'timer-fixes-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip:
  RTC: rtc-omap: Fix a leak of the IRQ during init failure
  posix clocks: Replace mutex with reader/writer semaphore
This commit is contained in:
Linus Torvalds 2011-04-19 10:56:46 -07:00
commit 4ae0ff16ef
3 changed files with 13 additions and 18 deletions

View file

@ -394,7 +394,7 @@ static int __init omap_rtc_probe(struct platform_device *pdev)
return 0; return 0;
fail2: fail2:
free_irq(omap_rtc_timer, NULL); free_irq(omap_rtc_timer, rtc);
fail1: fail1:
rtc_device_unregister(rtc); rtc_device_unregister(rtc);
fail0: fail0:

View file

@ -24,6 +24,7 @@
#include <linux/fs.h> #include <linux/fs.h>
#include <linux/poll.h> #include <linux/poll.h>
#include <linux/posix-timers.h> #include <linux/posix-timers.h>
#include <linux/rwsem.h>
struct posix_clock; struct posix_clock;
@ -104,7 +105,7 @@ struct posix_clock_operations {
* @ops: Functional interface to the clock * @ops: Functional interface to the clock
* @cdev: Character device instance for this clock * @cdev: Character device instance for this clock
* @kref: Reference count. * @kref: Reference count.
* @mutex: Protects the 'zombie' field from concurrent access. * @rwsem: Protects the 'zombie' field from concurrent access.
* @zombie: If 'zombie' is true, then the hardware has disappeared. * @zombie: If 'zombie' is true, then the hardware has disappeared.
* @release: A function to free the structure when the reference count reaches * @release: A function to free the structure when the reference count reaches
* zero. May be NULL if structure is statically allocated. * zero. May be NULL if structure is statically allocated.
@ -117,7 +118,7 @@ struct posix_clock {
struct posix_clock_operations ops; struct posix_clock_operations ops;
struct cdev cdev; struct cdev cdev;
struct kref kref; struct kref kref;
struct mutex mutex; struct rw_semaphore rwsem;
bool zombie; bool zombie;
void (*release)(struct posix_clock *clk); void (*release)(struct posix_clock *clk);
}; };

View file

@ -19,7 +19,6 @@
*/ */
#include <linux/device.h> #include <linux/device.h>
#include <linux/file.h> #include <linux/file.h>
#include <linux/mutex.h>
#include <linux/posix-clock.h> #include <linux/posix-clock.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/syscalls.h> #include <linux/syscalls.h>
@ -34,19 +33,19 @@ static struct posix_clock *get_posix_clock(struct file *fp)
{ {
struct posix_clock *clk = fp->private_data; struct posix_clock *clk = fp->private_data;
mutex_lock(&clk->mutex); down_read(&clk->rwsem);
if (!clk->zombie) if (!clk->zombie)
return clk; return clk;
mutex_unlock(&clk->mutex); up_read(&clk->rwsem);
return NULL; return NULL;
} }
static void put_posix_clock(struct posix_clock *clk) static void put_posix_clock(struct posix_clock *clk)
{ {
mutex_unlock(&clk->mutex); up_read(&clk->rwsem);
} }
static ssize_t posix_clock_read(struct file *fp, char __user *buf, static ssize_t posix_clock_read(struct file *fp, char __user *buf,
@ -156,7 +155,7 @@ static int posix_clock_open(struct inode *inode, struct file *fp)
struct posix_clock *clk = struct posix_clock *clk =
container_of(inode->i_cdev, struct posix_clock, cdev); container_of(inode->i_cdev, struct posix_clock, cdev);
mutex_lock(&clk->mutex); down_read(&clk->rwsem);
if (clk->zombie) { if (clk->zombie) {
err = -ENODEV; err = -ENODEV;
@ -172,7 +171,7 @@ static int posix_clock_open(struct inode *inode, struct file *fp)
fp->private_data = clk; fp->private_data = clk;
} }
out: out:
mutex_unlock(&clk->mutex); up_read(&clk->rwsem);
return err; return err;
} }
@ -211,25 +210,20 @@ int posix_clock_register(struct posix_clock *clk, dev_t devid)
int err; int err;
kref_init(&clk->kref); kref_init(&clk->kref);
mutex_init(&clk->mutex); init_rwsem(&clk->rwsem);
cdev_init(&clk->cdev, &posix_clock_file_operations); cdev_init(&clk->cdev, &posix_clock_file_operations);
clk->cdev.owner = clk->ops.owner; clk->cdev.owner = clk->ops.owner;
err = cdev_add(&clk->cdev, devid, 1); err = cdev_add(&clk->cdev, devid, 1);
if (err)
goto no_cdev;
return err; return err;
no_cdev:
mutex_destroy(&clk->mutex);
return err;
} }
EXPORT_SYMBOL_GPL(posix_clock_register); EXPORT_SYMBOL_GPL(posix_clock_register);
static void delete_clock(struct kref *kref) static void delete_clock(struct kref *kref)
{ {
struct posix_clock *clk = container_of(kref, struct posix_clock, kref); struct posix_clock *clk = container_of(kref, struct posix_clock, kref);
mutex_destroy(&clk->mutex);
if (clk->release) if (clk->release)
clk->release(clk); clk->release(clk);
} }
@ -238,9 +232,9 @@ void posix_clock_unregister(struct posix_clock *clk)
{ {
cdev_del(&clk->cdev); cdev_del(&clk->cdev);
mutex_lock(&clk->mutex); down_write(&clk->rwsem);
clk->zombie = true; clk->zombie = true;
mutex_unlock(&clk->mutex); up_write(&clk->rwsem);
kref_put(&clk->kref, delete_clock); kref_put(&clk->kref, delete_clock);
} }