Skip to content

Commit 800fe5e

Browse files
Vudentzholtmann
authored andcommitted
Bluetooth: btusb: Add support for queuing during polling interval
This makes btusb to queue ACL and events during a polling interval by using of a delayed work, with the interval working as a time window where frames received from different endpoints are considered to be arrived at same time and then attempt to resolve potential conflics by processing the events ahead of ACL packets. It worth noting though that priorizing events over ACL data may result in inverting the order compared to how they appeared over the air, for instance there may be packets received before a disconnect event that will be discarded and unencrypted packets received before encryption change which would considered encrypted, because of these potential changes on the order the support for queuing during the polling interval is not enabled by default so it requires setting force_poll_sync debugfs while the adapter is down. Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com> Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
1 parent fe92ee6 commit 800fe5e

File tree

1 file changed

+124
-5
lines changed

1 file changed

+124
-5
lines changed

drivers/bluetooth/btusb.c

Lines changed: 124 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
#include <linux/of_irq.h>
1717
#include <linux/suspend.h>
1818
#include <linux/gpio/consumer.h>
19+
#include <linux/debugfs.h>
1920
#include <asm/unaligned.h>
2021

2122
#include <net/bluetooth/bluetooth.h>
@@ -31,7 +32,6 @@
3132
static bool disable_scofix;
3233
static bool force_scofix;
3334
static bool enable_autosuspend = IS_ENABLED(CONFIG_BT_HCIBTUSB_AUTOSUSPEND);
34-
3535
static bool reset = true;
3636

3737
static struct usb_driver btusb_driver;
@@ -561,8 +561,13 @@ struct btusb_data {
561561

562562
unsigned long flags;
563563

564-
struct work_struct work;
565-
struct work_struct waker;
564+
bool poll_sync;
565+
int intr_interval;
566+
struct work_struct work;
567+
struct work_struct waker;
568+
struct delayed_work rx_work;
569+
570+
struct sk_buff_head acl_q;
566571

567572
struct usb_anchor deferred;
568573
struct usb_anchor tx_anchor;
@@ -727,6 +732,16 @@ static inline void btusb_free_frags(struct btusb_data *data)
727732
spin_unlock_irqrestore(&data->rxlock, flags);
728733
}
729734

735+
static int btusb_recv_event(struct btusb_data *data, struct sk_buff *skb)
736+
{
737+
if (data->intr_interval) {
738+
/* Trigger dequeue immediatelly if an event is received */
739+
schedule_delayed_work(&data->rx_work, 0);
740+
}
741+
742+
return data->recv_event(data->hdev, skb);
743+
}
744+
730745
static int btusb_recv_intr(struct btusb_data *data, void *buffer, int count)
731746
{
732747
struct sk_buff *skb;
@@ -772,7 +787,7 @@ static int btusb_recv_intr(struct btusb_data *data, void *buffer, int count)
772787

773788
if (!hci_skb_expect(skb)) {
774789
/* Complete frame */
775-
data->recv_event(data->hdev, skb);
790+
btusb_recv_event(data, skb);
776791
skb = NULL;
777792
}
778793
}
@@ -783,6 +798,20 @@ static int btusb_recv_intr(struct btusb_data *data, void *buffer, int count)
783798
return err;
784799
}
785800

801+
static int btusb_recv_acl(struct btusb_data *data, struct sk_buff *skb)
802+
{
803+
/* Only queue ACL packet if intr_interval is set as it means
804+
* force_poll_sync has been enabled.
805+
*/
806+
if (!data->intr_interval)
807+
return data->recv_acl(data->hdev, skb);
808+
809+
skb_queue_tail(&data->acl_q, skb);
810+
schedule_delayed_work(&data->rx_work, data->intr_interval);
811+
812+
return 0;
813+
}
814+
786815
static int btusb_recv_bulk(struct btusb_data *data, void *buffer, int count)
787816
{
788817
struct sk_buff *skb;
@@ -830,7 +859,7 @@ static int btusb_recv_bulk(struct btusb_data *data, void *buffer, int count)
830859

831860
if (!hci_skb_expect(skb)) {
832861
/* Complete frame */
833-
data->recv_acl(data->hdev, skb);
862+
btusb_recv_acl(data, skb);
834863
skb = NULL;
835864
}
836865
}
@@ -986,6 +1015,28 @@ static int btusb_submit_intr_urb(struct hci_dev *hdev, gfp_t mem_flags)
9861015
usb_unanchor_urb(urb);
9871016
}
9881017

1018+
/* Only initialize intr_interval if URB poll sync is enabled */
1019+
if (!data->poll_sync)
1020+
goto done;
1021+
1022+
/* The units are frames (milliseconds) for full and low speed devices,
1023+
* and microframes (1/8 millisecond) for highspeed and SuperSpeed
1024+
* devices.
1025+
*
1026+
* This is done once on open/resume so it shouldn't change even if
1027+
* force_poll_sync changes.
1028+
*/
1029+
switch (urb->dev->speed) {
1030+
case USB_SPEED_SUPER_PLUS:
1031+
case USB_SPEED_SUPER: /* units are 125us */
1032+
data->intr_interval = usecs_to_jiffies(urb->interval * 125);
1033+
break;
1034+
default:
1035+
data->intr_interval = msecs_to_jiffies(urb->interval);
1036+
break;
1037+
}
1038+
1039+
done:
9891040
usb_free_urb(urb);
9901041

9911042
return err;
@@ -1448,9 +1499,12 @@ static int btusb_close(struct hci_dev *hdev)
14481499

14491500
BT_DBG("%s", hdev->name);
14501501

1502+
cancel_delayed_work(&data->rx_work);
14511503
cancel_work_sync(&data->work);
14521504
cancel_work_sync(&data->waker);
14531505

1506+
skb_queue_purge(&data->acl_q);
1507+
14541508
clear_bit(BTUSB_ISOC_RUNNING, &data->flags);
14551509
clear_bit(BTUSB_BULK_RUNNING, &data->flags);
14561510
clear_bit(BTUSB_INTR_RUNNING, &data->flags);
@@ -1482,6 +1536,10 @@ static int btusb_flush(struct hci_dev *hdev)
14821536

14831537
BT_DBG("%s", hdev->name);
14841538

1539+
cancel_delayed_work(&data->rx_work);
1540+
1541+
skb_queue_purge(&data->acl_q);
1542+
14851543
usb_kill_anchored_urbs(&data->tx_anchor);
14861544
btusb_free_frags(data);
14871545

@@ -1845,6 +1903,17 @@ static void btusb_waker(struct work_struct *work)
18451903
usb_autopm_put_interface(data->intf);
18461904
}
18471905

1906+
static void btusb_rx_work(struct work_struct *work)
1907+
{
1908+
struct btusb_data *data = container_of(work, struct btusb_data,
1909+
rx_work.work);
1910+
struct sk_buff *skb;
1911+
1912+
/* Dequeue ACL data received during the interval */
1913+
while ((skb = skb_dequeue(&data->acl_q)))
1914+
data->recv_acl(data->hdev, skb);
1915+
}
1916+
18481917
static int btusb_setup_bcm92035(struct hci_dev *hdev)
18491918
{
18501919
struct sk_buff *skb;
@@ -3402,6 +3471,49 @@ static int btusb_shutdown_qca(struct hci_dev *hdev)
34023471
return 0;
34033472
}
34043473

3474+
static ssize_t force_poll_sync_read(struct file *file, char __user *user_buf,
3475+
size_t count, loff_t *ppos)
3476+
{
3477+
struct btusb_data *data = file->private_data;
3478+
char buf[3];
3479+
3480+
buf[0] = data->poll_sync ? 'Y' : 'N';
3481+
buf[1] = '\n';
3482+
buf[2] = '\0';
3483+
return simple_read_from_buffer(user_buf, count, ppos, buf, 2);
3484+
}
3485+
3486+
static ssize_t force_poll_sync_write(struct file *file,
3487+
const char __user *user_buf,
3488+
size_t count, loff_t *ppos)
3489+
{
3490+
struct btusb_data *data = file->private_data;
3491+
bool enable;
3492+
int err;
3493+
3494+
err = kstrtobool_from_user(user_buf, count, &enable);
3495+
if (err)
3496+
return err;
3497+
3498+
/* Only allow changes while the adapter is down */
3499+
if (test_bit(HCI_UP, &data->hdev->flags))
3500+
return -EPERM;
3501+
3502+
if (data->poll_sync == enable)
3503+
return -EALREADY;
3504+
3505+
data->poll_sync = enable;
3506+
3507+
return count;
3508+
}
3509+
3510+
static const struct file_operations force_poll_sync_fops = {
3511+
.open = simple_open,
3512+
.read = force_poll_sync_read,
3513+
.write = force_poll_sync_write,
3514+
.llseek = default_llseek,
3515+
};
3516+
34053517
static int btusb_probe(struct usb_interface *intf,
34063518
const struct usb_device_id *id)
34073519
{
@@ -3485,6 +3597,10 @@ static int btusb_probe(struct usb_interface *intf,
34853597

34863598
INIT_WORK(&data->work, btusb_work);
34873599
INIT_WORK(&data->waker, btusb_waker);
3600+
INIT_DELAYED_WORK(&data->rx_work, btusb_rx_work);
3601+
3602+
skb_queue_head_init(&data->acl_q);
3603+
34883604
init_usb_anchor(&data->deferred);
34893605
init_usb_anchor(&data->tx_anchor);
34903606
spin_lock_init(&data->txlock);
@@ -3750,6 +3866,9 @@ static int btusb_probe(struct usb_interface *intf,
37503866

37513867
usb_set_intfdata(intf, data);
37523868

3869+
debugfs_create_file("force_poll_sync", 0644, hdev->debugfs, data,
3870+
&force_poll_sync_fops);
3871+
37533872
return 0;
37543873

37553874
out_free_dev:

0 commit comments

Comments
 (0)