aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/isdn
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/isdn')
-rw-r--r--drivers/isdn/capi/capi.c75
1 files changed, 35 insertions, 40 deletions
diff --git a/drivers/isdn/capi/capi.c b/drivers/isdn/capi/capi.c
index 6704b2b004aa..46f85ae85f5f 100644
--- a/drivers/isdn/capi/capi.c
+++ b/drivers/isdn/capi/capi.c
@@ -85,7 +85,6 @@ struct datahandle_queue {
85}; 85};
86 86
87struct capiminor { 87struct capiminor {
88 struct list_head list;
89 struct capincci *nccip; 88 struct capincci *nccip;
90 unsigned int minor; 89 unsigned int minor;
91 struct dentry *capifs_dentry; 90 struct dentry *capifs_dentry;
@@ -151,8 +150,8 @@ static LIST_HEAD(capidev_list);
151 150
152#ifdef CONFIG_ISDN_CAPI_MIDDLEWARE 151#ifdef CONFIG_ISDN_CAPI_MIDDLEWARE
153 152
154static DEFINE_RWLOCK(capiminor_list_lock); 153static DEFINE_RWLOCK(capiminors_lock);
155static LIST_HEAD(capiminor_list); 154static struct capiminor **capiminors;
156 155
157/* -------- datahandles --------------------------------------------- */ 156/* -------- datahandles --------------------------------------------- */
158 157
@@ -213,8 +212,8 @@ static void capiminor_del_all_ack(struct capiminor *mp)
213 212
214static struct capiminor *capiminor_alloc(struct capi20_appl *ap, u32 ncci) 213static struct capiminor *capiminor_alloc(struct capi20_appl *ap, u32 ncci)
215{ 214{
216 struct capiminor *mp, *p; 215 struct capiminor *mp;
217 unsigned int minor = 0; 216 unsigned int minor;
218 unsigned long flags; 217 unsigned long flags;
219 218
220 mp = kzalloc(sizeof(*mp), GFP_KERNEL); 219 mp = kzalloc(sizeof(*mp), GFP_KERNEL);
@@ -233,31 +232,23 @@ static struct capiminor *capiminor_alloc(struct capi20_appl *ap, u32 ncci)
233 skb_queue_head_init(&mp->inqueue); 232 skb_queue_head_init(&mp->inqueue);
234 skb_queue_head_init(&mp->outqueue); 233 skb_queue_head_init(&mp->outqueue);
235 234
236 /* Allocate the least unused minor number. 235 /* Allocate the least unused minor number. */
237 */ 236 write_lock_irqsave(&capiminors_lock, flags);
238 write_lock_irqsave(&capiminor_list_lock, flags); 237 for (minor = 0; minor < capi_ttyminors; minor++)
239 if (list_empty(&capiminor_list)) 238 if (!capiminors[minor]) {
240 list_add(&mp->list, &capiminor_list); 239 capiminors[minor] = mp;
241 else { 240 break;
242 list_for_each_entry(p, &capiminor_list, list) {
243 if (p->minor > minor)
244 break;
245 minor++;
246 }
247
248 if (minor < capi_ttyminors) {
249 mp->minor = minor;
250 list_add(&mp->list, p->list.prev);
251 } 241 }
252 } 242 write_unlock_irqrestore(&capiminors_lock, flags);
253 write_unlock_irqrestore(&capiminor_list_lock, flags);
254 243
255 if (!(minor < capi_ttyminors)) { 244 if (minor == capi_ttyminors) {
256 printk(KERN_NOTICE "capi: out of minors\n"); 245 printk(KERN_NOTICE "capi: out of minors\n");
257 kfree(mp); 246 kfree(mp);
258 return NULL; 247 return NULL;
259 } 248 }
260 249
250 mp->minor = minor;
251
261 return mp; 252 return mp;
262} 253}
263 254
@@ -265,9 +256,9 @@ static void capiminor_free(struct capiminor *mp)
265{ 256{
266 unsigned long flags; 257 unsigned long flags;
267 258
268 write_lock_irqsave(&capiminor_list_lock, flags); 259 write_lock_irqsave(&capiminors_lock, flags);
269 list_del(&mp->list); 260 capiminors[mp->minor] = NULL;
270 write_unlock_irqrestore(&capiminor_list_lock, flags); 261 write_unlock_irqrestore(&capiminors_lock, flags);
271 262
272 kfree_skb(mp->ttyskb); 263 kfree_skb(mp->ttyskb);
273 mp->ttyskb = NULL; 264 mp->ttyskb = NULL;
@@ -279,20 +270,16 @@ static void capiminor_free(struct capiminor *mp)
279 270
280static struct capiminor *capiminor_find(unsigned int minor) 271static struct capiminor *capiminor_find(unsigned int minor)
281{ 272{
282 struct list_head *l; 273 struct capiminor *mp;
283 struct capiminor *p = NULL;
284 274
285 read_lock(&capiminor_list_lock); 275 if (minor >= capi_ttyminors)
286 list_for_each(l, &capiminor_list) {
287 p = list_entry(l, struct capiminor, list);
288 if (p->minor == minor)
289 break;
290 }
291 read_unlock(&capiminor_list_lock);
292 if (l == &capiminor_list)
293 return NULL; 276 return NULL;
294 277
295 return p; 278 read_lock(&capiminors_lock);
279 mp = capiminors[minor];
280 read_unlock(&capiminors_lock);
281
282 return mp;
296} 283}
297 284
298/* -------- struct capincci ----------------------------------------- */ 285/* -------- struct capincci ----------------------------------------- */
@@ -1329,10 +1316,16 @@ static int capinc_tty_init(void)
1329 if (capi_ttyminors <= 0) 1316 if (capi_ttyminors <= 0)
1330 capi_ttyminors = CAPINC_NR_PORTS; 1317 capi_ttyminors = CAPINC_NR_PORTS;
1331 1318
1332 drv = alloc_tty_driver(capi_ttyminors); 1319 capiminors = kzalloc(sizeof(struct capi_minor *) * capi_ttyminors,
1333 if (!drv) 1320 GFP_KERNEL);
1321 if (!capiminors)
1334 return -ENOMEM; 1322 return -ENOMEM;
1335 1323
1324 drv = alloc_tty_driver(capi_ttyminors);
1325 if (!drv) {
1326 kfree(capiminors);
1327 return -ENOMEM;
1328 }
1336 drv->owner = THIS_MODULE; 1329 drv->owner = THIS_MODULE;
1337 drv->driver_name = "capi_nc"; 1330 drv->driver_name = "capi_nc";
1338 drv->name = "capi"; 1331 drv->name = "capi";
@@ -1349,6 +1342,7 @@ static int capinc_tty_init(void)
1349 tty_set_operations(drv, &capinc_ops); 1342 tty_set_operations(drv, &capinc_ops);
1350 if (tty_register_driver(drv)) { 1343 if (tty_register_driver(drv)) {
1351 put_tty_driver(drv); 1344 put_tty_driver(drv);
1345 kfree(capiminors);
1352 printk(KERN_ERR "Couldn't register capi_nc driver\n"); 1346 printk(KERN_ERR "Couldn't register capi_nc driver\n");
1353 return -1; 1347 return -1;
1354 } 1348 }
@@ -1363,6 +1357,7 @@ static void capinc_tty_exit(void)
1363 if ((retval = tty_unregister_driver(drv))) 1357 if ((retval = tty_unregister_driver(drv)))
1364 printk(KERN_ERR "capi: failed to unregister capi_nc driver (%d)\n", retval); 1358 printk(KERN_ERR "capi: failed to unregister capi_nc driver (%d)\n", retval);
1365 put_tty_driver(drv); 1359 put_tty_driver(drv);
1360 kfree(capiminors);
1366} 1361}
1367 1362
1368#else /* !CONFIG_ISDN_CAPI_MIDDLEWARE */ 1363#else /* !CONFIG_ISDN_CAPI_MIDDLEWARE */