diff options
Diffstat (limited to 'net/bluetooth/rfcomm/tty.c')
-rw-r--r-- | net/bluetooth/rfcomm/tty.c | 133 |
1 files changed, 62 insertions, 71 deletions
diff --git a/net/bluetooth/rfcomm/tty.c b/net/bluetooth/rfcomm/tty.c index 4bf54b377255..d1820ff14aee 100644 --- a/net/bluetooth/rfcomm/tty.c +++ b/net/bluetooth/rfcomm/tty.c | |||
@@ -48,13 +48,12 @@ | |||
48 | static struct tty_driver *rfcomm_tty_driver; | 48 | static struct tty_driver *rfcomm_tty_driver; |
49 | 49 | ||
50 | struct rfcomm_dev { | 50 | struct rfcomm_dev { |
51 | struct tty_port port; | ||
51 | struct list_head list; | 52 | struct list_head list; |
52 | atomic_t refcnt; | ||
53 | 53 | ||
54 | char name[12]; | 54 | char name[12]; |
55 | int id; | 55 | int id; |
56 | unsigned long flags; | 56 | unsigned long flags; |
57 | atomic_t opened; | ||
58 | int err; | 57 | int err; |
59 | 58 | ||
60 | bdaddr_t src; | 59 | bdaddr_t src; |
@@ -64,9 +63,7 @@ struct rfcomm_dev { | |||
64 | uint modem_status; | 63 | uint modem_status; |
65 | 64 | ||
66 | struct rfcomm_dlc *dlc; | 65 | struct rfcomm_dlc *dlc; |
67 | struct tty_struct *tty; | ||
68 | wait_queue_head_t wait; | 66 | wait_queue_head_t wait; |
69 | struct work_struct wakeup_task; | ||
70 | 67 | ||
71 | struct device *tty_dev; | 68 | struct device *tty_dev; |
72 | 69 | ||
@@ -82,11 +79,18 @@ static void rfcomm_dev_data_ready(struct rfcomm_dlc *dlc, struct sk_buff *skb); | |||
82 | static void rfcomm_dev_state_change(struct rfcomm_dlc *dlc, int err); | 79 | static void rfcomm_dev_state_change(struct rfcomm_dlc *dlc, int err); |
83 | static void rfcomm_dev_modem_status(struct rfcomm_dlc *dlc, u8 v24_sig); | 80 | static void rfcomm_dev_modem_status(struct rfcomm_dlc *dlc, u8 v24_sig); |
84 | 81 | ||
85 | static void rfcomm_tty_wakeup(struct work_struct *work); | ||
86 | |||
87 | /* ---- Device functions ---- */ | 82 | /* ---- Device functions ---- */ |
88 | static void rfcomm_dev_destruct(struct rfcomm_dev *dev) | 83 | |
84 | /* | ||
85 | * The reason this isn't actually a race, as you no doubt have a little voice | ||
86 | * screaming at you in your head, is that the refcount should never actually | ||
87 | * reach zero unless the device has already been taken off the list, in | ||
88 | * rfcomm_dev_del(). And if that's not true, we'll hit the BUG() in | ||
89 | * rfcomm_dev_destruct() anyway. | ||
90 | */ | ||
91 | static void rfcomm_dev_destruct(struct tty_port *port) | ||
89 | { | 92 | { |
93 | struct rfcomm_dev *dev = container_of(port, struct rfcomm_dev, port); | ||
90 | struct rfcomm_dlc *dlc = dev->dlc; | 94 | struct rfcomm_dlc *dlc = dev->dlc; |
91 | 95 | ||
92 | BT_DBG("dev %p dlc %p", dev, dlc); | 96 | BT_DBG("dev %p dlc %p", dev, dlc); |
@@ -113,23 +117,9 @@ static void rfcomm_dev_destruct(struct rfcomm_dev *dev) | |||
113 | module_put(THIS_MODULE); | 117 | module_put(THIS_MODULE); |
114 | } | 118 | } |
115 | 119 | ||
116 | static inline void rfcomm_dev_hold(struct rfcomm_dev *dev) | 120 | static const struct tty_port_operations rfcomm_port_ops = { |
117 | { | 121 | .destruct = rfcomm_dev_destruct, |
118 | atomic_inc(&dev->refcnt); | 122 | }; |
119 | } | ||
120 | |||
121 | static inline void rfcomm_dev_put(struct rfcomm_dev *dev) | ||
122 | { | ||
123 | /* The reason this isn't actually a race, as you no | ||
124 | doubt have a little voice screaming at you in your | ||
125 | head, is that the refcount should never actually | ||
126 | reach zero unless the device has already been taken | ||
127 | off the list, in rfcomm_dev_del(). And if that's not | ||
128 | true, we'll hit the BUG() in rfcomm_dev_destruct() | ||
129 | anyway. */ | ||
130 | if (atomic_dec_and_test(&dev->refcnt)) | ||
131 | rfcomm_dev_destruct(dev); | ||
132 | } | ||
133 | 123 | ||
134 | static struct rfcomm_dev *__rfcomm_dev_get(int id) | 124 | static struct rfcomm_dev *__rfcomm_dev_get(int id) |
135 | { | 125 | { |
@@ -154,7 +144,7 @@ static inline struct rfcomm_dev *rfcomm_dev_get(int id) | |||
154 | if (test_bit(RFCOMM_TTY_RELEASED, &dev->flags)) | 144 | if (test_bit(RFCOMM_TTY_RELEASED, &dev->flags)) |
155 | dev = NULL; | 145 | dev = NULL; |
156 | else | 146 | else |
157 | rfcomm_dev_hold(dev); | 147 | tty_port_get(&dev->port); |
158 | } | 148 | } |
159 | 149 | ||
160 | spin_unlock(&rfcomm_dev_lock); | 150 | spin_unlock(&rfcomm_dev_lock); |
@@ -241,7 +231,6 @@ static int rfcomm_dev_add(struct rfcomm_dev_req *req, struct rfcomm_dlc *dlc) | |||
241 | sprintf(dev->name, "rfcomm%d", dev->id); | 231 | sprintf(dev->name, "rfcomm%d", dev->id); |
242 | 232 | ||
243 | list_add(&dev->list, head); | 233 | list_add(&dev->list, head); |
244 | atomic_set(&dev->refcnt, 1); | ||
245 | 234 | ||
246 | bacpy(&dev->src, &req->src); | 235 | bacpy(&dev->src, &req->src); |
247 | bacpy(&dev->dst, &req->dst); | 236 | bacpy(&dev->dst, &req->dst); |
@@ -250,10 +239,9 @@ static int rfcomm_dev_add(struct rfcomm_dev_req *req, struct rfcomm_dlc *dlc) | |||
250 | dev->flags = req->flags & | 239 | dev->flags = req->flags & |
251 | ((1 << RFCOMM_RELEASE_ONHUP) | (1 << RFCOMM_REUSE_DLC)); | 240 | ((1 << RFCOMM_RELEASE_ONHUP) | (1 << RFCOMM_REUSE_DLC)); |
252 | 241 | ||
253 | atomic_set(&dev->opened, 0); | 242 | tty_port_init(&dev->port); |
254 | 243 | dev->port.ops = &rfcomm_port_ops; | |
255 | init_waitqueue_head(&dev->wait); | 244 | init_waitqueue_head(&dev->wait); |
256 | INIT_WORK(&dev->wakeup_task, rfcomm_tty_wakeup); | ||
257 | 245 | ||
258 | skb_queue_head_init(&dev->pending); | 246 | skb_queue_head_init(&dev->pending); |
259 | 247 | ||
@@ -320,18 +308,23 @@ free: | |||
320 | 308 | ||
321 | static void rfcomm_dev_del(struct rfcomm_dev *dev) | 309 | static void rfcomm_dev_del(struct rfcomm_dev *dev) |
322 | { | 310 | { |
311 | unsigned long flags; | ||
323 | BT_DBG("dev %p", dev); | 312 | BT_DBG("dev %p", dev); |
324 | 313 | ||
325 | BUG_ON(test_and_set_bit(RFCOMM_TTY_RELEASED, &dev->flags)); | 314 | BUG_ON(test_and_set_bit(RFCOMM_TTY_RELEASED, &dev->flags)); |
326 | 315 | ||
327 | if (atomic_read(&dev->opened) > 0) | 316 | spin_lock_irqsave(&dev->port.lock, flags); |
317 | if (dev->port.count > 0) { | ||
318 | spin_unlock_irqrestore(&dev->port.lock, flags); | ||
328 | return; | 319 | return; |
320 | } | ||
321 | spin_unlock_irqrestore(&dev->port.lock, flags); | ||
329 | 322 | ||
330 | spin_lock(&rfcomm_dev_lock); | 323 | spin_lock(&rfcomm_dev_lock); |
331 | list_del_init(&dev->list); | 324 | list_del_init(&dev->list); |
332 | spin_unlock(&rfcomm_dev_lock); | 325 | spin_unlock(&rfcomm_dev_lock); |
333 | 326 | ||
334 | rfcomm_dev_put(dev); | 327 | tty_port_put(&dev->port); |
335 | } | 328 | } |
336 | 329 | ||
337 | /* ---- Send buffer ---- */ | 330 | /* ---- Send buffer ---- */ |
@@ -345,15 +338,16 @@ static inline unsigned int rfcomm_room(struct rfcomm_dlc *dlc) | |||
345 | static void rfcomm_wfree(struct sk_buff *skb) | 338 | static void rfcomm_wfree(struct sk_buff *skb) |
346 | { | 339 | { |
347 | struct rfcomm_dev *dev = (void *) skb->sk; | 340 | struct rfcomm_dev *dev = (void *) skb->sk; |
341 | struct tty_struct *tty = dev->port.tty; | ||
348 | atomic_sub(skb->truesize, &dev->wmem_alloc); | 342 | atomic_sub(skb->truesize, &dev->wmem_alloc); |
349 | if (test_bit(RFCOMM_TTY_ATTACHED, &dev->flags)) | 343 | if (test_bit(RFCOMM_TTY_ATTACHED, &dev->flags) && tty) |
350 | queue_work(system_nrt_wq, &dev->wakeup_task); | 344 | tty_wakeup(tty); |
351 | rfcomm_dev_put(dev); | 345 | tty_port_put(&dev->port); |
352 | } | 346 | } |
353 | 347 | ||
354 | static inline void rfcomm_set_owner_w(struct sk_buff *skb, struct rfcomm_dev *dev) | 348 | static inline void rfcomm_set_owner_w(struct sk_buff *skb, struct rfcomm_dev *dev) |
355 | { | 349 | { |
356 | rfcomm_dev_hold(dev); | 350 | tty_port_get(&dev->port); |
357 | atomic_add(skb->truesize, &dev->wmem_alloc); | 351 | atomic_add(skb->truesize, &dev->wmem_alloc); |
358 | skb->sk = (void *) dev; | 352 | skb->sk = (void *) dev; |
359 | skb->destructor = rfcomm_wfree; | 353 | skb->destructor = rfcomm_wfree; |
@@ -432,7 +426,7 @@ static int rfcomm_release_dev(void __user *arg) | |||
432 | return -ENODEV; | 426 | return -ENODEV; |
433 | 427 | ||
434 | if (dev->flags != NOCAP_FLAGS && !capable(CAP_NET_ADMIN)) { | 428 | if (dev->flags != NOCAP_FLAGS && !capable(CAP_NET_ADMIN)) { |
435 | rfcomm_dev_put(dev); | 429 | tty_port_put(&dev->port); |
436 | return -EPERM; | 430 | return -EPERM; |
437 | } | 431 | } |
438 | 432 | ||
@@ -440,12 +434,12 @@ static int rfcomm_release_dev(void __user *arg) | |||
440 | rfcomm_dlc_close(dev->dlc, 0); | 434 | rfcomm_dlc_close(dev->dlc, 0); |
441 | 435 | ||
442 | /* Shut down TTY synchronously before freeing rfcomm_dev */ | 436 | /* Shut down TTY synchronously before freeing rfcomm_dev */ |
443 | if (dev->tty) | 437 | if (dev->port.tty) |
444 | tty_vhangup(dev->tty); | 438 | tty_vhangup(dev->port.tty); |
445 | 439 | ||
446 | if (!test_bit(RFCOMM_RELEASE_ONHUP, &dev->flags)) | 440 | if (!test_bit(RFCOMM_RELEASE_ONHUP, &dev->flags)) |
447 | rfcomm_dev_del(dev); | 441 | rfcomm_dev_del(dev); |
448 | rfcomm_dev_put(dev); | 442 | tty_port_put(&dev->port); |
449 | return 0; | 443 | return 0; |
450 | } | 444 | } |
451 | 445 | ||
@@ -523,7 +517,7 @@ static int rfcomm_get_dev_info(void __user *arg) | |||
523 | if (copy_to_user(arg, &di, sizeof(di))) | 517 | if (copy_to_user(arg, &di, sizeof(di))) |
524 | err = -EFAULT; | 518 | err = -EFAULT; |
525 | 519 | ||
526 | rfcomm_dev_put(dev); | 520 | tty_port_put(&dev->port); |
527 | return err; | 521 | return err; |
528 | } | 522 | } |
529 | 523 | ||
@@ -559,7 +553,7 @@ static void rfcomm_dev_data_ready(struct rfcomm_dlc *dlc, struct sk_buff *skb) | |||
559 | return; | 553 | return; |
560 | } | 554 | } |
561 | 555 | ||
562 | tty = dev->tty; | 556 | tty = dev->port.tty; |
563 | if (!tty || !skb_queue_empty(&dev->pending)) { | 557 | if (!tty || !skb_queue_empty(&dev->pending)) { |
564 | skb_queue_tail(&dev->pending, skb); | 558 | skb_queue_tail(&dev->pending, skb); |
565 | return; | 559 | return; |
@@ -585,13 +579,13 @@ static void rfcomm_dev_state_change(struct rfcomm_dlc *dlc, int err) | |||
585 | wake_up_interruptible(&dev->wait); | 579 | wake_up_interruptible(&dev->wait); |
586 | 580 | ||
587 | if (dlc->state == BT_CLOSED) { | 581 | if (dlc->state == BT_CLOSED) { |
588 | if (!dev->tty) { | 582 | if (!dev->port.tty) { |
589 | if (test_bit(RFCOMM_RELEASE_ONHUP, &dev->flags)) { | 583 | if (test_bit(RFCOMM_RELEASE_ONHUP, &dev->flags)) { |
590 | /* Drop DLC lock here to avoid deadlock | 584 | /* Drop DLC lock here to avoid deadlock |
591 | * 1. rfcomm_dev_get will take rfcomm_dev_lock | 585 | * 1. rfcomm_dev_get will take rfcomm_dev_lock |
592 | * but in rfcomm_dev_add there's lock order: | 586 | * but in rfcomm_dev_add there's lock order: |
593 | * rfcomm_dev_lock -> dlc lock | 587 | * rfcomm_dev_lock -> dlc lock |
594 | * 2. rfcomm_dev_put will deadlock if it's | 588 | * 2. tty_port_put will deadlock if it's |
595 | * the last reference | 589 | * the last reference |
596 | */ | 590 | */ |
597 | rfcomm_dlc_unlock(dlc); | 591 | rfcomm_dlc_unlock(dlc); |
@@ -601,11 +595,11 @@ static void rfcomm_dev_state_change(struct rfcomm_dlc *dlc, int err) | |||
601 | } | 595 | } |
602 | 596 | ||
603 | rfcomm_dev_del(dev); | 597 | rfcomm_dev_del(dev); |
604 | rfcomm_dev_put(dev); | 598 | tty_port_put(&dev->port); |
605 | rfcomm_dlc_lock(dlc); | 599 | rfcomm_dlc_lock(dlc); |
606 | } | 600 | } |
607 | } else | 601 | } else |
608 | tty_hangup(dev->tty); | 602 | tty_hangup(dev->port.tty); |
609 | } | 603 | } |
610 | } | 604 | } |
611 | 605 | ||
@@ -618,8 +612,8 @@ static void rfcomm_dev_modem_status(struct rfcomm_dlc *dlc, u8 v24_sig) | |||
618 | BT_DBG("dlc %p dev %p v24_sig 0x%02x", dlc, dev, v24_sig); | 612 | BT_DBG("dlc %p dev %p v24_sig 0x%02x", dlc, dev, v24_sig); |
619 | 613 | ||
620 | if ((dev->modem_status & TIOCM_CD) && !(v24_sig & RFCOMM_V24_DV)) { | 614 | if ((dev->modem_status & TIOCM_CD) && !(v24_sig & RFCOMM_V24_DV)) { |
621 | if (dev->tty && !C_CLOCAL(dev->tty)) | 615 | if (dev->port.tty && !C_CLOCAL(dev->port.tty)) |
622 | tty_hangup(dev->tty); | 616 | tty_hangup(dev->port.tty); |
623 | } | 617 | } |
624 | 618 | ||
625 | dev->modem_status = | 619 | dev->modem_status = |
@@ -630,21 +624,9 @@ static void rfcomm_dev_modem_status(struct rfcomm_dlc *dlc, u8 v24_sig) | |||
630 | } | 624 | } |
631 | 625 | ||
632 | /* ---- TTY functions ---- */ | 626 | /* ---- TTY functions ---- */ |
633 | static void rfcomm_tty_wakeup(struct work_struct *work) | ||
634 | { | ||
635 | struct rfcomm_dev *dev = container_of(work, struct rfcomm_dev, | ||
636 | wakeup_task); | ||
637 | struct tty_struct *tty = dev->tty; | ||
638 | if (!tty) | ||
639 | return; | ||
640 | |||
641 | BT_DBG("dev %p tty %p", dev, tty); | ||
642 | tty_wakeup(tty); | ||
643 | } | ||
644 | |||
645 | static void rfcomm_tty_copy_pending(struct rfcomm_dev *dev) | 627 | static void rfcomm_tty_copy_pending(struct rfcomm_dev *dev) |
646 | { | 628 | { |
647 | struct tty_struct *tty = dev->tty; | 629 | struct tty_struct *tty = dev->port.tty; |
648 | struct sk_buff *skb; | 630 | struct sk_buff *skb; |
649 | int inserted = 0; | 631 | int inserted = 0; |
650 | 632 | ||
@@ -671,6 +653,7 @@ static int rfcomm_tty_open(struct tty_struct *tty, struct file *filp) | |||
671 | DECLARE_WAITQUEUE(wait, current); | 653 | DECLARE_WAITQUEUE(wait, current); |
672 | struct rfcomm_dev *dev; | 654 | struct rfcomm_dev *dev; |
673 | struct rfcomm_dlc *dlc; | 655 | struct rfcomm_dlc *dlc; |
656 | unsigned long flags; | ||
674 | int err, id; | 657 | int err, id; |
675 | 658 | ||
676 | id = tty->index; | 659 | id = tty->index; |
@@ -686,10 +669,14 @@ static int rfcomm_tty_open(struct tty_struct *tty, struct file *filp) | |||
686 | return -ENODEV; | 669 | return -ENODEV; |
687 | 670 | ||
688 | BT_DBG("dev %p dst %s channel %d opened %d", dev, batostr(&dev->dst), | 671 | BT_DBG("dev %p dst %s channel %d opened %d", dev, batostr(&dev->dst), |
689 | dev->channel, atomic_read(&dev->opened)); | 672 | dev->channel, dev->port.count); |
690 | 673 | ||
691 | if (atomic_inc_return(&dev->opened) > 1) | 674 | spin_lock_irqsave(&dev->port.lock, flags); |
675 | if (++dev->port.count > 1) { | ||
676 | spin_unlock_irqrestore(&dev->port.lock, flags); | ||
692 | return 0; | 677 | return 0; |
678 | } | ||
679 | spin_unlock_irqrestore(&dev->port.lock, flags); | ||
693 | 680 | ||
694 | dlc = dev->dlc; | 681 | dlc = dev->dlc; |
695 | 682 | ||
@@ -697,7 +684,7 @@ static int rfcomm_tty_open(struct tty_struct *tty, struct file *filp) | |||
697 | 684 | ||
698 | rfcomm_dlc_lock(dlc); | 685 | rfcomm_dlc_lock(dlc); |
699 | tty->driver_data = dev; | 686 | tty->driver_data = dev; |
700 | dev->tty = tty; | 687 | dev->port.tty = tty; |
701 | rfcomm_dlc_unlock(dlc); | 688 | rfcomm_dlc_unlock(dlc); |
702 | set_bit(RFCOMM_TTY_ATTACHED, &dev->flags); | 689 | set_bit(RFCOMM_TTY_ATTACHED, &dev->flags); |
703 | 690 | ||
@@ -744,13 +731,17 @@ static int rfcomm_tty_open(struct tty_struct *tty, struct file *filp) | |||
744 | static void rfcomm_tty_close(struct tty_struct *tty, struct file *filp) | 731 | static void rfcomm_tty_close(struct tty_struct *tty, struct file *filp) |
745 | { | 732 | { |
746 | struct rfcomm_dev *dev = (struct rfcomm_dev *) tty->driver_data; | 733 | struct rfcomm_dev *dev = (struct rfcomm_dev *) tty->driver_data; |
734 | unsigned long flags; | ||
735 | |||
747 | if (!dev) | 736 | if (!dev) |
748 | return; | 737 | return; |
749 | 738 | ||
750 | BT_DBG("tty %p dev %p dlc %p opened %d", tty, dev, dev->dlc, | 739 | BT_DBG("tty %p dev %p dlc %p opened %d", tty, dev, dev->dlc, |
751 | atomic_read(&dev->opened)); | 740 | dev->port.count); |
752 | 741 | ||
753 | if (atomic_dec_and_test(&dev->opened)) { | 742 | spin_lock_irqsave(&dev->port.lock, flags); |
743 | if (!--dev->port.count) { | ||
744 | spin_unlock_irqrestore(&dev->port.lock, flags); | ||
754 | if (dev->tty_dev->parent) | 745 | if (dev->tty_dev->parent) |
755 | device_move(dev->tty_dev, NULL, DPM_ORDER_DEV_LAST); | 746 | device_move(dev->tty_dev, NULL, DPM_ORDER_DEV_LAST); |
756 | 747 | ||
@@ -758,11 +749,10 @@ static void rfcomm_tty_close(struct tty_struct *tty, struct file *filp) | |||
758 | rfcomm_dlc_close(dev->dlc, 0); | 749 | rfcomm_dlc_close(dev->dlc, 0); |
759 | 750 | ||
760 | clear_bit(RFCOMM_TTY_ATTACHED, &dev->flags); | 751 | clear_bit(RFCOMM_TTY_ATTACHED, &dev->flags); |
761 | cancel_work_sync(&dev->wakeup_task); | ||
762 | 752 | ||
763 | rfcomm_dlc_lock(dev->dlc); | 753 | rfcomm_dlc_lock(dev->dlc); |
764 | tty->driver_data = NULL; | 754 | tty->driver_data = NULL; |
765 | dev->tty = NULL; | 755 | dev->port.tty = NULL; |
766 | rfcomm_dlc_unlock(dev->dlc); | 756 | rfcomm_dlc_unlock(dev->dlc); |
767 | 757 | ||
768 | if (test_bit(RFCOMM_TTY_RELEASED, &dev->flags)) { | 758 | if (test_bit(RFCOMM_TTY_RELEASED, &dev->flags)) { |
@@ -770,11 +760,12 @@ static void rfcomm_tty_close(struct tty_struct *tty, struct file *filp) | |||
770 | list_del_init(&dev->list); | 760 | list_del_init(&dev->list); |
771 | spin_unlock(&rfcomm_dev_lock); | 761 | spin_unlock(&rfcomm_dev_lock); |
772 | 762 | ||
773 | rfcomm_dev_put(dev); | 763 | tty_port_put(&dev->port); |
774 | } | 764 | } |
775 | } | 765 | } else |
766 | spin_unlock_irqrestore(&dev->port.lock, flags); | ||
776 | 767 | ||
777 | rfcomm_dev_put(dev); | 768 | tty_port_put(&dev->port); |
778 | } | 769 | } |
779 | 770 | ||
780 | static int rfcomm_tty_write(struct tty_struct *tty, const unsigned char *buf, int count) | 771 | static int rfcomm_tty_write(struct tty_struct *tty, const unsigned char *buf, int count) |
@@ -1083,7 +1074,7 @@ static void rfcomm_tty_hangup(struct tty_struct *tty) | |||
1083 | if (rfcomm_dev_get(dev->id) == NULL) | 1074 | if (rfcomm_dev_get(dev->id) == NULL) |
1084 | return; | 1075 | return; |
1085 | rfcomm_dev_del(dev); | 1076 | rfcomm_dev_del(dev); |
1086 | rfcomm_dev_put(dev); | 1077 | tty_port_put(&dev->port); |
1087 | } | 1078 | } |
1088 | } | 1079 | } |
1089 | 1080 | ||