aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/bluetooth/btusb.c
diff options
context:
space:
mode:
authorMarcel Holtmann <marcel@holtmann.org>2014-09-14 03:11:06 -0400
committerMarcel Holtmann <marcel@holtmann.org>2014-09-14 12:35:28 -0400
commit047b2ec8d3778a046d6985d4ad410c85211a86a4 (patch)
tree436d743621b934984bd60ddac6a3adc5bf602f08 /drivers/bluetooth/btusb.c
parente9753eff1b875d579dc04d675e72d6e31e866927 (diff)
Bluetooth: btusb: Separate TX URB allocation and submission
The complete TX URB handling is done via a switch statement in the btusb_send_frame function. To allow for more clear separation between control, bulk and isoc URBs, split them into allocation and submission. Previously the inc_tx function has been used for tracking in-flight URB for HCI commands and ACL data packets. Convert that into a common function that either submits the URB or queues it when needed. This provides the flexibility to allow vendor specific hdev->send_frame callbacks without having to duplicate the whole URB handling logic. Signed-off-by: Marcel Holtmann <marcel@holtmann.org> Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
Diffstat (limited to 'drivers/bluetooth/btusb.c')
-rw-r--r--drivers/bluetooth/btusb.c206
1 files changed, 125 insertions, 81 deletions
diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c
index d696e68f326a..c89b330cfa9e 100644
--- a/drivers/bluetooth/btusb.c
+++ b/drivers/bluetooth/btusb.c
@@ -296,20 +296,6 @@ struct btusb_data {
296 int suspend_count; 296 int suspend_count;
297}; 297};
298 298
299static int inc_tx(struct btusb_data *data)
300{
301 unsigned long flags;
302 int rv;
303
304 spin_lock_irqsave(&data->txlock, flags);
305 rv = test_bit(BTUSB_SUSPENDING, &data->flags);
306 if (!rv)
307 data->tx_in_flight++;
308 spin_unlock_irqrestore(&data->txlock, flags);
309
310 return rv;
311}
312
313static void btusb_intr_complete(struct urb *urb) 299static void btusb_intr_complete(struct urb *urb)
314{ 300{
315 struct hci_dev *hdev = urb->context; 301 struct hci_dev *hdev = urb->context;
@@ -752,100 +738,96 @@ static int btusb_flush(struct hci_dev *hdev)
752 return 0; 738 return 0;
753} 739}
754 740
755static int btusb_send_frame(struct hci_dev *hdev, struct sk_buff *skb) 741static struct urb *alloc_ctrl_urb(struct hci_dev *hdev, struct sk_buff *skb)
756{ 742{
757 struct btusb_data *data = hci_get_drvdata(hdev); 743 struct btusb_data *data = hci_get_drvdata(hdev);
758 struct usb_ctrlrequest *dr; 744 struct usb_ctrlrequest *dr;
759 struct urb *urb; 745 struct urb *urb;
760 unsigned int pipe; 746 unsigned int pipe;
761 int err;
762 747
763 BT_DBG("%s", hdev->name); 748 urb = usb_alloc_urb(0, GFP_KERNEL);
749 if (!urb)
750 return ERR_PTR(-ENOMEM);
764 751
765 if (!test_bit(HCI_RUNNING, &hdev->flags)) 752 dr = kmalloc(sizeof(*dr), GFP_KERNEL);
766 return -EBUSY; 753 if (!dr) {
754 usb_free_urb(urb);
755 return ERR_PTR(-ENOMEM);
756 }
767 757
768 skb->dev = (void *) hdev; 758 dr->bRequestType = data->cmdreq_type;
759 dr->bRequest = 0;
760 dr->wIndex = 0;
761 dr->wValue = 0;
762 dr->wLength = __cpu_to_le16(skb->len);
769 763
770 switch (bt_cb(skb)->pkt_type) { 764 pipe = usb_sndctrlpipe(data->udev, 0x00);
771 case HCI_COMMAND_PKT:
772 urb = usb_alloc_urb(0, GFP_KERNEL);
773 if (!urb)
774 return -ENOMEM;
775
776 dr = kmalloc(sizeof(*dr), GFP_KERNEL);
777 if (!dr) {
778 usb_free_urb(urb);
779 return -ENOMEM;
780 }
781 765
782 dr->bRequestType = data->cmdreq_type; 766 usb_fill_control_urb(urb, data->udev, pipe, (void *) dr,
783 dr->bRequest = 0; 767 skb->data, skb->len, btusb_tx_complete, skb);
784 dr->wIndex = 0;
785 dr->wValue = 0;
786 dr->wLength = __cpu_to_le16(skb->len);
787 768
788 pipe = usb_sndctrlpipe(data->udev, 0x00); 769 skb->dev = (void *) hdev;
789 770
790 usb_fill_control_urb(urb, data->udev, pipe, (void *) dr, 771 return urb;
791 skb->data, skb->len, btusb_tx_complete, skb); 772}
792 773
793 hdev->stat.cmd_tx++; 774static struct urb *alloc_bulk_urb(struct hci_dev *hdev, struct sk_buff *skb)
794 break; 775{
776 struct btusb_data *data = hci_get_drvdata(hdev);
777 struct urb *urb;
778 unsigned int pipe;
795 779
796 case HCI_ACLDATA_PKT: 780 if (!data->bulk_tx_ep)
797 if (!data->bulk_tx_ep) 781 return ERR_PTR(-ENODEV);
798 return -ENODEV;
799 782
800 urb = usb_alloc_urb(0, GFP_KERNEL); 783 urb = usb_alloc_urb(0, GFP_KERNEL);
801 if (!urb) 784 if (!urb)
802 return -ENOMEM; 785 return ERR_PTR(-ENOMEM);
803 786
804 pipe = usb_sndbulkpipe(data->udev, 787 pipe = usb_sndbulkpipe(data->udev, data->bulk_tx_ep->bEndpointAddress);
805 data->bulk_tx_ep->bEndpointAddress);
806 788
807 usb_fill_bulk_urb(urb, data->udev, pipe, 789 usb_fill_bulk_urb(urb, data->udev, pipe,
808 skb->data, skb->len, btusb_tx_complete, skb); 790 skb->data, skb->len, btusb_tx_complete, skb);
809 791
810 hdev->stat.acl_tx++; 792 skb->dev = (void *) hdev;
811 break;
812 793
813 case HCI_SCODATA_PKT: 794 return urb;
814 if (!data->isoc_tx_ep || hci_conn_num(hdev, SCO_LINK) < 1) 795}
815 return -ENODEV;
816 796
817 urb = usb_alloc_urb(BTUSB_MAX_ISOC_FRAMES, GFP_KERNEL); 797static struct urb *alloc_isoc_urb(struct hci_dev *hdev, struct sk_buff *skb)
818 if (!urb) 798{
819 return -ENOMEM; 799 struct btusb_data *data = hci_get_drvdata(hdev);
800 struct urb *urb;
801 unsigned int pipe;
820 802
821 pipe = usb_sndisocpipe(data->udev, 803 if (!data->isoc_tx_ep)
822 data->isoc_tx_ep->bEndpointAddress); 804 return ERR_PTR(-ENODEV);
823 805
824 usb_fill_int_urb(urb, data->udev, pipe, 806 urb = usb_alloc_urb(BTUSB_MAX_ISOC_FRAMES, GFP_KERNEL);
825 skb->data, skb->len, btusb_isoc_tx_complete, 807 if (!urb)
826 skb, data->isoc_tx_ep->bInterval); 808 return ERR_PTR(-ENOMEM);
827 809
828 urb->transfer_flags = URB_ISO_ASAP; 810 pipe = usb_sndisocpipe(data->udev, data->isoc_tx_ep->bEndpointAddress);
829 811
830 __fill_isoc_descriptor(urb, skb->len, 812 usb_fill_int_urb(urb, data->udev, pipe,
831 le16_to_cpu(data->isoc_tx_ep->wMaxPacketSize)); 813 skb->data, skb->len, btusb_isoc_tx_complete,
814 skb, data->isoc_tx_ep->bInterval);
832 815
833 hdev->stat.sco_tx++; 816 urb->transfer_flags = URB_ISO_ASAP;
834 goto skip_waking;
835 817
836 default: 818 __fill_isoc_descriptor(urb, skb->len,
837 return -EILSEQ; 819 le16_to_cpu(data->isoc_tx_ep->wMaxPacketSize));
838 }
839 820
840 err = inc_tx(data); 821 skb->dev = (void *) hdev;
841 if (err) { 822
842 usb_anchor_urb(urb, &data->deferred); 823 return urb;
843 schedule_work(&data->waker); 824}
844 err = 0; 825
845 goto done; 826static int submit_tx_urb(struct hci_dev *hdev, struct urb *urb)
846 } 827{
828 struct btusb_data *data = hci_get_drvdata(hdev);
829 int err;
847 830
848skip_waking:
849 usb_anchor_urb(urb, &data->tx_anchor); 831 usb_anchor_urb(urb, &data->tx_anchor);
850 832
851 err = usb_submit_urb(urb, GFP_KERNEL); 833 err = usb_submit_urb(urb, GFP_KERNEL);
@@ -859,11 +841,73 @@ skip_waking:
859 usb_mark_last_busy(data->udev); 841 usb_mark_last_busy(data->udev);
860 } 842 }
861 843
862done:
863 usb_free_urb(urb); 844 usb_free_urb(urb);
864 return err; 845 return err;
865} 846}
866 847
848static int submit_or_queue_tx_urb(struct hci_dev *hdev, struct urb *urb)
849{
850 struct btusb_data *data = hci_get_drvdata(hdev);
851 unsigned long flags;
852 bool suspending;
853
854 spin_lock_irqsave(&data->txlock, flags);
855 suspending = test_bit(BTUSB_SUSPENDING, &data->flags);
856 if (!suspending)
857 data->tx_in_flight++;
858 spin_unlock_irqrestore(&data->txlock, flags);
859
860 if (!suspending)
861 return submit_tx_urb(hdev, urb);
862
863 usb_anchor_urb(urb, &data->deferred);
864 schedule_work(&data->waker);
865
866 usb_free_urb(urb);
867 return 0;
868}
869
870static int btusb_send_frame(struct hci_dev *hdev, struct sk_buff *skb)
871{
872 struct urb *urb;
873
874 BT_DBG("%s", hdev->name);
875
876 if (!test_bit(HCI_RUNNING, &hdev->flags))
877 return -EBUSY;
878
879 switch (bt_cb(skb)->pkt_type) {
880 case HCI_COMMAND_PKT:
881 urb = alloc_ctrl_urb(hdev, skb);
882 if (IS_ERR(urb))
883 return PTR_ERR(urb);
884
885 hdev->stat.cmd_tx++;
886 return submit_or_queue_tx_urb(hdev, urb);
887
888 case HCI_ACLDATA_PKT:
889 urb = alloc_bulk_urb(hdev, skb);
890 if (IS_ERR(urb))
891 return PTR_ERR(urb);
892
893 hdev->stat.acl_tx++;
894 return submit_or_queue_tx_urb(hdev, urb);
895
896 case HCI_SCODATA_PKT:
897 if (hci_conn_num(hdev, SCO_LINK) < 1)
898 return -ENODEV;
899
900 urb = alloc_isoc_urb(hdev, skb);
901 if (IS_ERR(urb))
902 return PTR_ERR(urb);
903
904 hdev->stat.sco_tx++;
905 return submit_tx_urb(hdev, urb);
906 }
907
908 return -EILSEQ;
909}
910
867static void btusb_notify(struct hci_dev *hdev, unsigned int evt) 911static void btusb_notify(struct hci_dev *hdev, unsigned int evt)
868{ 912{
869 struct btusb_data *data = hci_get_drvdata(hdev); 913 struct btusb_data *data = hci_get_drvdata(hdev);