diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2013-05-01 20:51:54 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2013-05-01 20:51:54 -0400 |
commit | 20b4fb485227404329e41ad15588afad3df23050 (patch) | |
tree | f3e099f0ab3da8a93b447203e294d2bb22f6dc05 /drivers/isdn/mISDN | |
parent | b9394d8a657cd3c064fa432aa0905c1b58b38fe9 (diff) | |
parent | ac3e3c5b1164397656df81b9e9ab4991184d3236 (diff) |
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs
Pull VFS updates from Al Viro,
Misc cleanups all over the place, mainly wrt /proc interfaces (switch
create_proc_entry to proc_create(), get rid of the deprecated
create_proc_read_entry() in favor of using proc_create_data() and
seq_file etc).
7kloc removed.
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs: (204 commits)
don't bother with deferred freeing of fdtables
proc: Move non-public stuff from linux/proc_fs.h to fs/proc/internal.h
proc: Make the PROC_I() and PDE() macros internal to procfs
proc: Supply a function to remove a proc entry by PDE
take cgroup_open() and cpuset_open() to fs/proc/base.c
ppc: Clean up scanlog
ppc: Clean up rtas_flash driver somewhat
hostap: proc: Use remove_proc_subtree()
drm: proc: Use remove_proc_subtree()
drm: proc: Use minor->index to label things, not PDE->name
drm: Constify drm_proc_list[]
zoran: Don't print proc_dir_entry data in debug
reiserfs: Don't access the proc_dir_entry in r_open(), r_start() r_show()
proc: Supply an accessor for getting the data from a PDE's parent
airo: Use remove_proc_subtree()
rtl8192u: Don't need to save device proc dir PDE
rtl8187se: Use a dir under /proc/net/r8180/
proc: Add proc_mkdir_data()
proc: Move some bits from linux/proc_fs.h to linux/{of.h,signal.h,tty.h}
proc: Move PDE_NET() to fs/proc/proc_net.c
...
Diffstat (limited to 'drivers/isdn/mISDN')
-rw-r--r-- | drivers/isdn/mISDN/timerdev.c | 76 |
1 files changed, 41 insertions, 35 deletions
diff --git a/drivers/isdn/mISDN/timerdev.c b/drivers/isdn/mISDN/timerdev.c index 1094667d8f31..9438d7ec3308 100644 --- a/drivers/isdn/mISDN/timerdev.c +++ b/drivers/isdn/mISDN/timerdev.c | |||
@@ -64,7 +64,6 @@ mISDN_open(struct inode *ino, struct file *filep) | |||
64 | dev->work = 0; | 64 | dev->work = 0; |
65 | init_waitqueue_head(&dev->wait); | 65 | init_waitqueue_head(&dev->wait); |
66 | filep->private_data = dev; | 66 | filep->private_data = dev; |
67 | __module_get(THIS_MODULE); | ||
68 | return nonseekable_open(ino, filep); | 67 | return nonseekable_open(ino, filep); |
69 | } | 68 | } |
70 | 69 | ||
@@ -72,19 +71,28 @@ static int | |||
72 | mISDN_close(struct inode *ino, struct file *filep) | 71 | mISDN_close(struct inode *ino, struct file *filep) |
73 | { | 72 | { |
74 | struct mISDNtimerdev *dev = filep->private_data; | 73 | struct mISDNtimerdev *dev = filep->private_data; |
74 | struct list_head *list = &dev->pending; | ||
75 | struct mISDNtimer *timer, *next; | 75 | struct mISDNtimer *timer, *next; |
76 | 76 | ||
77 | if (*debug & DEBUG_TIMER) | 77 | if (*debug & DEBUG_TIMER) |
78 | printk(KERN_DEBUG "%s(%p,%p)\n", __func__, ino, filep); | 78 | printk(KERN_DEBUG "%s(%p,%p)\n", __func__, ino, filep); |
79 | list_for_each_entry_safe(timer, next, &dev->pending, list) { | 79 | |
80 | del_timer(&timer->tl); | 80 | spin_lock_irq(&dev->lock); |
81 | while (!list_empty(list)) { | ||
82 | timer = list_first_entry(list, struct mISDNtimer, list); | ||
83 | spin_unlock_irq(&dev->lock); | ||
84 | del_timer_sync(&timer->tl); | ||
85 | spin_lock_irq(&dev->lock); | ||
86 | /* it might have been moved to ->expired */ | ||
87 | list_del(&timer->list); | ||
81 | kfree(timer); | 88 | kfree(timer); |
82 | } | 89 | } |
90 | spin_unlock_irq(&dev->lock); | ||
91 | |||
83 | list_for_each_entry_safe(timer, next, &dev->expired, list) { | 92 | list_for_each_entry_safe(timer, next, &dev->expired, list) { |
84 | kfree(timer); | 93 | kfree(timer); |
85 | } | 94 | } |
86 | kfree(dev); | 95 | kfree(dev); |
87 | module_put(THIS_MODULE); | ||
88 | return 0; | 96 | return 0; |
89 | } | 97 | } |
90 | 98 | ||
@@ -92,36 +100,41 @@ static ssize_t | |||
92 | mISDN_read(struct file *filep, char __user *buf, size_t count, loff_t *off) | 100 | mISDN_read(struct file *filep, char __user *buf, size_t count, loff_t *off) |
93 | { | 101 | { |
94 | struct mISDNtimerdev *dev = filep->private_data; | 102 | struct mISDNtimerdev *dev = filep->private_data; |
103 | struct list_head *list = &dev->expired; | ||
95 | struct mISDNtimer *timer; | 104 | struct mISDNtimer *timer; |
96 | u_long flags; | ||
97 | int ret = 0; | 105 | int ret = 0; |
98 | 106 | ||
99 | if (*debug & DEBUG_TIMER) | 107 | if (*debug & DEBUG_TIMER) |
100 | printk(KERN_DEBUG "%s(%p, %p, %d, %p)\n", __func__, | 108 | printk(KERN_DEBUG "%s(%p, %p, %d, %p)\n", __func__, |
101 | filep, buf, (int)count, off); | 109 | filep, buf, (int)count, off); |
102 | 110 | ||
103 | if (list_empty(&dev->expired) && (dev->work == 0)) { | 111 | if (count < sizeof(int)) |
112 | return -ENOSPC; | ||
113 | |||
114 | spin_lock_irq(&dev->lock); | ||
115 | while (list_empty(list) && (dev->work == 0)) { | ||
116 | spin_unlock_irq(&dev->lock); | ||
104 | if (filep->f_flags & O_NONBLOCK) | 117 | if (filep->f_flags & O_NONBLOCK) |
105 | return -EAGAIN; | 118 | return -EAGAIN; |
106 | wait_event_interruptible(dev->wait, (dev->work || | 119 | wait_event_interruptible(dev->wait, (dev->work || |
107 | !list_empty(&dev->expired))); | 120 | !list_empty(list))); |
108 | if (signal_pending(current)) | 121 | if (signal_pending(current)) |
109 | return -ERESTARTSYS; | 122 | return -ERESTARTSYS; |
123 | spin_lock_irq(&dev->lock); | ||
110 | } | 124 | } |
111 | if (count < sizeof(int)) | ||
112 | return -ENOSPC; | ||
113 | if (dev->work) | 125 | if (dev->work) |
114 | dev->work = 0; | 126 | dev->work = 0; |
115 | if (!list_empty(&dev->expired)) { | 127 | if (!list_empty(list)) { |
116 | spin_lock_irqsave(&dev->lock, flags); | 128 | timer = list_first_entry(list, struct mISDNtimer, list); |
117 | timer = (struct mISDNtimer *)dev->expired.next; | ||
118 | list_del(&timer->list); | 129 | list_del(&timer->list); |
119 | spin_unlock_irqrestore(&dev->lock, flags); | 130 | spin_unlock_irq(&dev->lock); |
120 | if (put_user(timer->id, (int __user *)buf)) | 131 | if (put_user(timer->id, (int __user *)buf)) |
121 | ret = -EFAULT; | 132 | ret = -EFAULT; |
122 | else | 133 | else |
123 | ret = sizeof(int); | 134 | ret = sizeof(int); |
124 | kfree(timer); | 135 | kfree(timer); |
136 | } else { | ||
137 | spin_unlock_irq(&dev->lock); | ||
125 | } | 138 | } |
126 | return ret; | 139 | return ret; |
127 | } | 140 | } |
@@ -153,7 +166,8 @@ dev_expire_timer(unsigned long data) | |||
153 | u_long flags; | 166 | u_long flags; |
154 | 167 | ||
155 | spin_lock_irqsave(&timer->dev->lock, flags); | 168 | spin_lock_irqsave(&timer->dev->lock, flags); |
156 | list_move_tail(&timer->list, &timer->dev->expired); | 169 | if (timer->id >= 0) |
170 | list_move_tail(&timer->list, &timer->dev->expired); | ||
157 | spin_unlock_irqrestore(&timer->dev->lock, flags); | 171 | spin_unlock_irqrestore(&timer->dev->lock, flags); |
158 | wake_up_interruptible(&timer->dev->wait); | 172 | wake_up_interruptible(&timer->dev->wait); |
159 | } | 173 | } |
@@ -162,7 +176,6 @@ static int | |||
162 | misdn_add_timer(struct mISDNtimerdev *dev, int timeout) | 176 | misdn_add_timer(struct mISDNtimerdev *dev, int timeout) |
163 | { | 177 | { |
164 | int id; | 178 | int id; |
165 | u_long flags; | ||
166 | struct mISDNtimer *timer; | 179 | struct mISDNtimer *timer; |
167 | 180 | ||
168 | if (!timeout) { | 181 | if (!timeout) { |
@@ -173,19 +186,16 @@ misdn_add_timer(struct mISDNtimerdev *dev, int timeout) | |||
173 | timer = kzalloc(sizeof(struct mISDNtimer), GFP_KERNEL); | 186 | timer = kzalloc(sizeof(struct mISDNtimer), GFP_KERNEL); |
174 | if (!timer) | 187 | if (!timer) |
175 | return -ENOMEM; | 188 | return -ENOMEM; |
176 | spin_lock_irqsave(&dev->lock, flags); | 189 | timer->dev = dev; |
177 | timer->id = dev->next_id++; | 190 | setup_timer(&timer->tl, dev_expire_timer, (long)timer); |
191 | spin_lock_irq(&dev->lock); | ||
192 | id = timer->id = dev->next_id++; | ||
178 | if (dev->next_id < 0) | 193 | if (dev->next_id < 0) |
179 | dev->next_id = 1; | 194 | dev->next_id = 1; |
180 | list_add_tail(&timer->list, &dev->pending); | 195 | list_add_tail(&timer->list, &dev->pending); |
181 | spin_unlock_irqrestore(&dev->lock, flags); | ||
182 | timer->dev = dev; | ||
183 | timer->tl.data = (long)timer; | ||
184 | timer->tl.function = dev_expire_timer; | ||
185 | init_timer(&timer->tl); | ||
186 | timer->tl.expires = jiffies + ((HZ * (u_long)timeout) / 1000); | 196 | timer->tl.expires = jiffies + ((HZ * (u_long)timeout) / 1000); |
187 | add_timer(&timer->tl); | 197 | add_timer(&timer->tl); |
188 | id = timer->id; | 198 | spin_unlock_irq(&dev->lock); |
189 | } | 199 | } |
190 | return id; | 200 | return id; |
191 | } | 201 | } |
@@ -193,26 +203,21 @@ misdn_add_timer(struct mISDNtimerdev *dev, int timeout) | |||
193 | static int | 203 | static int |
194 | misdn_del_timer(struct mISDNtimerdev *dev, int id) | 204 | misdn_del_timer(struct mISDNtimerdev *dev, int id) |
195 | { | 205 | { |
196 | u_long flags; | ||
197 | struct mISDNtimer *timer; | 206 | struct mISDNtimer *timer; |
198 | int ret = 0; | ||
199 | 207 | ||
200 | spin_lock_irqsave(&dev->lock, flags); | 208 | spin_lock_irq(&dev->lock); |
201 | list_for_each_entry(timer, &dev->pending, list) { | 209 | list_for_each_entry(timer, &dev->pending, list) { |
202 | if (timer->id == id) { | 210 | if (timer->id == id) { |
203 | list_del_init(&timer->list); | 211 | list_del_init(&timer->list); |
204 | /* RED-PEN AK: race -- timer can be still running on | 212 | timer->id = -1; |
205 | * other CPU. Needs reference count I think | 213 | spin_unlock_irq(&dev->lock); |
206 | */ | 214 | del_timer_sync(&timer->tl); |
207 | del_timer(&timer->tl); | ||
208 | ret = timer->id; | ||
209 | kfree(timer); | 215 | kfree(timer); |
210 | goto unlock; | 216 | return id; |
211 | } | 217 | } |
212 | } | 218 | } |
213 | unlock: | 219 | spin_unlock_irq(&dev->lock); |
214 | spin_unlock_irqrestore(&dev->lock, flags); | 220 | return 0; |
215 | return ret; | ||
216 | } | 221 | } |
217 | 222 | ||
218 | static long | 223 | static long |
@@ -262,6 +267,7 @@ mISDN_ioctl(struct file *filep, unsigned int cmd, unsigned long arg) | |||
262 | } | 267 | } |
263 | 268 | ||
264 | static const struct file_operations mISDN_fops = { | 269 | static const struct file_operations mISDN_fops = { |
270 | .owner = THIS_MODULE, | ||
265 | .read = mISDN_read, | 271 | .read = mISDN_read, |
266 | .poll = mISDN_poll, | 272 | .poll = mISDN_poll, |
267 | .unlocked_ioctl = mISDN_ioctl, | 273 | .unlocked_ioctl = mISDN_ioctl, |