From e9753eff1b875d579dc04d675e72d6e31e866927 Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Sun, 14 Sep 2014 08:49:34 +0300 Subject: [PATCH 01/19] Bluetooth: btusb: Use GFP_KERNEL in btusb_send_frame() All hdev->send() calls are these days done through a work queue. For the btusb driver this means the btusb_send_frame() function. Because of this we can safely use GFP_KERNEL for all memory allocations in this code path. Signed-off-by: Johan Hedberg Signed-off-by: Marcel Holtmann --- drivers/bluetooth/btusb.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c index a79d657c0845b..d696e68f326a2 100644 --- a/drivers/bluetooth/btusb.c +++ b/drivers/bluetooth/btusb.c @@ -769,11 +769,11 @@ static int btusb_send_frame(struct hci_dev *hdev, struct sk_buff *skb) switch (bt_cb(skb)->pkt_type) { case HCI_COMMAND_PKT: - urb = usb_alloc_urb(0, GFP_ATOMIC); + urb = usb_alloc_urb(0, GFP_KERNEL); if (!urb) return -ENOMEM; - dr = kmalloc(sizeof(*dr), GFP_ATOMIC); + dr = kmalloc(sizeof(*dr), GFP_KERNEL); if (!dr) { usb_free_urb(urb); return -ENOMEM; @@ -797,7 +797,7 @@ static int btusb_send_frame(struct hci_dev *hdev, struct sk_buff *skb) if (!data->bulk_tx_ep) return -ENODEV; - urb = usb_alloc_urb(0, GFP_ATOMIC); + urb = usb_alloc_urb(0, GFP_KERNEL); if (!urb) return -ENOMEM; @@ -814,7 +814,7 @@ static int btusb_send_frame(struct hci_dev *hdev, struct sk_buff *skb) if (!data->isoc_tx_ep || hci_conn_num(hdev, SCO_LINK) < 1) return -ENODEV; - urb = usb_alloc_urb(BTUSB_MAX_ISOC_FRAMES, GFP_ATOMIC); + urb = usb_alloc_urb(BTUSB_MAX_ISOC_FRAMES, GFP_KERNEL); if (!urb) return -ENOMEM; @@ -848,7 +848,7 @@ static int btusb_send_frame(struct hci_dev *hdev, struct sk_buff *skb) skip_waking: usb_anchor_urb(urb, &data->tx_anchor); - err = usb_submit_urb(urb, GFP_ATOMIC); + err = usb_submit_urb(urb, GFP_KERNEL); if (err < 0) { if (err != -EPERM && err != -ENODEV) BT_ERR("%s urb %p submission failed (%d)", From 047b2ec8d3778a046d6985d4ad410c85211a86a4 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Sun, 14 Sep 2014 09:11:06 +0200 Subject: [PATCH 02/19] 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 Signed-off-by: Johan Hedberg --- drivers/bluetooth/btusb.c | 206 +++++++++++++++++++++++--------------- 1 file changed, 125 insertions(+), 81 deletions(-) diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c index d696e68f326a2..c89b330cfa9e8 100644 --- a/drivers/bluetooth/btusb.c +++ b/drivers/bluetooth/btusb.c @@ -296,20 +296,6 @@ struct btusb_data { int suspend_count; }; -static int inc_tx(struct btusb_data *data) -{ - unsigned long flags; - int rv; - - spin_lock_irqsave(&data->txlock, flags); - rv = test_bit(BTUSB_SUSPENDING, &data->flags); - if (!rv) - data->tx_in_flight++; - spin_unlock_irqrestore(&data->txlock, flags); - - return rv; -} - static void btusb_intr_complete(struct urb *urb) { struct hci_dev *hdev = urb->context; @@ -752,100 +738,96 @@ static int btusb_flush(struct hci_dev *hdev) return 0; } -static int btusb_send_frame(struct hci_dev *hdev, struct sk_buff *skb) +static struct urb *alloc_ctrl_urb(struct hci_dev *hdev, struct sk_buff *skb) { struct btusb_data *data = hci_get_drvdata(hdev); struct usb_ctrlrequest *dr; struct urb *urb; unsigned int pipe; - int err; - BT_DBG("%s", hdev->name); + urb = usb_alloc_urb(0, GFP_KERNEL); + if (!urb) + return ERR_PTR(-ENOMEM); - if (!test_bit(HCI_RUNNING, &hdev->flags)) - return -EBUSY; + dr = kmalloc(sizeof(*dr), GFP_KERNEL); + if (!dr) { + usb_free_urb(urb); + return ERR_PTR(-ENOMEM); + } - skb->dev = (void *) hdev; + dr->bRequestType = data->cmdreq_type; + dr->bRequest = 0; + dr->wIndex = 0; + dr->wValue = 0; + dr->wLength = __cpu_to_le16(skb->len); - switch (bt_cb(skb)->pkt_type) { - case HCI_COMMAND_PKT: - urb = usb_alloc_urb(0, GFP_KERNEL); - if (!urb) - return -ENOMEM; - - dr = kmalloc(sizeof(*dr), GFP_KERNEL); - if (!dr) { - usb_free_urb(urb); - return -ENOMEM; - } + pipe = usb_sndctrlpipe(data->udev, 0x00); - dr->bRequestType = data->cmdreq_type; - dr->bRequest = 0; - dr->wIndex = 0; - dr->wValue = 0; - dr->wLength = __cpu_to_le16(skb->len); + usb_fill_control_urb(urb, data->udev, pipe, (void *) dr, + skb->data, skb->len, btusb_tx_complete, skb); - pipe = usb_sndctrlpipe(data->udev, 0x00); + skb->dev = (void *) hdev; - usb_fill_control_urb(urb, data->udev, pipe, (void *) dr, - skb->data, skb->len, btusb_tx_complete, skb); + return urb; +} - hdev->stat.cmd_tx++; - break; +static struct urb *alloc_bulk_urb(struct hci_dev *hdev, struct sk_buff *skb) +{ + struct btusb_data *data = hci_get_drvdata(hdev); + struct urb *urb; + unsigned int pipe; - case HCI_ACLDATA_PKT: - if (!data->bulk_tx_ep) - return -ENODEV; + if (!data->bulk_tx_ep) + return ERR_PTR(-ENODEV); - urb = usb_alloc_urb(0, GFP_KERNEL); - if (!urb) - return -ENOMEM; + urb = usb_alloc_urb(0, GFP_KERNEL); + if (!urb) + return ERR_PTR(-ENOMEM); - pipe = usb_sndbulkpipe(data->udev, - data->bulk_tx_ep->bEndpointAddress); + pipe = usb_sndbulkpipe(data->udev, data->bulk_tx_ep->bEndpointAddress); - usb_fill_bulk_urb(urb, data->udev, pipe, - skb->data, skb->len, btusb_tx_complete, skb); + usb_fill_bulk_urb(urb, data->udev, pipe, + skb->data, skb->len, btusb_tx_complete, skb); - hdev->stat.acl_tx++; - break; + skb->dev = (void *) hdev; - case HCI_SCODATA_PKT: - if (!data->isoc_tx_ep || hci_conn_num(hdev, SCO_LINK) < 1) - return -ENODEV; + return urb; +} - urb = usb_alloc_urb(BTUSB_MAX_ISOC_FRAMES, GFP_KERNEL); - if (!urb) - return -ENOMEM; +static struct urb *alloc_isoc_urb(struct hci_dev *hdev, struct sk_buff *skb) +{ + struct btusb_data *data = hci_get_drvdata(hdev); + struct urb *urb; + unsigned int pipe; - pipe = usb_sndisocpipe(data->udev, - data->isoc_tx_ep->bEndpointAddress); + if (!data->isoc_tx_ep) + return ERR_PTR(-ENODEV); - usb_fill_int_urb(urb, data->udev, pipe, - skb->data, skb->len, btusb_isoc_tx_complete, - skb, data->isoc_tx_ep->bInterval); + urb = usb_alloc_urb(BTUSB_MAX_ISOC_FRAMES, GFP_KERNEL); + if (!urb) + return ERR_PTR(-ENOMEM); - urb->transfer_flags = URB_ISO_ASAP; + pipe = usb_sndisocpipe(data->udev, data->isoc_tx_ep->bEndpointAddress); - __fill_isoc_descriptor(urb, skb->len, - le16_to_cpu(data->isoc_tx_ep->wMaxPacketSize)); + usb_fill_int_urb(urb, data->udev, pipe, + skb->data, skb->len, btusb_isoc_tx_complete, + skb, data->isoc_tx_ep->bInterval); - hdev->stat.sco_tx++; - goto skip_waking; + urb->transfer_flags = URB_ISO_ASAP; - default: - return -EILSEQ; - } + __fill_isoc_descriptor(urb, skb->len, + le16_to_cpu(data->isoc_tx_ep->wMaxPacketSize)); - err = inc_tx(data); - if (err) { - usb_anchor_urb(urb, &data->deferred); - schedule_work(&data->waker); - err = 0; - goto done; - } + skb->dev = (void *) hdev; + + return urb; +} + +static int submit_tx_urb(struct hci_dev *hdev, struct urb *urb) +{ + struct btusb_data *data = hci_get_drvdata(hdev); + int err; -skip_waking: usb_anchor_urb(urb, &data->tx_anchor); err = usb_submit_urb(urb, GFP_KERNEL); @@ -859,11 +841,73 @@ static int btusb_send_frame(struct hci_dev *hdev, struct sk_buff *skb) usb_mark_last_busy(data->udev); } -done: usb_free_urb(urb); return err; } +static int submit_or_queue_tx_urb(struct hci_dev *hdev, struct urb *urb) +{ + struct btusb_data *data = hci_get_drvdata(hdev); + unsigned long flags; + bool suspending; + + spin_lock_irqsave(&data->txlock, flags); + suspending = test_bit(BTUSB_SUSPENDING, &data->flags); + if (!suspending) + data->tx_in_flight++; + spin_unlock_irqrestore(&data->txlock, flags); + + if (!suspending) + return submit_tx_urb(hdev, urb); + + usb_anchor_urb(urb, &data->deferred); + schedule_work(&data->waker); + + usb_free_urb(urb); + return 0; +} + +static int btusb_send_frame(struct hci_dev *hdev, struct sk_buff *skb) +{ + struct urb *urb; + + BT_DBG("%s", hdev->name); + + if (!test_bit(HCI_RUNNING, &hdev->flags)) + return -EBUSY; + + switch (bt_cb(skb)->pkt_type) { + case HCI_COMMAND_PKT: + urb = alloc_ctrl_urb(hdev, skb); + if (IS_ERR(urb)) + return PTR_ERR(urb); + + hdev->stat.cmd_tx++; + return submit_or_queue_tx_urb(hdev, urb); + + case HCI_ACLDATA_PKT: + urb = alloc_bulk_urb(hdev, skb); + if (IS_ERR(urb)) + return PTR_ERR(urb); + + hdev->stat.acl_tx++; + return submit_or_queue_tx_urb(hdev, urb); + + case HCI_SCODATA_PKT: + if (hci_conn_num(hdev, SCO_LINK) < 1) + return -ENODEV; + + urb = alloc_isoc_urb(hdev, skb); + if (IS_ERR(urb)) + return PTR_ERR(urb); + + hdev->stat.sco_tx++; + return submit_tx_urb(hdev, urb); + } + + return -EILSEQ; +} + static void btusb_notify(struct hci_dev *hdev, unsigned int evt) { struct btusb_data *data = hci_get_drvdata(hdev); From 7cb9d20fd9f8fb41f29e294734c4f8b5dc81ed93 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Sun, 14 Sep 2014 22:50:46 +0200 Subject: [PATCH 03/19] Bluetooth: Add BUILD_BUG_ON check for SKB control buffer size The struct bt_skb_cb size needs to stay within the limits of skb->cb at all times and to ensure that add a BUILD_BUG_ON to check for it at compile time. Signed-off-by: Marcel Holtmann Signed-off-by: Johan Hedberg --- net/bluetooth/af_bluetooth.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/net/bluetooth/af_bluetooth.c b/net/bluetooth/af_bluetooth.c index 4dca0299ed968..339c74ad45538 100644 --- a/net/bluetooth/af_bluetooth.c +++ b/net/bluetooth/af_bluetooth.c @@ -709,8 +709,11 @@ EXPORT_SYMBOL_GPL(bt_debugfs); static int __init bt_init(void) { + struct sk_buff *skb; int err; + BUILD_BUG_ON(sizeof(struct bt_skb_cb) > sizeof(skb->cb)); + BT_INFO("Core ver %s", VERSION); bt_debugfs = debugfs_create_dir("bluetooth", NULL); From 43e73e4e2ad05d9bf3b438cfbe1e71b57a85f26c Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Sun, 14 Sep 2014 23:06:28 +0200 Subject: [PATCH 04/19] Bluetooth: Provide HCI command opcode information to driver The Bluetooth core already does processing of the HCI command header and puts it together before sending it to the driver. It is not really efficient for the driver to look at the HCI command header again in case it has to make certain decisions about certain commands. To make this easier, just provide the opcode as part of the SKB control buffer information. The extra information about the opcode is optional and only provided for HCI commands. Signed-off-by: Marcel Holtmann Signed-off-by: Johan Hedberg --- include/net/bluetooth/bluetooth.h | 1 + net/bluetooth/hci_core.c | 1 + 2 files changed, 2 insertions(+) diff --git a/include/net/bluetooth/bluetooth.h b/include/net/bluetooth/bluetooth.h index 373000de610d4..7e666d06b97ff 100644 --- a/include/net/bluetooth/bluetooth.h +++ b/include/net/bluetooth/bluetooth.h @@ -284,6 +284,7 @@ struct hci_req_ctrl { struct bt_skb_cb { __u8 pkt_type; __u8 incoming; + __u16 opcode; __u16 expect; __u8 force_active; struct l2cap_chan *chan; diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c index 067526d9680de..41948678f5145 100644 --- a/net/bluetooth/hci_core.c +++ b/net/bluetooth/hci_core.c @@ -4547,6 +4547,7 @@ static struct sk_buff *hci_prepare_cmd(struct hci_dev *hdev, u16 opcode, BT_DBG("skb len %d", skb->len); bt_cb(skb)->pkt_type = HCI_COMMAND_PKT; + bt_cb(skb)->opcode = opcode; return skb; } From 6970c34cea87ad54aab84e743970b84b1fdf1c7d Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Mon, 15 Sep 2014 11:03:36 +0300 Subject: [PATCH 05/19] MAINTAINERS: add maintainer for generic 6LoWPAN Add Jukka to 6LoWPAN maintainer list. He will concentrate on generic and bluetooth part of 6LoWPAN stack. Signed-off-by: Jukka Rissanen Acked-by: Alexander Aring Signed-off-by: Marcel Holtmann --- MAINTAINERS | 1 + 1 file changed, 1 insertion(+) diff --git a/MAINTAINERS b/MAINTAINERS index 0b7007a9c8a42..94ad1bab633a2 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -152,6 +152,7 @@ F: drivers/scsi/53c700* 6LOWPAN GENERIC (BTLE/IEEE 802.15.4) M: Alexander Aring +M: Jukka Rissanen L: linux-bluetooth@vger.kernel.org L: linux-wpan@vger.kernel.org S: Maintained From 89e7533d0a96860f8aa24d05c9e35b18fdc28a61 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Tue, 16 Sep 2014 04:44:50 +0200 Subject: [PATCH 06/19] Bluetooth: btusb: Fix old coding style issues The btusb driver has been around for a while now and it is time to bring its coding style in sync with what has been done for the Bluetooth subsystem and other drivers. Signed-off-by: Marcel Holtmann Signed-off-by: Johan Hedberg --- drivers/bluetooth/btusb.c | 114 +++++++++++++++++++------------------- 1 file changed, 58 insertions(+), 56 deletions(-) diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c index c89b330cfa9e8..cf07fef65fd51 100644 --- a/drivers/bluetooth/btusb.c +++ b/drivers/bluetooth/btusb.c @@ -302,8 +302,8 @@ static void btusb_intr_complete(struct urb *urb) struct btusb_data *data = hci_get_drvdata(hdev); int err; - BT_DBG("%s urb %p status %d count %d", hdev->name, - urb, urb->status, urb->actual_length); + BT_DBG("%s urb %p status %d count %d", hdev->name, urb, urb->status, + urb->actual_length); if (!test_bit(HCI_RUNNING, &hdev->flags)) return; @@ -312,8 +312,8 @@ static void btusb_intr_complete(struct urb *urb) hdev->stat.byte_rx += urb->actual_length; if (hci_recv_fragment(hdev, HCI_EVENT_PKT, - urb->transfer_buffer, - urb->actual_length) < 0) { + urb->transfer_buffer, + urb->actual_length) < 0) { BT_ERR("%s corrupted event packet", hdev->name); hdev->stat.err_rx++; } @@ -334,7 +334,7 @@ static void btusb_intr_complete(struct urb *urb) * -ENODEV: device got disconnected */ if (err != -EPERM && err != -ENODEV) BT_ERR("%s urb %p failed to resubmit (%d)", - hdev->name, urb, -err); + hdev->name, urb, -err); usb_unanchor_urb(urb); } } @@ -367,8 +367,7 @@ static int btusb_submit_intr_urb(struct hci_dev *hdev, gfp_t mem_flags) pipe = usb_rcvintpipe(data->udev, data->intr_ep->bEndpointAddress); usb_fill_int_urb(urb, data->udev, pipe, buf, size, - btusb_intr_complete, hdev, - data->intr_ep->bInterval); + btusb_intr_complete, hdev, data->intr_ep->bInterval); urb->transfer_flags |= URB_FREE_BUFFER; @@ -378,7 +377,7 @@ static int btusb_submit_intr_urb(struct hci_dev *hdev, gfp_t mem_flags) if (err < 0) { if (err != -EPERM && err != -ENODEV) BT_ERR("%s urb %p submission failed (%d)", - hdev->name, urb, -err); + hdev->name, urb, -err); usb_unanchor_urb(urb); } @@ -393,8 +392,8 @@ static void btusb_bulk_complete(struct urb *urb) struct btusb_data *data = hci_get_drvdata(hdev); int err; - BT_DBG("%s urb %p status %d count %d", hdev->name, - urb, urb->status, urb->actual_length); + BT_DBG("%s urb %p status %d count %d", hdev->name, urb, urb->status, + urb->actual_length); if (!test_bit(HCI_RUNNING, &hdev->flags)) return; @@ -403,8 +402,8 @@ static void btusb_bulk_complete(struct urb *urb) hdev->stat.byte_rx += urb->actual_length; if (hci_recv_fragment(hdev, HCI_ACLDATA_PKT, - urb->transfer_buffer, - urb->actual_length) < 0) { + urb->transfer_buffer, + urb->actual_length) < 0) { BT_ERR("%s corrupted ACL packet", hdev->name); hdev->stat.err_rx++; } @@ -425,7 +424,7 @@ static void btusb_bulk_complete(struct urb *urb) * -ENODEV: device got disconnected */ if (err != -EPERM && err != -ENODEV) BT_ERR("%s urb %p failed to resubmit (%d)", - hdev->name, urb, -err); + hdev->name, urb, -err); usb_unanchor_urb(urb); } } @@ -455,8 +454,8 @@ static int btusb_submit_bulk_urb(struct hci_dev *hdev, gfp_t mem_flags) pipe = usb_rcvbulkpipe(data->udev, data->bulk_rx_ep->bEndpointAddress); - usb_fill_bulk_urb(urb, data->udev, pipe, - buf, size, btusb_bulk_complete, hdev); + usb_fill_bulk_urb(urb, data->udev, pipe, buf, size, + btusb_bulk_complete, hdev); urb->transfer_flags |= URB_FREE_BUFFER; @@ -467,7 +466,7 @@ static int btusb_submit_bulk_urb(struct hci_dev *hdev, gfp_t mem_flags) if (err < 0) { if (err != -EPERM && err != -ENODEV) BT_ERR("%s urb %p submission failed (%d)", - hdev->name, urb, -err); + hdev->name, urb, -err); usb_unanchor_urb(urb); } @@ -482,8 +481,8 @@ static void btusb_isoc_complete(struct urb *urb) struct btusb_data *data = hci_get_drvdata(hdev); int i, err; - BT_DBG("%s urb %p status %d count %d", hdev->name, - urb, urb->status, urb->actual_length); + BT_DBG("%s urb %p status %d count %d", hdev->name, urb, urb->status, + urb->actual_length); if (!test_bit(HCI_RUNNING, &hdev->flags)) return; @@ -499,8 +498,8 @@ static void btusb_isoc_complete(struct urb *urb) hdev->stat.byte_rx += length; if (hci_recv_fragment(hdev, HCI_SCODATA_PKT, - urb->transfer_buffer + offset, - length) < 0) { + urb->transfer_buffer + offset, + length) < 0) { BT_ERR("%s corrupted SCO packet", hdev->name); hdev->stat.err_rx++; } @@ -521,7 +520,7 @@ static void btusb_isoc_complete(struct urb *urb) * -ENODEV: device got disconnected */ if (err != -EPERM && err != -ENODEV) BT_ERR("%s urb %p failed to resubmit (%d)", - hdev->name, urb, -err); + hdev->name, urb, -err); usb_unanchor_urb(urb); } } @@ -576,12 +575,12 @@ static int btusb_submit_isoc_urb(struct hci_dev *hdev, gfp_t mem_flags) pipe = usb_rcvisocpipe(data->udev, data->isoc_rx_ep->bEndpointAddress); usb_fill_int_urb(urb, data->udev, pipe, buf, size, btusb_isoc_complete, - hdev, data->isoc_rx_ep->bInterval); + hdev, data->isoc_rx_ep->bInterval); - urb->transfer_flags = URB_FREE_BUFFER | URB_ISO_ASAP; + urb->transfer_flags = URB_FREE_BUFFER | URB_ISO_ASAP; __fill_isoc_descriptor(urb, size, - le16_to_cpu(data->isoc_rx_ep->wMaxPacketSize)); + le16_to_cpu(data->isoc_rx_ep->wMaxPacketSize)); usb_anchor_urb(urb, &data->isoc_anchor); @@ -589,7 +588,7 @@ static int btusb_submit_isoc_urb(struct hci_dev *hdev, gfp_t mem_flags) if (err < 0) { if (err != -EPERM && err != -ENODEV) BT_ERR("%s urb %p submission failed (%d)", - hdev->name, urb, -err); + hdev->name, urb, -err); usb_unanchor_urb(urb); } @@ -601,11 +600,11 @@ static int btusb_submit_isoc_urb(struct hci_dev *hdev, gfp_t mem_flags) static void btusb_tx_complete(struct urb *urb) { struct sk_buff *skb = urb->context; - struct hci_dev *hdev = (struct hci_dev *) skb->dev; + struct hci_dev *hdev = (struct hci_dev *)skb->dev; struct btusb_data *data = hci_get_drvdata(hdev); - BT_DBG("%s urb %p status %d count %d", hdev->name, - urb, urb->status, urb->actual_length); + BT_DBG("%s urb %p status %d count %d", hdev->name, urb, urb->status, + urb->actual_length); if (!test_bit(HCI_RUNNING, &hdev->flags)) goto done; @@ -628,10 +627,10 @@ static void btusb_tx_complete(struct urb *urb) static void btusb_isoc_tx_complete(struct urb *urb) { struct sk_buff *skb = urb->context; - struct hci_dev *hdev = (struct hci_dev *) skb->dev; + struct hci_dev *hdev = (struct hci_dev *)skb->dev; - BT_DBG("%s urb %p status %d count %d", hdev->name, - urb, urb->status, urb->actual_length); + BT_DBG("%s urb %p status %d count %d", hdev->name, urb, urb->status, + urb->actual_length); if (!test_bit(HCI_RUNNING, &hdev->flags)) goto done; @@ -763,10 +762,10 @@ static struct urb *alloc_ctrl_urb(struct hci_dev *hdev, struct sk_buff *skb) pipe = usb_sndctrlpipe(data->udev, 0x00); - usb_fill_control_urb(urb, data->udev, pipe, (void *) dr, + usb_fill_control_urb(urb, data->udev, pipe, (void *)dr, skb->data, skb->len, btusb_tx_complete, skb); - skb->dev = (void *) hdev; + skb->dev = (void *)hdev; return urb; } @@ -789,7 +788,7 @@ static struct urb *alloc_bulk_urb(struct hci_dev *hdev, struct sk_buff *skb) usb_fill_bulk_urb(urb, data->udev, pipe, skb->data, skb->len, btusb_tx_complete, skb); - skb->dev = (void *) hdev; + skb->dev = (void *)hdev; return urb; } @@ -818,7 +817,7 @@ static struct urb *alloc_isoc_urb(struct hci_dev *hdev, struct sk_buff *skb) __fill_isoc_descriptor(urb, skb->len, le16_to_cpu(data->isoc_tx_ep->wMaxPacketSize)); - skb->dev = (void *) hdev; + skb->dev = (void *)hdev; return urb; } @@ -834,7 +833,7 @@ static int submit_tx_urb(struct hci_dev *hdev, struct urb *urb) if (err < 0) { if (err != -EPERM && err != -ENODEV) BT_ERR("%s urb %p submission failed (%d)", - hdev->name, urb, -err); + hdev->name, urb, -err); kfree(urb->setup_packet); usb_unanchor_urb(urb); } else { @@ -984,6 +983,7 @@ static void btusb_work(struct work_struct *work) if (hdev->voice_setting & 0x0020) { static const int alts[3] = { 2, 4, 5 }; + new_alts = alts[data->sco_num - 1]; } else { new_alts = data->sco_num; @@ -1056,7 +1056,7 @@ static int btusb_setup_csr(struct hci_dev *hdev) return -PTR_ERR(skb); } - rp = (struct hci_rp_read_local_version *) skb->data; + rp = (struct hci_rp_read_local_version *)skb->data; if (!rp->status) { if (le16_to_cpu(rp->manufacturer) != 10) { @@ -1094,7 +1094,7 @@ struct intel_version { } __packed; static const struct firmware *btusb_setup_intel_get_fw(struct hci_dev *hdev, - struct intel_version *ver) + struct intel_version *ver) { const struct firmware *fw; char fwname[64]; @@ -1270,7 +1270,7 @@ static int btusb_check_bdaddr_intel(struct hci_dev *hdev) return -EIO; } - rp = (struct hci_rp_read_bd_addr *) skb->data; + rp = (struct hci_rp_read_bd_addr *)skb->data; if (rp->status) { BT_ERR("%s Intel device address result failed (%02x)", hdev->name, rp->status); @@ -1400,6 +1400,7 @@ static int btusb_setup_intel(struct hci_dev *hdev) if (skb->data[0]) { u8 evt_status = skb->data[0]; + BT_ERR("%s enable Intel manufacturer mode event failed (%02x)", hdev->name, evt_status); kfree_skb(skb); @@ -1509,7 +1510,7 @@ static int btusb_set_bdaddr_intel(struct hci_dev *hdev, const bdaddr_t *bdaddr) if (IS_ERR(skb)) { ret = PTR_ERR(skb); BT_ERR("%s: changing Intel device address failed (%ld)", - hdev->name, ret); + hdev->name, ret); return ret; } kfree_skb(skb); @@ -1584,19 +1585,19 @@ static int btusb_setup_bcm_patchram(struct hci_dev *hdev) if (IS_ERR(skb)) { ret = PTR_ERR(skb); BT_ERR("%s: HCI_OP_READ_LOCAL_VERSION failed (%ld)", - hdev->name, ret); + hdev->name, ret); goto done; } if (skb->len != sizeof(*ver)) { BT_ERR("%s: HCI_OP_READ_LOCAL_VERSION event length mismatch", - hdev->name); + hdev->name); kfree_skb(skb); ret = -EIO; goto done; } - ver = (struct hci_rp_read_local_version *) skb->data; + ver = (struct hci_rp_read_local_version *)skb->data; BT_INFO("%s: BCM: patching hci_ver=%02x hci_rev=%04x lmp_ver=%02x " "lmp_subver=%04x", hdev->name, ver->hci_ver, ver->hci_rev, ver->lmp_ver, ver->lmp_subver); @@ -1607,7 +1608,7 @@ static int btusb_setup_bcm_patchram(struct hci_dev *hdev) if (IS_ERR(skb)) { ret = PTR_ERR(skb); BT_ERR("%s: BCM: Download Minidrv command failed (%ld)", - hdev->name, ret); + hdev->name, ret); goto reset_fw; } kfree_skb(skb); @@ -1619,13 +1620,13 @@ static int btusb_setup_bcm_patchram(struct hci_dev *hdev) fw_size = fw->size; while (fw_size >= sizeof(*cmd)) { - cmd = (struct hci_command_hdr *) fw_ptr; + cmd = (struct hci_command_hdr *)fw_ptr; fw_ptr += sizeof(*cmd); fw_size -= sizeof(*cmd); if (fw_size < cmd->plen) { BT_ERR("%s: BCM: patch %s is corrupted", - hdev->name, fw_name); + hdev->name, fw_name); ret = -EINVAL; goto reset_fw; } @@ -1641,7 +1642,7 @@ static int btusb_setup_bcm_patchram(struct hci_dev *hdev) if (IS_ERR(skb)) { ret = PTR_ERR(skb); BT_ERR("%s: BCM: patch command %04x failed (%ld)", - hdev->name, opcode, ret); + hdev->name, opcode, ret); goto reset_fw; } kfree_skb(skb); @@ -1666,19 +1667,19 @@ static int btusb_setup_bcm_patchram(struct hci_dev *hdev) if (IS_ERR(skb)) { ret = PTR_ERR(skb); BT_ERR("%s: HCI_OP_READ_LOCAL_VERSION failed (%ld)", - hdev->name, ret); + hdev->name, ret); goto done; } if (skb->len != sizeof(*ver)) { BT_ERR("%s: HCI_OP_READ_LOCAL_VERSION event length mismatch", - hdev->name); + hdev->name); kfree_skb(skb); ret = -EIO; goto done; } - ver = (struct hci_rp_read_local_version *) skb->data; + ver = (struct hci_rp_read_local_version *)skb->data; BT_INFO("%s: BCM: firmware hci_ver=%02x hci_rev=%04x lmp_ver=%02x " "lmp_subver=%04x", hdev->name, ver->hci_ver, ver->hci_rev, ver->lmp_ver, ver->lmp_subver); @@ -1690,19 +1691,19 @@ static int btusb_setup_bcm_patchram(struct hci_dev *hdev) if (IS_ERR(skb)) { ret = PTR_ERR(skb); BT_ERR("%s: HCI_OP_READ_BD_ADDR failed (%ld)", - hdev->name, ret); + hdev->name, ret); goto done; } if (skb->len != sizeof(*bda)) { BT_ERR("%s: HCI_OP_READ_BD_ADDR event length mismatch", - hdev->name); + hdev->name); kfree_skb(skb); ret = -EIO; goto done; } - bda = (struct hci_rp_read_bd_addr *) skb->data; + bda = (struct hci_rp_read_bd_addr *)skb->data; if (bda->status) { BT_ERR("%s: HCI_OP_READ_BD_ADDR error status (%02x)", hdev->name, bda->status); @@ -1737,7 +1738,7 @@ static int btusb_set_bdaddr_bcm(struct hci_dev *hdev, const bdaddr_t *bdaddr) if (IS_ERR(skb)) { ret = PTR_ERR(skb); BT_ERR("%s: BCM: Change address command failed (%ld)", - hdev->name, ret); + hdev->name, ret); return ret; } kfree_skb(skb); @@ -1746,7 +1747,7 @@ static int btusb_set_bdaddr_bcm(struct hci_dev *hdev, const bdaddr_t *bdaddr) } static int btusb_probe(struct usb_interface *intf, - const struct usb_device_id *id) + const struct usb_device_id *id) { struct usb_endpoint_descriptor *ep_desc; struct btusb_data *data; @@ -1761,6 +1762,7 @@ static int btusb_probe(struct usb_interface *intf, if (!id->driver_info) { const struct usb_device_id *match; + match = usb_match_id(intf, blacklist_table); if (match) id = match; @@ -1911,7 +1913,7 @@ static int btusb_probe(struct usb_interface *intf, if (data->isoc) { err = usb_driver_claim_interface(&btusb_driver, - data->isoc, data); + data->isoc, data); if (err < 0) { hci_free_dev(hdev); return err; From 1ffa4ad042c3151b57ba3f316d5582166f964537 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Tue, 16 Sep 2014 05:33:33 +0200 Subject: [PATCH 07/19] Bluetooth: btusb: Split fragement receiption into separate functions The actual packet reassembly should be done inside the driver. To allow this to happen cleanly in future patches, split the fragment reception into its own functions. Signed-off-by: Marcel Holtmann Signed-off-by: Johan Hedberg --- drivers/bluetooth/btusb.c | 30 +++++++++++++++++++++--------- 1 file changed, 21 insertions(+), 9 deletions(-) diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c index cf07fef65fd51..df585ab064fa0 100644 --- a/drivers/bluetooth/btusb.c +++ b/drivers/bluetooth/btusb.c @@ -296,6 +296,21 @@ struct btusb_data { int suspend_count; }; +static int btusb_recv_intr(struct btusb_data *data, void *buffer, int count) +{ + return hci_recv_fragment(data->hdev, HCI_EVENT_PKT, buffer, count); +} + +static int btusb_recv_bulk(struct btusb_data *data, void *buffer, int count) +{ + return hci_recv_fragment(data->hdev, HCI_ACLDATA_PKT, buffer, count); +} + +static int btusb_recv_isoc(struct btusb_data *data, void *buffer, int count) +{ + return hci_recv_fragment(data->hdev, HCI_SCODATA_PKT, buffer, count); +} + static void btusb_intr_complete(struct urb *urb) { struct hci_dev *hdev = urb->context; @@ -311,9 +326,8 @@ static void btusb_intr_complete(struct urb *urb) if (urb->status == 0) { hdev->stat.byte_rx += urb->actual_length; - if (hci_recv_fragment(hdev, HCI_EVENT_PKT, - urb->transfer_buffer, - urb->actual_length) < 0) { + if (btusb_recv_intr(data, urb->transfer_buffer, + urb->actual_length) < 0) { BT_ERR("%s corrupted event packet", hdev->name); hdev->stat.err_rx++; } @@ -401,9 +415,8 @@ static void btusb_bulk_complete(struct urb *urb) if (urb->status == 0) { hdev->stat.byte_rx += urb->actual_length; - if (hci_recv_fragment(hdev, HCI_ACLDATA_PKT, - urb->transfer_buffer, - urb->actual_length) < 0) { + if (btusb_recv_bulk(data, urb->transfer_buffer, + urb->actual_length) < 0) { BT_ERR("%s corrupted ACL packet", hdev->name); hdev->stat.err_rx++; } @@ -497,9 +510,8 @@ static void btusb_isoc_complete(struct urb *urb) hdev->stat.byte_rx += length; - if (hci_recv_fragment(hdev, HCI_SCODATA_PKT, - urb->transfer_buffer + offset, - length) < 0) { + if (btusb_recv_isoc(data, urb->transfer_buffer + offset, + length) < 0) { BT_ERR("%s corrupted SCO packet", hdev->name); hdev->stat.err_rx++; } From 803b58367ffb7ae89397637122f9a71b2ee40687 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Tue, 16 Sep 2014 08:00:29 +0200 Subject: [PATCH 08/19] Bluetooth: btusb: Implement driver internal packet reassembly When receiving USB interrupt, bulk or isochronous packet, they normally come in fragments. So far the driver just handed each fragment off to the hci_recv_fragment function of the Bluetooth core. That function is however so specific that is does not belong in the core. This patch implements the same reassembly logic in the driver. In addition this fixes a long standing bug where multiple complete packets are received within a single USB packet. Signed-off-by: Marcel Holtmann Signed-off-by: Johan Hedberg --- drivers/bluetooth/btusb.c | 197 ++++++++++++++++++++++++++++++++++++-- 1 file changed, 189 insertions(+), 8 deletions(-) diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c index df585ab064fa0..a423b84a0ed34 100644 --- a/drivers/bluetooth/btusb.c +++ b/drivers/bluetooth/btusb.c @@ -275,13 +275,19 @@ struct btusb_data { struct work_struct work; struct work_struct waker; + struct usb_anchor deferred; struct usb_anchor tx_anchor; + int tx_in_flight; + spinlock_t txlock; + struct usb_anchor intr_anchor; struct usb_anchor bulk_anchor; struct usb_anchor isoc_anchor; - struct usb_anchor deferred; - int tx_in_flight; - spinlock_t txlock; + spinlock_t rxlock; + + struct sk_buff *evt_skb; + struct sk_buff *acl_skb; + struct sk_buff *sco_skb; struct usb_endpoint_descriptor *intr_ep; struct usb_endpoint_descriptor *bulk_tx_ep; @@ -296,19 +302,189 @@ struct btusb_data { int suspend_count; }; +static inline void btusb_free_frags(struct btusb_data *data) +{ + unsigned long flags; + + spin_lock_irqsave(&data->rxlock, flags); + + kfree_skb(data->evt_skb); + data->evt_skb = NULL; + + kfree_skb(data->acl_skb); + data->acl_skb = NULL; + + kfree_skb(data->sco_skb); + data->sco_skb = NULL; + + spin_unlock_irqrestore(&data->rxlock, flags); +} + static int btusb_recv_intr(struct btusb_data *data, void *buffer, int count) { - return hci_recv_fragment(data->hdev, HCI_EVENT_PKT, buffer, count); + struct sk_buff *skb; + int err = 0; + + spin_lock(&data->rxlock); + skb = data->evt_skb; + + while (count) { + int len; + + if (!skb) { + skb = bt_skb_alloc(HCI_MAX_EVENT_SIZE, GFP_ATOMIC); + if (!skb) { + err = -ENOMEM; + break; + } + + bt_cb(skb)->pkt_type = HCI_EVENT_PKT; + bt_cb(skb)->expect = HCI_EVENT_HDR_SIZE; + } + + len = min_t(uint, bt_cb(skb)->expect, count); + memcpy(skb_put(skb, len), buffer, len); + + count -= len; + buffer += len; + bt_cb(skb)->expect -= len; + + if (skb->len == HCI_EVENT_HDR_SIZE) { + /* Complete event header */ + bt_cb(skb)->expect = hci_event_hdr(skb)->plen; + + if (skb_tailroom(skb) < bt_cb(skb)->expect) { + kfree_skb(skb); + skb = NULL; + + err = -EILSEQ; + break; + } + } + + if (bt_cb(skb)->expect == 0) { + /* Complete frame */ + hci_recv_frame(data->hdev, skb); + skb = NULL; + } + } + + data->evt_skb = skb; + spin_unlock(&data->rxlock); + + return err; } static int btusb_recv_bulk(struct btusb_data *data, void *buffer, int count) { - return hci_recv_fragment(data->hdev, HCI_ACLDATA_PKT, buffer, count); + struct sk_buff *skb; + int err = 0; + + spin_lock(&data->rxlock); + skb = data->acl_skb; + + while (count) { + int len; + + if (!skb) { + skb = bt_skb_alloc(HCI_MAX_FRAME_SIZE, GFP_ATOMIC); + if (!skb) { + err = -ENOMEM; + break; + } + + bt_cb(skb)->pkt_type = HCI_ACLDATA_PKT; + bt_cb(skb)->expect = HCI_ACL_HDR_SIZE; + } + + len = min_t(uint, bt_cb(skb)->expect, count); + memcpy(skb_put(skb, len), buffer, len); + + count -= len; + buffer += len; + bt_cb(skb)->expect -= len; + + if (skb->len == HCI_ACL_HDR_SIZE) { + __le16 dlen = hci_acl_hdr(skb)->dlen; + + /* Complete ACL header */ + bt_cb(skb)->expect = __le16_to_cpu(dlen); + + if (skb_tailroom(skb) < bt_cb(skb)->expect) { + kfree_skb(skb); + skb = NULL; + + err = -EILSEQ; + break; + } + } + + if (bt_cb(skb)->expect == 0) { + /* Complete frame */ + hci_recv_frame(data->hdev, skb); + skb = NULL; + } + } + + data->acl_skb = skb; + spin_unlock(&data->rxlock); + + return err; } static int btusb_recv_isoc(struct btusb_data *data, void *buffer, int count) { - return hci_recv_fragment(data->hdev, HCI_SCODATA_PKT, buffer, count); + struct sk_buff *skb; + int err = 0; + + spin_lock(&data->rxlock); + skb = data->sco_skb; + + while (count) { + int len; + + if (!skb) { + skb = bt_skb_alloc(HCI_MAX_SCO_SIZE, GFP_ATOMIC); + if (!skb) { + err = -ENOMEM; + break; + } + + bt_cb(skb)->pkt_type = HCI_SCODATA_PKT; + bt_cb(skb)->expect = HCI_SCO_HDR_SIZE; + } + + len = min_t(uint, bt_cb(skb)->expect, count); + memcpy(skb_put(skb, len), buffer, len); + + count -= len; + buffer += len; + bt_cb(skb)->expect -= len; + + if (skb->len == HCI_SCO_HDR_SIZE) { + /* Complete SCO header */ + bt_cb(skb)->expect = hci_sco_hdr(skb)->dlen; + + if (skb_tailroom(skb) < bt_cb(skb)->expect) { + kfree_skb(skb); + skb = NULL; + + err = -EILSEQ; + break; + } + } + + if (bt_cb(skb)->expect == 0) { + /* Complete frame */ + hci_recv_frame(data->hdev, skb); + skb = NULL; + } + } + + data->sco_skb = skb; + spin_unlock(&data->rxlock); + + return err; } static void btusb_intr_complete(struct urb *urb) @@ -726,6 +902,8 @@ static int btusb_close(struct hci_dev *hdev) clear_bit(BTUSB_INTR_RUNNING, &data->flags); btusb_stop_traffic(data); + btusb_free_frags(data); + err = usb_autopm_get_interface(data->intf); if (err < 0) goto failed; @@ -745,6 +923,7 @@ static int btusb_flush(struct hci_dev *hdev) BT_DBG("%s", hdev->name); usb_kill_anchored_urbs(&data->tx_anchor); + btusb_free_frags(data); return 0; } @@ -1827,13 +2006,14 @@ static int btusb_probe(struct usb_interface *intf, INIT_WORK(&data->work, btusb_work); INIT_WORK(&data->waker, btusb_waker); + init_usb_anchor(&data->deferred); + init_usb_anchor(&data->tx_anchor); spin_lock_init(&data->txlock); - init_usb_anchor(&data->tx_anchor); init_usb_anchor(&data->intr_anchor); init_usb_anchor(&data->bulk_anchor); init_usb_anchor(&data->isoc_anchor); - init_usb_anchor(&data->deferred); + spin_lock_init(&data->rxlock); hdev = hci_alloc_dev(); if (!hdev) @@ -1966,6 +2146,7 @@ static void btusb_disconnect(struct usb_interface *intf) else if (data->isoc) usb_driver_release_interface(&btusb_driver, data->isoc); + btusb_free_frags(data); hci_free_dev(hdev); } From 0097db06f5ab2df1756bc4cbf4395593024d87a1 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Tue, 16 Sep 2014 21:36:09 +0200 Subject: [PATCH 09/19] Bluetooth: Remove exported hci_recv_fragment function The hci_recv_fragment function is no longer used by any driver and thus do not export it. In fact it is not even needed by the core and it can be removed altogether. Signed-off-by: Marcel Holtmann Signed-off-by: Johan Hedberg --- include/net/bluetooth/hci_core.h | 1 - net/bluetooth/hci_core.c | 20 -------------------- 2 files changed, 21 deletions(-) diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h index 206b92bfeebbd..37ff1aef0845e 100644 --- a/include/net/bluetooth/hci_core.h +++ b/include/net/bluetooth/hci_core.h @@ -926,7 +926,6 @@ int hci_remove_remote_oob_data(struct hci_dev *hdev, bdaddr_t *bdaddr); void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb); int hci_recv_frame(struct hci_dev *hdev, struct sk_buff *skb); -int hci_recv_fragment(struct hci_dev *hdev, int type, void *data, int count); int hci_recv_stream_fragment(struct hci_dev *hdev, void *data, int count); void hci_init_sysfs(struct hci_dev *hdev); diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c index 41948678f5145..cb05d7f16a34a 100644 --- a/net/bluetooth/hci_core.c +++ b/net/bluetooth/hci_core.c @@ -4374,26 +4374,6 @@ static int hci_reassembly(struct hci_dev *hdev, int type, void *data, return remain; } -int hci_recv_fragment(struct hci_dev *hdev, int type, void *data, int count) -{ - int rem = 0; - - if (type < HCI_ACLDATA_PKT || type > HCI_EVENT_PKT) - return -EILSEQ; - - while (count) { - rem = hci_reassembly(hdev, type, data, count, type - 1); - if (rem < 0) - return rem; - - data += (count - rem); - count = rem; - } - - return rem; -} -EXPORT_SYMBOL(hci_recv_fragment); - #define STREAM_REASSEMBLY 0 int hci_recv_stream_fragment(struct hci_dev *hdev, void *data, int count) From 5eb596f55cacc2389554a8d7572d90d5e9d4269d Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Thu, 18 Sep 2014 11:26:32 +0300 Subject: [PATCH 10/19] Bluetooth: Fix setting correct security level when initiating SMP We can only determine the final security level when both pairing request and response have been exchanged. When initiating pairing the starting target security level is set to MEDIUM unless explicitly specified to be HIGH, so that we can still perform pairing even if the remote doesn't have MITM capabilities. However, once we've received the pairing response we should re-consult the remote and local IO capabilities and upgrade the target security level if necessary. Without this patch the resulting Long Term Key will occasionally be reported to be unauthenticated when it in reality is an authenticated one. Signed-off-by: Johan Hedberg Signed-off-by: Marcel Holtmann Cc: stable@vger.kernel.org --- net/bluetooth/smp.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c index 51fc7db2d84e9..f09b6b65cf6b2 100644 --- a/net/bluetooth/smp.c +++ b/net/bluetooth/smp.c @@ -494,8 +494,11 @@ static int tk_request(struct l2cap_conn *conn, u8 remote_oob, u8 auth, } /* Not Just Works/Confirm results in MITM Authentication */ - if (method != JUST_CFM) + if (method != JUST_CFM) { set_bit(SMP_FLAG_MITM_AUTH, &smp->flags); + if (hcon->pending_sec_level < BT_SECURITY_HIGH) + hcon->pending_sec_level = BT_SECURITY_HIGH; + } /* If both devices have Keyoard-Display I/O, the master * Confirms and the slave Enters the passkey. From 48e68ff5e55af6907d3f90233e5c4d5601a628a6 Mon Sep 17 00:00:00 2001 From: Bernhard Thaler Date: Tue, 23 Sep 2014 11:01:07 +0200 Subject: [PATCH 11/19] Bluetooth: Check for SCO type before setting retransmission effort SCO connection cannot be setup to devices that do not support retransmission. Patch based on http://permalink.gmane.org/gmane.linux.bluez.kernel/7779 and adapted for this kernel version. Code changed to check SCO/eSCO type before setting retransmission effort and max. latency. The purpose of the patch is to support older devices not capable of eSCO. Tested on Blackberry 655+ headset which does not support retransmission. Credits go to Alexander Sommerhuber. Signed-off-by: Bernhard Thaler Signed-off-by: Marcel Holtmann --- net/bluetooth/hci_conn.c | 22 +++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c index e3d7ae9e2edd6..22b253750f787 100644 --- a/net/bluetooth/hci_conn.c +++ b/net/bluetooth/hci_conn.c @@ -38,7 +38,7 @@ struct sco_param { u16 max_latency; }; -static const struct sco_param sco_param_cvsd[] = { +static const struct sco_param esco_param_cvsd[] = { { EDR_ESCO_MASK & ~ESCO_2EV3, 0x000a }, /* S3 */ { EDR_ESCO_MASK & ~ESCO_2EV3, 0x0007 }, /* S2 */ { EDR_ESCO_MASK | ESCO_EV3, 0x0007 }, /* S1 */ @@ -46,6 +46,11 @@ static const struct sco_param sco_param_cvsd[] = { { EDR_ESCO_MASK | ESCO_HV1, 0xffff }, /* D0 */ }; +static const struct sco_param sco_param_cvsd[] = { + { EDR_ESCO_MASK | ESCO_HV3, 0xffff }, /* D1 */ + { EDR_ESCO_MASK | ESCO_HV1, 0xffff }, /* D0 */ +}; + static const struct sco_param sco_param_wideband[] = { { EDR_ESCO_MASK & ~ESCO_2EV3, 0x000d }, /* T2 */ { EDR_ESCO_MASK | ESCO_EV3, 0x0008 }, /* T1 */ @@ -207,10 +212,17 @@ bool hci_setup_sync(struct hci_conn *conn, __u16 handle) param = &sco_param_wideband[conn->attempt - 1]; break; case SCO_AIRMODE_CVSD: - if (conn->attempt > ARRAY_SIZE(sco_param_cvsd)) - return false; - cp.retrans_effort = 0x01; - param = &sco_param_cvsd[conn->attempt - 1]; + if (lmp_esco_capable(conn->link)) { + if (conn->attempt > ARRAY_SIZE(esco_param_cvsd)) + return false; + cp.retrans_effort = 0x01; + param = &esco_param_cvsd[conn->attempt - 1]; + } else { + if (conn->attempt > ARRAY_SIZE(sco_param_cvsd)) + return false; + cp.retrans_effort = 0xff; + param = &sco_param_cvsd[conn->attempt - 1]; + } break; default: return false; From 2b0bf6c85a4940e00516f68ff7103329abf8512d Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Mon, 22 Sep 2014 11:17:41 -0700 Subject: [PATCH 12/19] Bluetooth: Convert bt_ logging functions to return void No caller or macro uses the return value so make all the functions return void. Signed-off-by: Joe Perches Signed-off-by: Marcel Holtmann --- include/net/bluetooth/bluetooth.h | 4 ++-- net/bluetooth/lib.c | 14 ++++---------- 2 files changed, 6 insertions(+), 12 deletions(-) diff --git a/include/net/bluetooth/bluetooth.h b/include/net/bluetooth/bluetooth.h index 7e666d06b97ff..58695ffeb1381 100644 --- a/include/net/bluetooth/bluetooth.h +++ b/include/net/bluetooth/bluetooth.h @@ -120,9 +120,9 @@ struct bt_voice { #define BT_RCVMTU 13 __printf(1, 2) -int bt_info(const char *fmt, ...); +void bt_info(const char *fmt, ...); __printf(1, 2) -int bt_err(const char *fmt, ...); +void bt_err(const char *fmt, ...); #define BT_INFO(fmt, ...) bt_info(fmt "\n", ##__VA_ARGS__) #define BT_ERR(fmt, ...) bt_err(fmt "\n", ##__VA_ARGS__) diff --git a/net/bluetooth/lib.c b/net/bluetooth/lib.c index 941ad7530eda4..b36bc04158542 100644 --- a/net/bluetooth/lib.c +++ b/net/bluetooth/lib.c @@ -135,40 +135,34 @@ int bt_to_errno(__u16 code) } EXPORT_SYMBOL(bt_to_errno); -int bt_info(const char *format, ...) +void bt_info(const char *format, ...) { struct va_format vaf; va_list args; - int r; va_start(args, format); vaf.fmt = format; vaf.va = &args; - r = pr_info("%pV", &vaf); + pr_info("%pV", &vaf); va_end(args); - - return r; } EXPORT_SYMBOL(bt_info); -int bt_err(const char *format, ...) +void bt_err(const char *format, ...) { struct va_format vaf; va_list args; - int r; va_start(args, format); vaf.fmt = format; vaf.va = &args; - r = pr_err("%pV", &vaf); + pr_err("%pV", &vaf); va_end(args); - - return r; } EXPORT_SYMBOL(bt_err); From d41c15cf95bd91b9c333f6f749670e22c8a47ad9 Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Wed, 24 Sep 2014 13:14:46 +0300 Subject: [PATCH 13/19] Bluetooth: Fix reason code used for rejecting SCO connections The core specification defines valid values for the HCI_Reject_Synchronous_Connection_Request command to be 0x0D-0x0F. So far the code has been using HCI_ERROR_REMOTE_USER_TERM (0x13) which is not a valid value and is therefore being rejected by some controllers: > HCI Event: Connect Request (0x04) plen 10 bdaddr 40:6F:2A:6A:E5:E0 class 0x000000 type eSCO < HCI Command: Reject Synchronous Connection (0x01|0x002a) plen 7 bdaddr 40:6F:2A:6A:E5:E0 reason 0x13 Reason: Remote User Terminated Connection > HCI Event: Command Status (0x0f) plen 4 Reject Synchronous Connection (0x01|0x002a) status 0x12 ncmd 1 Error: Invalid HCI Command Parameters This patch introduces a new define for a value from the valid range (0x0d == Connection Rejected Due To Limited Resources) and uses it instead for rejecting incoming connections. Signed-off-by: Johan Hedberg Signed-off-by: Marcel Holtmann --- include/net/bluetooth/hci.h | 1 + net/bluetooth/hci_conn.c | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h index 3f8547f1c6f8c..6e8f249673089 100644 --- a/include/net/bluetooth/hci.h +++ b/include/net/bluetooth/hci.h @@ -385,6 +385,7 @@ enum { #define HCI_ERROR_AUTH_FAILURE 0x05 #define HCI_ERROR_MEMORY_EXCEEDED 0x07 #define HCI_ERROR_CONNECTION_TIMEOUT 0x08 +#define HCI_ERROR_REJ_LIMITED_RESOURCES 0x0d #define HCI_ERROR_REJ_BAD_ADDR 0x0f #define HCI_ERROR_REMOTE_USER_TERM 0x13 #define HCI_ERROR_REMOTE_LOW_RESOURCES 0x14 diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c index 22b253750f787..445829cd363c7 100644 --- a/net/bluetooth/hci_conn.c +++ b/net/bluetooth/hci_conn.c @@ -121,7 +121,7 @@ static void hci_reject_sco(struct hci_conn *conn) { struct hci_cp_reject_sync_conn_req cp; - cp.reason = HCI_ERROR_REMOTE_USER_TERM; + cp.reason = HCI_ERROR_REJ_LIMITED_RESOURCES; bacpy(&cp.bdaddr, &conn->dst); hci_send_cmd(conn->hdev, HCI_OP_REJECT_SYNC_CONN_REQ, sizeof(cp), &cp); From 529160dc73a1cb4bb377887f5453d33b6d84d18f Mon Sep 17 00:00:00 2001 From: Varka Bhadram Date: Wed, 24 Sep 2014 12:21:30 +0200 Subject: [PATCH 14/19] mrf24j40: fix Missing a blank line after declarations Signed-off-by: Varka Bhadram Acked-by: Alan Ott Signed-off-by: Alexander Aring Signed-off-by: Marcel Holtmann --- drivers/net/ieee802154/mrf24j40.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/net/ieee802154/mrf24j40.c b/drivers/net/ieee802154/mrf24j40.c index 9e6a124b13f2c..466da572e3f53 100644 --- a/drivers/net/ieee802154/mrf24j40.c +++ b/drivers/net/ieee802154/mrf24j40.c @@ -412,6 +412,7 @@ static void mrf24j40_stop(struct ieee802154_dev *dev) struct mrf24j40 *devrec = dev->priv; u8 val; int ret; + dev_dbg(printdev(devrec), "stop\n"); ret = read_short_reg(devrec, REG_INTCON, &val); @@ -465,6 +466,7 @@ static int mrf24j40_filter(struct ieee802154_dev *dev, if (changed & IEEE802515_AFILT_SADDR_CHANGED) { /* Short Addr */ u8 addrh, addrl; + addrh = le16_to_cpu(filt->short_addr) >> 8 & 0xff; addrl = le16_to_cpu(filt->short_addr) & 0xff; @@ -493,6 +495,7 @@ static int mrf24j40_filter(struct ieee802154_dev *dev, if (changed & IEEE802515_AFILT_PANID_CHANGED) { /* PAN ID */ u8 panidl, panidh; + panidh = le16_to_cpu(filt->pan_id) >> 8 & 0xff; panidl = le16_to_cpu(filt->pan_id) & 0xff; write_short_reg(devrec, REG_PANIDH, panidh); From 3d920f06e2f2f8f601084718da6c55f8885d7a7f Mon Sep 17 00:00:00 2001 From: Varka Bhadram Date: Wed, 24 Sep 2014 12:21:31 +0200 Subject: [PATCH 15/19] mrf24j40: remove unnecessary return statement Remove the return statement in the void function. Signed-off-by: Varka Bhadram Acked-by: Alan Ott Signed-off-by: Alexander Aring Signed-off-by: Marcel Holtmann --- drivers/net/ieee802154/mrf24j40.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/net/ieee802154/mrf24j40.c b/drivers/net/ieee802154/mrf24j40.c index 466da572e3f53..2c617e368dca2 100644 --- a/drivers/net/ieee802154/mrf24j40.c +++ b/drivers/net/ieee802154/mrf24j40.c @@ -420,8 +420,6 @@ static void mrf24j40_stop(struct ieee802154_dev *dev) return; val |= 0x1|0x8; /* Set TXNIE and RXIE. Disable Interrupts */ write_short_reg(devrec, REG_INTCON, val); - - return; } static int mrf24j40_set_channel(struct ieee802154_dev *dev, From ca079ad6af0d9948101992d03e7145ab8b426f66 Mon Sep 17 00:00:00 2001 From: Varka Bhadram Date: Wed, 24 Sep 2014 12:21:32 +0200 Subject: [PATCH 16/19] mrf24j40: use pr_* / dev_* instead of printk() Replace printk() with dev_*() pr_*(). Signed-off-by: Varka Bhadram Acked-by: Alan Ott Signed-off-by: Alexander Aring Signed-off-by: Marcel Holtmann --- drivers/net/ieee802154/mrf24j40.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/net/ieee802154/mrf24j40.c b/drivers/net/ieee802154/mrf24j40.c index 2c617e368dca2..07e0b887c350f 100644 --- a/drivers/net/ieee802154/mrf24j40.c +++ b/drivers/net/ieee802154/mrf24j40.c @@ -323,8 +323,8 @@ static int mrf24j40_read_rx_buf(struct mrf24j40 *devrec, #ifdef DEBUG print_hex_dump(KERN_DEBUG, "mrf24j40 rx: ", DUMP_PREFIX_OFFSET, 16, 1, data, *len, 0); - printk(KERN_DEBUG "mrf24j40 rx: lqi: %02hhx rssi: %02hhx\n", - lqi_rssi[0], lqi_rssi[1]); + pr_debug("mrf24j40 rx: lqi: %02hhx rssi: %02hhx\n", + lqi_rssi[0], lqi_rssi[1]); #endif out: @@ -385,7 +385,7 @@ static int mrf24j40_tx(struct ieee802154_dev *dev, struct sk_buff *skb) static int mrf24j40_ed(struct ieee802154_dev *dev, u8 *level) { /* TODO: */ - printk(KERN_WARNING "mrf24j40: ed not implemented\n"); + pr_warn("mrf24j40: ed not implemented\n"); *level = 0; return 0; } @@ -483,10 +483,10 @@ static int mrf24j40_filter(struct ieee802154_dev *dev, write_short_reg(devrec, REG_EADR0 + i, addr[i]); #ifdef DEBUG - printk(KERN_DEBUG "Set long addr to: "); + pr_debug("Set long addr to: "); for (i = 0; i < 8; i++) - printk("%02hhx ", addr[7 - i]); - printk(KERN_DEBUG "\n"); + pr_debug("%02hhx ", addr[7 - i]); + pr_debug("\n"); #endif } @@ -702,7 +702,7 @@ static int mrf24j40_probe(struct spi_device *spi) int ret = -ENOMEM; struct mrf24j40 *devrec; - printk(KERN_INFO "mrf24j40: probe(). IRQ: %d\n", spi->irq); + dev_info(&spi->dev, "probe(). IRQ: %d\n", spi->irq); devrec = devm_kzalloc(&spi->dev, sizeof(struct mrf24j40), GFP_KERNEL); if (!devrec) From f19f4f9525cf32f97341fac20ce66392e86a1b67 Mon Sep 17 00:00:00 2001 From: Simon Vincent Date: Wed, 24 Sep 2014 12:21:33 +0200 Subject: [PATCH 17/19] ieee802154: 6lowpan: ensure header compression does not corrupt ipv6 header The 6lowpan ipv6 header compression was causing problems for other interfaces that expected a ipv6 header to still be in place, as we were replacing the ipv6 header with a compressed version. This happened if you sent a packet to a multicast address as the packet would be output on 802.15.4, ethernet, and also be sent to the loopback interface. The skb data was shared between these interfaces so all interfaces ended up with a compressed ipv6 header. The solution is to ensure that before we do any header compression we are not sharing the skb or skb data with any other interface. If we are then we must take a copy of the skb and skb data before modifying the ipv6 header. The only place we can copy the skb is inside the xmit function so we don't leave dangling references to skb. This patch moves all the header compression to inside the xmit function. Very little code has been changed it has mostly been moved from lowpan_header_create to lowpan_xmit. At the top of the xmit function we now check if the skb is shared and if so copy it. In lowpan_header_create all we do now is store the source and destination addresses for use later when we compress the header. Signed-off-by: Simon Vincent Signed-off-by: Alexander Aring Signed-off-by: Marcel Holtmann --- net/ieee802154/6lowpan_rtnl.c | 125 ++++++++++++++++++++++++---------- 1 file changed, 89 insertions(+), 36 deletions(-) diff --git a/net/ieee802154/6lowpan_rtnl.c b/net/ieee802154/6lowpan_rtnl.c index 5e788cdc499a3..44136297b673a 100644 --- a/net/ieee802154/6lowpan_rtnl.c +++ b/net/ieee802154/6lowpan_rtnl.c @@ -71,20 +71,42 @@ struct lowpan_dev_record { struct list_head list; }; +/* don't save pan id, it's intra pan */ +struct lowpan_addr { + u8 mode; + union { + /* IPv6 needs big endian here */ + __be64 extended_addr; + __be16 short_addr; + } u; +}; + +struct lowpan_addr_info { + struct lowpan_addr daddr; + struct lowpan_addr saddr; +}; + static inline struct lowpan_dev_info *lowpan_dev_info(const struct net_device *dev) { return netdev_priv(dev); } +static inline struct +lowpan_addr_info *lowpan_skb_priv(const struct sk_buff *skb) +{ + WARN_ON_ONCE(skb_headroom(skb) < sizeof(struct lowpan_addr_info)); + return (struct lowpan_addr_info *)(skb->data - + sizeof(struct lowpan_addr_info)); +} + static int lowpan_header_create(struct sk_buff *skb, struct net_device *dev, unsigned short type, const void *_daddr, const void *_saddr, unsigned int len) { const u8 *saddr = _saddr; const u8 *daddr = _daddr; - struct ieee802154_addr sa, da; - struct ieee802154_mac_cb *cb = mac_cb_init(skb); + struct lowpan_addr_info *info; /* TODO: * if this package isn't ipv6 one, where should it be routed? @@ -98,41 +120,17 @@ static int lowpan_header_create(struct sk_buff *skb, struct net_device *dev, raw_dump_inline(__func__, "saddr", (unsigned char *)saddr, 8); raw_dump_inline(__func__, "daddr", (unsigned char *)daddr, 8); - lowpan_header_compress(skb, dev, type, daddr, saddr, len); - - /* NOTE1: I'm still unsure about the fact that compression and WPAN - * header are created here and not later in the xmit. So wait for - * an opinion of net maintainers. - */ - /* NOTE2: to be absolutely correct, we must derive PANid information - * from MAC subif of the 'dev' and 'real_dev' network devices, but - * this isn't implemented in mainline yet, so currently we assign 0xff - */ - cb->type = IEEE802154_FC_TYPE_DATA; - - /* prepare wpan address data */ - sa.mode = IEEE802154_ADDR_LONG; - sa.pan_id = ieee802154_mlme_ops(dev)->get_pan_id(dev); - sa.extended_addr = ieee802154_devaddr_from_raw(saddr); - - /* intra-PAN communications */ - da.pan_id = sa.pan_id; - - /* if the destination address is the broadcast address, use the - * corresponding short address - */ - if (lowpan_is_addr_broadcast(daddr)) { - da.mode = IEEE802154_ADDR_SHORT; - da.short_addr = cpu_to_le16(IEEE802154_ADDR_BROADCAST); - } else { - da.mode = IEEE802154_ADDR_LONG; - da.extended_addr = ieee802154_devaddr_from_raw(daddr); - } + info = lowpan_skb_priv(skb); - cb->ackreq = !lowpan_is_addr_broadcast(daddr); + /* TODO: Currently we only support extended_addr */ + info->daddr.mode = IEEE802154_ADDR_LONG; + memcpy(&info->daddr.u.extended_addr, daddr, + sizeof(info->daddr.u.extended_addr)); + info->saddr.mode = IEEE802154_ADDR_LONG; + memcpy(&info->saddr.u.extended_addr, saddr, + sizeof(info->daddr.u.extended_addr)); - return dev_hard_header(skb, lowpan_dev_info(dev)->real_dev, - type, (void *)&da, (void *)&sa, 0); + return 0; } static int lowpan_give_skb_to_devices(struct sk_buff *skb, @@ -330,13 +328,68 @@ lowpan_xmit_fragmented(struct sk_buff *skb, struct net_device *dev, return rc; } +static int lowpan_header(struct sk_buff *skb, struct net_device *dev) +{ + struct ieee802154_addr sa, da; + struct ieee802154_mac_cb *cb = mac_cb_init(skb); + struct lowpan_addr_info info; + void *daddr, *saddr; + + memcpy(&info, lowpan_skb_priv(skb), sizeof(info)); + + /* TODO: Currently we only support extended_addr */ + daddr = &info.daddr.u.extended_addr; + saddr = &info.saddr.u.extended_addr; + + lowpan_header_compress(skb, dev, ETH_P_IPV6, daddr, saddr, skb->len); + + cb->type = IEEE802154_FC_TYPE_DATA; + + /* prepare wpan address data */ + sa.mode = IEEE802154_ADDR_LONG; + sa.pan_id = ieee802154_mlme_ops(dev)->get_pan_id(dev); + sa.extended_addr = ieee802154_devaddr_from_raw(saddr); + + /* intra-PAN communications */ + da.pan_id = sa.pan_id; + + /* if the destination address is the broadcast address, use the + * corresponding short address + */ + if (lowpan_is_addr_broadcast((const u8 *)daddr)) { + da.mode = IEEE802154_ADDR_SHORT; + da.short_addr = cpu_to_le16(IEEE802154_ADDR_BROADCAST); + cb->ackreq = false; + } else { + da.mode = IEEE802154_ADDR_LONG; + da.extended_addr = ieee802154_devaddr_from_raw(daddr); + cb->ackreq = true; + } + + return dev_hard_header(skb, lowpan_dev_info(dev)->real_dev, + ETH_P_IPV6, (void *)&da, (void *)&sa, 0); +} + static netdev_tx_t lowpan_xmit(struct sk_buff *skb, struct net_device *dev) { struct ieee802154_hdr wpan_hdr; - int max_single; + int max_single, ret; pr_debug("package xmit\n"); + /* We must take a copy of the skb before we modify/replace the ipv6 + * header as the header could be used elsewhere + */ + skb = skb_unshare(skb, GFP_ATOMIC); + if (!skb) + return NET_XMIT_DROP; + + ret = lowpan_header(skb, dev); + if (ret < 0) { + kfree_skb(skb); + return NET_XMIT_DROP; + } + if (ieee802154_hdr_peek(skb, &wpan_hdr) < 0) { kfree_skb(skb); return NET_XMIT_DROP; From c7da579763f29cf45a861ad4c339aba590d8b80d Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Wed, 24 Sep 2014 22:41:46 +0300 Subject: [PATCH 18/19] Bluetooth: Add retransmission effort into SCO parameter table It is expected that new parameter combinations will have the retransmission effort value different between some entries (mainly because of the new S4 configuration added by HFP 1.7), so it makes sense to move it into the table instead of having it hard coded based on the selected SCO_AIRMODE_*. Signed-off-by: Johan Hedberg Signed-off-by: Marcel Holtmann --- net/bluetooth/hci_conn.c | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c index 445829cd363c7..06047142797c7 100644 --- a/net/bluetooth/hci_conn.c +++ b/net/bluetooth/hci_conn.c @@ -36,24 +36,25 @@ struct sco_param { u16 pkt_type; u16 max_latency; + u8 retrans_effort; }; static const struct sco_param esco_param_cvsd[] = { - { EDR_ESCO_MASK & ~ESCO_2EV3, 0x000a }, /* S3 */ - { EDR_ESCO_MASK & ~ESCO_2EV3, 0x0007 }, /* S2 */ - { EDR_ESCO_MASK | ESCO_EV3, 0x0007 }, /* S1 */ - { EDR_ESCO_MASK | ESCO_HV3, 0xffff }, /* D1 */ - { EDR_ESCO_MASK | ESCO_HV1, 0xffff }, /* D0 */ + { EDR_ESCO_MASK & ~ESCO_2EV3, 0x000a, 0x01 }, /* S3 */ + { EDR_ESCO_MASK & ~ESCO_2EV3, 0x0007, 0x01 }, /* S2 */ + { EDR_ESCO_MASK | ESCO_EV3, 0x0007, 0x01 }, /* S1 */ + { EDR_ESCO_MASK | ESCO_HV3, 0xffff, 0x01 }, /* D1 */ + { EDR_ESCO_MASK | ESCO_HV1, 0xffff, 0x01 }, /* D0 */ }; static const struct sco_param sco_param_cvsd[] = { - { EDR_ESCO_MASK | ESCO_HV3, 0xffff }, /* D1 */ - { EDR_ESCO_MASK | ESCO_HV1, 0xffff }, /* D0 */ + { EDR_ESCO_MASK | ESCO_HV3, 0xffff, 0xff }, /* D1 */ + { EDR_ESCO_MASK | ESCO_HV1, 0xffff, 0xff }, /* D0 */ }; static const struct sco_param sco_param_wideband[] = { - { EDR_ESCO_MASK & ~ESCO_2EV3, 0x000d }, /* T2 */ - { EDR_ESCO_MASK | ESCO_EV3, 0x0008 }, /* T1 */ + { EDR_ESCO_MASK & ~ESCO_2EV3, 0x000d, 0x02 }, /* T2 */ + { EDR_ESCO_MASK | ESCO_EV3, 0x0008, 0x02 }, /* T1 */ }; static void hci_le_create_connection_cancel(struct hci_conn *conn) @@ -208,19 +209,16 @@ bool hci_setup_sync(struct hci_conn *conn, __u16 handle) case SCO_AIRMODE_TRANSP: if (conn->attempt > ARRAY_SIZE(sco_param_wideband)) return false; - cp.retrans_effort = 0x02; param = &sco_param_wideband[conn->attempt - 1]; break; case SCO_AIRMODE_CVSD: if (lmp_esco_capable(conn->link)) { if (conn->attempt > ARRAY_SIZE(esco_param_cvsd)) return false; - cp.retrans_effort = 0x01; param = &esco_param_cvsd[conn->attempt - 1]; } else { if (conn->attempt > ARRAY_SIZE(sco_param_cvsd)) return false; - cp.retrans_effort = 0xff; param = &sco_param_cvsd[conn->attempt - 1]; } break; @@ -228,6 +226,7 @@ bool hci_setup_sync(struct hci_conn *conn, __u16 handle) return false; } + cp.retrans_effort = param->retrans_effort; cp.pkt_type = __cpu_to_le16(param->pkt_type); cp.max_latency = __cpu_to_le16(param->max_latency); From 565766b087a6d6ff257f5b79c8ceda0188c9169f Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Thu, 25 Sep 2014 09:48:01 +0300 Subject: [PATCH 19/19] Bluetooth: Rename sco_param_wideband table to esco_param_msbc The sco_param_wideband table represents the eSCO parameters for specifically mSBC encoding. This patch renames the table to the more descriptive esco_param_msbc name. Signed-off-by: Johan Hedberg Signed-off-by: Marcel Holtmann --- net/bluetooth/hci_conn.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c index 06047142797c7..b9517bd171901 100644 --- a/net/bluetooth/hci_conn.c +++ b/net/bluetooth/hci_conn.c @@ -52,7 +52,7 @@ static const struct sco_param sco_param_cvsd[] = { { EDR_ESCO_MASK | ESCO_HV1, 0xffff, 0xff }, /* D0 */ }; -static const struct sco_param sco_param_wideband[] = { +static const struct sco_param esco_param_msbc[] = { { EDR_ESCO_MASK & ~ESCO_2EV3, 0x000d, 0x02 }, /* T2 */ { EDR_ESCO_MASK | ESCO_EV3, 0x0008, 0x02 }, /* T1 */ }; @@ -207,9 +207,9 @@ bool hci_setup_sync(struct hci_conn *conn, __u16 handle) switch (conn->setting & SCO_AIRMODE_MASK) { case SCO_AIRMODE_TRANSP: - if (conn->attempt > ARRAY_SIZE(sco_param_wideband)) + if (conn->attempt > ARRAY_SIZE(esco_param_msbc)) return false; - param = &sco_param_wideband[conn->attempt - 1]; + param = &esco_param_msbc[conn->attempt - 1]; break; case SCO_AIRMODE_CVSD: if (lmp_esco_capable(conn->link)) {