Hi Balakrishna, > 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@xxxxxxxxxxxxxx> > --- > drivers/bluetooth/btqca.c | 39 ++++++++++++++++++++++++++++++++++++++- > drivers/bluetooth/btqca.h | 3 +++ > 2 files changed, 41 insertions(+), 1 deletion(-) > > diff --git a/drivers/bluetooth/btqca.c b/drivers/bluetooth/btqca.c > index ec9e03a6b778..0b533f65f652 100644 > --- a/drivers/bluetooth/btqca.c > +++ b/drivers/bluetooth/btqca.c > @@ -144,6 +144,7 @@ static void qca_tlv_check_data(struct rome_config *config, > * In case VSE is skipped, only the last segment is acked. > */ > config->dnld_mode = tlv_patch->download_mode; > + config->dnld_type = config->dnld_mode; > > BT_DBG("Total Length : %d bytes", > le32_to_cpu(tlv_patch->total_size)); > @@ -264,6 +265,31 @@ static int qca_tlv_send_segment(struct hci_dev *hdev, int seg_size, > return err; > } > > +static int qca_inject_cmd_complete_event(struct hci_dev *hdev) > +{ > + struct hci_event_hdr *hdr; > + struct hci_ev_cmd_complete *evt; > + struct sk_buff *skb; > + > + skb = bt_skb_alloc(sizeof(*hdr) + sizeof(*evt) + 1, GFP_KERNEL); > + if (!skb) > + return -ENOMEM; > + > + hdr = skb_put(skb, sizeof(*hdr)); > + hdr->evt = HCI_EV_CMD_COMPLETE; > + hdr->plen = sizeof(*evt) + 1; > + > + evt = skb_put(skb, sizeof(*evt)); > + evt->ncmd = 1; > + evt->opcode = HCI_OP_NOP; > + > + skb_put_u8(skb, QCA_HCI_CC_SUCCESS); > + > + hci_skb_pkt_type(skb) = HCI_EVENT_PKT; > + > + return hci_recv_frame(hdev, skb); > +} > + > static int qca_download_firmware(struct hci_dev *hdev, > struct rome_config *config) > { > @@ -297,11 +323,22 @@ static int qca_download_firmware(struct hci_dev *hdev, > ret = qca_tlv_send_segment(hdev, segsize, segment, > config->dnld_mode); > if (ret) > - break; > + goto out; > > segment += segsize; > } > > + /* Latest qualcomm chipsets are not sending a command complete event > + * for every fw packet sent. They only respond with a vendor specific > + * event for the last packet. This optimization in the chip will > + * decrease the BT in initialization time. Here we will inject a command > + * complete event to avoid a command timeout error message. > + */ > + if ((config->dnld_type == ROME_SKIP_EVT_VSE_CC || > + config->dnld_type == ROME_SKIP_EVT_VSE)) > + return qca_inject_cmd_complete_event(hdev); > + have you actually considered using __hci_cmd_send in that case. It is allowed for vendor OGF to use that command. I see you actually do use it and now I am failing to understand what this is for. Regards Marcel