diff options
| -rw-r--r-- | include/linux/posix-clock.h | 5 | ||||
| -rw-r--r-- | kernel/time/posix-clock.c | 24 |
2 files changed, 12 insertions, 17 deletions
diff --git a/include/linux/posix-clock.h b/include/linux/posix-clock.h index 369e19d3750b..7f1183dcd119 100644 --- a/include/linux/posix-clock.h +++ b/include/linux/posix-clock.h | |||
| @@ -24,6 +24,7 @@ | |||
| 24 | #include <linux/fs.h> | 24 | #include <linux/fs.h> |
| 25 | #include <linux/poll.h> | 25 | #include <linux/poll.h> |
| 26 | #include <linux/posix-timers.h> | 26 | #include <linux/posix-timers.h> |
| 27 | #include <linux/rwsem.h> | ||
| 27 | 28 | ||
| 28 | struct posix_clock; | 29 | struct posix_clock; |
| 29 | 30 | ||
| @@ -104,7 +105,7 @@ struct posix_clock_operations { | |||
| 104 | * @ops: Functional interface to the clock | 105 | * @ops: Functional interface to the clock |
| 105 | * @cdev: Character device instance for this clock | 106 | * @cdev: Character device instance for this clock |
| 106 | * @kref: Reference count. | 107 | * @kref: Reference count. |
| 107 | * @mutex: Protects the 'zombie' field from concurrent access. | 108 | * @rwsem: Protects the 'zombie' field from concurrent access. |
| 108 | * @zombie: If 'zombie' is true, then the hardware has disappeared. | 109 | * @zombie: If 'zombie' is true, then the hardware has disappeared. |
| 109 | * @release: A function to free the structure when the reference count reaches | 110 | * @release: A function to free the structure when the reference count reaches |
| 110 | * zero. May be NULL if structure is statically allocated. | 111 | * zero. May be NULL if structure is statically allocated. |
| @@ -117,7 +118,7 @@ struct posix_clock { | |||
| 117 | struct posix_clock_operations ops; | 118 | struct posix_clock_operations ops; |
| 118 | struct cdev cdev; | 119 | struct cdev cdev; |
| 119 | struct kref kref; | 120 | struct kref kref; |
| 120 | struct mutex mutex; | 121 | struct rw_semaphore rwsem; |
| 121 | bool zombie; | 122 | bool zombie; |
| 122 | void (*release)(struct posix_clock *clk); | 123 | void (*release)(struct posix_clock *clk); |
| 123 | }; | 124 | }; |
diff --git a/kernel/time/posix-clock.c b/kernel/time/posix-clock.c index 25028dd4fa18..c340ca658f37 100644 --- a/kernel/time/posix-clock.c +++ b/kernel/time/posix-clock.c | |||
| @@ -19,7 +19,6 @@ | |||
| 19 | */ | 19 | */ |
| 20 | #include <linux/device.h> | 20 | #include <linux/device.h> |
| 21 | #include <linux/file.h> | 21 | #include <linux/file.h> |
| 22 | #include <linux/mutex.h> | ||
| 23 | #include <linux/posix-clock.h> | 22 | #include <linux/posix-clock.h> |
| 24 | #include <linux/slab.h> | 23 | #include <linux/slab.h> |
| 25 | #include <linux/syscalls.h> | 24 | #include <linux/syscalls.h> |
| @@ -34,19 +33,19 @@ static struct posix_clock *get_posix_clock(struct file *fp) | |||
| 34 | { | 33 | { |
| 35 | struct posix_clock *clk = fp->private_data; | 34 | struct posix_clock *clk = fp->private_data; |
| 36 | 35 | ||
| 37 | mutex_lock(&clk->mutex); | 36 | down_read(&clk->rwsem); |
| 38 | 37 | ||
| 39 | if (!clk->zombie) | 38 | if (!clk->zombie) |
| 40 | return clk; | 39 | return clk; |
| 41 | 40 | ||
| 42 | mutex_unlock(&clk->mutex); | 41 | up_read(&clk->rwsem); |
| 43 | 42 | ||
| 44 | return NULL; | 43 | return NULL; |
| 45 | } | 44 | } |
| 46 | 45 | ||
| 47 | static void put_posix_clock(struct posix_clock *clk) | 46 | static void put_posix_clock(struct posix_clock *clk) |
| 48 | { | 47 | { |
| 49 | mutex_unlock(&clk->mutex); | 48 | up_read(&clk->rwsem); |
| 50 | } | 49 | } |
| 51 | 50 | ||
| 52 | static ssize_t posix_clock_read(struct file *fp, char __user *buf, | 51 | 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) | |||
| 156 | struct posix_clock *clk = | 155 | struct posix_clock *clk = |
| 157 | container_of(inode->i_cdev, struct posix_clock, cdev); | 156 | container_of(inode->i_cdev, struct posix_clock, cdev); |
| 158 | 157 | ||
| 159 | mutex_lock(&clk->mutex); | 158 | down_read(&clk->rwsem); |
| 160 | 159 | ||
| 161 | if (clk->zombie) { | 160 | if (clk->zombie) { |
| 162 | err = -ENODEV; | 161 | err = -ENODEV; |
| @@ -172,7 +171,7 @@ static int posix_clock_open(struct inode *inode, struct file *fp) | |||
| 172 | fp->private_data = clk; | 171 | fp->private_data = clk; |
| 173 | } | 172 | } |
| 174 | out: | 173 | out: |
| 175 | mutex_unlock(&clk->mutex); | 174 | up_read(&clk->rwsem); |
| 176 | return err; | 175 | return err; |
| 177 | } | 176 | } |
| 178 | 177 | ||
| @@ -211,25 +210,20 @@ int posix_clock_register(struct posix_clock *clk, dev_t devid) | |||
| 211 | int err; | 210 | int err; |
| 212 | 211 | ||
| 213 | kref_init(&clk->kref); | 212 | kref_init(&clk->kref); |
| 214 | mutex_init(&clk->mutex); | 213 | init_rwsem(&clk->rwsem); |
| 215 | 214 | ||
| 216 | cdev_init(&clk->cdev, &posix_clock_file_operations); | 215 | cdev_init(&clk->cdev, &posix_clock_file_operations); |
| 217 | clk->cdev.owner = clk->ops.owner; | 216 | clk->cdev.owner = clk->ops.owner; |
| 218 | err = cdev_add(&clk->cdev, devid, 1); | 217 | err = cdev_add(&clk->cdev, devid, 1); |
| 219 | if (err) | ||
| 220 | goto no_cdev; | ||
| 221 | 218 | ||
| 222 | return err; | 219 | return err; |
| 223 | no_cdev: | ||
| 224 | mutex_destroy(&clk->mutex); | ||
| 225 | return err; | ||
| 226 | } | 220 | } |
| 227 | EXPORT_SYMBOL_GPL(posix_clock_register); | 221 | EXPORT_SYMBOL_GPL(posix_clock_register); |
| 228 | 222 | ||
| 229 | static void delete_clock(struct kref *kref) | 223 | static void delete_clock(struct kref *kref) |
| 230 | { | 224 | { |
| 231 | struct posix_clock *clk = container_of(kref, struct posix_clock, kref); | 225 | struct posix_clock *clk = container_of(kref, struct posix_clock, kref); |
| 232 | mutex_destroy(&clk->mutex); | 226 | |
| 233 | if (clk->release) | 227 | if (clk->release) |
| 234 | clk->release(clk); | 228 | clk->release(clk); |
| 235 | } | 229 | } |
| @@ -238,9 +232,9 @@ void posix_clock_unregister(struct posix_clock *clk) | |||
| 238 | { | 232 | { |
| 239 | cdev_del(&clk->cdev); | 233 | cdev_del(&clk->cdev); |
| 240 | 234 | ||
| 241 | mutex_lock(&clk->mutex); | 235 | down_write(&clk->rwsem); |
| 242 | clk->zombie = true; | 236 | clk->zombie = true; |
| 243 | mutex_unlock(&clk->mutex); | 237 | up_write(&clk->rwsem); |
| 244 | 238 | ||
| 245 | kref_put(&clk->kref, delete_clock); | 239 | kref_put(&clk->kref, delete_clock); |
| 246 | } | 240 | } |
