lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Date:   Thu, 24 Aug 2017 11:15:45 +0200
From:   Marcel Holtmann <marcel@...tmann.org>
To:     Kai-Heng Feng <kai.heng.feng@...onical.com>
Cc:     "Gustavo F. Padovan" <gustavo@...ovan.org>,
        Johan Hedberg <johan.hedberg@...il.com>,
        linux-bluetooth@...r.kernel.org, linux-kernel@...r.kernel.org
Subject: Re: [PATCH 2/2] Bluetooth: btusb: ath3k: Cache firmware for already
 patched Bluetooth chip

Hi Kai-Heng,

> 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 <kai.heng.feng@...onical.com>
> ---
> 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

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ