From 5aac49378742a52bbe8af3d25bc51b487be7b17f Mon Sep 17 00:00:00 2001 From: Andrea Parri Date: Tue, 14 Aug 2018 20:41:06 +0200 Subject: [PATCH 01/19] Bluetooth: Remove unnecessary smp_mb__{before,after}_atomic The barriers are unneeded; wait_woken() and woken_wake_function() already provide us with the required synchronization: remove them and document that we're relying on the (implicit) synchronization provided by wait_woken() and woken_wake_function(). Signed-off-by: Andrea Parri Reviewed-by: Brian Norris Signed-off-by: Marcel Holtmann --- net/bluetooth/bnep/core.c | 7 ++++--- net/bluetooth/cmtp/core.c | 14 ++++++++------ net/bluetooth/hidp/core.c | 13 ++++++++----- 3 files changed, 20 insertions(+), 14 deletions(-) diff --git a/net/bluetooth/bnep/core.c b/net/bluetooth/bnep/core.c index 7b3965861013..43c284158f63 100644 --- a/net/bluetooth/bnep/core.c +++ b/net/bluetooth/bnep/core.c @@ -489,9 +489,6 @@ static int bnep_session(void *arg) add_wait_queue(sk_sleep(sk), &wait); while (1) { - /* Ensure session->terminate is updated */ - smp_mb__before_atomic(); - if (atomic_read(&s->terminate)) break; /* RX */ @@ -512,6 +509,10 @@ static int bnep_session(void *arg) break; netif_wake_queue(dev); + /* + * wait_woken() performs the necessary memory barriers + * for us; see the header comment for this primitive. + */ wait_woken(&wait, TASK_INTERRUPTIBLE, MAX_SCHEDULE_TIMEOUT); } remove_wait_queue(sk_sleep(sk), &wait); diff --git a/net/bluetooth/cmtp/core.c b/net/bluetooth/cmtp/core.c index 7f26a5a19ff6..07cfa3249f83 100644 --- a/net/bluetooth/cmtp/core.c +++ b/net/bluetooth/cmtp/core.c @@ -288,9 +288,6 @@ static int cmtp_session(void *arg) add_wait_queue(sk_sleep(sk), &wait); while (1) { - /* Ensure session->terminate is updated */ - smp_mb__before_atomic(); - if (atomic_read(&session->terminate)) break; if (sk->sk_state != BT_CONNECTED) @@ -306,6 +303,10 @@ static int cmtp_session(void *arg) cmtp_process_transmit(session); + /* + * wait_woken() performs the necessary memory barriers + * for us; see the header comment for this primitive. + */ wait_woken(&wait, TASK_INTERRUPTIBLE, MAX_SCHEDULE_TIMEOUT); } remove_wait_queue(sk_sleep(sk), &wait); @@ -431,9 +432,10 @@ int cmtp_del_connection(struct cmtp_conndel_req *req) /* Stop session thread */ atomic_inc(&session->terminate); - /* Ensure session->terminate is updated */ - smp_mb__after_atomic(); - + /* + * See the comment preceding the call to wait_woken() + * in cmtp_session(). + */ wake_up_interruptible(sk_sleep(session->sock->sk)); } else err = -ENOENT; diff --git a/net/bluetooth/hidp/core.c b/net/bluetooth/hidp/core.c index 253975cce943..3734dc1788b4 100644 --- a/net/bluetooth/hidp/core.c +++ b/net/bluetooth/hidp/core.c @@ -1074,6 +1074,10 @@ static int hidp_session_start_sync(struct hidp_session *session) static void hidp_session_terminate(struct hidp_session *session) { atomic_inc(&session->terminate); + /* + * See the comment preceding the call to wait_woken() + * in hidp_session_run(). + */ wake_up_interruptible(&hidp_session_wq); } @@ -1193,8 +1197,6 @@ static void hidp_session_run(struct hidp_session *session) * thread is woken up by ->sk_state_changed(). */ - /* Ensure session->terminate is updated */ - smp_mb__before_atomic(); if (atomic_read(&session->terminate)) break; @@ -1228,14 +1230,15 @@ static void hidp_session_run(struct hidp_session *session) hidp_process_transmit(session, &session->ctrl_transmit, session->ctrl_sock); + /* + * wait_woken() performs the necessary memory barriers + * for us; see the header comment for this primitive. + */ wait_woken(&wait, TASK_INTERRUPTIBLE, MAX_SCHEDULE_TIMEOUT); } remove_wait_queue(&hidp_session_wq, &wait); atomic_inc(&session->terminate); - - /* Ensure session->terminate is updated */ - smp_mb__after_atomic(); } static int hidp_session_wake_function(wait_queue_entry_t *wait, From ca30ccd2191842ebfd36229bee91da2db8c16361 Mon Sep 17 00:00:00 2001 From: Balakrishna Godavarthi Date: Wed, 22 Aug 2018 17:50:04 +0530 Subject: [PATCH 02/19] Bluetooth: hci_qca: Remove serdev_device_open/close function calls Removed serdev_device_open/close functions from qca_open/close as they are called in hci_uart_register_device() and hci_uart_unregister_device() functions. Signed-off-by: Balakrishna Godavarthi Signed-off-by: Marcel Holtmann --- drivers/bluetooth/hci_qca.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/bluetooth/hci_qca.c b/drivers/bluetooth/hci_qca.c index e182f6019f68..a740d5703914 100644 --- a/drivers/bluetooth/hci_qca.c +++ b/drivers/bluetooth/hci_qca.c @@ -499,7 +499,6 @@ static int qca_open(struct hci_uart *hu) hu->priv = qca; if (hu->serdev) { - serdev_device_open(hu->serdev); qcadev = serdev_device_get_drvdata(hu->serdev); if (qcadev->btsoc_type != QCA_WCN3990) { @@ -613,7 +612,6 @@ static int qca_close(struct hci_uart *hu) else gpiod_set_value_cansleep(qcadev->bt_en, 0); - serdev_device_close(hu->serdev); } kfree_skb(qca->rx_skb); From c2d7827338618a9e73a3f892ca63d9082bb7a94d Mon Sep 17 00:00:00 2001 From: Balakrishna Godavarthi Date: Wed, 22 Aug 2018 17:50:05 +0530 Subject: [PATCH 03/19] Bluetooth: hci_qca: Remove hdev dereference in qca_close(). When flag KASAN is set, we are seeing an following crash while removing hci_uart module. [ 50.589909] Unable to handle kernel paging request at virtual address 6b6b6b6b6b6b73 [ 50.597902] Mem abort info: [ 50.600846] Exception class = DABT (current EL), IL = 32 bits [ 50.606959] SET = 0, FnV = 0 [ 50.610142] EA = 0, S1PTW = 0 [ 50.613396] Data abort info: [ 50.616401] ISV = 0, ISS = 0x00000004 [ 50.620373] CM = 0, WnR = 0 [ 50.623466] [006b6b6b6b6b6b73] address between user and kernel address ranges [ 50.630818] Internal error: Oops: 96000004 [#1] PREEMPT SMP [ 50.671670] PC is at qca_power_shutdown+0x28/0x100 [hci_uart] [ 50.677593] LR is at qca_close+0x74/0xb0 [hci_uart] [ 50.775689] Process rmmod (pid: 2144, stack limit = 0xffffff801ba90000) [ 50.782493] Call trace: [ 50.872150] [] qca_power_shutdown+0x28/0x100 [hci_uart] [ 50.879138] [] qca_close+0x74/0xb0 [hci_uart] [ 50.885238] [] hci_uart_unregister_device+0x44/0x50 [hci_uart] [ 50.892846] [] qca_serdev_remove+0x50/0x5c [hci_uart] [ 50.899654] [] serdev_drv_remove+0x28/0x38 [ 50.905489] [] device_release_driver_internal+0x140/0x1e4 [ 50.912653] [] driver_detach+0x78/0x84 [ 50.918121] [] bus_remove_driver+0x80/0xa8 [ 50.923942] [] driver_unregister+0x4c/0x58 [ 50.929768] [] qca_deinit+0x24/0x598 [hci_uart] [ 50.936045] [] hci_uart_exit+0x10/0x48 [hci_uart] [ 50.942495] [] SyS_delete_module+0x17c/0x224 This crash is due to dereference of hdev, after freeing it. Signed-off-by: Balakrishna Godavarthi Signed-off-by: Marcel Holtmann --- drivers/bluetooth/hci_qca.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/drivers/bluetooth/hci_qca.c b/drivers/bluetooth/hci_qca.c index a740d5703914..74f5fede0274 100644 --- a/drivers/bluetooth/hci_qca.c +++ b/drivers/bluetooth/hci_qca.c @@ -167,7 +167,7 @@ struct qca_serdev { }; static int qca_power_setup(struct hci_uart *hu, bool on); -static void qca_power_shutdown(struct hci_dev *hdev); +static void qca_power_shutdown(struct hci_uart *hu); static void __serial_clock_on(struct tty_struct *tty) { @@ -608,7 +608,7 @@ static int qca_close(struct hci_uart *hu) if (hu->serdev) { qcadev = serdev_device_get_drvdata(hu->serdev); if (qcadev->btsoc_type == QCA_WCN3990) - qca_power_shutdown(hu->hdev); + qca_power_shutdown(hu); else gpiod_set_value_cansleep(qcadev->bt_en, 0); @@ -1230,12 +1230,15 @@ static const struct qca_vreg_data qca_soc_data = { .num_vregs = 4, }; -static void qca_power_shutdown(struct hci_dev *hdev) +static void qca_power_shutdown(struct hci_uart *hu) { - struct hci_uart *hu = hci_get_drvdata(hdev); + struct serdev_device *serdev = hu->serdev; + unsigned char cmd = QCA_WCN3990_POWEROFF_PULSE; host_set_baudrate(hu, 2400); - qca_send_power_pulse(hdev, QCA_WCN3990_POWEROFF_PULSE); + hci_uart_set_flow_control(hu, true); + serdev_device_write_buf(serdev, &cmd, sizeof(cmd)); + hci_uart_set_flow_control(hu, false); qca_power_setup(hu, false); } @@ -1411,7 +1414,7 @@ static void qca_serdev_remove(struct serdev_device *serdev) struct qca_serdev *qcadev = serdev_device_get_drvdata(serdev); if (qcadev->btsoc_type == QCA_WCN3990) - qca_power_shutdown(qcadev->serdev_hu.hdev); + qca_power_shutdown(&qcadev->serdev_hu); else clk_disable_unprepare(qcadev->susclk); From 7cf7846d27bfc9731e449857db3eec5e0e9701ba Mon Sep 17 00:00:00 2001 From: Balakrishna Godavarthi Date: Wed, 22 Aug 2018 17:34:11 +0530 Subject: [PATCH 04/19] Bluetooth: hci_serdev: clear HCI_UART_PROTO_READY to avoid closing proto races Clearing HCI_UART_PROTO_READY will avoid usage of proto function pointers before running the proto close function pointer. There is chance of kernel crash, due to usage of non proto close function pointers after proto close. Signed-off-by: Balakrishna Godavarthi Signed-off-by: Marcel Holtmann --- drivers/bluetooth/hci_serdev.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/bluetooth/hci_serdev.c b/drivers/bluetooth/hci_serdev.c index aa2543b3c286..46e20444ba19 100644 --- a/drivers/bluetooth/hci_serdev.c +++ b/drivers/bluetooth/hci_serdev.c @@ -368,6 +368,7 @@ void hci_uart_unregister_device(struct hci_uart *hu) { struct hci_dev *hdev = hu->hdev; + clear_bit(HCI_UART_PROTO_READY, &hu->flags); hci_unregister_dev(hdev); hci_free_dev(hdev); From 5a637751e216de2cad77f24f92b9e97e61e459d9 Mon Sep 17 00:00:00 2001 From: Balakrishna Godavarthi Date: Wed, 22 Aug 2018 17:34:12 +0530 Subject: [PATCH 05/19] Bluetooth: hci_serdev: Add protocol check in hci_uart_dequeue(). This will help to check the status of protocol while dequeuing an skb packet. In some instaces we will end up kernel crash, where proto close is called and we trying to dequeue an packet. [ 500.142902] [] do_raw_spin_lock+0x1c/0xe0 [ 500.148643] [] _raw_spin_lock_irqsave+0x38/0x48 [ 500.154917] [] skb_dequeue+0x28/0x84 [ 500.160209] [] 0xffffff8000ad6f48 [ 500.165230] [] 0xffffff8000ad6610 [ 500.170257] [] process_one_work+0x238/0x3e4 [ 500.176174] [] worker_thread+0x2bc/0x3d4 [ 500.181821] [] kthread+0x138/0x140 [ 500.186945] [] ret_from_fork+0x10/0x18 Signed-off-by: Balakrishna Godavarthi Signed-off-by: Marcel Holtmann --- drivers/bluetooth/hci_serdev.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/bluetooth/hci_serdev.c b/drivers/bluetooth/hci_serdev.c index 46e20444ba19..a541e6ee085e 100644 --- a/drivers/bluetooth/hci_serdev.c +++ b/drivers/bluetooth/hci_serdev.c @@ -57,9 +57,10 @@ static inline struct sk_buff *hci_uart_dequeue(struct hci_uart *hu) { struct sk_buff *skb = hu->tx_skb; - if (!skb) - skb = hu->proto->dequeue(hu); - else + if (!skb) { + if (test_bit(HCI_UART_PROTO_READY, &hu->flags)) + skb = hu->proto->dequeue(hu); + } else hu->tx_skb = NULL; return skb; From e5070e0719c7e7303b1441e98a385709e19dadd6 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Wed, 26 Sep 2018 09:32:08 +0100 Subject: [PATCH 06/19] Bluetooth: btrtl: Make array extension_sig static, shrinks object size Don't populate the array extension_sig on the stack but instead make it static. Makes the object code smaller by 75 bytes: Before: text data bss dec hex filename 14325 4920 0 19245 4b2d drivers/bluetooth/btrtl.o After: text data bss dec hex filename 14186 4984 0 19170 4ae2 drivers/bluetooth/btrtl.o (gcc version 8.2.0 x86_64) Signed-off-by: Colin Ian King Signed-off-by: Marcel Holtmann --- drivers/bluetooth/btrtl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/bluetooth/btrtl.c b/drivers/bluetooth/btrtl.c index 7f9ea8e4c1b2..52a9a55057c0 100644 --- a/drivers/bluetooth/btrtl.c +++ b/drivers/bluetooth/btrtl.c @@ -206,7 +206,7 @@ static int rtlbt_parse_firmware(struct hci_dev *hdev, struct btrtl_device_info *btrtl_dev, unsigned char **_buf) { - const u8 extension_sig[] = { 0x51, 0x04, 0xfd, 0x77 }; + static const u8 extension_sig[] = { 0x51, 0x04, 0xfd, 0x77 }; struct rtl_epatch_header *epatch_info; unsigned char *buf; int i, len; From f7785021947949e81f046a5ba2d3c205bda9cccb Mon Sep 17 00:00:00 2001 From: Justin TerAvest Date: Tue, 25 Sep 2018 11:04:57 -0600 Subject: [PATCH 07/19] Bluetooth: btusb: Add quirk for BTUSB_INTEL_NEW Intel "new" controllers can do both LE scan and BR/EDR inquiry at once. Signed-off-by: Justin TerAvest Signed-off-by: Marcel Holtmann --- drivers/bluetooth/btusb.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c index cd2e5cf14ea5..61cde1a7ec1b 100644 --- a/drivers/bluetooth/btusb.c +++ b/drivers/bluetooth/btusb.c @@ -3096,6 +3096,7 @@ static int btusb_probe(struct usb_interface *intf, hdev->set_diag = btintel_set_diag; hdev->set_bdaddr = btintel_set_bdaddr; set_bit(HCI_QUIRK_STRICT_DUPLICATE_FILTER, &hdev->quirks); + set_bit(HCI_QUIRK_SIMULTANEOUS_DISCOVERY, &hdev->quirks); set_bit(HCI_QUIRK_NON_PERSISTENT_DIAG, &hdev->quirks); } From 3e4be65eb82c843a2d8544c93b7a9f5d4984b03b Mon Sep 17 00:00:00 2001 From: Balakrishna Godavarthi Date: Mon, 24 Sep 2018 20:14:45 +0530 Subject: [PATCH 08/19] Bluetooth: hci_qca: Add poweroff support during hci down for wcn3990 This patch enables power off support for hci down and power on support for hci up. As wcn3990 power sources are ignited by regulators, we will turn off them during hci down, i.e. an complete power off of wcn3990. So while hci up, will call vendor setup which will turn on the regulators, requests BT chip version and download the firmware. Signed-off-by: Balakrishna Godavarthi Signed-off-by: Marcel Holtmann --- drivers/bluetooth/hci_qca.c | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/drivers/bluetooth/hci_qca.c b/drivers/bluetooth/hci_qca.c index 74f5fede0274..d98ed0442201 100644 --- a/drivers/bluetooth/hci_qca.c +++ b/drivers/bluetooth/hci_qca.c @@ -168,6 +168,7 @@ struct qca_serdev { static int qca_power_setup(struct hci_uart *hu, bool on); static void qca_power_shutdown(struct hci_uart *hu); +static int qca_power_off(struct hci_dev *hdev); static void __serial_clock_on(struct tty_struct *tty) { @@ -1099,8 +1100,26 @@ static int qca_set_speed(struct hci_uart *hu, enum qca_speed_type speed_type) static int qca_wcn3990_init(struct hci_uart *hu) { struct hci_dev *hdev = hu->hdev; + struct qca_serdev *qcadev; int ret; + /* Check for vregs status, may be hci down has turned + * off the voltage regulator. + */ + qcadev = serdev_device_get_drvdata(hu->serdev); + if (!qcadev->bt_power->vregs_on) { + serdev_device_close(hu->serdev); + ret = qca_power_setup(hu, true); + if (ret) + return ret; + + ret = serdev_device_open(hu->serdev); + if (ret) { + bt_dev_err(hu->hdev, "failed to open port"); + return ret; + } + } + /* Forcefully enable wcn3990 to enter in to boot mode. */ host_set_baudrate(hu, 2400); ret = qca_send_power_pulse(hdev, QCA_WCN3990_POWEROFF_PULSE); @@ -1152,6 +1171,12 @@ static int qca_setup(struct hci_uart *hu) if (qcadev->btsoc_type == QCA_WCN3990) { bt_dev_info(hdev, "setting up wcn3990"); + + /* Enable NON_PERSISTENT_SETUP QUIRK to ensure to execute + * setup for every hci up. + */ + set_bit(HCI_QUIRK_NON_PERSISTENT_SETUP, &hdev->quirks); + hu->hdev->shutdown = qca_power_off; ret = qca_wcn3990_init(hu); if (ret) return ret; @@ -1242,6 +1267,14 @@ static void qca_power_shutdown(struct hci_uart *hu) qca_power_setup(hu, false); } +static int qca_power_off(struct hci_dev *hdev) +{ + struct hci_uart *hu = hci_get_drvdata(hdev); + + qca_power_shutdown(hu); + return 0; +} + static int qca_enable_regulator(struct qca_vreg vregs, struct regulator *regulator) { From b950aa88638c52a013504f025e0b8f99bf2dc26e Mon Sep 17 00:00:00 2001 From: Ankit Navik Date: Fri, 17 Aug 2018 07:29:19 +0530 Subject: [PATCH 09/19] Bluetooth: Add definitions and track LE resolve list modification Add the definitions for adding entries to the LE resolve list and removing entries from the LE resolve list. When the LE resolve list gets changed via HCI commands make sure that the internal storage of the resolve list entries gets updated. Signed-off-by: Ankit Navik Signed-off-by: Marcel Holtmann --- include/net/bluetooth/hci.h | 14 +++++++ include/net/bluetooth/hci_core.h | 15 ++++++++ net/bluetooth/hci_core.c | 63 ++++++++++++++++++++++++++++++++ net/bluetooth/hci_event.c | 47 ++++++++++++++++++++++++ 4 files changed, 139 insertions(+) diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h index cdd9f1fe7cfa..c36dc1e20556 100644 --- a/include/net/bluetooth/hci.h +++ b/include/net/bluetooth/hci.h @@ -1517,6 +1517,20 @@ struct hci_cp_le_write_def_data_len { __le16 tx_time; } __packed; +#define HCI_OP_LE_ADD_TO_RESOLV_LIST 0x2027 +struct hci_cp_le_add_to_resolv_list { + __u8 bdaddr_type; + bdaddr_t bdaddr; + __u8 peer_irk[16]; + __u8 local_irk[16]; +} __packed; + +#define HCI_OP_LE_DEL_FROM_RESOLV_LIST 0x2028 +struct hci_cp_le_del_from_resolv_list { + __u8 bdaddr_type; + bdaddr_t bdaddr; +} __packed; + #define HCI_OP_LE_CLEAR_RESOLV_LIST 0x2029 #define HCI_OP_LE_READ_RESOLV_LIST_SIZE 0x202a diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h index 0db1b9b428b7..9b0f821b2d3a 100644 --- a/include/net/bluetooth/hci_core.h +++ b/include/net/bluetooth/hci_core.h @@ -103,6 +103,14 @@ struct bdaddr_list { u8 bdaddr_type; }; +struct bdaddr_list_with_irk { + struct list_head list; + bdaddr_t bdaddr; + u8 bdaddr_type; + u8 peer_irk[16]; + u8 local_irk[16]; +}; + struct bt_uuid { struct list_head list; u8 uuid[16]; @@ -1058,8 +1066,15 @@ int hci_inquiry(void __user *arg); struct bdaddr_list *hci_bdaddr_list_lookup(struct list_head *list, bdaddr_t *bdaddr, u8 type); +struct bdaddr_list_with_irk *hci_bdaddr_list_lookup_with_irk( + struct list_head *list, bdaddr_t *bdaddr, + u8 type); int hci_bdaddr_list_add(struct list_head *list, bdaddr_t *bdaddr, u8 type); +int hci_bdaddr_list_add_with_irk(struct list_head *list, bdaddr_t *bdaddr, + u8 type, u8 *peer_irk, u8 *local_irk); int hci_bdaddr_list_del(struct list_head *list, bdaddr_t *bdaddr, u8 type); +int hci_bdaddr_list_del_with_irk(struct list_head *list, bdaddr_t *bdaddr, + u8 type); void hci_bdaddr_list_clear(struct list_head *list); struct hci_conn_params *hci_conn_params_lookup(struct hci_dev *hdev, diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c index 74b29c7d841c..0f1a8820d75c 100644 --- a/net/bluetooth/hci_core.c +++ b/net/bluetooth/hci_core.c @@ -2839,6 +2839,20 @@ struct bdaddr_list *hci_bdaddr_list_lookup(struct list_head *bdaddr_list, return NULL; } +struct bdaddr_list_with_irk *hci_bdaddr_list_lookup_with_irk( + struct list_head *bdaddr_list, bdaddr_t *bdaddr, + u8 type) +{ + struct bdaddr_list_with_irk *b; + + list_for_each_entry(b, bdaddr_list, list) { + if (!bacmp(&b->bdaddr, bdaddr) && b->bdaddr_type == type) + return b; + } + + return NULL; +} + void hci_bdaddr_list_clear(struct list_head *bdaddr_list) { struct bdaddr_list *b, *n; @@ -2871,6 +2885,35 @@ int hci_bdaddr_list_add(struct list_head *list, bdaddr_t *bdaddr, u8 type) return 0; } +int hci_bdaddr_list_add_with_irk(struct list_head *list, bdaddr_t *bdaddr, + u8 type, u8 *peer_irk, u8 *local_irk) +{ + struct bdaddr_list_with_irk *entry; + + if (!bacmp(bdaddr, BDADDR_ANY)) + return -EBADF; + + if (hci_bdaddr_list_lookup(list, bdaddr, type)) + return -EEXIST; + + entry = kzalloc(sizeof(*entry), GFP_KERNEL); + if (!entry) + return -ENOMEM; + + bacpy(&entry->bdaddr, bdaddr); + entry->bdaddr_type = type; + + if (peer_irk) + memcpy(entry->peer_irk, peer_irk, 16); + + if (local_irk) + memcpy(entry->local_irk, local_irk, 16); + + list_add(&entry->list, list); + + return 0; +} + int hci_bdaddr_list_del(struct list_head *list, bdaddr_t *bdaddr, u8 type) { struct bdaddr_list *entry; @@ -2890,6 +2933,26 @@ int hci_bdaddr_list_del(struct list_head *list, bdaddr_t *bdaddr, u8 type) return 0; } +int hci_bdaddr_list_del_with_irk(struct list_head *list, bdaddr_t *bdaddr, + u8 type) +{ + struct bdaddr_list_with_irk *entry; + + if (!bacmp(bdaddr, BDADDR_ANY)) { + hci_bdaddr_list_clear(list); + return 0; + } + + entry = hci_bdaddr_list_lookup_with_irk(list, bdaddr, type); + if (!entry) + return -ENOENT; + + list_del(&entry->list); + kfree(entry); + + return 0; +} + /* This function requires the caller holds hdev->lock */ struct hci_conn_params *hci_conn_params_lookup(struct hci_dev *hdev, bdaddr_t *addr, u8 addr_type) diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index f12555f23a49..f47f8fad757a 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c @@ -1454,6 +1454,45 @@ static void hci_cc_le_write_def_data_len(struct hci_dev *hdev, hdev->le_def_tx_time = le16_to_cpu(sent->tx_time); } +static void hci_cc_le_add_to_resolv_list(struct hci_dev *hdev, + struct sk_buff *skb) +{ + struct hci_cp_le_add_to_resolv_list *sent; + __u8 status = *((__u8 *) skb->data); + + BT_DBG("%s status 0x%2.2x", hdev->name, status); + + if (status) + return; + + sent = hci_sent_cmd_data(hdev, HCI_OP_LE_ADD_TO_RESOLV_LIST); + if (!sent) + return; + + hci_bdaddr_list_add_with_irk(&hdev->le_resolv_list, &sent->bdaddr, + sent->bdaddr_type, sent->peer_irk, + sent->local_irk); +} + +static void hci_cc_le_del_from_resolv_list(struct hci_dev *hdev, + struct sk_buff *skb) +{ + struct hci_cp_le_del_from_resolv_list *sent; + __u8 status = *((__u8 *) skb->data); + + BT_DBG("%s status 0x%2.2x", hdev->name, status); + + if (status) + return; + + sent = hci_sent_cmd_data(hdev, HCI_OP_LE_DEL_FROM_RESOLV_LIST); + if (!sent) + return; + + hci_bdaddr_list_del_with_irk(&hdev->le_resolv_list, &sent->bdaddr, + sent->bdaddr_type); +} + static void hci_cc_le_clear_resolv_list(struct hci_dev *hdev, struct sk_buff *skb) { @@ -3279,6 +3318,14 @@ static void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *skb, hci_cc_le_write_def_data_len(hdev, skb); break; + case HCI_OP_LE_ADD_TO_RESOLV_LIST: + hci_cc_le_add_to_resolv_list(hdev, skb); + break; + + case HCI_OP_LE_DEL_FROM_RESOLV_LIST: + hci_cc_le_del_from_resolv_list(hdev, skb); + break; + case HCI_OP_LE_CLEAR_RESOLV_LIST: hci_cc_le_clear_resolv_list(hdev, skb); break; From ea9ed991c3fc25f56f37fdc537581211426e03df Mon Sep 17 00:00:00 2001 From: Jagdish Tirumala Date: Tue, 11 Sep 2018 08:40:38 -0700 Subject: [PATCH 10/19] Bluetooth: hci_serdev: Fixed error space required before open paranethesis Fixed error in space required before paranthesis in drivers/bluetooth/hci_serdev.c Signed-off-by: Jagdish Tirumala Signed-off-by: Marcel Holtmann --- drivers/bluetooth/hci_serdev.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/bluetooth/hci_serdev.c b/drivers/bluetooth/hci_serdev.c index a541e6ee085e..c445aa9ac511 100644 --- a/drivers/bluetooth/hci_serdev.c +++ b/drivers/bluetooth/hci_serdev.c @@ -95,7 +95,7 @@ static void hci_uart_write_work(struct work_struct *work) hci_uart_tx_complete(hu, hci_skb_pkt_type(skb)); kfree_skb(skb); } - } while(test_bit(HCI_UART_TX_WAKEUP, &hu->tx_state)); + } while (test_bit(HCI_UART_TX_WAKEUP, &hu->tx_state)); clear_bit(HCI_UART_SENDING, &hu->tx_state); } From 8ecfdc95b30a17b0c27ace6f13a1c4fb37e2bb96 Mon Sep 17 00:00:00 2001 From: Alex Lu Date: Sat, 8 Sep 2018 12:05:59 -0500 Subject: [PATCH 11/19] Bluetooth: btrtl: Add support for RTL8822C with USB interface This device is included in the RTL8822CU combination wifi and BT part, as well as the BT part of the RTL8822CE. The necessary firmware has been submitted to the linux-firmware project. Signed-off-by: Alex Lu Signed-off-by: Larry Finger Signed-off-by: Marcel Holtmann --- drivers/bluetooth/btrtl.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/bluetooth/btrtl.c b/drivers/bluetooth/btrtl.c index 52a9a55057c0..41405de27d66 100644 --- a/drivers/bluetooth/btrtl.c +++ b/drivers/bluetooth/btrtl.c @@ -138,6 +138,13 @@ static const struct id_table ic_id_table[] = { .fw_name = "rtl_bt/rtl8761a_fw.bin", .cfg_name = "rtl_bt/rtl8761a_config" }, + /* 8822C with USB interface */ + { IC_INFO(RTL_ROM_LMP_8822B, 0xc), + .config_needed = false, + .has_rom_version = true, + .fw_name = "rtl_bt/rtl8822cu_fw.bin", + .cfg_name = "rtl_bt/rtl8822cu_config" }, + /* 8822B */ { IC_INFO(RTL_ROM_LMP_8822B, 0xb), .config_needed = true, @@ -228,6 +235,7 @@ static int rtlbt_parse_firmware(struct hci_dev *hdev, { RTL_ROM_LMP_8822B, 8 }, { RTL_ROM_LMP_8723B, 9 }, /* 8723D */ { RTL_ROM_LMP_8821A, 10 }, /* 8821C */ + { RTL_ROM_LMP_8822B, 13 }, /* 8822C */ }; min_size = sizeof(struct rtl_epatch_header) + sizeof(extension_sig) + 3; From a357ea098c9605f60d92a66a9073f56ce25726da Mon Sep 17 00:00:00 2001 From: Christian Hewitt Date: Tue, 4 Sep 2018 21:50:57 +0400 Subject: [PATCH 12/19] Bluetooth: btbcm: Add entry for BCM4335C0 UART bluetooth This patch adds the device ID for the AMPAK AP6335 combo module used in the 1st generation WeTek Hub Android/LibreELEC HTPC box. The WiFI chip identifies itself as BCM4339, while Bluetooth identifies itself as BCM4335 (rev C0): ``` [ 4.864248] Bluetooth: hci0: BCM: chip id 86 [ 4.866388] Bluetooth: hci0: BCM: features 0x2f [ 4.889317] Bluetooth: hci0: BCM4335C0 [ 4.889332] Bluetooth: hci0: BCM4335C0 (003.001.009) build 0000 [ 9.778383] Bluetooth: hci0: BCM4335C0 (003.001.009) build 0268 ``` Output from hciconfig: ``` hci0: Type: Primary Bus: UART BD Address: 43:39:00:00:1F:AC ACL MTU: 1021:8 SCO MTU: 64:1 UP RUNNING RX bytes:7567 acl:234 sco:0 events:386 errors:0 TX bytes:53844 acl:77 sco:0 commands:304 errors:0 Features: 0xbf 0xfe 0xcf 0xfe 0xdb 0xff 0x7b 0x87 Packet type: DM1 DM3 DM5 DH1 DH3 DH5 HV1 HV2 HV3 Link policy: RSWITCH SNIFF Link mode: SLAVE ACCEPT Name: 'HUB' Class: 0x0c0000 Service Classes: Rendering, Capturing Device Class: Miscellaneous, HCI Version: 4.0 (0x6) Revision: 0x10c LMP Version: 4.0 (0x6) Subversion: 0x6109 Manufacturer: Broadcom Corporation (15) ``` Signed-off-by: Christian Hewitt Signed-off-by: Marcel Holtmann --- drivers/bluetooth/btbcm.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/bluetooth/btbcm.c b/drivers/bluetooth/btbcm.c index 99cde1f9467d..e3e4d929e74f 100644 --- a/drivers/bluetooth/btbcm.c +++ b/drivers/bluetooth/btbcm.c @@ -324,6 +324,7 @@ static const struct bcm_subver_table bcm_uart_subver_table[] = { { 0x4103, "BCM4330B1" }, /* 002.001.003 */ { 0x410e, "BCM43341B0" }, /* 002.001.014 */ { 0x4406, "BCM4324B3" }, /* 002.004.006 */ + { 0x6109, "BCM4335C0" }, /* 003.001.009 */ { 0x610c, "BCM4354" }, /* 003.001.012 */ { 0x2122, "BCM4343A0" }, /* 001.001.034 */ { 0x2209, "BCM43430A1" }, /* 001.002.009 */ From fe1493101ac1313cbdbef1af65342fb17d944e71 Mon Sep 17 00:00:00 2001 From: Luiz Augusto von Dentz Date: Tue, 4 Sep 2018 13:39:20 +0300 Subject: [PATCH 13/19] Bluetooth: L2CAP: Derive MPS from connection MTU This ensures the MPS can fit in a single HCI fragment so each segment don't have to be reassembled at HCI level, in addition to that also remove the debugfs entry to configure the MPS. Signed-off-by: Luiz Augusto von Dentz Signed-off-by: Marcel Holtmann --- include/net/bluetooth/l2cap.h | 1 - net/bluetooth/l2cap_core.c | 14 +++++++------- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h index 0697fd413087..17296675a0b1 100644 --- a/include/net/bluetooth/l2cap.h +++ b/include/net/bluetooth/l2cap.h @@ -456,7 +456,6 @@ struct l2cap_conn_param_update_rsp { #define L2CAP_CONN_PARAM_REJECTED 0x0001 #define L2CAP_LE_MAX_CREDITS 10 -#define L2CAP_LE_DEFAULT_MPS 230 struct l2cap_le_conn_req { __le16 psm; diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c index d17a4736e47c..8a60db6261f7 100644 --- a/net/bluetooth/l2cap_core.c +++ b/net/bluetooth/l2cap_core.c @@ -52,7 +52,6 @@ static LIST_HEAD(chan_list); static DEFINE_RWLOCK(chan_list_lock); static u16 le_max_credits = L2CAP_LE_MAX_CREDITS; -static u16 le_default_mps = L2CAP_LE_DEFAULT_MPS; static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn, u8 code, u8 ident, u16 dlen, void *data); @@ -520,7 +519,8 @@ static void l2cap_le_flowctl_init(struct l2cap_chan *chan) chan->sdu_len = 0; chan->tx_credits = 0; chan->rx_credits = le_max_credits; - chan->mps = min_t(u16, chan->imtu, le_default_mps); + /* Derive MPS from connection MTU to stop HCI fragmentation */ + chan->mps = min_t(u16, chan->imtu, chan->conn->mtu - L2CAP_HDR_SIZE); skb_queue_head_init(&chan->tx_q); } @@ -1282,6 +1282,8 @@ static void l2cap_le_connect(struct l2cap_chan *chan) if (test_and_set_bit(FLAG_LE_CONN_REQ_SENT, &chan->flags)) return; + l2cap_le_flowctl_init(chan); + req.psm = chan->psm; req.scid = cpu_to_le16(chan->scid); req.mtu = cpu_to_le16(chan->imtu); @@ -5493,8 +5495,6 @@ static int l2cap_le_connect_req(struct l2cap_conn *conn, goto response_unlock; } - l2cap_le_flowctl_init(chan); - bacpy(&chan->src, &conn->hcon->src); bacpy(&chan->dst, &conn->hcon->dst); chan->src_type = bdaddr_src_type(conn->hcon); @@ -5506,6 +5506,9 @@ static int l2cap_le_connect_req(struct l2cap_conn *conn, chan->tx_credits = __le16_to_cpu(req->credits); __l2cap_chan_add(conn, chan); + + l2cap_le_flowctl_init(chan); + dcid = chan->scid; credits = chan->rx_credits; @@ -7102,7 +7105,6 @@ int l2cap_chan_connect(struct l2cap_chan *chan, __le16 psm, u16 cid, case L2CAP_MODE_BASIC: break; case L2CAP_MODE_LE_FLOWCTL: - l2cap_le_flowctl_init(chan); break; case L2CAP_MODE_ERTM: case L2CAP_MODE_STREAMING: @@ -7647,8 +7649,6 @@ int __init l2cap_init(void) debugfs_create_u16("l2cap_le_max_credits", 0644, bt_debugfs, &le_max_credits); - debugfs_create_u16("l2cap_le_default_mps", 0644, bt_debugfs, - &le_default_mps); return 0; } From 96cd8eaa131f0ffd4cfae09e1b4bdfafb9570907 Mon Sep 17 00:00:00 2001 From: Luiz Augusto von Dentz Date: Tue, 4 Sep 2018 13:39:21 +0300 Subject: [PATCH 14/19] Bluetooth: L2CAP: Derive rx credits from MTU and MPS Give enough rx credits for a full packet instead of using an arbitrary number which may not be enough depending on the MTU and MPS which can cause interruptions while waiting for more credits, also remove debugfs entry for l2cap_le_max_credits. With these changes the credits are restored after each SDU is received instead of using fixed threshold, this way it is garanteed that there will always be enough credits to send a packet without waiting more credits to arrive. Signed-off-by: Luiz Augusto von Dentz Signed-off-by: Marcel Holtmann --- include/net/bluetooth/l2cap.h | 2 -- net/bluetooth/l2cap_core.c | 42 ++++++++++++++++++++++------------- 2 files changed, 27 insertions(+), 17 deletions(-) diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h index 17296675a0b1..3555440e14fc 100644 --- a/include/net/bluetooth/l2cap.h +++ b/include/net/bluetooth/l2cap.h @@ -455,8 +455,6 @@ struct l2cap_conn_param_update_rsp { #define L2CAP_CONN_PARAM_ACCEPTED 0x0000 #define L2CAP_CONN_PARAM_REJECTED 0x0001 -#define L2CAP_LE_MAX_CREDITS 10 - struct l2cap_le_conn_req { __le16 psm; __le16 scid; diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c index 8a60db6261f7..3fb2d757df88 100644 --- a/net/bluetooth/l2cap_core.c +++ b/net/bluetooth/l2cap_core.c @@ -51,8 +51,6 @@ static u32 l2cap_feat_mask = L2CAP_FEAT_FIXED_CHAN | L2CAP_FEAT_UCD; static LIST_HEAD(chan_list); static DEFINE_RWLOCK(chan_list_lock); -static u16 le_max_credits = L2CAP_LE_MAX_CREDITS; - static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn, u8 code, u8 ident, u16 dlen, void *data); static void l2cap_send_cmd(struct l2cap_conn *conn, u8 ident, u8 code, u16 len, @@ -518,9 +516,10 @@ static void l2cap_le_flowctl_init(struct l2cap_chan *chan) chan->sdu_last_frag = NULL; chan->sdu_len = 0; chan->tx_credits = 0; - chan->rx_credits = le_max_credits; /* Derive MPS from connection MTU to stop HCI fragmentation */ chan->mps = min_t(u16, chan->imtu, chan->conn->mtu - L2CAP_HDR_SIZE); + /* Give enough credits for a full packet */ + chan->rx_credits = (chan->imtu / chan->mps) + 1; skb_queue_head_init(&chan->tx_q); } @@ -6702,13 +6701,10 @@ static void l2cap_chan_le_send_credits(struct l2cap_chan *chan) struct l2cap_le_credits pkt; u16 return_credits; - /* We return more credits to the sender only after the amount of - * credits falls below half of the initial amount. - */ - if (chan->rx_credits >= (le_max_credits + 1) / 2) - return; + return_credits = ((chan->imtu / chan->mps) + 1) - chan->rx_credits; - return_credits = le_max_credits - chan->rx_credits; + if (!return_credits) + return; BT_DBG("chan %p returning %u credits to sender", chan, return_credits); @@ -6722,6 +6718,21 @@ static void l2cap_chan_le_send_credits(struct l2cap_chan *chan) l2cap_send_cmd(conn, chan->ident, L2CAP_LE_CREDITS, sizeof(pkt), &pkt); } +static int l2cap_le_recv(struct l2cap_chan *chan, struct sk_buff *skb) +{ + int err; + + BT_DBG("SDU reassemble complete: chan %p skb->len %u", chan, skb->len); + + /* Wait recv to confirm reception before updating the credits */ + err = chan->ops->recv(chan, skb); + + /* Update credits whenever an SDU is received */ + l2cap_chan_le_send_credits(chan); + + return err; +} + static int l2cap_le_data_rcv(struct l2cap_chan *chan, struct sk_buff *skb) { int err; @@ -6740,7 +6751,11 @@ static int l2cap_le_data_rcv(struct l2cap_chan *chan, struct sk_buff *skb) chan->rx_credits--; BT_DBG("rx_credits %u -> %u", chan->rx_credits + 1, chan->rx_credits); - l2cap_chan_le_send_credits(chan); + /* Update if remote had run out of credits, this should only happens + * if the remote is not using the entire MPS. + */ + if (!chan->rx_credits) + l2cap_chan_le_send_credits(chan); err = 0; @@ -6766,7 +6781,7 @@ static int l2cap_le_data_rcv(struct l2cap_chan *chan, struct sk_buff *skb) } if (skb->len == sdu_len) - return chan->ops->recv(chan, skb); + return l2cap_le_recv(chan, skb); chan->sdu = skb; chan->sdu_len = sdu_len; @@ -6788,7 +6803,7 @@ static int l2cap_le_data_rcv(struct l2cap_chan *chan, struct sk_buff *skb) skb = NULL; if (chan->sdu->len == chan->sdu_len) { - err = chan->ops->recv(chan, chan->sdu); + err = l2cap_le_recv(chan, chan->sdu); if (!err) { chan->sdu = NULL; chan->sdu_last_frag = NULL; @@ -7647,9 +7662,6 @@ int __init l2cap_init(void) l2cap_debugfs = debugfs_create_file("l2cap", 0444, bt_debugfs, NULL, &l2cap_debugfs_fops); - debugfs_create_u16("l2cap_le_max_credits", 0644, bt_debugfs, - &le_max_credits); - return 0; } From a5c3021bb62b970713550db3f7fd08aa70665d7e Mon Sep 17 00:00:00 2001 From: Luiz Augusto von Dentz Date: Tue, 4 Sep 2018 13:39:22 +0300 Subject: [PATCH 15/19] Bluetooth: L2CAP: Detect if remote is not able to use the whole MPS If the remote is not able to fully utilize the MPS choosen recalculate the credits based on the actual amount it is sending that way it can still send packets of MTU size without credits dropping to 0. Signed-off-by: Luiz Augusto von Dentz Signed-off-by: Marcel Holtmann --- net/bluetooth/l2cap_core.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c index 3fb2d757df88..514899f7f0d4 100644 --- a/net/bluetooth/l2cap_core.c +++ b/net/bluetooth/l2cap_core.c @@ -6787,6 +6787,16 @@ static int l2cap_le_data_rcv(struct l2cap_chan *chan, struct sk_buff *skb) chan->sdu_len = sdu_len; chan->sdu_last_frag = skb; + /* Detect if remote is not able to use the selected MPS */ + if (skb->len + L2CAP_SDULEN_SIZE < chan->mps) { + u16 mps_len = skb->len + L2CAP_SDULEN_SIZE; + + /* Adjust the number of credits */ + BT_DBG("chan->mps %u -> %u", chan->mps, mps_len); + chan->mps = mps_len; + l2cap_chan_le_send_credits(chan); + } + return 0; } From 7cbfd1e2aad410d96fa6162aeb3f9cff1fecfc58 Mon Sep 17 00:00:00 2001 From: Sanjay Kumar Konduri Date: Mon, 3 Sep 2018 11:27:46 +0530 Subject: [PATCH 16/19] Bluetooth: btrsi: fix bt tx timeout issue observed sometimes data is coming with unaligned address from kernel BT stack. If unaligned address is passed, some data in payload is stripped when packet is loading to firmware and this results, BT connection timeout is happening. sh# hciconfig hci0 up Can't init device hci0: hci0 command 0x0c03 tx timeout Fixed this by moving the data to aligned address. Signed-off-by: Sanjay Kumar Konduri Signed-off-by: Siva Rebbagondla Signed-off-by: Marcel Holtmann --- drivers/bluetooth/btrsi.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/drivers/bluetooth/btrsi.c b/drivers/bluetooth/btrsi.c index 60d1419590ba..3951f7b23840 100644 --- a/drivers/bluetooth/btrsi.c +++ b/drivers/bluetooth/btrsi.c @@ -21,8 +21,9 @@ #include #include -#define RSI_HEADROOM_FOR_BT_HAL 16 +#define RSI_DMA_ALIGN 8 #define RSI_FRAME_DESC_SIZE 16 +#define RSI_HEADROOM_FOR_BT_HAL (RSI_FRAME_DESC_SIZE + RSI_DMA_ALIGN) struct rsi_hci_adapter { void *priv; @@ -70,6 +71,16 @@ static int rsi_hci_send_pkt(struct hci_dev *hdev, struct sk_buff *skb) bt_cb(new_skb)->pkt_type = hci_skb_pkt_type(skb); kfree_skb(skb); skb = new_skb; + if (!IS_ALIGNED((unsigned long)skb->data, RSI_DMA_ALIGN)) { + u8 *skb_data = skb->data; + int skb_len = skb->len; + + skb_push(skb, RSI_DMA_ALIGN); + skb_pull(skb, PTR_ALIGN(skb->data, + RSI_DMA_ALIGN) - skb->data); + memmove(skb->data, skb_data, skb_len); + skb_trim(skb, skb_len); + } } return h_adapter->proto_ops->coex_send_pkt(h_adapter->priv, skb, From 385613506aef4d21448f8f167513f46a008a3b0c Mon Sep 17 00:00:00 2001 From: Ding Xiang Date: Sun, 26 Aug 2018 22:55:00 -0400 Subject: [PATCH 17/19] Bluetooth: bt3c_cs: Fix obsolete function simple_strtol and simple_strtoul are obsolete, both place use kstrtouint instead. V2: fix error tmp += tn V3: fix compile error Signed-off-by: Ding Xiang Signed-off-by: Marcel Holtmann --- drivers/bluetooth/bt3c_cs.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/drivers/bluetooth/bt3c_cs.c b/drivers/bluetooth/bt3c_cs.c index 25b0cf952b91..54713833951a 100644 --- a/drivers/bluetooth/bt3c_cs.c +++ b/drivers/bluetooth/bt3c_cs.c @@ -448,7 +448,7 @@ static int bt3c_load_firmware(struct bt3c_info *info, { char *ptr = (char *) firmware; char b[9]; - unsigned int iobase, tmp; + unsigned int iobase, tmp, tn; unsigned long size, addr, fcs; int i, err = 0; @@ -490,7 +490,9 @@ static int bt3c_load_firmware(struct bt3c_info *info, memset(b, 0, sizeof(b)); for (tmp = 0, i = 0; i < size; i++) { memcpy(b, ptr + (i * 2) + 2, 2); - tmp += simple_strtol(b, NULL, 16); + if (kstrtouint(b, 16, &tn)) + return -EINVAL; + tmp += tn; } if (((tmp + fcs) & 0xff) != 0xff) { @@ -505,7 +507,8 @@ static int bt3c_load_firmware(struct bt3c_info *info, memset(b, 0, sizeof(b)); for (i = 0; i < (size - 4) / 2; i++) { memcpy(b, ptr + (i * 4) + 12, 4); - tmp = simple_strtoul(b, NULL, 16); + if (kstrtouint(b, 16, &tmp)) + return -EINVAL; bt3c_put(iobase, tmp); } } From d6b372f6f3dba1f496d6583a30a584e4dd324e77 Mon Sep 17 00:00:00 2001 From: Luiz Carlos Ramos Date: Thu, 27 Sep 2018 17:19:26 -0300 Subject: [PATCH 18/19] Bluetooth: ath3k: add more information to error message When there is an error in either ath3k_load_firmware() or ath3k_load_fwfile(), the inlined function ath3k_log_failed_loading() is called receiving the error returned and both the block size requested to load and the size actually loaded. These values are printed in an error message using the macro BT_ERR. This patch changes that function in order to print the variable "count" as well, to show more information when a failing firmware loading operation happens. The calls to the older function were changed to the new one. This event is being monitored in a laptop with an adapter which identifies itself as 0cf3:0036, where sometimes there are errors in the firmware loading process. Signed-off-by: Luiz Carlos Ramos Signed-off-by: Marcel Holtmann --- drivers/bluetooth/ath3k.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/drivers/bluetooth/ath3k.c b/drivers/bluetooth/ath3k.c index 3d7a5c149af3..1ad4991753bb 100644 --- a/drivers/bluetooth/ath3k.c +++ b/drivers/bluetooth/ath3k.c @@ -203,10 +203,11 @@ static const struct usb_device_id ath3k_blist_tbl[] = { { } /* Terminating entry */ }; -static inline void ath3k_log_failed_loading(int err, int len, int size) +static inline void ath3k_log_failed_loading(int err, int len, int size, + int count) { - BT_ERR("Error in firmware loading err = %d, len = %d, size = %d", - err, len, size); + BT_ERR("Firmware loading err = %d, len = %d, size = %d, count = %d", + err, len, size, count); } #define USB_REQ_DFU_DNLOAD 1 @@ -257,7 +258,7 @@ static int ath3k_load_firmware(struct usb_device *udev, &len, 3000); if (err || (len != size)) { - ath3k_log_failed_loading(err, len, size); + ath3k_log_failed_loading(err, len, size, count); goto error; } @@ -356,7 +357,7 @@ static int ath3k_load_fwfile(struct usb_device *udev, err = usb_bulk_msg(udev, pipe, send_buf, size, &len, 3000); if (err || (len != size)) { - ath3k_log_failed_loading(err, len, size); + ath3k_log_failed_loading(err, len, size, count); kfree(send_buf); return err; } From 30d65e0804d58a03d1a8ea4e12c6fc07ed08218b Mon Sep 17 00:00:00 2001 From: Matias Karhumaa Date: Fri, 28 Sep 2018 21:54:30 +0300 Subject: [PATCH 19/19] Bluetooth: Fix debugfs NULL pointer dereference Fix crash caused by NULL pointer dereference when debugfs functions le_max_key_read, le_max_key_size_write, le_min_key_size_read or le_min_key_size_write and Bluetooth adapter was powered off. Fix is to move max_key_size and min_key_size from smp_dev to hci_dev. At the same time they were renamed to le_max_key_size and le_min_key_size. BUG: unable to handle kernel NULL pointer dereference at 00000000000002e8 PGD 0 P4D 0 Oops: 0000 [#24] SMP PTI CPU: 2 PID: 6255 Comm: cat Tainted: G D OE 4.18.9-200.fc28.x86_64 #1 Hardware name: LENOVO 4286CTO/4286CTO, BIOS 8DET76WW (1.46 ) 06/21/2018 RIP: 0010:le_max_key_size_read+0x45/0xb0 [bluetooth] Code: 00 00 00 48 83 ec 10 65 48 8b 04 25 28 00 00 00 48 89 44 24 08 31 c0 48 8b 87 c8 00 00 00 48 8d 7c 24 04 48 8b 80 48 0a 00 00 <48> 8b 80 e8 02 00 00 0f b6 48 52 e8 fb b6 b3 ed be 04 00 00 00 48 RSP: 0018:ffffab23c3ff3df0 EFLAGS: 00010246 RAX: 0000000000000000 RBX: 00007f0b4ca2e000 RCX: ffffab23c3ff3f08 RDX: ffffffffc0ddb033 RSI: 0000000000000004 RDI: ffffab23c3ff3df4 RBP: 0000000000020000 R08: 0000000000000000 R09: 0000000000000000 R10: ffffab23c3ff3ed8 R11: 0000000000000000 R12: ffffab23c3ff3f08 R13: 00007f0b4ca2e000 R14: 0000000000020000 R15: ffffab23c3ff3f08 FS: 00007f0b4ca0f540(0000) GS:ffff91bd5e280000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: 00000000000002e8 CR3: 00000000629fa006 CR4: 00000000000606e0 Call Trace: full_proxy_read+0x53/0x80 __vfs_read+0x36/0x180 vfs_read+0x8a/0x140 ksys_read+0x4f/0xb0 do_syscall_64+0x5b/0x160 entry_SYSCALL_64_after_hwframe+0x44/0xa9 Signed-off-by: Matias Karhumaa Signed-off-by: Marcel Holtmann --- include/net/bluetooth/hci_core.h | 2 ++ net/bluetooth/hci_core.c | 2 ++ net/bluetooth/smp.c | 23 +++++++++-------------- 3 files changed, 13 insertions(+), 14 deletions(-) diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h index 9b0f821b2d3a..e5ea633ea368 100644 --- a/include/net/bluetooth/hci_core.h +++ b/include/net/bluetooth/hci_core.h @@ -267,6 +267,8 @@ struct hci_dev { __u16 le_max_tx_time; __u16 le_max_rx_len; __u16 le_max_rx_time; + __u8 le_max_key_size; + __u8 le_min_key_size; __u16 discov_interleaved_timeout; __u16 conn_info_min_age; __u16 conn_info_max_age; diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c index 0f1a8820d75c..7352fe85674b 100644 --- a/net/bluetooth/hci_core.c +++ b/net/bluetooth/hci_core.c @@ -3147,6 +3147,8 @@ struct hci_dev *hci_alloc_dev(void) hdev->le_max_tx_time = 0x0148; hdev->le_max_rx_len = 0x001b; hdev->le_max_rx_time = 0x0148; + hdev->le_max_key_size = SMP_MAX_ENC_KEY_SIZE; + hdev->le_min_key_size = SMP_MIN_ENC_KEY_SIZE; hdev->le_tx_def_phys = HCI_LE_SET_PHY_1M; hdev->le_rx_def_phys = HCI_LE_SET_PHY_1M; diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c index 3a7b0773536b..090670fe385f 100644 --- a/net/bluetooth/smp.c +++ b/net/bluetooth/smp.c @@ -88,9 +88,6 @@ struct smp_dev { u8 local_rand[16]; bool debug_key; - u8 min_key_size; - u8 max_key_size; - struct crypto_cipher *tfm_aes; struct crypto_shash *tfm_cmac; struct crypto_kpp *tfm_ecdh; @@ -720,7 +717,7 @@ static void build_pairing_cmd(struct l2cap_conn *conn, if (rsp == NULL) { req->io_capability = conn->hcon->io_capability; req->oob_flag = oob_flag; - req->max_key_size = SMP_DEV(hdev)->max_key_size; + req->max_key_size = hdev->le_max_key_size; req->init_key_dist = local_dist; req->resp_key_dist = remote_dist; req->auth_req = (authreq & AUTH_REQ_MASK(hdev)); @@ -731,7 +728,7 @@ static void build_pairing_cmd(struct l2cap_conn *conn, rsp->io_capability = conn->hcon->io_capability; rsp->oob_flag = oob_flag; - rsp->max_key_size = SMP_DEV(hdev)->max_key_size; + rsp->max_key_size = hdev->le_max_key_size; rsp->init_key_dist = req->init_key_dist & remote_dist; rsp->resp_key_dist = req->resp_key_dist & local_dist; rsp->auth_req = (authreq & AUTH_REQ_MASK(hdev)); @@ -745,7 +742,7 @@ static u8 check_enc_key_size(struct l2cap_conn *conn, __u8 max_key_size) struct hci_dev *hdev = conn->hcon->hdev; struct smp_chan *smp = chan->data; - if (max_key_size > SMP_DEV(hdev)->max_key_size || + if (max_key_size > hdev->le_max_key_size || max_key_size < SMP_MIN_ENC_KEY_SIZE) return SMP_ENC_KEY_SIZE; @@ -3243,8 +3240,6 @@ static struct l2cap_chan *smp_add_cid(struct hci_dev *hdev, u16 cid) smp->tfm_aes = tfm_aes; smp->tfm_cmac = tfm_cmac; smp->tfm_ecdh = tfm_ecdh; - smp->min_key_size = SMP_MIN_ENC_KEY_SIZE; - smp->max_key_size = SMP_MAX_ENC_KEY_SIZE; create_chan: chan = l2cap_chan_create(); @@ -3370,7 +3365,7 @@ static ssize_t le_min_key_size_read(struct file *file, struct hci_dev *hdev = file->private_data; char buf[4]; - snprintf(buf, sizeof(buf), "%2u\n", SMP_DEV(hdev)->min_key_size); + snprintf(buf, sizeof(buf), "%2u\n", hdev->le_min_key_size); return simple_read_from_buffer(user_buf, count, ppos, buf, strlen(buf)); } @@ -3391,11 +3386,11 @@ static ssize_t le_min_key_size_write(struct file *file, sscanf(buf, "%hhu", &key_size); - if (key_size > SMP_DEV(hdev)->max_key_size || + if (key_size > hdev->le_max_key_size || key_size < SMP_MIN_ENC_KEY_SIZE) return -EINVAL; - SMP_DEV(hdev)->min_key_size = key_size; + hdev->le_min_key_size = key_size; return count; } @@ -3414,7 +3409,7 @@ static ssize_t le_max_key_size_read(struct file *file, struct hci_dev *hdev = file->private_data; char buf[4]; - snprintf(buf, sizeof(buf), "%2u\n", SMP_DEV(hdev)->max_key_size); + snprintf(buf, sizeof(buf), "%2u\n", hdev->le_max_key_size); return simple_read_from_buffer(user_buf, count, ppos, buf, strlen(buf)); } @@ -3436,10 +3431,10 @@ static ssize_t le_max_key_size_write(struct file *file, sscanf(buf, "%hhu", &key_size); if (key_size > SMP_MAX_ENC_KEY_SIZE || - key_size < SMP_DEV(hdev)->min_key_size) + key_size < hdev->le_min_key_size) return -EINVAL; - SMP_DEV(hdev)->max_key_size = key_size; + hdev->le_max_key_size = key_size; return count; }