Skip to content

Commit 1996d9c

Browse files
khfengholtmann
authored andcommitted
Bluetooth: btrtl: Ask 8821C to drop old firmware
Some platforms keep USB power even when they are powered off and in S5, this makes Realtek 8821C keep its firmware even after a cold boot, and make 8821C never load new firmware. So use vendor specific HCI command to ask 8821C drop its firmware after system shutdown. Newer firmware doesn't have this issue so we only use this trick for old 8821C firmware version. Suggested-by: Max Chou <[email protected]> Signed-off-by: Kai-Heng Feng <[email protected]> Signed-off-by: Marcel Holtmann <[email protected]>
1 parent 6f9ff24 commit 1996d9c

File tree

1 file changed

+46
-0
lines changed

1 file changed

+46
-0
lines changed

drivers/bluetooth/btrtl.c

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ struct btrtl_device_info {
5656
int fw_len;
5757
u8 *cfg_data;
5858
int cfg_len;
59+
bool drop_fw;
5960
};
6061

6162
static const struct id_table ic_id_table[] = {
@@ -537,6 +538,8 @@ struct btrtl_device_info *btrtl_initialize(struct hci_dev *hdev,
537538
u16 hci_rev, lmp_subver;
538539
u8 hci_ver;
539540
int ret;
541+
u16 opcode;
542+
u8 cmd[2];
540543

541544
btrtl_dev = kzalloc(sizeof(*btrtl_dev), GFP_KERNEL);
542545
if (!btrtl_dev) {
@@ -558,6 +561,49 @@ struct btrtl_device_info *btrtl_initialize(struct hci_dev *hdev,
558561
hci_ver = resp->hci_ver;
559562
hci_rev = le16_to_cpu(resp->hci_rev);
560563
lmp_subver = le16_to_cpu(resp->lmp_subver);
564+
565+
if (resp->hci_ver == 0x8 && le16_to_cpu(resp->hci_rev) == 0x826c &&
566+
resp->lmp_ver == 0x8 && le16_to_cpu(resp->lmp_subver) == 0xa99e)
567+
btrtl_dev->drop_fw = true;
568+
569+
if (btrtl_dev->drop_fw) {
570+
opcode = hci_opcode_pack(0x3f, 0x66);
571+
cmd[0] = opcode & 0xff;
572+
cmd[1] = opcode >> 8;
573+
574+
skb = bt_skb_alloc(sizeof(cmd), GFP_KERNEL);
575+
if (IS_ERR(skb))
576+
goto out_free;
577+
578+
skb_put_data(skb, cmd, sizeof(cmd));
579+
hci_skb_pkt_type(skb) = HCI_COMMAND_PKT;
580+
581+
hdev->send(hdev, skb);
582+
583+
/* Ensure the above vendor command is sent to controller and
584+
* process has done.
585+
*/
586+
msleep(200);
587+
588+
/* Read the local version again. Expect to have the vanilla
589+
* version as cold boot.
590+
*/
591+
skb = btrtl_read_local_version(hdev);
592+
if (IS_ERR(skb)) {
593+
ret = PTR_ERR(skb);
594+
goto err_free;
595+
}
596+
597+
resp = (struct hci_rp_read_local_version *)skb->data;
598+
rtl_dev_info(hdev, "examining hci_ver=%02x hci_rev=%04x lmp_ver=%02x lmp_subver=%04x",
599+
resp->hci_ver, resp->hci_rev,
600+
resp->lmp_ver, resp->lmp_subver);
601+
602+
hci_ver = resp->hci_ver;
603+
hci_rev = le16_to_cpu(resp->hci_rev);
604+
lmp_subver = le16_to_cpu(resp->lmp_subver);
605+
}
606+
out_free:
561607
kfree_skb(skb);
562608

563609
btrtl_dev->ic_info = btrtl_match_ic(lmp_subver, hci_rev, hci_ver,

0 commit comments

Comments
 (0)