aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/isdn/mISDN
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2013-05-01 20:51:54 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2013-05-01 20:51:54 -0400
commit20b4fb485227404329e41ad15588afad3df23050 (patch)
treef3e099f0ab3da8a93b447203e294d2bb22f6dc05 /drivers/isdn/mISDN
parentb9394d8a657cd3c064fa432aa0905c1b58b38fe9 (diff)
parentac3e3c5b1164397656df81b9e9ab4991184d3236 (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.c76
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
72mISDN_close(struct inode *ino, struct file *filep) 71mISDN_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
92mISDN_read(struct file *filep, char __user *buf, size_t count, loff_t *off) 100mISDN_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
162misdn_add_timer(struct mISDNtimerdev *dev, int timeout) 176misdn_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)
193static int 203static int
194misdn_del_timer(struct mISDNtimerdev *dev, int id) 204misdn_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 }
213unlock: 219 spin_unlock_irq(&dev->lock);
214 spin_unlock_irqrestore(&dev->lock, flags); 220 return 0;
215 return ret;
216} 221}
217 222
218static long 223static long
@@ -262,6 +267,7 @@ mISDN_ioctl(struct file *filep, unsigned int cmd, unsigned long arg)
262} 267}
263 268
264static const struct file_operations mISDN_fops = { 269static 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,