diff mbox series

Bluetooth: btrtl: Ask 8821C to drop old firmware after shutdown

Message ID 20201022142648.446-1-kai.heng.feng@canonical.com (mailing list archive)
State New, archived
Headers show
Series Bluetooth: btrtl: Ask 8821C to drop old firmware after shutdown | expand

Commit Message

Kai-Heng Feng Oct. 22, 2020, 2:26 p.m. UTC
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.

Signed-off-by: Kai-Heng Feng <kai.heng.feng@canonical.com>
---
 drivers/bluetooth/btrtl.c | 25 +++++++++++++++++++++++++
 1 file changed, 25 insertions(+)

Comments

kernel test robot Oct. 23, 2020, 1:42 p.m. UTC | #1
Hi Kai-Heng,

Thank you for the patch! Perhaps something to improve:

[auto build test WARNING on bluetooth-next/master]
[also build test WARNING on bluetooth/master v5.9 next-20201023]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch]

url:    https://github.com/0day-ci/linux/commits/Kai-Heng-Feng/Bluetooth-btrtl-Ask-8821C-to-drop-old-firmware-after-shutdown/20201022-222743
base:   https://git.kernel.org/pub/scm/linux/kernel/git/bluetooth/bluetooth-next.git master
config: m68k-randconfig-s031-20201023 (attached as .config)
compiler: m68k-linux-gcc (GCC) 9.3.0
reproduce:
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # apt-get install sparse
        # sparse version: v0.6.3-17-g2d3af347-dirty
        # https://github.com/0day-ci/linux/commit/d430672c074dec68229560c1d1309c99cc769efe
        git remote add linux-review https://github.com/0day-ci/linux
        git fetch --no-tags linux-review Kai-Heng-Feng/Bluetooth-btrtl-Ask-8821C-to-drop-old-firmware-after-shutdown/20201022-222743
        git checkout d430672c074dec68229560c1d1309c99cc769efe
        # save the attached .config to linux build tree
        COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-9.3.0 make.cross C=1 CF='-fdiagnostic-prefix -D__CHECK_ENDIAN__' ARCH=m68k 

If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <lkp@intel.com>


"sparse warnings: (new ones prefixed by >>)"
>> drivers/bluetooth/btrtl.c:589:37: sparse: sparse: restricted __le16 degrades to integer
>> drivers/bluetooth/btrtl.c:589:37: sparse: sparse: cast to restricted __le16
>> drivers/bluetooth/btrtl.c:589:37: sparse: sparse: restricted __le16 degrades to integer
>> drivers/bluetooth/btrtl.c:589:37: sparse: sparse: cast to restricted __le16
>> drivers/bluetooth/btrtl.c:589:37: sparse: sparse: restricted __le16 degrades to integer
>> drivers/bluetooth/btrtl.c:589:37: sparse: sparse: cast to restricted __le16
>> drivers/bluetooth/btrtl.c:589:37: sparse: sparse: restricted __le16 degrades to integer
>> drivers/bluetooth/btrtl.c:589:37: sparse: sparse: cast to restricted __le16
   drivers/bluetooth/btrtl.c:590:37: sparse: sparse: restricted __le16 degrades to integer
   drivers/bluetooth/btrtl.c:590:37: sparse: sparse: cast to restricted __le16
   drivers/bluetooth/btrtl.c:590:37: sparse: sparse: restricted __le16 degrades to integer
   drivers/bluetooth/btrtl.c:590:37: sparse: sparse: cast to restricted __le16
   drivers/bluetooth/btrtl.c:590:37: sparse: sparse: restricted __le16 degrades to integer
   drivers/bluetooth/btrtl.c:590:37: sparse: sparse: cast to restricted __le16
   drivers/bluetooth/btrtl.c:590:37: sparse: sparse: restricted __le16 degrades to integer
   drivers/bluetooth/btrtl.c:590:37: sparse: sparse: cast to restricted __le16
   drivers/bluetooth/btrtl.c: note: in included file:
   drivers/bluetooth/btrtl.h:47:45: sparse: sparse: array of flexible structures

vim +589 drivers/bluetooth/btrtl.c

   556	
   557	struct btrtl_device_info *btrtl_initialize(struct hci_dev *hdev,
   558						   const char *postfix)
   559	{
   560		struct btrtl_device_info *btrtl_dev;
   561		struct sk_buff *skb;
   562		struct hci_rp_read_local_version *resp;
   563		char cfg_name[40];
   564		u16 hci_rev, lmp_subver;
   565		u8 hci_ver;
   566		int ret;
   567	
   568		btrtl_dev = kzalloc(sizeof(*btrtl_dev), GFP_KERNEL);
   569		if (!btrtl_dev) {
   570			ret = -ENOMEM;
   571			goto err_alloc;
   572		}
   573	
   574		skb = btrtl_read_local_version(hdev);
   575		if (IS_ERR(skb)) {
   576			ret = PTR_ERR(skb);
   577			goto err_free;
   578		}
   579	
   580		resp = (struct hci_rp_read_local_version *)skb->data;
   581		rtl_dev_info(hdev, "examining hci_ver=%02x hci_rev=%04x lmp_ver=%02x lmp_subver=%04x",
   582			     resp->hci_ver, resp->hci_rev,
   583			     resp->lmp_ver, resp->lmp_subver);
   584	
   585		hci_ver = resp->hci_ver;
   586		hci_rev = le16_to_cpu(resp->hci_rev);
   587		lmp_subver = le16_to_cpu(resp->lmp_subver);
   588	
 > 589		if (resp->hci_ver == 0x8 && le16_to_cpu(resp->hci_rev == 0x826c) &&
   590		    resp->lmp_ver == 0x8 && le16_to_cpu(resp->lmp_subver == 0xa99e))
   591			btrtl_dev->drop_fw = true;
   592	
   593		kfree_skb(skb);
   594	
   595		btrtl_dev->ic_info = btrtl_match_ic(lmp_subver, hci_rev, hci_ver,
   596						    hdev->bus);
   597	
   598		if (!btrtl_dev->ic_info) {
   599			rtl_dev_info(hdev, "unknown IC info, lmp subver %04x, hci rev %04x, hci ver %04x",
   600				    lmp_subver, hci_rev, hci_ver);
   601			return btrtl_dev;
   602		}
   603	
   604		if (btrtl_dev->ic_info->has_rom_version) {
   605			ret = rtl_read_rom_version(hdev, &btrtl_dev->rom_version);
   606			if (ret)
   607				goto err_free;
   608		}
   609	
   610		btrtl_dev->fw_len = rtl_load_file(hdev, btrtl_dev->ic_info->fw_name,
   611						  &btrtl_dev->fw_data);
   612		if (btrtl_dev->fw_len < 0) {
   613			rtl_dev_err(hdev, "firmware file %s not found",
   614				    btrtl_dev->ic_info->fw_name);
   615			ret = btrtl_dev->fw_len;
   616			goto err_free;
   617		}
   618	
   619		if (btrtl_dev->ic_info->cfg_name) {
   620			if (postfix) {
   621				snprintf(cfg_name, sizeof(cfg_name), "%s-%s.bin",
   622					 btrtl_dev->ic_info->cfg_name, postfix);
   623			} else {
   624				snprintf(cfg_name, sizeof(cfg_name), "%s.bin",
   625					 btrtl_dev->ic_info->cfg_name);
   626			}
   627			btrtl_dev->cfg_len = rtl_load_file(hdev, cfg_name,
   628							   &btrtl_dev->cfg_data);
   629			if (btrtl_dev->ic_info->config_needed &&
   630			    btrtl_dev->cfg_len <= 0) {
   631				rtl_dev_err(hdev, "mandatory config file %s not found",
   632					    btrtl_dev->ic_info->cfg_name);
   633				ret = btrtl_dev->cfg_len;
   634				goto err_free;
   635			}
   636		}
   637	
   638		return btrtl_dev;
   639	
   640	err_free:
   641		btrtl_free(btrtl_dev);
   642	err_alloc:
   643		return ERR_PTR(ret);
   644	}
   645	EXPORT_SYMBOL_GPL(btrtl_initialize);
   646	

---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org
diff mbox series

Patch

diff --git a/drivers/bluetooth/btrtl.c b/drivers/bluetooth/btrtl.c
index 3a9afc905f24..2f3843fb2b95 100644
--- a/drivers/bluetooth/btrtl.c
+++ b/drivers/bluetooth/btrtl.c
@@ -55,6 +55,7 @@  struct btrtl_device_info {
 	int fw_len;
 	u8 *cfg_data;
 	int cfg_len;
+	bool drop_fw;
 };
 
 static const struct id_table ic_id_table[] = {
@@ -584,6 +585,11 @@  struct btrtl_device_info *btrtl_initialize(struct hci_dev *hdev,
 	hci_ver = resp->hci_ver;
 	hci_rev = le16_to_cpu(resp->hci_rev);
 	lmp_subver = le16_to_cpu(resp->lmp_subver);
+
+	if (resp->hci_ver == 0x8 && le16_to_cpu(resp->hci_rev == 0x826c) &&
+	    resp->lmp_ver == 0x8 && le16_to_cpu(resp->lmp_subver == 0xa99e))
+		btrtl_dev->drop_fw = true;
+
 	kfree_skb(skb);
 
 	btrtl_dev->ic_info = btrtl_match_ic(lmp_subver, hci_rev, hci_ver,
@@ -671,6 +677,9 @@  EXPORT_SYMBOL_GPL(btrtl_download_firmware);
 int btrtl_setup_realtek(struct hci_dev *hdev)
 {
 	struct btrtl_device_info *btrtl_dev;
+	struct sk_buff *skb;
+	u16 opcode;
+	u8 cmd[2];
 	int ret;
 
 	btrtl_dev = btrtl_initialize(hdev, NULL);
@@ -679,6 +688,22 @@  int btrtl_setup_realtek(struct hci_dev *hdev)
 
 	ret = btrtl_download_firmware(hdev, btrtl_dev);
 
+	if (btrtl_dev->drop_fw) {
+		opcode = hci_opcode_pack(0x3f, 0x66);
+		cmd[0] = opcode & 0xff;
+		cmd[1] = opcode >> 8;
+
+		skb = bt_skb_alloc(sizeof(cmd), GFP_KERNEL);
+		if (IS_ERR(skb))
+			goto out_free;
+
+		skb_put_data(skb, cmd, sizeof(cmd));
+		hci_skb_pkt_type(skb) = HCI_COMMAND_PKT;
+
+		hdev->send(hdev, skb);
+	}
+
+out_free:
 	btrtl_free(btrtl_dev);
 
 	/* Enable controller to do both LE scan and BR/EDR inquiry