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:
commit
4ae0ff16ef
3 changed files with 13 additions and 18 deletions
|
@ -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:
|
||||||
|
|
|
@ -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);
|
||||||
};
|
};
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
Reference in a new issue