aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/isdn
diff options
context:
space:
mode:
authorJan Kiszka <jan.kiszka@web.de>2010-02-08 05:12:29 -0500
committerDavid S. Miller <davem@davemloft.net>2010-02-16 19:01:29 -0500
commitfb4b4881ef951f6ed8fb8564ca1821dea10778c4 (patch)
tree290168531f4941d485fa7159cbd94a682605290c /drivers/isdn
parent46324511809251adbedb874cc08692e247f7ed68 (diff)
CAPI: Use tty_port to keep track of capiminor's tty
Use the reference management features of tty_port to look up and drop again the tty_struct associated with a capiminor. Signed-off-by: Jan Kiszka <jan.kiszka@web.de> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/isdn')
-rw-r--r--drivers/isdn/capi/capi.c94
1 files changed, 62 insertions, 32 deletions
diff --git a/drivers/isdn/capi/capi.c b/drivers/isdn/capi/capi.c
index 3e4997ac67ae..e164a8fb9693 100644
--- a/drivers/isdn/capi/capi.c
+++ b/drivers/isdn/capi/capi.c
@@ -94,7 +94,7 @@ struct capiminor {
94 u16 datahandle; 94 u16 datahandle;
95 u16 msgid; 95 u16 msgid;
96 96
97 struct tty_struct *tty; 97 struct tty_port port;
98 int ttyinstop; 98 int ttyinstop;
99 int ttyoutstop; 99 int ttyoutstop;
100 struct sk_buff *ttyskb; 100 struct sk_buff *ttyskb;
@@ -212,6 +212,8 @@ static void capiminor_del_all_ack(struct capiminor *mp)
212 212
213/* -------- struct capiminor ---------------------------------------- */ 213/* -------- struct capiminor ---------------------------------------- */
214 214
215static const struct tty_port_operations capiminor_port_ops; /* we have none */
216
215static struct capiminor *capiminor_alloc(struct capi20_appl *ap, u32 ncci) 217static struct capiminor *capiminor_alloc(struct capi20_appl *ap, u32 ncci)
216{ 218{
217 struct capiminor *mp; 219 struct capiminor *mp;
@@ -237,6 +239,9 @@ static struct capiminor *capiminor_alloc(struct capi20_appl *ap, u32 ncci)
237 skb_queue_head_init(&mp->inqueue); 239 skb_queue_head_init(&mp->inqueue);
238 skb_queue_head_init(&mp->outqueue); 240 skb_queue_head_init(&mp->outqueue);
239 241
242 tty_port_init(&mp->port);
243 mp->port.ops = &capiminor_port_ops;
244
240 /* Allocate the least unused minor number. */ 245 /* Allocate the least unused minor number. */
241 write_lock_irqsave(&capiminors_lock, flags); 246 write_lock_irqsave(&capiminors_lock, flags);
242 for (minor = 0; minor < capi_ttyminors; minor++) 247 for (minor = 0; minor < capi_ttyminors; minor++)
@@ -335,18 +340,22 @@ static void capincci_alloc_minor(struct capidev *cdev, struct capincci *np)
335static void capincci_free_minor(struct capincci *np) 340static void capincci_free_minor(struct capincci *np)
336{ 341{
337 struct capiminor *mp = np->minorp; 342 struct capiminor *mp = np->minorp;
343 struct tty_struct *tty;
338 344
339 if (mp) { 345 if (mp) {
340 capifs_free_ncci(mp->capifs_dentry); 346 capifs_free_ncci(mp->capifs_dentry);
341 if (mp->tty) { 347
348 tty = tty_port_tty_get(&mp->port);
349 if (tty) {
342 mp->nccip = NULL; 350 mp->nccip = NULL;
343#ifdef _DEBUG_REFCOUNT 351#ifdef _DEBUG_REFCOUNT
344 printk(KERN_DEBUG "reset mp->nccip\n"); 352 printk(KERN_DEBUG "reset mp->nccip\n");
345#endif 353#endif
346 tty_hangup(mp->tty); 354 tty_hangup(tty);
347 } else { 355 tty_kref_put(tty);
348 capiminor_free(mp);
349 } 356 }
357
358 capiminor_free(mp);
350 } 359 }
351} 360}
352 361
@@ -433,44 +442,48 @@ gen_data_b3_resp_for(struct capiminor *mp, struct sk_buff *skb)
433 442
434static int handle_recv_skb(struct capiminor *mp, struct sk_buff *skb) 443static int handle_recv_skb(struct capiminor *mp, struct sk_buff *skb)
435{ 444{
445 struct tty_struct *tty;
436 struct sk_buff *nskb; 446 struct sk_buff *nskb;
437 int datalen; 447 int datalen;
438 u16 errcode, datahandle; 448 u16 errcode, datahandle;
439 struct tty_ldisc *ld; 449 struct tty_ldisc *ld;
440 450 int ret = -1;
451
441 datalen = skb->len - CAPIMSG_LEN(skb->data); 452 datalen = skb->len - CAPIMSG_LEN(skb->data);
442 if (mp->tty == NULL) 453
443 { 454 tty = tty_port_tty_get(&mp->port);
455 if (!tty) {
444#ifdef _DEBUG_DATAFLOW 456#ifdef _DEBUG_DATAFLOW
445 printk(KERN_DEBUG "capi: currently no receiver\n"); 457 printk(KERN_DEBUG "capi: currently no receiver\n");
446#endif 458#endif
447 return -1; 459 return -1;
448 } 460 }
449 461
450 ld = tty_ldisc_ref(mp->tty); 462 ld = tty_ldisc_ref(tty);
451 if (ld == NULL) 463 if (!ld)
452 return -1; 464 goto out1;
465
453 if (ld->ops->receive_buf == NULL) { 466 if (ld->ops->receive_buf == NULL) {
454#if defined(_DEBUG_DATAFLOW) || defined(_DEBUG_TTYFUNCS) 467#if defined(_DEBUG_DATAFLOW) || defined(_DEBUG_TTYFUNCS)
455 printk(KERN_DEBUG "capi: ldisc has no receive_buf function\n"); 468 printk(KERN_DEBUG "capi: ldisc has no receive_buf function\n");
456#endif 469#endif
457 goto bad; 470 goto out2;
458 } 471 }
459 if (mp->ttyinstop) { 472 if (mp->ttyinstop) {
460#if defined(_DEBUG_DATAFLOW) || defined(_DEBUG_TTYFUNCS) 473#if defined(_DEBUG_DATAFLOW) || defined(_DEBUG_TTYFUNCS)
461 printk(KERN_DEBUG "capi: recv tty throttled\n"); 474 printk(KERN_DEBUG "capi: recv tty throttled\n");
462#endif 475#endif
463 goto bad; 476 goto out2;
464 } 477 }
465 if (mp->tty->receive_room < datalen) { 478 if (tty->receive_room < datalen) {
466#if defined(_DEBUG_DATAFLOW) || defined(_DEBUG_TTYFUNCS) 479#if defined(_DEBUG_DATAFLOW) || defined(_DEBUG_TTYFUNCS)
467 printk(KERN_DEBUG "capi: no room in tty\n"); 480 printk(KERN_DEBUG "capi: no room in tty\n");
468#endif 481#endif
469 goto bad; 482 goto out2;
470 } 483 }
471 if ((nskb = gen_data_b3_resp_for(mp, skb)) == NULL) { 484 if ((nskb = gen_data_b3_resp_for(mp, skb)) == NULL) {
472 printk(KERN_ERR "capi: gen_data_b3_resp failed\n"); 485 printk(KERN_ERR "capi: gen_data_b3_resp failed\n");
473 goto bad; 486 goto out2;
474 } 487 }
475 datahandle = CAPIMSG_U16(skb->data,CAPIMSG_BASELEN+4); 488 datahandle = CAPIMSG_U16(skb->data,CAPIMSG_BASELEN+4);
476 errcode = capi20_put_message(mp->ap, nskb); 489 errcode = capi20_put_message(mp->ap, nskb);
@@ -478,20 +491,21 @@ static int handle_recv_skb(struct capiminor *mp, struct sk_buff *skb)
478 printk(KERN_ERR "capi: send DATA_B3_RESP failed=%x\n", 491 printk(KERN_ERR "capi: send DATA_B3_RESP failed=%x\n",
479 errcode); 492 errcode);
480 kfree_skb(nskb); 493 kfree_skb(nskb);
481 goto bad; 494 goto out2;
482 } 495 }
483 (void)skb_pull(skb, CAPIMSG_LEN(skb->data)); 496 (void)skb_pull(skb, CAPIMSG_LEN(skb->data));
484#ifdef _DEBUG_DATAFLOW 497#ifdef _DEBUG_DATAFLOW
485 printk(KERN_DEBUG "capi: DATA_B3_RESP %u len=%d => ldisc\n", 498 printk(KERN_DEBUG "capi: DATA_B3_RESP %u len=%d => ldisc\n",
486 datahandle, skb->len); 499 datahandle, skb->len);
487#endif 500#endif
488 ld->ops->receive_buf(mp->tty, skb->data, NULL, skb->len); 501 ld->ops->receive_buf(tty, skb->data, NULL, skb->len);
489 kfree_skb(skb); 502 kfree_skb(skb);
503 ret = 0;
504out2:
490 tty_ldisc_deref(ld); 505 tty_ldisc_deref(ld);
491 return 0; 506out1:
492bad: 507 tty_kref_put(tty);
493 tty_ldisc_deref(ld); 508 return ret;
494 return -1;
495} 509}
496 510
497static void handle_minor_recv(struct capiminor *mp) 511static void handle_minor_recv(struct capiminor *mp)
@@ -510,16 +524,22 @@ static void handle_minor_recv(struct capiminor *mp)
510 524
511static int handle_minor_send(struct capiminor *mp) 525static int handle_minor_send(struct capiminor *mp)
512{ 526{
527 struct tty_struct *tty;
513 struct sk_buff *skb; 528 struct sk_buff *skb;
514 u16 len; 529 u16 len;
515 int count = 0; 530 int count = 0;
516 u16 errcode; 531 u16 errcode;
517 u16 datahandle; 532 u16 datahandle;
518 533
519 if (mp->tty && mp->ttyoutstop) { 534 tty = tty_port_tty_get(&mp->port);
535 if (!tty)
536 return 0;
537
538 if (mp->ttyoutstop) {
520#if defined(_DEBUG_DATAFLOW) || defined(_DEBUG_TTYFUNCS) 539#if defined(_DEBUG_DATAFLOW) || defined(_DEBUG_TTYFUNCS)
521 printk(KERN_DEBUG "capi: send: tty stopped\n"); 540 printk(KERN_DEBUG "capi: send: tty stopped\n");
522#endif 541#endif
542 tty_kref_put(tty);
523 return 0; 543 return 0;
524 } 544 }
525 545
@@ -542,6 +562,7 @@ static int handle_minor_send(struct capiminor *mp)
542 if (capiminor_add_ack(mp, datahandle) < 0) { 562 if (capiminor_add_ack(mp, datahandle) < 0) {
543 skb_pull(skb, CAPI_DATA_B3_REQ_LEN); 563 skb_pull(skb, CAPI_DATA_B3_REQ_LEN);
544 skb_queue_head(&mp->outqueue, skb); 564 skb_queue_head(&mp->outqueue, skb);
565 tty_kref_put(tty);
545 return count; 566 return count;
546 } 567 }
547 errcode = capi20_put_message(mp->ap, skb); 568 errcode = capi20_put_message(mp->ap, skb);
@@ -568,6 +589,7 @@ static int handle_minor_send(struct capiminor *mp)
568 mp->outbytes -= len; 589 mp->outbytes -= len;
569 kfree_skb(skb); 590 kfree_skb(skb);
570 } 591 }
592 tty_kref_put(tty);
571 return count; 593 return count;
572} 594}
573 595
@@ -578,6 +600,7 @@ static void capi_recv_message(struct capi20_appl *ap, struct sk_buff *skb)
578{ 600{
579 struct capidev *cdev = ap->private; 601 struct capidev *cdev = ap->private;
580#ifdef CONFIG_ISDN_CAPI_MIDDLEWARE 602#ifdef CONFIG_ISDN_CAPI_MIDDLEWARE
603 struct tty_struct *tty;
581 struct capiminor *mp; 604 struct capiminor *mp;
582 u16 datahandle; 605 u16 datahandle;
583#endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */ 606#endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */
@@ -641,8 +664,11 @@ static void capi_recv_message(struct capi20_appl *ap, struct sk_buff *skb)
641#endif 664#endif
642 kfree_skb(skb); 665 kfree_skb(skb);
643 (void)capiminor_del_ack(mp, datahandle); 666 (void)capiminor_del_ack(mp, datahandle);
644 if (mp->tty) 667 tty = tty_port_tty_get(&mp->port);
645 tty_wakeup(mp->tty); 668 if (tty) {
669 tty_wakeup(tty);
670 tty_kref_put(tty);
671 }
646 (void)handle_minor_send(mp); 672 (void)handle_minor_send(mp);
647 673
648 } else { 674 } else {
@@ -1029,14 +1055,17 @@ static void capinc_tty_cleanup(struct tty_struct *tty)
1029 capiminor_put(mp); 1055 capiminor_put(mp);
1030} 1056}
1031 1057
1032static int capinc_tty_open(struct tty_struct * tty, struct file * file) 1058static int capinc_tty_open(struct tty_struct *tty, struct file *filp)
1033{ 1059{
1034 struct capiminor *mp = tty->driver_data; 1060 struct capiminor *mp = tty->driver_data;
1035 unsigned long flags; 1061 unsigned long flags;
1062 int err;
1063
1064 err = tty_port_open(&mp->port, tty, filp);
1065 if (err)
1066 return err;
1036 1067
1037 spin_lock_irqsave(&workaround_lock, flags); 1068 spin_lock_irqsave(&workaround_lock, flags);
1038 if (atomic_read(&mp->ttyopencount) == 0)
1039 mp->tty = tty;
1040 atomic_inc(&mp->ttyopencount); 1069 atomic_inc(&mp->ttyopencount);
1041#ifdef _DEBUG_REFCOUNT 1070#ifdef _DEBUG_REFCOUNT
1042 printk(KERN_DEBUG "capinc_tty_open ocount=%d\n", atomic_read(&mp->ttyopencount)); 1071 printk(KERN_DEBUG "capinc_tty_open ocount=%d\n", atomic_read(&mp->ttyopencount));
@@ -1046,7 +1075,7 @@ static int capinc_tty_open(struct tty_struct * tty, struct file * file)
1046 return 0; 1075 return 0;
1047} 1076}
1048 1077
1049static void capinc_tty_close(struct tty_struct * tty, struct file * file) 1078static void capinc_tty_close(struct tty_struct *tty, struct file *filp)
1050{ 1079{
1051 struct capiminor *mp = tty->driver_data; 1080 struct capiminor *mp = tty->driver_data;
1052 1081
@@ -1054,17 +1083,15 @@ static void capinc_tty_close(struct tty_struct * tty, struct file * file)
1054#ifdef _DEBUG_REFCOUNT 1083#ifdef _DEBUG_REFCOUNT
1055 printk(KERN_DEBUG "capinc_tty_close lastclose\n"); 1084 printk(KERN_DEBUG "capinc_tty_close lastclose\n");
1056#endif 1085#endif
1057 mp->tty = NULL;
1058 } 1086 }
1059#ifdef _DEBUG_REFCOUNT 1087#ifdef _DEBUG_REFCOUNT
1060 printk(KERN_DEBUG "capinc_tty_close ocount=%d\n", atomic_read(&mp->ttyopencount)); 1088 printk(KERN_DEBUG "capinc_tty_close ocount=%d\n", atomic_read(&mp->ttyopencount));
1061#endif 1089#endif
1062 if (mp->nccip == NULL)
1063 capiminor_free(mp);
1064 1090
1065#ifdef _DEBUG_REFCOUNT 1091#ifdef _DEBUG_REFCOUNT
1066 printk(KERN_DEBUG "capinc_tty_close\n"); 1092 printk(KERN_DEBUG "capinc_tty_close\n");
1067#endif 1093#endif
1094 tty_port_close(&mp->port, tty, filp);
1068} 1095}
1069 1096
1070static int capinc_tty_write(struct tty_struct * tty, 1097static int capinc_tty_write(struct tty_struct * tty,
@@ -1292,9 +1319,12 @@ static void capinc_tty_start(struct tty_struct *tty)
1292 1319
1293static void capinc_tty_hangup(struct tty_struct *tty) 1320static void capinc_tty_hangup(struct tty_struct *tty)
1294{ 1321{
1322 struct capiminor *mp = tty->driver_data;
1323
1295#ifdef _DEBUG_TTYFUNCS 1324#ifdef _DEBUG_TTYFUNCS
1296 printk(KERN_DEBUG "capinc_tty_hangup\n"); 1325 printk(KERN_DEBUG "capinc_tty_hangup\n");
1297#endif 1326#endif
1327 tty_port_hangup(&mp->port);
1298} 1328}
1299 1329
1300static int capinc_tty_break_ctl(struct tty_struct *tty, int state) 1330static int capinc_tty_break_ctl(struct tty_struct *tty, int state)