[PATCH 1/2] Bluetooth: btusb: ath3k: Decide firmware name before checking update status

Subsystems: bluetooth drivers, the rest

STALE3266d

5 messages, 2 authors, 2017-08-24 · open the first message on its own page

[PATCH 1/2] Bluetooth: btusb: ath3k: Decide firmware name before checking update status

From: Kai-Heng Feng <hidden>
Date: 2017-08-24 09:06:39

Decide firmware name before checking patch update status. Firmware name is
required for caching.

Also, version information in btusb_setup_qca() is being calculated twice,
reduce it to one.

Signed-off-by: Kai-Heng Feng <redacted>
---
 drivers/bluetooth/ath3k.c | 10 +++----
 drivers/bluetooth/btusb.c | 72 +++++++++++++++++++++++------------------------
 2 files changed, 41 insertions(+), 41 deletions(-)
diff --git a/drivers/bluetooth/ath3k.c b/drivers/bluetooth/ath3k.c
index b793853ff05f..280849dba51e 100644
--- a/drivers/bluetooth/ath3k.c
+++ b/drivers/bluetooth/ath3k.c
@@ -409,11 +409,6 @@ static int ath3k_load_patch(struct usb_device *udev)
 		return ret;
 	}
 
-	if (fw_state & ATH3K_PATCH_UPDATE) {
-		BT_DBG("Patch was already downloaded");
-		return 0;
-	}
-
 	ret = ath3k_get_version(udev, &fw_version);
 	if (ret < 0) {
 		BT_ERR("Can't get version to change to load ram patch err");
@@ -423,6 +418,11 @@ static int ath3k_load_patch(struct usb_device *udev)
 	snprintf(filename, ATH3K_NAME_LEN, "ar3k/AthrBT_0x%08x.dfu",
 		 le32_to_cpu(fw_version.rom_version));
 
+	if (fw_state & ATH3K_PATCH_UPDATE) {
+		BT_DBG("Patch was already downloaded");
+		return 0;
+	}
+
 	ret = request_firmware(&firmware, filename, &udev->dev);
 	if (ret < 0) {
 		BT_ERR("Patch file not found %s", filename);
diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c
index fa24d693af24..732fe6c3e789 100644
--- a/drivers/bluetooth/btusb.c
+++ b/drivers/bluetooth/btusb.c
@@ -1518,18 +1518,12 @@ static int btusb_setup_csr(struct hci_dev *hdev)
 }
 
 static const struct firmware *btusb_setup_intel_get_fw(struct hci_dev *hdev,
-						       struct intel_version *ver)
+						       const char *fwname,
+						       const char *default_fwname)
 {
 	const struct firmware *fw;
-	char fwname[64];
 	int ret;
 
-	snprintf(fwname, sizeof(fwname),
-		 "intel/ibt-hw-%x.%x.%x-fw-%x.%x.%x.%x.%x.bseq",
-		 ver->hw_platform, ver->hw_variant, ver->hw_revision,
-		 ver->fw_variant,  ver->fw_revision, ver->fw_build_num,
-		 ver->fw_build_ww, ver->fw_build_yy);
-
 	ret = request_firmware(&fw, fwname, &hdev->dev);
 	if (ret < 0) {
 		if (ret == -EINVAL) {
@@ -1544,11 +1538,9 @@ static const struct firmware *btusb_setup_intel_get_fw(struct hci_dev *hdev,
 		/* If the correct firmware patch file is not found, use the
 		 * default firmware patch file instead
 		 */
-		snprintf(fwname, sizeof(fwname), "intel/ibt-hw-%x.%x.bseq",
-			 ver->hw_platform, ver->hw_variant);
-		if (request_firmware(&fw, fwname, &hdev->dev) < 0) {
+		if (request_firmware(&fw, default_fwname, &hdev->dev) < 0) {
 			BT_ERR("%s failed to open default Intel fw file: %s",
-			       hdev->name, fwname);
+			       hdev->name, default_fwname);
 			return NULL;
 		}
 	}
@@ -1676,6 +1668,8 @@ static int btusb_setup_intel_patching(struct hci_dev *hdev,
 static int btusb_setup_intel(struct hci_dev *hdev)
 {
 	struct sk_buff *skb;
+	char fwname[64];
+	char default_fwname[64];
 	const struct firmware *fw;
 	const u8 *fw_ptr;
 	int disable_patch, err;
@@ -1714,6 +1708,15 @@ static int btusb_setup_intel(struct hci_dev *hdev)
 		ver.fw_variant,  ver.fw_revision, ver.fw_build_num,
 		ver.fw_build_ww, ver.fw_build_yy, ver.fw_patch_num);
 
+	snprintf(fwname, sizeof(fwname),
+		 "intel/ibt-hw-%x.%x.%x-fw-%x.%x.%x.%x.%x.bseq",
+		 ver.hw_platform, ver.hw_variant, ver.hw_revision,
+		 ver.fw_variant,  ver.fw_revision, ver.fw_build_num,
+		 ver.fw_build_ww, ver.fw_build_yy);
+
+	snprintf(default_fwname, sizeof(default_fwname),
+		"intel/ibt-hw-%x.%x.bseq", ver.hw_platform, ver.hw_variant);
+
 	/* fw_patch_num indicates the version of patch the device currently
 	 * have. If there is no patch data in the device, it is always 0x00.
 	 * So, if it is other than 0x00, no need to patch the device again.
@@ -1730,7 +1733,7 @@ static int btusb_setup_intel(struct hci_dev *hdev)
 	 * If no patch file is found, allow the device to operate without
 	 * a patch.
 	 */
-	fw = btusb_setup_intel_get_fw(hdev, &ver);
+	fw = btusb_setup_intel_get_fw(hdev, fwname, default_fwname);
 	if (!fw)
 		goto complete;
 	fw_ptr = fw->data;
@@ -2592,21 +2595,15 @@ static int btusb_setup_qca_download_fw(struct hci_dev *hdev,
 }
 
 static int btusb_setup_qca_load_rampatch(struct hci_dev *hdev,
-					 struct qca_version *ver,
+					 const char *fwname,
+					 const struct qca_version *ver,
 					 const struct qca_device_info *info)
 {
 	struct qca_rampatch_version *rver;
 	const struct firmware *fw;
-	u32 ver_rom, ver_patch;
 	u16 rver_rom, rver_patch;
-	char fwname[64];
 	int err;
 
-	ver_rom = le32_to_cpu(ver->rom_version);
-	ver_patch = le32_to_cpu(ver->patch_version);
-
-	snprintf(fwname, sizeof(fwname), "qca/rampatch_usb_%08x.bin", ver_rom);
-
 	err = request_firmware(&fw, fwname, &hdev->dev);
 	if (err) {
 		BT_ERR("%s: failed to request rampatch file: %s (%d)",
@@ -2620,11 +2617,11 @@ static int btusb_setup_qca_load_rampatch(struct hci_dev *hdev,
 	rver_rom = le16_to_cpu(rver->rom_version);
 	rver_patch = le16_to_cpu(rver->patch_version);
 
-	BT_INFO("%s: QCA: patch rome 0x%x build 0x%x, firmware rome 0x%x "
-		"build 0x%x", hdev->name, rver_rom, rver_patch, ver_rom,
-		ver_patch);
+	BT_INFO("%s: QCA: patch rome 0x%x build 0x%x, firmware rome 0x%x build 0x%x",
+		hdev->name, rver_rom, rver_patch,
+		ver->rom_version, ver->patch_version);
 
-	if (rver_rom != ver_rom || rver_patch <= ver_patch) {
+	if (rver_rom != ver->rom_version || rver_patch <= ver->patch_version) {
 		BT_ERR("%s: rampatch file version did not match with firmware",
 		       hdev->name);
 		err = -EINVAL;
@@ -2640,16 +2637,12 @@ static int btusb_setup_qca_load_rampatch(struct hci_dev *hdev,
 }
 
 static int btusb_setup_qca_load_nvm(struct hci_dev *hdev,
-				    struct qca_version *ver,
+				    const char *fwname,
 				    const struct qca_device_info *info)
 {
 	const struct firmware *fw;
-	char fwname[64];
 	int err;
 
-	snprintf(fwname, sizeof(fwname), "qca/nvm_usb_%08x.bin",
-		 le32_to_cpu(ver->rom_version));
-
 	err = request_firmware(&fw, fwname, &hdev->dev);
 	if (err) {
 		BT_ERR("%s: failed to request NVM file: %s (%d)",
@@ -2670,7 +2663,7 @@ static int btusb_setup_qca(struct hci_dev *hdev)
 {
 	const struct qca_device_info *info = NULL;
 	struct qca_version ver;
-	u32 ver_rom;
+	char fwname[64];
 	u8 status;
 	int i, err;
 
@@ -2679,14 +2672,15 @@ static int btusb_setup_qca(struct hci_dev *hdev)
 	if (err < 0)
 		return err;
 
-	ver_rom = le32_to_cpu(ver.rom_version);
+	ver.rom_version = le32_to_cpu(ver.rom_version);
+	ver.patch_version = le32_to_cpu(ver.patch_version);
 	for (i = 0; i < ARRAY_SIZE(qca_devices_table); i++) {
-		if (ver_rom == qca_devices_table[i].rom_version)
+		if (ver.rom_version == qca_devices_table[i].rom_version)
 			info = &qca_devices_table[i];
 	}
 	if (!info) {
 		BT_ERR("%s: don't support firmware rome 0x%x", hdev->name,
-		       ver_rom);
+		       ver.rom_version);
 		return -ENODEV;
 	}
 
@@ -2695,14 +2689,20 @@ static int btusb_setup_qca(struct hci_dev *hdev)
 	if (err < 0)
 		return err;
 
+	snprintf(fwname, sizeof(fwname), "qca/rampatch_usb_%08x.bin",
+		 ver.rom_version);
+
 	if (!(status & QCA_PATCH_UPDATED)) {
-		err = btusb_setup_qca_load_rampatch(hdev, &ver, info);
+		err = btusb_setup_qca_load_rampatch(hdev, fwname, &ver, info);
 		if (err < 0)
 			return err;
 	}
 
+	snprintf(fwname, sizeof(fwname), "qca/nvm_usb_%08x.bin",
+		 ver.rom_version);
+
 	if (!(status & QCA_SYSCFG_UPDATED)) {
-		err = btusb_setup_qca_load_nvm(hdev, &ver, info);
+		err = btusb_setup_qca_load_nvm(hdev, fwname, info);
 		if (err < 0)
 			return err;
 	}
-- 
2.14.1

[PATCH 2/2] Bluetooth: btusb: ath3k: Cache firmware for already patched Bluetooth chip

From: Kai-Heng Feng <hidden>
Date: 2017-08-24 09:06:46

When a system reboot, the USB power never gets cut off, so the firmware
is already updated on the Bluetooth chip.

Several btusb setup functions check firmware updated status before
download firmware, the loading part will be skipped if it's updated.
Because the firmware is never asked by request_firmware(),
firmware_class does not know it needs to be cached before system enters
sleep.

Now, system suspend/resume may cause the driver failed to request the
firmware because it's not in the firmware cache:

[   87.539434] firmware request while host is not available

This can be solved by calling request_firmware() even if the chip is
already updated - now the firmware_class knows what to cache.

In this case, we don't really need to wait for the firmware content, so
we use the async version of request_firmware().

Signed-off-by: Kai-Heng Feng <redacted>
---
 drivers/bluetooth/ath3k.c | 49 +++++++++++++++++++++++++++++++++++++++++
 drivers/bluetooth/btusb.c | 56 +++++++++++++++++++++++++++++++++++++++++++++--
 2 files changed, 103 insertions(+), 2 deletions(-)
diff --git a/drivers/bluetooth/ath3k.c b/drivers/bluetooth/ath3k.c
index 280849dba51e..27a7415f9fd7 100644
--- a/drivers/bluetooth/ath3k.c
+++ b/drivers/bluetooth/ath3k.c
@@ -208,6 +208,54 @@ static const struct usb_device_id ath3k_blist_tbl[] = {
 #define TIMEGAP_USEC_MIN	50
 #define TIMEGAP_USEC_MAX	100
 
+#ifdef CONFIG_PM_SLEEP
+static void ath3k_request_firmware_done(const struct firmware *firmware,
+					void *context)
+{
+	const char *name = (const char *)context;
+
+	if (!firmware) {
+		BT_WARN("firmware %s will not be cached", name);
+		goto done;
+	}
+
+	BT_DBG("firmware %s will be cached", name);
+
+	release_firmware(firmware);
+done:
+	kfree_const(name);
+}
+
+static int ath3k_request_firmware_async(struct usb_device *udev,
+					const char *fwname)
+{
+	const char *name;
+	int err;
+
+	name = kstrdup_const(fwname, GFP_KERNEL);
+	if (!name)
+		return -ENOMEM;
+
+	err = request_firmware_nowait(THIS_MODULE, true, name, &udev->dev,
+				      GFP_KERNEL, (void *)name,
+				      ath3k_request_firmware_done);
+	if (err) {
+		BT_WARN("%s %s: failed to async request firmware for file: %s (%d)",
+			udev->manufacturer, udev->product, name, err);
+		kfree_const(name);
+		return err;
+	}
+
+	return 0;
+}
+#else
+static int ath3k_request_firmware_async(struct usb_device *udev,
+					const char *fwname)
+{
+	return 0;
+}
+#endif
+
 static int ath3k_load_firmware(struct usb_device *udev,
 				const struct firmware *firmware)
 {
@@ -420,6 +468,7 @@ static int ath3k_load_patch(struct usb_device *udev)
 
 	if (fw_state & ATH3K_PATCH_UPDATE) {
 		BT_DBG("Patch was already downloaded");
+		ath3k_request_firmware_async(udev, filename);
 		return 0;
 	}
 
diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c
index 732fe6c3e789..7de2156debd8 100644
--- a/drivers/bluetooth/btusb.c
+++ b/drivers/bluetooth/btusb.c
@@ -1459,6 +1459,54 @@ static void btusb_waker(struct work_struct *work)
 	usb_autopm_put_interface(data->intf);
 }
 
+#ifdef CONFIG_PM_SLEEP
+static void btusb_request_firmware_done(const struct firmware *firmware,
+					void *context)
+{
+	const char *name = (const char *)context;
+
+	if (!firmware) {
+		BT_WARN("firmware %s will not be cached", name);
+		goto done;
+	}
+
+	BT_DBG("firmware %s will be cached", name);
+
+	release_firmware(firmware);
+done:
+	kfree_const(name);
+}
+
+static int btusb_request_firmware_async(struct hci_dev *hdev,
+					const char *fwname)
+{
+	const char *name;
+	int err;
+
+	name = kstrdup_const(fwname, GFP_KERNEL);
+	if (!name)
+		return -ENOMEM;
+
+	err = request_firmware_nowait(THIS_MODULE, true, name, &hdev->dev,
+				      GFP_KERNEL, (void *)name,
+				      btusb_request_firmware_done);
+	if (err) {
+		BT_WARN("%s: failed to async request firmware for file: %s (%d)",
+			hdev->name, name, err);
+		kfree_const(name);
+		return err;
+	}
+
+	return 0;
+}
+#else
+static int btusb_request_firmware_async(struct hci_dev *hdev,
+					const char *fwname)
+{
+	return 0;
+}
+#endif
+
 static int btusb_setup_bcm92035(struct hci_dev *hdev)
 {
 	struct sk_buff *skb;
@@ -1724,6 +1772,8 @@ static int btusb_setup_intel(struct hci_dev *hdev)
 	if (ver.fw_patch_num) {
 		BT_INFO("%s: Intel device is already patched. patch num: %02x",
 			hdev->name, ver.fw_patch_num);
+		btusb_request_firmware_async(hdev, fwname);
+		btusb_request_firmware_async(hdev, default_fwname);
 		goto complete;
 	}
 
@@ -2696,7 +2746,8 @@ static int btusb_setup_qca(struct hci_dev *hdev)
 		err = btusb_setup_qca_load_rampatch(hdev, fwname, &ver, info);
 		if (err < 0)
 			return err;
-	}
+	} else
+		btusb_request_firmware_async(hdev, fwname);
 
 	snprintf(fwname, sizeof(fwname), "qca/nvm_usb_%08x.bin",
 		 ver.rom_version);
@@ -2705,7 +2756,8 @@ static int btusb_setup_qca(struct hci_dev *hdev)
 		err = btusb_setup_qca_load_nvm(hdev, fwname, info);
 		if (err < 0)
 			return err;
-	}
+	} else
+		btusb_request_firmware_async(hdev, fwname);
 
 	return 0;
 }
-- 
2.14.1

Re: [PATCH 2/2] Bluetooth: btusb: ath3k: Cache firmware for already patched Bluetooth chip

From: Marcel Holtmann <marcel@holtmann.org>
Date: 2017-08-24 09:15:48

Hi Kai-Heng,
quoted hunk
When a system reboot, the USB power never gets cut off, so the firmware
is already updated on the Bluetooth chip.

Several btusb setup functions check firmware updated status before
download firmware, the loading part will be skipped if it's updated.
Because the firmware is never asked by request_firmware(),
firmware_class does not know it needs to be cached before system enters
sleep.

Now, system suspend/resume may cause the driver failed to request the
firmware because it's not in the firmware cache:

[   87.539434] firmware request while host is not available

This can be solved by calling request_firmware() even if the chip is
already updated - now the firmware_class knows what to cache.

In this case, we don't really need to wait for the firmware content, so
we use the async version of request_firmware().

Signed-off-by: Kai-Heng Feng <redacted>
---
drivers/bluetooth/ath3k.c | 49 +++++++++++++++++++++++++++++++++++++++++
drivers/bluetooth/btusb.c | 56 +++++++++++++++++++++++++++++++++++++++++++++--
2 files changed, 103 insertions(+), 2 deletions(-)
diff --git a/drivers/bluetooth/ath3k.c b/drivers/bluetooth/ath3k.c
index 280849dba51e..27a7415f9fd7 100644
--- a/drivers/bluetooth/ath3k.c
+++ b/drivers/bluetooth/ath3k.c
@@ -208,6 +208,54 @@ static const struct usb_device_id ath3k_blist_tbl[] = {
#define TIMEGAP_USEC_MIN	50
#define TIMEGAP_USEC_MAX	100

+#ifdef CONFIG_PM_SLEEP
+static void ath3k_request_firmware_done(const struct firmware *firmware,
+					void *context)
+{
+	const char *name = (const char *)context;
+
+	if (!firmware) {
+		BT_WARN("firmware %s will not be cached", name);
+		goto done;
+	}
+
+	BT_DBG("firmware %s will be cached", name);
+
+	release_firmware(firmware);
+done:
+	kfree_const(name);
+}
+
+static int ath3k_request_firmware_async(struct usb_device *udev,
+					const char *fwname)
+{
+	const char *name;
+	int err;
+
+	name = kstrdup_const(fwname, GFP_KERNEL);
+	if (!name)
+		return -ENOMEM;
+
+	err = request_firmware_nowait(THIS_MODULE, true, name, &udev->dev,
+				      GFP_KERNEL, (void *)name,
+				      ath3k_request_firmware_done);
+	if (err) {
+		BT_WARN("%s %s: failed to async request firmware for file: %s (%d)",
+			udev->manufacturer, udev->product, name, err);
+		kfree_const(name);
+		return err;
+	}
+
+	return 0;
+}
+#else
+static int ath3k_request_firmware_async(struct usb_device *udev,
+					const char *fwname)
+{
+	return 0;
+}
+#endif
+
static int ath3k_load_firmware(struct usb_device *udev,
				const struct firmware *firmware)
{
@@ -420,6 +468,7 @@ static int ath3k_load_patch(struct usb_device *udev)
	if (fw_state & ATH3K_PATCH_UPDATE) {
		BT_DBG("Patch was already downloaded");
+		ath3k_request_firmware_async(udev, filename);
		return 0;
	}
diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c
index 732fe6c3e789..7de2156debd8 100644
--- a/drivers/bluetooth/btusb.c
+++ b/drivers/bluetooth/btusb.c
@@ -1459,6 +1459,54 @@ static void btusb_waker(struct work_struct *work)
	usb_autopm_put_interface(data->intf);
}

+#ifdef CONFIG_PM_SLEEP
+static void btusb_request_firmware_done(const struct firmware *firmware,
+					void *context)
+{
+	const char *name = (const char *)context;
+
+	if (!firmware) {
+		BT_WARN("firmware %s will not be cached", name);
+		goto done;
+	}
+
+	BT_DBG("firmware %s will be cached", name);
+
+	release_firmware(firmware);
+done:
+	kfree_const(name);
+}
+
+static int btusb_request_firmware_async(struct hci_dev *hdev,
+					const char *fwname)
+{
+	const char *name;
+	int err;
+
+	name = kstrdup_const(fwname, GFP_KERNEL);
+	if (!name)
+		return -ENOMEM;
+
+	err = request_firmware_nowait(THIS_MODULE, true, name, &hdev->dev,
+				      GFP_KERNEL, (void *)name,
+				      btusb_request_firmware_done);
+	if (err) {
+		BT_WARN("%s: failed to async request firmware for file: %s (%d)",
+			hdev->name, name, err);
+		kfree_const(name);
+		return err;
+	}
+
+	return 0;
+}
+#else
+static int btusb_request_firmware_async(struct hci_dev *hdev,
+					const char *fwname)
+{
+	return 0;
+}
+#endif
+
static int btusb_setup_bcm92035(struct hci_dev *hdev)
{
	struct sk_buff *skb;
@@ -1724,6 +1772,8 @@ static int btusb_setup_intel(struct hci_dev *hdev)
	if (ver.fw_patch_num) {
		BT_INFO("%s: Intel device is already patched. patch num: %02x",
			hdev->name, ver.fw_patch_num);
+		btusb_request_firmware_async(hdev, fwname);
+		btusb_request_firmware_async(hdev, default_fwname);
		goto complete;
	}
I do not like intermixing of different vendors in a single patch.

Regards

Marcel

Re: [PATCH 2/2] Bluetooth: btusb: ath3k: Cache firmware for already patched Bluetooth chip

From: Kai-Heng Feng <hidden>
Date: 2017-08-24 09:33:45

On Thu, Aug 24, 2017 at 5:15 PM, Marcel Holtmann [off-list ref] wrote:
Hi Kai-Heng,
quoted
When a system reboot, the USB power never gets cut off, so the firmware
is already updated on the Bluetooth chip.

Several btusb setup functions check firmware updated status before
download firmware, the loading part will be skipped if it's updated.
Because the firmware is never asked by request_firmware(),
firmware_class does not know it needs to be cached before system enters
sleep.

Now, system suspend/resume may cause the driver failed to request the
firmware because it's not in the firmware cache:

[   87.539434] firmware request while host is not available

This can be solved by calling request_firmware() even if the chip is
already updated - now the firmware_class knows what to cache.

In this case, we don't really need to wait for the firmware content, so
we use the async version of request_firmware().

Signed-off-by: Kai-Heng Feng <redacted>
---
drivers/bluetooth/ath3k.c | 49 +++++++++++++++++++++++++++++++++++++++++
drivers/bluetooth/btusb.c | 56 +++++++++++++++++++++++++++++++++++++++++++++--
2 files changed, 103 insertions(+), 2 deletions(-)
diff --git a/drivers/bluetooth/ath3k.c b/drivers/bluetooth/ath3k.c
index 280849dba51e..27a7415f9fd7 100644
--- a/drivers/bluetooth/ath3k.c
+++ b/drivers/bluetooth/ath3k.c
@@ -208,6 +208,54 @@ static const struct usb_device_id ath3k_blist_tbl[] = {
#define TIMEGAP_USEC_MIN      50
#define TIMEGAP_USEC_MAX      100

+#ifdef CONFIG_PM_SLEEP
+static void ath3k_request_firmware_done(const struct firmware *firmware,
+                                     void *context)
+{
+     const char *name = (const char *)context;
+
+     if (!firmware) {
+             BT_WARN("firmware %s will not be cached", name);
+             goto done;
+     }
+
+     BT_DBG("firmware %s will be cached", name);
+
+     release_firmware(firmware);
+done:
+     kfree_const(name);
+}
+
+static int ath3k_request_firmware_async(struct usb_device *udev,
+                                     const char *fwname)
+{
+     const char *name;
+     int err;
+
+     name = kstrdup_const(fwname, GFP_KERNEL);
+     if (!name)
+             return -ENOMEM;
+
+     err = request_firmware_nowait(THIS_MODULE, true, name, &udev->dev,
+                                   GFP_KERNEL, (void *)name,
+                                   ath3k_request_firmware_done);
+     if (err) {
+             BT_WARN("%s %s: failed to async request firmware for file: %s (%d)",
+                     udev->manufacturer, udev->product, name, err);
+             kfree_const(name);
+             return err;
+     }
+
+     return 0;
+}
+#else
+static int ath3k_request_firmware_async(struct usb_device *udev,
+                                     const char *fwname)
+{
+     return 0;
+}
+#endif
+
static int ath3k_load_firmware(struct usb_device *udev,
                              const struct firmware *firmware)
{
@@ -420,6 +468,7 @@ static int ath3k_load_patch(struct usb_device *udev)

      if (fw_state & ATH3K_PATCH_UPDATE) {
              BT_DBG("Patch was already downloaded");
+             ath3k_request_firmware_async(udev, filename);
              return 0;
      }
diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c
index 732fe6c3e789..7de2156debd8 100644
--- a/drivers/bluetooth/btusb.c
+++ b/drivers/bluetooth/btusb.c
@@ -1459,6 +1459,54 @@ static void btusb_waker(struct work_struct *work)
      usb_autopm_put_interface(data->intf);
}

+#ifdef CONFIG_PM_SLEEP
+static void btusb_request_firmware_done(const struct firmware *firmware,
+                                     void *context)
+{
+     const char *name = (const char *)context;
+
+     if (!firmware) {
+             BT_WARN("firmware %s will not be cached", name);
+             goto done;
+     }
+
+     BT_DBG("firmware %s will be cached", name);
+
+     release_firmware(firmware);
+done:
+     kfree_const(name);
+}
+
+static int btusb_request_firmware_async(struct hci_dev *hdev,
+                                     const char *fwname)
+{
+     const char *name;
+     int err;
+
+     name = kstrdup_const(fwname, GFP_KERNEL);
+     if (!name)
+             return -ENOMEM;
+
+     err = request_firmware_nowait(THIS_MODULE, true, name, &hdev->dev,
+                                   GFP_KERNEL, (void *)name,
+                                   btusb_request_firmware_done);
+     if (err) {
+             BT_WARN("%s: failed to async request firmware for file: %s (%d)",
+                     hdev->name, name, err);
+             kfree_const(name);
+             return err;
+     }
+
+     return 0;
+}
+#else
+static int btusb_request_firmware_async(struct hci_dev *hdev,
+                                     const char *fwname)
+{
+     return 0;
+}
+#endif
+
static int btusb_setup_bcm92035(struct hci_dev *hdev)
{
      struct sk_buff *skb;
@@ -1724,6 +1772,8 @@ static int btusb_setup_intel(struct hci_dev *hdev)
      if (ver.fw_patch_num) {
              BT_INFO("%s: Intel device is already patched. patch num: %02x",
                      hdev->name, ver.fw_patch_num);
+             btusb_request_firmware_async(hdev, fwname);
+             btusb_request_firmware_async(hdev, default_fwname);
              goto complete;
      }
I do not like intermixing of different vendors in a single patch.
Thanks, I'll split them into Intel/QCA/ath3k patches.

Do you have any concern about the approach?
Regards

Marcel

Re: [PATCH 1/2] Bluetooth: btusb: ath3k: Decide firmware name before checking update status

From: Marcel Holtmann <marcel@holtmann.org>
Date: 2017-08-24 09:14:31

Hi Kai-Heng,
quoted hunk
Decide firmware name before checking patch update status. Firmware name is
required for caching.

Also, version information in btusb_setup_qca() is being calculated twice,
reduce it to one.

Signed-off-by: Kai-Heng Feng <redacted>
---
drivers/bluetooth/ath3k.c | 10 +++----
drivers/bluetooth/btusb.c | 72 +++++++++++++++++++++++------------------------
2 files changed, 41 insertions(+), 41 deletions(-)
diff --git a/drivers/bluetooth/ath3k.c b/drivers/bluetooth/ath3k.c
index b793853ff05f..280849dba51e 100644
--- a/drivers/bluetooth/ath3k.c
+++ b/drivers/bluetooth/ath3k.c
@@ -409,11 +409,6 @@ static int ath3k_load_patch(struct usb_device *udev)
		return ret;
	}

-	if (fw_state & ATH3K_PATCH_UPDATE) {
-		BT_DBG("Patch was already downloaded");
-		return 0;
-	}
-
	ret = ath3k_get_version(udev, &fw_version);
	if (ret < 0) {
		BT_ERR("Can't get version to change to load ram patch err");
@@ -423,6 +418,11 @@ static int ath3k_load_patch(struct usb_device *udev)
	snprintf(filename, ATH3K_NAME_LEN, "ar3k/AthrBT_0x%08x.dfu",
		 le32_to_cpu(fw_version.rom_version));

+	if (fw_state & ATH3K_PATCH_UPDATE) {
+		BT_DBG("Patch was already downloaded");
+		return 0;
+	}
+
	ret = request_firmware(&firmware, filename, &udev->dev);
	if (ret < 0) {
		BT_ERR("Patch file not found %s", filename);
diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c
index fa24d693af24..732fe6c3e789 100644
--- a/drivers/bluetooth/btusb.c
+++ b/drivers/bluetooth/btusb.c
@@ -1518,18 +1518,12 @@ static int btusb_setup_csr(struct hci_dev *hdev)
}

static const struct firmware *btusb_setup_intel_get_fw(struct hci_dev *hdev,
-						       struct intel_version *ver)
+						       const char *fwname,
+						       const char *default_fwname)
{
	const struct firmware *fw;
-	char fwname[64];
	int ret;

-	snprintf(fwname, sizeof(fwname),
-		 "intel/ibt-hw-%x.%x.%x-fw-%x.%x.%x.%x.%x.bseq",
-		 ver->hw_platform, ver->hw_variant, ver->hw_revision,
-		 ver->fw_variant,  ver->fw_revision, ver->fw_build_num,
-		 ver->fw_build_ww, ver->fw_build_yy);
-
	ret = request_firmware(&fw, fwname, &hdev->dev);
	if (ret < 0) {
		if (ret == -EINVAL) {
@@ -1544,11 +1538,9 @@ static const struct firmware *btusb_setup_intel_get_fw(struct hci_dev *hdev,
		/* If the correct firmware patch file is not found, use the
		 * default firmware patch file instead
		 */
-		snprintf(fwname, sizeof(fwname), "intel/ibt-hw-%x.%x.bseq",
-			 ver->hw_platform, ver->hw_variant);
-		if (request_firmware(&fw, fwname, &hdev->dev) < 0) {
+		if (request_firmware(&fw, default_fwname, &hdev->dev) < 0) {
			BT_ERR("%s failed to open default Intel fw file: %s",
-			       hdev->name, fwname);
+			       hdev->name, default_fwname);
			return NULL;
		}
	}
@@ -1676,6 +1668,8 @@ static int btusb_setup_intel_patching(struct hci_dev *hdev,
static int btusb_setup_intel(struct hci_dev *hdev)
{
	struct sk_buff *skb;
+	char fwname[64];
+	char default_fwname[64];
	const struct firmware *fw;
	const u8 *fw_ptr;
	int disable_patch, err;
@@ -1714,6 +1708,15 @@ static int btusb_setup_intel(struct hci_dev *hdev)
		ver.fw_variant,  ver.fw_revision, ver.fw_build_num,
		ver.fw_build_ww, ver.fw_build_yy, ver.fw_patch_num);

+	snprintf(fwname, sizeof(fwname),
+		 "intel/ibt-hw-%x.%x.%x-fw-%x.%x.%x.%x.%x.bseq",
+		 ver.hw_platform, ver.hw_variant, ver.hw_revision,
+		 ver.fw_variant,  ver.fw_revision, ver.fw_build_num,
+		 ver.fw_build_ww, ver.fw_build_yy);
+
+	snprintf(default_fwname, sizeof(default_fwname),
+		"intel/ibt-hw-%x.%x.bseq", ver.hw_platform, ver.hw_variant);
+
this doesn’t belong in this patch since it is about Intel hardware and not Qualcomm hardware. Split this out if it is needed.

Regards

Marcel
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help