From 8059ba0bd0e4694e51c2ee6438a77b325f06c0d5 Mon Sep 17 00:00:00 2001 From: Matthias Kaehlcke Date: Tue, 9 Jul 2019 15:44:50 -0700 Subject: Bluetooth: btqca: Add a short delay before downloading the NVM On WCN3990 downloading the NVM sometimes fails with a "TLV response size mismatch" error: [ 174.949955] Bluetooth: btqca.c:qca_download_firmware() hci0: QCA Downloading qca/crnv21.bin [ 174.958718] Bluetooth: btqca.c:qca_tlv_send_segment() hci0: QCA TLV response size mismatch It seems the controller needs a short time after downloading the firmware before it is ready for the NVM. A delay as short as 1 ms seems sufficient, make it 10 ms just in case. No event is received during the delay, hence we don't just silently drop an extra event. Signed-off-by: Matthias Kaehlcke Signed-off-by: Marcel Holtmann --- drivers/bluetooth/btqca.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers/bluetooth/btqca.c') diff --git a/drivers/bluetooth/btqca.c b/drivers/bluetooth/btqca.c index 8b33128dccee..c59ca5782b63 100644 --- a/drivers/bluetooth/btqca.c +++ b/drivers/bluetooth/btqca.c @@ -388,6 +388,9 @@ int qca_uart_setup(struct hci_dev *hdev, uint8_t baudrate, return err; } + /* Give the controller some time to get ready to receive the NVM */ + msleep(10); + /* Download NVM configuration */ config.type = TLV_TYPE_NVM; if (firmware_name) -- cgit v1.2.3-55-g7522 From 2fde6afb8c7fce8e679c1072891cd31d54af5b83 Mon Sep 17 00:00:00 2001 From: Matthias Kaehlcke Date: Mon, 8 Jul 2019 14:57:42 -0700 Subject: Bluetooth: btqca: Use correct byte format for opcode of injected command The opcode of the command injected by commit 32646db8cc28 ("Bluetooth: btqca: inject command complete event during fw download") uses the CPU byte format, however it should always be little endian. In practice it shouldn't really matter, since all we need is an opcode != 0, but still let's do things correctly and keep sparse happy. Fixes: 32646db8cc28 ("Bluetooth: btqca: inject command complete event during fw download") Reported-by: kbuild test robot Signed-off-by: Matthias Kaehlcke Signed-off-by: Marcel Holtmann --- drivers/bluetooth/btqca.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/bluetooth/btqca.c') diff --git a/drivers/bluetooth/btqca.c b/drivers/bluetooth/btqca.c index c59ca5782b63..81a5c45bdcd9 100644 --- a/drivers/bluetooth/btqca.c +++ b/drivers/bluetooth/btqca.c @@ -268,7 +268,7 @@ static int qca_inject_cmd_complete_event(struct hci_dev *hdev) evt = skb_put(skb, sizeof(*evt)); evt->ncmd = 1; - evt->opcode = QCA_HCI_CC_OPCODE; + evt->opcode = cpu_to_le16(QCA_HCI_CC_OPCODE); skb_put_u8(skb, QCA_HCI_CC_SUCCESS); -- cgit v1.2.3-55-g7522 From a2780889e247561744dd8efbd3478a1999b72ae3 Mon Sep 17 00:00:00 2001 From: Harish Bandi Date: Fri, 12 Jul 2019 10:39:40 +0530 Subject: Bluetooth: hci_qca: Send VS pre shutdown command. WCN399x chips are coex chips, it needs a VS pre shutdown command while turning off the BT. So that chip can inform BT is OFF to other active clients. Signed-off-by: Harish Bandi Signed-off-by: Marcel Holtmann --- drivers/bluetooth/btqca.c | 21 +++++++++++++++++++++ drivers/bluetooth/btqca.h | 7 +++++++ drivers/bluetooth/hci_qca.c | 3 +++ 3 files changed, 31 insertions(+) (limited to 'drivers/bluetooth/btqca.c') diff --git a/drivers/bluetooth/btqca.c b/drivers/bluetooth/btqca.c index 81a5c45bdcd9..2221935fac7e 100644 --- a/drivers/bluetooth/btqca.c +++ b/drivers/bluetooth/btqca.c @@ -99,6 +99,27 @@ static int qca_send_reset(struct hci_dev *hdev) return 0; } +int qca_send_pre_shutdown_cmd(struct hci_dev *hdev) +{ + struct sk_buff *skb; + int err; + + bt_dev_dbg(hdev, "QCA pre shutdown cmd"); + + skb = __hci_cmd_sync(hdev, QCA_PRE_SHUTDOWN_CMD, 0, + NULL, HCI_INIT_TIMEOUT); + if (IS_ERR(skb)) { + err = PTR_ERR(skb); + bt_dev_err(hdev, "QCA preshutdown_cmd failed (%d)", err); + return err; + } + + kfree_skb(skb); + + return 0; +} +EXPORT_SYMBOL_GPL(qca_send_pre_shutdown_cmd); + static void qca_tlv_check_data(struct rome_config *config, const struct firmware *fw) { diff --git a/drivers/bluetooth/btqca.h b/drivers/bluetooth/btqca.h index 6a291a7a5d96..69c5315a65fd 100644 --- a/drivers/bluetooth/btqca.h +++ b/drivers/bluetooth/btqca.h @@ -13,6 +13,7 @@ #define EDL_PATCH_TLV_REQ_CMD (0x1E) #define EDL_NVM_ACCESS_SET_REQ_CMD (0x01) #define MAX_SIZE_PER_TLV_SEGMENT (243) +#define QCA_PRE_SHUTDOWN_CMD (0xFC08) #define EDL_CMD_REQ_RES_EVT (0x00) #define EDL_PATCH_VER_RES_EVT (0x19) @@ -135,6 +136,7 @@ int qca_uart_setup(struct hci_dev *hdev, uint8_t baudrate, const char *firmware_name); int qca_read_soc_version(struct hci_dev *hdev, u32 *soc_version); int qca_set_bdaddr(struct hci_dev *hdev, const bdaddr_t *bdaddr); +int qca_send_pre_shutdown_cmd(struct hci_dev *hdev); static inline bool qca_is_wcn399x(enum qca_btsoc_type soc_type) { return soc_type == QCA_WCN3990 || soc_type == QCA_WCN3998; @@ -167,4 +169,9 @@ static inline bool qca_is_wcn399x(enum qca_btsoc_type soc_type) { return false; } + +static inline int qca_send_pre_shutdown_cmd(struct hci_dev *hdev) +{ + return -EOPNOTSUPP; +} #endif diff --git a/drivers/bluetooth/hci_qca.c b/drivers/bluetooth/hci_qca.c index 3c9fd165fda6..0cfa5b831d39 100644 --- a/drivers/bluetooth/hci_qca.c +++ b/drivers/bluetooth/hci_qca.c @@ -1386,6 +1386,9 @@ static int qca_power_off(struct hci_dev *hdev) { struct hci_uart *hu = hci_get_drvdata(hdev); + /* Perform pre shutdown command */ + qca_send_pre_shutdown_cmd(hdev); + qca_power_shutdown(hu); return 0; } -- cgit v1.2.3-55-g7522 From c7c5ae2902bf8fe9acc75f798c0de75ac9295ccf Mon Sep 17 00:00:00 2001 From: Claire Chang Date: Tue, 6 Aug 2019 17:56:29 +0800 Subject: Bluetooth: btqca: release_firmware after qca_inject_cmd_complete_event commit 32646db8cc28 ("Bluetooth: btqca: inject command complete event during fw download") added qca_inject_cmd_complete_event() for certain qualcomm chips. However, qca_download_firmware() will return without calling release_firmware() in this case. This leads to a memory leak like the following found by kmemleak: unreferenced object 0xfffffff3868a5880 (size 128): comm "kworker/u17:5", pid 347, jiffies 4294676481 (age 312.157s) hex dump (first 32 bytes): ac fd 00 00 00 00 00 00 00 d0 7e 17 80 ff ff ff ..........~..... 00 00 00 00 00 00 00 00 00 59 8a 86 f3 ff ff ff .........Y...... backtrace: [<00000000978ce31d>] kmem_cache_alloc_trace+0x194/0x298 [<000000006ea0398c>] _request_firmware+0x74/0x4e4 [<000000004da31ca0>] request_firmware+0x44/0x64 [<0000000094572996>] qca_download_firmware+0x74/0x6e4 [btqca] [<00000000b24d615a>] qca_uart_setup+0xc0/0x2b0 [btqca] [<00000000364a6d5a>] qca_setup+0x204/0x570 [hci_uart] [<000000006be1a544>] hci_uart_setup+0xa8/0x148 [hci_uart] [<00000000d64c0f4f>] hci_dev_do_open+0x144/0x530 [bluetooth] [<00000000f69f5110>] hci_power_on+0x84/0x288 [bluetooth] [<00000000d4151583>] process_one_work+0x210/0x420 [<000000003cf3dcfb>] worker_thread+0x2c4/0x3e4 [<000000007ccaf055>] kthread+0x124/0x134 [<00000000bef1f723>] ret_from_fork+0x10/0x18 [<00000000c36ee3dd>] 0xffffffffffffffff unreferenced object 0xfffffff37b16de00 (size 128): comm "kworker/u17:5", pid 347, jiffies 4294676873 (age 311.766s) hex dump (first 32 bytes): da 07 00 00 00 00 00 00 00 50 ff 0b 80 ff ff ff .........P...... 00 00 00 00 00 00 00 00 00 dd 16 7b f3 ff ff ff ...........{.... backtrace: [<00000000978ce31d>] kmem_cache_alloc_trace+0x194/0x298 [<000000006ea0398c>] _request_firmware+0x74/0x4e4 [<000000004da31ca0>] request_firmware+0x44/0x64 [<0000000094572996>] qca_download_firmware+0x74/0x6e4 [btqca] [<000000000cde20a9>] qca_uart_setup+0x144/0x2b0 [btqca] [<00000000364a6d5a>] qca_setup+0x204/0x570 [hci_uart] [<000000006be1a544>] hci_uart_setup+0xa8/0x148 [hci_uart] [<00000000d64c0f4f>] hci_dev_do_open+0x144/0x530 [bluetooth] [<00000000f69f5110>] hci_power_on+0x84/0x288 [bluetooth] [<00000000d4151583>] process_one_work+0x210/0x420 [<000000003cf3dcfb>] worker_thread+0x2c4/0x3e4 [<000000007ccaf055>] kthread+0x124/0x134 [<00000000bef1f723>] ret_from_fork+0x10/0x18 [<00000000c36ee3dd>] 0xffffffffffffffff Make sure release_firmware() is called aftre qca_inject_cmd_complete_event() to avoid the memory leak. Fixes: 32646db8cc28 ("Bluetooth: btqca: inject command complete event during fw download") Signed-off-by: Claire Chang Reviewed-by: Balakrishna Godavarthi Signed-off-by: Marcel Holtmann --- drivers/bluetooth/btqca.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/bluetooth/btqca.c') diff --git a/drivers/bluetooth/btqca.c b/drivers/bluetooth/btqca.c index 2221935fac7e..8f0fec5acade 100644 --- a/drivers/bluetooth/btqca.c +++ b/drivers/bluetooth/btqca.c @@ -344,7 +344,7 @@ static int qca_download_firmware(struct hci_dev *hdev, */ if (config->dnld_type == ROME_SKIP_EVT_VSE_CC || config->dnld_type == ROME_SKIP_EVT_VSE) - return qca_inject_cmd_complete_event(hdev); + ret = qca_inject_cmd_complete_event(hdev); out: release_firmware(fw); -- cgit v1.2.3-55-g7522 From 12072a68961af20e84ddb4aba2387ba5f70e8c14 Mon Sep 17 00:00:00 2001 From: Balakrishna Godavarthi Date: Thu, 8 Aug 2019 14:26:08 +0530 Subject: Bluetooth: btqca: Reset download type to default This patch will reset the download flag to default value before retrieving the download mode type. Fixes: 32646db8cc28 ("Bluetooth: btqca: inject command complete event during fw download") Signed-off-by: Balakrishna Godavarthi Tested-by: Claire Chang Reviewed-by: Claire Chang Signed-off-by: Marcel Holtmann --- drivers/bluetooth/btqca.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/bluetooth/btqca.c') diff --git a/drivers/bluetooth/btqca.c b/drivers/bluetooth/btqca.c index 8f0fec5acade..0875470a7806 100644 --- a/drivers/bluetooth/btqca.c +++ b/drivers/bluetooth/btqca.c @@ -140,6 +140,7 @@ static void qca_tlv_check_data(struct rome_config *config, BT_DBG("Length\t\t : %d bytes", length); config->dnld_mode = ROME_SKIP_EVT_NONE; + config->dnld_type = ROME_SKIP_EVT_NONE; switch (config->type) { case TLV_TYPE_PATCH: -- cgit v1.2.3-55-g7522