summaryrefslogtreecommitdiffstats
path: root/drivers/bluetooth
diff options
context:
space:
mode:
authorBalakrishna Godavarthi <bgodavar@codeaurora.org>2019-05-28 17:43:22 -0400
committerMarcel Holtmann <marcel@holtmann.org>2019-07-06 06:45:02 -0400
commit32646db8cc2862a14788de1bb4c365d0a27fb532 (patch)
treeac088126ff11fc18ab30d62b8e0a2a1b344dc666 /drivers/bluetooth
parent82b7d856649988b5ddaad5f17abb787f6909107f (diff)
Bluetooth: btqca: inject command complete event during fw download
Latest qualcomm chips are not sending an command complete event for every firmware packet sent to chip. They only respond with a vendor specific event for the last firmware packet. This optimization will decrease the BT ON time. Due to this we are seeing a timeout error message logs on the console during firmware download. Now we are injecting a command complete event once we receive an vendor specific event for the last RAM firmware packet. Signed-off-by: Balakrishna Godavarthi <bgodavar@codeaurora.org> Tested-by: Matthias Kaehlcke <mka@chromium.org> Reviewed-by: Matthias Kaehlcke <mka@chromium.org> Signed-off-by: Matthias Kaehlcke <mka@chromium.org> Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
Diffstat (limited to 'drivers/bluetooth')
-rw-r--r--drivers/bluetooth/btqca.c39
-rw-r--r--drivers/bluetooth/btqca.h4
2 files changed, 42 insertions, 1 deletions
diff --git a/drivers/bluetooth/btqca.c b/drivers/bluetooth/btqca.c
index aff1d22223bd..6ce5c8835efe 100644
--- a/drivers/bluetooth/btqca.c
+++ b/drivers/bluetooth/btqca.c
@@ -131,6 +131,7 @@ static void qca_tlv_check_data(struct rome_config *config,
131 * In case VSE is skipped, only the last segment is acked. 131 * In case VSE is skipped, only the last segment is acked.
132 */ 132 */
133 config->dnld_mode = tlv_patch->download_mode; 133 config->dnld_mode = tlv_patch->download_mode;
134 config->dnld_type = config->dnld_mode;
134 135
135 BT_DBG("Total Length : %d bytes", 136 BT_DBG("Total Length : %d bytes",
136 le32_to_cpu(tlv_patch->total_size)); 137 le32_to_cpu(tlv_patch->total_size));
@@ -251,6 +252,31 @@ out:
251 return err; 252 return err;
252} 253}
253 254
255static int qca_inject_cmd_complete_event(struct hci_dev *hdev)
256{
257 struct hci_event_hdr *hdr;
258 struct hci_ev_cmd_complete *evt;
259 struct sk_buff *skb;
260
261 skb = bt_skb_alloc(sizeof(*hdr) + sizeof(*evt) + 1, GFP_KERNEL);
262 if (!skb)
263 return -ENOMEM;
264
265 hdr = skb_put(skb, sizeof(*hdr));
266 hdr->evt = HCI_EV_CMD_COMPLETE;
267 hdr->plen = sizeof(*evt) + 1;
268
269 evt = skb_put(skb, sizeof(*evt));
270 evt->ncmd = 1;
271 evt->opcode = QCA_HCI_CC_OPCODE;
272
273 skb_put_u8(skb, QCA_HCI_CC_SUCCESS);
274
275 hci_skb_pkt_type(skb) = HCI_EVENT_PKT;
276
277 return hci_recv_frame(hdev, skb);
278}
279
254static int qca_download_firmware(struct hci_dev *hdev, 280static int qca_download_firmware(struct hci_dev *hdev,
255 struct rome_config *config) 281 struct rome_config *config)
256{ 282{
@@ -284,11 +310,22 @@ static int qca_download_firmware(struct hci_dev *hdev,
284 ret = qca_tlv_send_segment(hdev, segsize, segment, 310 ret = qca_tlv_send_segment(hdev, segsize, segment,
285 config->dnld_mode); 311 config->dnld_mode);
286 if (ret) 312 if (ret)
287 break; 313 goto out;
288 314
289 segment += segsize; 315 segment += segsize;
290 } 316 }
291 317
318 /* Latest qualcomm chipsets are not sending a command complete event
319 * for every fw packet sent. They only respond with a vendor specific
320 * event for the last packet. This optimization in the chip will
321 * decrease the BT in initialization time. Here we will inject a command
322 * complete event to avoid a command timeout error message.
323 */
324 if (config->dnld_type == ROME_SKIP_EVT_VSE_CC ||
325 config->dnld_type == ROME_SKIP_EVT_VSE)
326 return qca_inject_cmd_complete_event(hdev);
327
328out:
292 release_firmware(fw); 329 release_firmware(fw);
293 330
294 return ret; 331 return ret;
diff --git a/drivers/bluetooth/btqca.h b/drivers/bluetooth/btqca.h
index e9c999959603..03fdec20730b 100644
--- a/drivers/bluetooth/btqca.h
+++ b/drivers/bluetooth/btqca.h
@@ -28,6 +28,9 @@
28#define QCA_WCN3990_POWERON_PULSE 0xFC 28#define QCA_WCN3990_POWERON_PULSE 0xFC
29#define QCA_WCN3990_POWEROFF_PULSE 0xC0 29#define QCA_WCN3990_POWEROFF_PULSE 0xC0
30 30
31#define QCA_HCI_CC_OPCODE 0xFC00
32#define QCA_HCI_CC_SUCCESS 0x00
33
31enum qca_baudrate { 34enum qca_baudrate {
32 QCA_BAUDRATE_115200 = 0, 35 QCA_BAUDRATE_115200 = 0,
33 QCA_BAUDRATE_57600, 36 QCA_BAUDRATE_57600,
@@ -69,6 +72,7 @@ struct rome_config {
69 char fwname[64]; 72 char fwname[64];
70 uint8_t user_baud_rate; 73 uint8_t user_baud_rate;
71 enum rome_tlv_dnld_mode dnld_mode; 74 enum rome_tlv_dnld_mode dnld_mode;
75 enum rome_tlv_dnld_mode dnld_type;
72}; 76};
73 77
74struct edl_event_hdr { 78struct edl_event_hdr {