2018-01-24 03:17:45

by Tedd Ho-Jeong An

[permalink] [raw]
Subject: [PATCH 1/5] Bluetooth: hci_intel: Update firmware filename for Intel 9x60 and later

The format of Intel Bluetooth firmware for bootloader product is
ibt-<hw_variant>-<device_revision_id>.sfi and .ddc.

But for the 9x60 SKU, there are three variants of FW, which cannot be
differenticate just with hw_variant and device_revision_id.
So, to pick the appropriate FW file for 9x60 SKU, three fields,
hw_variant, hw_revision, and fw_revision, needs to be used rather than
hw_variant and device_revision_id.

Format will be like this:
ibt-<hw_variant>-<hw_revision>-<fw_revision>.sfi and .ddc

Signed-off-by: Tedd Ho-Jeong An <[email protected]>
---
drivers/bluetooth/hci_intel.c | 56 +++++++++++++++++++++++++++++++++++++------
1 file changed, 49 insertions(+), 7 deletions(-)

diff --git a/drivers/bluetooth/hci_intel.c b/drivers/bluetooth/hci_intel.c
index aad07e4..9758684 100644
--- a/drivers/bluetooth/hci_intel.c
+++ b/drivers/bluetooth/hci_intel.c
@@ -708,16 +708,43 @@ static int intel_setup(struct hci_uart *hu)
}

/* With this Intel bootloader only the hardware variant and device
- * revision information are used to select the right firmware.
+ * revision information are used to select the right firmware for SfP
+ * and WsP.
*
* The firmware filename is ibt-<hw_variant>-<dev_revid>.sfi.
*
* Currently the supported hardware variants are:
* 11 (0x0b) for iBT 3.0 (LnP/SfP)
+ * 12 (0x0c) for iBT 3.5 (WsP)
+ *
+ * For ThP/JfP and for future SKU's, the FW name varies based on HW
+ * variant, HW revision and FW revision, as these are dependent on CNVi
+ * and RF Combination.
+ *
+ * 18 (0x12) for iBT3.5 (ThP/JfP)
+ *
+ * The firmware file name for these will be
+ * ibt-<hw_variant>-<hw_revision>-<fw_revision>.sfi.
+ *
*/
- snprintf(fwname, sizeof(fwname), "intel/ibt-%u-%u.sfi",
- le16_to_cpu(ver.hw_variant),
- le16_to_cpu(params->dev_revid));
+ switch (ver.hw_variant) {
+ case 0x0b: /* SfP */
+ case 0x0c: /* WsP */
+ snprintf(fwname, sizeof(fwname), "intel/ibt-%u-%u.sfi",
+ le16_to_cpu(ver.hw_variant),
+ le16_to_cpu(params->dev_revid));
+ break;
+ case 0x12: /* ThP */
+ snprintf(fwname, sizeof(fwname), "intel/ibt-%u-%u-%u.sfi",
+ le16_to_cpu(ver.hw_variant),
+ le16_to_cpu(ver.hw_revision),
+ le16_to_cpu(ver.fw_revision));
+ break;
+ default:
+ bt_dev_err(hdev, "Unsupported Intel hardware variant (%u)",
+ ver.hw_variant);
+ return -EINVAL;
+ }

err = request_firmware(&fw, fwname, &hdev->dev);
if (err < 0) {
@@ -730,9 +757,24 @@ static int intel_setup(struct hci_uart *hu)
bt_dev_info(hdev, "Found device firmware: %s", fwname);

/* Save the DDC file name for later */
- snprintf(fwname, sizeof(fwname), "intel/ibt-%u-%u.ddc",
- le16_to_cpu(ver.hw_variant),
- le16_to_cpu(params->dev_revid));
+ switch (ver.hw_variant) {
+ case 0x0b: /* SfP */
+ case 0x0c: /* WsP */
+ snprintf(fwname, sizeof(fwname), "intel/ibt-%u-%u.ddc",
+ le16_to_cpu(ver.hw_variant),
+ le16_to_cpu(params->dev_revid));
+ break;
+ case 0x12: /* ThP */
+ snprintf(fwname, sizeof(fwname), "intel/ibt-%u-%u-%u.ddc",
+ le16_to_cpu(ver.hw_variant),
+ le16_to_cpu(ver.hw_revision),
+ le16_to_cpu(ver.fw_revision));
+ break;
+ default:
+ bt_dev_err(hdev, "Unsupported Intel hardware variant (%u)",
+ ver.hw_variant);
+ return -EINVAL;
+ }

kfree_skb(skb);

--
2.7.4



2018-01-24 07:34:50

by Marcel Holtmann

[permalink] [raw]
Subject: Re: [PATCH 2/5] Bluetooth: btintel: Create common function for Intel Reset

Hi Tedd,

> The Intel_Reset command is used to reset the device after downloading
> the firmware and this is Intel generic command used in both USB and
> UART.
>
> Signed-off-by: Tedd Ho-Jeong An <[email protected]>
> ---
> drivers/bluetooth/btintel.c | 20 ++++++++++++++++++++
> drivers/bluetooth/btintel.h | 15 +++++++++++++++
> drivers/bluetooth/btusb.c | 15 +++++++--------
> drivers/bluetooth/hci_intel.c | 15 +++++++--------
> 4 files changed, 49 insertions(+), 16 deletions(-)
>
> diff --git a/drivers/bluetooth/btintel.c b/drivers/bluetooth/btintel.c
> index 07f00e4..067df4e 100644
> --- a/drivers/bluetooth/btintel.c
> +++ b/drivers/bluetooth/btintel.c
> @@ -569,6 +569,26 @@ struct regmap *btintel_regmap_init(struct hci_dev *hdev, u16 opcode_read,
> }
> EXPORT_SYMBOL_GPL(btintel_regmap_init);
>
> +int btintel_send_intel_reset(struct hci_dev *hdev, u32 boot_param)
> +{
> + struct sk_buff *skb;
> + struct intel_reset params = { 0x00, 0x01, 0x00, 0x01, 0x00000000 };

flip these two around please.

> +
> + params.boot_param = cpu_to_le32(boot_param);
> +
> + skb = __hci_cmd_sync(hdev, 0xfc01, sizeof(params), &params,
> + HCI_INIT_TIMEOUT);
> + if (IS_ERR(skb)) {
> + bt_dev_err(hdev, "Failed to send Intel Reset command");
> + return PTR_ERR(skb);
> + }
> +
> + kfree_skb(skb);
> +
> + return 0;
> +}
> +EXPORT_SYMBOL_GPL(btintel_send_intel_reset);
> +
> MODULE_AUTHOR("Marcel Holtmann <[email protected]>");
> MODULE_DESCRIPTION("Bluetooth support for Intel devices ver " VERSION);
> MODULE_VERSION(VERSION);
> diff --git a/drivers/bluetooth/btintel.h b/drivers/bluetooth/btintel.h
> index 1e8955a..3ef2db7 100644
> --- a/drivers/bluetooth/btintel.h
> +++ b/drivers/bluetooth/btintel.h
> @@ -69,6 +69,14 @@ struct intel_secure_send_result {
> __u8 status;
> } __packed;
>
> +struct intel_reset {
> + __u8 reset_type;
> + __u8 patch_enable;
> + __u8 ddc_reload;
> + __u8 boot_option;
> + __u32 boot_param;

And this has to be __le32 btw.

> +} __packed;
> +
> #if IS_ENABLED(CONFIG_BT_INTEL)
>
> int btintel_check_bdaddr(struct hci_dev *hdev);
> @@ -89,6 +97,7 @@ int btintel_read_version(struct hci_dev *hdev, struct intel_version *ver);
>
> struct regmap *btintel_regmap_init(struct hci_dev *hdev, u16 opcode_read,
> u16 opcode_write);
> +int btintel_send_intel_reset(struct hci_dev *hdev, u32 boot_param);
>
> #else
>
> @@ -165,4 +174,10 @@ static inline struct regmap *btintel_regmap_init(struct hci_dev *hdev,
> {
> return ERR_PTR(-EINVAL);
> }
> +
> +static inline int btintel_send_intel_reset(struct hci_dev *hdev,
> + u32 reset_param)
> +{
> + return -EOPNOTSUPP;
> +}
> #endif
> diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c
> index 29977eb..93db5b9 100644
> --- a/drivers/bluetooth/btusb.c
> +++ b/drivers/bluetooth/btusb.c
> @@ -2009,8 +2009,6 @@ static int btusb_send_frame_intel(struct hci_dev *hdev, struct sk_buff *skb)
>
> static int btusb_setup_intel_new(struct hci_dev *hdev)
> {
> - static const u8 reset_param[] = { 0x00, 0x01, 0x00, 0x01,
> - 0x00, 0x08, 0x04, 0x00 };
> struct btusb_data *data = hci_get_drvdata(hdev);
> struct sk_buff *skb;
> struct intel_version ver;
> @@ -2018,6 +2016,7 @@ static int btusb_setup_intel_new(struct hci_dev *hdev)
> const struct firmware *fw;
> const u8 *fw_ptr;
> u32 frag_len;
> + u32 boot_param;
> char fwname[64];
> ktime_t calltime, delta, rettime;
> unsigned long long duration;
> @@ -2025,6 +2024,9 @@ static int btusb_setup_intel_new(struct hci_dev *hdev)
>
> BT_DBG("%s", hdev->name);
>
> + /* The default boot parameter */
> + boot_param = 0x00040800;
> +
> calltime = ktime_get();
>
> /* Read the Intel version information to determine if the device
> @@ -2341,12 +2343,9 @@ static int btusb_setup_intel_new(struct hci_dev *hdev)
>
> set_bit(BTUSB_BOOTING, &data->flags);
>
> - skb = __hci_cmd_sync(hdev, 0xfc01, sizeof(reset_param), reset_param,
> - HCI_INIT_TIMEOUT);
> - if (IS_ERR(skb))
> - return PTR_ERR(skb);
> -
> - kfree_skb(skb);
> + err = btintel_send_intel_reset(hdev, boot_param);
> + if (err)
> + return err;
>
> /* The bootloader will not indicate when the device is ready. This
> * is done by the operational firmware sending bootup notification.
> diff --git a/drivers/bluetooth/hci_intel.c b/drivers/bluetooth/hci_intel.c
> index 9758684..acac48d 100644
> --- a/drivers/bluetooth/hci_intel.c
> +++ b/drivers/bluetooth/hci_intel.c
> @@ -540,8 +540,6 @@ static int intel_set_baudrate(struct hci_uart *hu, unsigned int speed)
>
> static int intel_setup(struct hci_uart *hu)
> {
> - static const u8 reset_param[] = { 0x00, 0x01, 0x00, 0x01,
> - 0x00, 0x08, 0x04, 0x00 };
> struct intel_data *intel = hu->priv;
> struct hci_dev *hdev = hu->hdev;
> struct sk_buff *skb;
> @@ -552,6 +550,7 @@ static int intel_setup(struct hci_uart *hu)
> const u8 *fw_ptr;
> char fwname[64];
> u32 frag_len;
> + u32 boot_param;
> ktime_t calltime, delta, rettime;
> unsigned long long duration;
> unsigned int init_speed, oper_speed;
> @@ -563,6 +562,9 @@ static int intel_setup(struct hci_uart *hu)
> hu->hdev->set_diag = btintel_set_diag;
> hu->hdev->set_bdaddr = btintel_set_bdaddr;
>
> + /* Default boot parameter */
> + boot_param = 0x00040800;
> +
> calltime = ktime_get();
>
> if (hu->init_speed)
> @@ -911,12 +913,9 @@ static int intel_setup(struct hci_uart *hu)
>
> set_bit(STATE_BOOTING, &intel->flags);
>
> - skb = __hci_cmd_sync(hdev, 0xfc01, sizeof(reset_param), reset_param,
> - HCI_CMD_TIMEOUT);
> - if (IS_ERR(skb))
> - return PTR_ERR(skb);
> -
> - kfree_skb(skb);
> + err = btintel_send_intel_reset(hdev, boot_param);
> + if (err)
> + return err;
>
> /* The bootloader will not indicate when the device is ready. This
> * is done by the operational firmware sending bootup notification.

Regards

Marcel


2018-01-24 07:34:47

by Marcel Holtmann

[permalink] [raw]
Subject: Re: [PATCH 3/5] Bluetooth: btintel: Use boot parameter from firmware file

Hi Tedd,

> Each RAM SKU has a different boot parameter which is used in
> HCI_Intel_Reset command after downloading the firmware.
> The boot parameter is embedded in the firmware data and to support
> multiple SKUs, driver reads the boot parameter while downloading
> the firmware instead of using static values per SKU.
>
> Signed-off-by: Tedd Ho-Jeong An <[email protected]>
> ---
> drivers/bluetooth/btusb.c | 22 ++++++++++++++++++++--
> drivers/bluetooth/hci_intel.c | 23 +++++++++++++++++++++--
> 2 files changed, 41 insertions(+), 4 deletions(-)
>
> diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c
> index 93db5b9..979d530 100644
> --- a/drivers/bluetooth/btusb.c
> +++ b/drivers/bluetooth/btusb.c
> @@ -2024,8 +2024,11 @@ static int btusb_setup_intel_new(struct hci_dev *hdev)
>
> BT_DBG("%s", hdev->name);
>
> - /* The default boot parameter */
> - boot_param = 0x00040800;
> + /* Set the default boot parameter to 0x0 and it is updated to
> + * SKU specific boot parameter after reading Intel_Write_Boot_Params
> + * command while downloading the firmware.
> + */
> + boot_param = 0x00000000;
>
> calltime = ktime_get();
>
> @@ -2269,6 +2272,21 @@ static int btusb_setup_intel_new(struct hci_dev *hdev)
> while (fw_ptr - fw->data < fw->size) {
> struct hci_command_hdr *cmd = (void *)(fw_ptr + frag_len);
>
> + /* Each SKU has a different reset parameter to use in the
> + * HCI_Intel_Reset command and it is embedded in the firmware
> + * data. So, instead of using static value per SKU, check
> + * the firmware data and save it for later use.
> + */
> + if (cmd->opcode == 0xfc0e) {
> +

scrap this empty line here.

> + /* The boot parameter is the first 32-bit value
> + * and rest of 3 octets are reserved.
> + */
> + boot_param = get_unaligned_le32(fw_ptr + sizeof(*cmd));
> +
> + bt_dev_dbg(hdev, "boot_param=0x%x", boot_param);
> + }
> +
> frag_len += sizeof(*cmd) + cmd->plen;
>
> /* The parameter length of the secure send command requires
> diff --git a/drivers/bluetooth/hci_intel.c b/drivers/bluetooth/hci_intel.c
> index acac48d..2053d73 100644
> --- a/drivers/bluetooth/hci_intel.c
> +++ b/drivers/bluetooth/hci_intel.c
> @@ -33,6 +33,7 @@
> #include <linux/acpi.h>
> #include <linux/interrupt.h>
> #include <linux/pm_runtime.h>
> +#include <asm/unaligned.h>
>
> #include <net/bluetooth/bluetooth.h>
> #include <net/bluetooth/hci_core.h>
> @@ -562,8 +563,11 @@ static int intel_setup(struct hci_uart *hu)
> hu->hdev->set_diag = btintel_set_diag;
> hu->hdev->set_bdaddr = btintel_set_bdaddr;
>
> - /* Default boot parameter */
> - boot_param = 0x00040800;
> + /* Set the default boot parameter to 0x0 and it is updated to
> + * SKU specific boot parameter after reading Intel_Write_Boot_Params
> + * command while downloading the firmware.
> + */
> + boot_param = 0x00000000;
>
> calltime = ktime_get();
>
> @@ -824,6 +828,21 @@ static int intel_setup(struct hci_uart *hu)
> while (fw_ptr - fw->data < fw->size) {
> struct hci_command_hdr *cmd = (void *)(fw_ptr + frag_len);
>
> + /* Each SKU has a different reset parameter to use in the
> + * HCI_Intel_Reset command and it is embedded in the firmware
> + * data. So, instead of using static value per SKU, check
> + * the firmware data and save it for later use.
> + */
> + if (cmd->opcode == 0xfc0e) {
> +

Same here. Remove this empty line.

> + /* The boot parameter is the first 32-bit value
> + * and rest of 3 octets are reserved.
> + */
> + boot_param = get_unaligned_le32(fw_ptr + sizeof(*cmd));
> +
> + bt_dev_dbg(hdev, "boot_param=0x%x", boot_param);
> + }
> +
> frag_len += sizeof(*cmd) + cmd->plen;
>
> bt_dev_dbg(hdev, "Patching %td/%zu", (fw_ptr - fw->data),

Regards

Marcel


2018-01-24 03:17:46

by Tedd Ho-Jeong An

[permalink] [raw]
Subject: [PATCH 2/5] Bluetooth: btintel: Create common function for Intel Reset

The Intel_Reset command is used to reset the device after downloading
the firmware and this is Intel generic command used in both USB and
UART.

Signed-off-by: Tedd Ho-Jeong An <[email protected]>
---
drivers/bluetooth/btintel.c | 20 ++++++++++++++++++++
drivers/bluetooth/btintel.h | 15 +++++++++++++++
drivers/bluetooth/btusb.c | 15 +++++++--------
drivers/bluetooth/hci_intel.c | 15 +++++++--------
4 files changed, 49 insertions(+), 16 deletions(-)

diff --git a/drivers/bluetooth/btintel.c b/drivers/bluetooth/btintel.c
index 07f00e4..067df4e 100644
--- a/drivers/bluetooth/btintel.c
+++ b/drivers/bluetooth/btintel.c
@@ -569,6 +569,26 @@ struct regmap *btintel_regmap_init(struct hci_dev *hdev, u16 opcode_read,
}
EXPORT_SYMBOL_GPL(btintel_regmap_init);

+int btintel_send_intel_reset(struct hci_dev *hdev, u32 boot_param)
+{
+ struct sk_buff *skb;
+ struct intel_reset params = { 0x00, 0x01, 0x00, 0x01, 0x00000000 };
+
+ params.boot_param = cpu_to_le32(boot_param);
+
+ skb = __hci_cmd_sync(hdev, 0xfc01, sizeof(params), &params,
+ HCI_INIT_TIMEOUT);
+ if (IS_ERR(skb)) {
+ bt_dev_err(hdev, "Failed to send Intel Reset command");
+ return PTR_ERR(skb);
+ }
+
+ kfree_skb(skb);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(btintel_send_intel_reset);
+
MODULE_AUTHOR("Marcel Holtmann <[email protected]>");
MODULE_DESCRIPTION("Bluetooth support for Intel devices ver " VERSION);
MODULE_VERSION(VERSION);
diff --git a/drivers/bluetooth/btintel.h b/drivers/bluetooth/btintel.h
index 1e8955a..3ef2db7 100644
--- a/drivers/bluetooth/btintel.h
+++ b/drivers/bluetooth/btintel.h
@@ -69,6 +69,14 @@ struct intel_secure_send_result {
__u8 status;
} __packed;

+struct intel_reset {
+ __u8 reset_type;
+ __u8 patch_enable;
+ __u8 ddc_reload;
+ __u8 boot_option;
+ __u32 boot_param;
+} __packed;
+
#if IS_ENABLED(CONFIG_BT_INTEL)

int btintel_check_bdaddr(struct hci_dev *hdev);
@@ -89,6 +97,7 @@ int btintel_read_version(struct hci_dev *hdev, struct intel_version *ver);

struct regmap *btintel_regmap_init(struct hci_dev *hdev, u16 opcode_read,
u16 opcode_write);
+int btintel_send_intel_reset(struct hci_dev *hdev, u32 boot_param);

#else

@@ -165,4 +174,10 @@ static inline struct regmap *btintel_regmap_init(struct hci_dev *hdev,
{
return ERR_PTR(-EINVAL);
}
+
+static inline int btintel_send_intel_reset(struct hci_dev *hdev,
+ u32 reset_param)
+{
+ return -EOPNOTSUPP;
+}
#endif
diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c
index 29977eb..93db5b9 100644
--- a/drivers/bluetooth/btusb.c
+++ b/drivers/bluetooth/btusb.c
@@ -2009,8 +2009,6 @@ static int btusb_send_frame_intel(struct hci_dev *hdev, struct sk_buff *skb)

static int btusb_setup_intel_new(struct hci_dev *hdev)
{
- static const u8 reset_param[] = { 0x00, 0x01, 0x00, 0x01,
- 0x00, 0x08, 0x04, 0x00 };
struct btusb_data *data = hci_get_drvdata(hdev);
struct sk_buff *skb;
struct intel_version ver;
@@ -2018,6 +2016,7 @@ static int btusb_setup_intel_new(struct hci_dev *hdev)
const struct firmware *fw;
const u8 *fw_ptr;
u32 frag_len;
+ u32 boot_param;
char fwname[64];
ktime_t calltime, delta, rettime;
unsigned long long duration;
@@ -2025,6 +2024,9 @@ static int btusb_setup_intel_new(struct hci_dev *hdev)

BT_DBG("%s", hdev->name);

+ /* The default boot parameter */
+ boot_param = 0x00040800;
+
calltime = ktime_get();

/* Read the Intel version information to determine if the device
@@ -2341,12 +2343,9 @@ static int btusb_setup_intel_new(struct hci_dev *hdev)

set_bit(BTUSB_BOOTING, &data->flags);

- skb = __hci_cmd_sync(hdev, 0xfc01, sizeof(reset_param), reset_param,
- HCI_INIT_TIMEOUT);
- if (IS_ERR(skb))
- return PTR_ERR(skb);
-
- kfree_skb(skb);
+ err = btintel_send_intel_reset(hdev, boot_param);
+ if (err)
+ return err;

/* The bootloader will not indicate when the device is ready. This
* is done by the operational firmware sending bootup notification.
diff --git a/drivers/bluetooth/hci_intel.c b/drivers/bluetooth/hci_intel.c
index 9758684..acac48d 100644
--- a/drivers/bluetooth/hci_intel.c
+++ b/drivers/bluetooth/hci_intel.c
@@ -540,8 +540,6 @@ static int intel_set_baudrate(struct hci_uart *hu, unsigned int speed)

static int intel_setup(struct hci_uart *hu)
{
- static const u8 reset_param[] = { 0x00, 0x01, 0x00, 0x01,
- 0x00, 0x08, 0x04, 0x00 };
struct intel_data *intel = hu->priv;
struct hci_dev *hdev = hu->hdev;
struct sk_buff *skb;
@@ -552,6 +550,7 @@ static int intel_setup(struct hci_uart *hu)
const u8 *fw_ptr;
char fwname[64];
u32 frag_len;
+ u32 boot_param;
ktime_t calltime, delta, rettime;
unsigned long long duration;
unsigned int init_speed, oper_speed;
@@ -563,6 +562,9 @@ static int intel_setup(struct hci_uart *hu)
hu->hdev->set_diag = btintel_set_diag;
hu->hdev->set_bdaddr = btintel_set_bdaddr;

+ /* Default boot parameter */
+ boot_param = 0x00040800;
+
calltime = ktime_get();

if (hu->init_speed)
@@ -911,12 +913,9 @@ static int intel_setup(struct hci_uart *hu)

set_bit(STATE_BOOTING, &intel->flags);

- skb = __hci_cmd_sync(hdev, 0xfc01, sizeof(reset_param), reset_param,
- HCI_CMD_TIMEOUT);
- if (IS_ERR(skb))
- return PTR_ERR(skb);
-
- kfree_skb(skb);
+ err = btintel_send_intel_reset(hdev, boot_param);
+ if (err)
+ return err;

/* The bootloader will not indicate when the device is ready. This
* is done by the operational firmware sending bootup notification.
--
2.7.4


2018-01-24 03:17:49

by Tedd Ho-Jeong An

[permalink] [raw]
Subject: [PATCH 5/5] Bluetooth: btintel: Create common function for firmware download

The firmware download flow for RAM SKU is same for both USB and UART
and this patch creates a common function for both driver.

Signed-off-by: Tedd Ho-Jeong An <[email protected]>
---
drivers/bluetooth/btintel.c | 85 +++++++++++++++++++++++++++++++++++++++++++
drivers/bluetooth/btintel.h | 10 ++++-
drivers/bluetooth/btusb.c | 77 ++-------------------------------------
drivers/bluetooth/hci_intel.c | 84 ++----------------------------------------
4 files changed, 100 insertions(+), 156 deletions(-)

diff --git a/drivers/bluetooth/btintel.c b/drivers/bluetooth/btintel.c
index 46f0e3e..81c39e3 100644
--- a/drivers/bluetooth/btintel.c
+++ b/drivers/bluetooth/btintel.c
@@ -24,6 +24,7 @@
#include <linux/module.h>
#include <linux/firmware.h>
#include <linux/regmap.h>
+#include <asm/unaligned.h>

#include <net/bluetooth/bluetooth.h>
#include <net/bluetooth/hci_core.h>
@@ -640,6 +641,90 @@ int btintel_read_boot_params(struct hci_dev *hdev,
}
EXPORT_SYMBOL_GPL(btintel_read_boot_params);

+int btintel_download_firmware(struct hci_dev *hdev, const struct firmware *fw,
+ u32 *boot_param)
+{
+ int err;
+ const u8 *fw_ptr;
+ u32 frag_len;
+
+ /* Start the firmware download transaction with the Init fragment
+ * represented by the 128 bytes of CSS header.
+ */
+ err = btintel_secure_send(hdev, 0x00, 128, fw->data);
+ if (err < 0) {
+ bt_dev_err(hdev, "Failed to send firmware header (%d)", err);
+ goto done;
+ }
+
+ /* Send the 256 bytes of public key information from the firmware
+ * as the PKey fragment.
+ */
+ err = btintel_secure_send(hdev, 0x03, 256, fw->data + 128);
+ if (err < 0) {
+ bt_dev_err(hdev, "Failed to send firmware pkey (%d)", err);
+ goto done;
+ }
+
+ /* Send the 256 bytes of signature information from the firmware
+ * as the Sign fragment.
+ */
+ err = btintel_secure_send(hdev, 0x02, 256, fw->data + 388);
+ if (err < 0) {
+ bt_dev_err(hdev, "Failed to send firmware signature (%d)", err);
+ goto done;
+ }
+
+ fw_ptr = fw->data + 644;
+ frag_len = 0;
+
+ while (fw_ptr - fw->data < fw->size) {
+ struct hci_command_hdr *cmd = (void *)(fw_ptr + frag_len);
+
+ /* Each SKU has a different reset parameter to use in the
+ * HCI_Intel_Reset command and it is embedded in the firmware
+ * data. So, instead of using static value per SKU, check
+ * the firmware data and save it for later use.
+ */
+ if (cmd->opcode == 0xfc0e) {
+
+ /* The boot parameter is the first 32-bit value
+ * and rest of 3 octets are reserved.
+ */
+ *boot_param = get_unaligned_le32(fw_ptr + sizeof(*cmd));
+
+ bt_dev_dbg(hdev, "boot_param=0x%x", *boot_param);
+ }
+
+ frag_len += sizeof(*cmd) + cmd->plen;
+
+ /* The parameter length of the secure send command requires
+ * a 4 byte alignment. It happens so that the firmware file
+ * contains proper Intel_NOP commands to align the fragments
+ * as needed.
+ *
+ * Send set of commands with 4 byte alignment from the
+ * firmware data buffer as a single Data fragement.
+ */
+ if (!(frag_len % 4)) {
+ err = btintel_secure_send(hdev, 0x01, frag_len, fw_ptr);
+ if (err < 0) {
+ bt_dev_err(hdev,
+ "Failed to send firmware data (%d)",
+ err);
+ goto done;
+ }
+
+ fw_ptr += frag_len;
+ frag_len = 0;
+ }
+ }
+
+done:
+ return err;
+}
+EXPORT_SYMBOL_GPL(btintel_download_firmware);
+
MODULE_AUTHOR("Marcel Holtmann <[email protected]>");
MODULE_DESCRIPTION("Bluetooth support for Intel devices ver " VERSION);
MODULE_VERSION(VERSION);
diff --git a/drivers/bluetooth/btintel.h b/drivers/bluetooth/btintel.h
index 28727b2..d2f355b 100644
--- a/drivers/bluetooth/btintel.h
+++ b/drivers/bluetooth/btintel.h
@@ -100,7 +100,8 @@ struct regmap *btintel_regmap_init(struct hci_dev *hdev, u16 opcode_read,
int btintel_send_intel_reset(struct hci_dev *hdev, u32 boot_param);
int btintel_read_boot_params(struct hci_dev *hdev,
struct intel_boot_params *params);
-
+int btintel_download_firmware(struct hci_dev *dev, const struct firmware *fw,
+ u32 *boot_param);
#else

static inline int btintel_check_bdaddr(struct hci_dev *hdev)
@@ -188,4 +189,11 @@ static inline int btintel_read_boot_params(struct hci_dev *hdev,
{
return -EOPNOTSUPP;
}
+
+static inline int btintel_download_firmware(struct hci_dev *dev,
+ const struct firmware *fw,
+ u32 *boot_param);
+{
+ return -EOPNOTSUPP;
+}
#endif
diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c
index 808c245..2a55380 100644
--- a/drivers/bluetooth/btusb.c
+++ b/drivers/bluetooth/btusb.c
@@ -2013,8 +2013,6 @@ static int btusb_setup_intel_new(struct hci_dev *hdev)
struct intel_version ver;
struct intel_boot_params params;
const struct firmware *fw;
- const u8 *fw_ptr;
- u32 frag_len;
u32 boot_param;
char fwname[64];
ktime_t calltime, delta, rettime;
@@ -2201,79 +2199,10 @@ static int btusb_setup_intel_new(struct hci_dev *hdev)

set_bit(BTUSB_DOWNLOADING, &data->flags);

- /* Start the firmware download transaction with the Init fragment
- * represented by the 128 bytes of CSS header.
- */
- err = btintel_secure_send(hdev, 0x00, 128, fw->data);
- if (err < 0) {
- BT_ERR("%s: Failed to send firmware header (%d)",
- hdev->name, err);
- goto done;
- }
-
- /* Send the 256 bytes of public key information from the firmware
- * as the PKey fragment.
- */
- err = btintel_secure_send(hdev, 0x03, 256, fw->data + 128);
- if (err < 0) {
- BT_ERR("%s: Failed to send firmware public key (%d)",
- hdev->name, err);
- goto done;
- }
-
- /* Send the 256 bytes of signature information from the firmware
- * as the Sign fragment.
- */
- err = btintel_secure_send(hdev, 0x02, 256, fw->data + 388);
- if (err < 0) {
- BT_ERR("%s: Failed to send firmware signature (%d)",
- hdev->name, err);
+ /* Start firmware downloading and get boot parameter */
+ err = btintel_download_firmware(hdev, fw, &boot_param);
+ if (err < 0)
goto done;
- }
-
- fw_ptr = fw->data + 644;
- frag_len = 0;
-
- while (fw_ptr - fw->data < fw->size) {
- struct hci_command_hdr *cmd = (void *)(fw_ptr + frag_len);
-
- /* Each SKU has a different reset parameter to use in the
- * HCI_Intel_Reset command and it is embedded in the firmware
- * data. So, instead of using static value per SKU, check
- * the firmware data and save it for later use.
- */
- if (cmd->opcode == 0xfc0e) {
-
- /* The boot parameter is the first 32-bit value
- * and rest of 3 octets are reserved.
- */
- boot_param = get_unaligned_le32(fw_ptr + sizeof(*cmd));
-
- bt_dev_dbg(hdev, "boot_param=0x%x", boot_param);
- }
-
- frag_len += sizeof(*cmd) + cmd->plen;
-
- /* The parameter length of the secure send command requires
- * a 4 byte alignment. It happens so that the firmware file
- * contains proper Intel_NOP commands to align the fragments
- * as needed.
- *
- * Send set of commands with 4 byte alignment from the
- * firmware data buffer as a single Data fragement.
- */
- if (!(frag_len % 4)) {
- err = btintel_secure_send(hdev, 0x01, frag_len, fw_ptr);
- if (err < 0) {
- BT_ERR("%s: Failed to send firmware data (%d)",
- hdev->name, err);
- goto done;
- }
-
- fw_ptr += frag_len;
- frag_len = 0;
- }
- }

set_bit(BTUSB_FIRMWARE_LOADED, &data->flags);

diff --git a/drivers/bluetooth/hci_intel.c b/drivers/bluetooth/hci_intel.c
index f83b9da..7c166e3 100644
--- a/drivers/bluetooth/hci_intel.c
+++ b/drivers/bluetooth/hci_intel.c
@@ -33,7 +33,6 @@
#include <linux/acpi.h>
#include <linux/interrupt.h>
#include <linux/pm_runtime.h>
-#include <asm/unaligned.h>

#include <net/bluetooth/bluetooth.h>
#include <net/bluetooth/hci_core.h>
@@ -548,9 +547,7 @@ static int intel_setup(struct hci_uart *hu)
struct intel_boot_params params;
struct list_head *p;
const struct firmware *fw;
- const u8 *fw_ptr;
char fwname[64];
- u32 frag_len;
u32 boot_param;
ktime_t calltime, delta, rettime;
unsigned long long duration;
@@ -761,85 +758,10 @@ static int intel_setup(struct hci_uart *hu)

set_bit(STATE_DOWNLOADING, &intel->flags);

- /* Start the firmware download transaction with the Init fragment
- * represented by the 128 bytes of CSS header.
- */
- err = btintel_secure_send(hdev, 0x00, 128, fw->data);
- if (err < 0) {
- bt_dev_err(hdev, "Failed to send firmware header (%d)", err);
- goto done;
- }
-
- /* Send the 256 bytes of public key information from the firmware
- * as the PKey fragment.
- */
- err = btintel_secure_send(hdev, 0x03, 256, fw->data + 128);
- if (err < 0) {
- bt_dev_err(hdev, "Failed to send firmware public key (%d)",
- err);
- goto done;
- }
-
- /* Send the 256 bytes of signature information from the firmware
- * as the Sign fragment.
- */
- err = btintel_secure_send(hdev, 0x02, 256, fw->data + 388);
- if (err < 0) {
- bt_dev_err(hdev, "Failed to send firmware signature (%d)",
- err);
+ /* Start firmware downloading and get boot parameter */
+ err = btintel_download_firmware(hdev, fw, &boot_param);
+ if (err < 0)
goto done;
- }
-
- fw_ptr = fw->data + 644;
- frag_len = 0;
-
- while (fw_ptr - fw->data < fw->size) {
- struct hci_command_hdr *cmd = (void *)(fw_ptr + frag_len);
-
- /* Each SKU has a different reset parameter to use in the
- * HCI_Intel_Reset command and it is embedded in the firmware
- * data. So, instead of using static value per SKU, check
- * the firmware data and save it for later use.
- */
- if (cmd->opcode == 0xfc0e) {
-
- /* The boot parameter is the first 32-bit value
- * and rest of 3 octets are reserved.
- */
- boot_param = get_unaligned_le32(fw_ptr + sizeof(*cmd));
-
- bt_dev_dbg(hdev, "boot_param=0x%x", boot_param);
- }
-
- frag_len += sizeof(*cmd) + cmd->plen;
-
- bt_dev_dbg(hdev, "Patching %td/%zu", (fw_ptr - fw->data),
- fw->size);
-
- /* The parameter length of the secure send command requires
- * a 4 byte alignment. It happens so that the firmware file
- * contains proper Intel_NOP commands to align the fragments
- * as needed.
- *
- * Send set of commands with 4 byte alignment from the
- * firmware data buffer as a single Data fragement.
- */
- if (frag_len % 4)
- continue;
-
- /* Send each command from the firmware data buffer as
- * a single Data fragment.
- */
- err = btintel_secure_send(hdev, 0x01, frag_len, fw_ptr);
- if (err < 0) {
- bt_dev_err(hdev, "Failed to send firmware data (%d)",
- err);
- goto done;
- }
-
- fw_ptr += frag_len;
- frag_len = 0;
- }

set_bit(STATE_FIRMWARE_LOADED, &intel->flags);

--
2.7.4


2018-01-24 03:17:47

by Tedd Ho-Jeong An

[permalink] [raw]
Subject: [PATCH 3/5] Bluetooth: btintel: Use boot parameter from firmware file

Each RAM SKU has a different boot parameter which is used in
HCI_Intel_Reset command after downloading the firmware.
The boot parameter is embedded in the firmware data and to support
multiple SKUs, driver reads the boot parameter while downloading
the firmware instead of using static values per SKU.

Signed-off-by: Tedd Ho-Jeong An <[email protected]>
---
drivers/bluetooth/btusb.c | 22 ++++++++++++++++++++--
drivers/bluetooth/hci_intel.c | 23 +++++++++++++++++++++--
2 files changed, 41 insertions(+), 4 deletions(-)

diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c
index 93db5b9..979d530 100644
--- a/drivers/bluetooth/btusb.c
+++ b/drivers/bluetooth/btusb.c
@@ -2024,8 +2024,11 @@ static int btusb_setup_intel_new(struct hci_dev *hdev)

BT_DBG("%s", hdev->name);

- /* The default boot parameter */
- boot_param = 0x00040800;
+ /* Set the default boot parameter to 0x0 and it is updated to
+ * SKU specific boot parameter after reading Intel_Write_Boot_Params
+ * command while downloading the firmware.
+ */
+ boot_param = 0x00000000;

calltime = ktime_get();

@@ -2269,6 +2272,21 @@ static int btusb_setup_intel_new(struct hci_dev *hdev)
while (fw_ptr - fw->data < fw->size) {
struct hci_command_hdr *cmd = (void *)(fw_ptr + frag_len);

+ /* Each SKU has a different reset parameter to use in the
+ * HCI_Intel_Reset command and it is embedded in the firmware
+ * data. So, instead of using static value per SKU, check
+ * the firmware data and save it for later use.
+ */
+ if (cmd->opcode == 0xfc0e) {
+
+ /* The boot parameter is the first 32-bit value
+ * and rest of 3 octets are reserved.
+ */
+ boot_param = get_unaligned_le32(fw_ptr + sizeof(*cmd));
+
+ bt_dev_dbg(hdev, "boot_param=0x%x", boot_param);
+ }
+
frag_len += sizeof(*cmd) + cmd->plen;

/* The parameter length of the secure send command requires
diff --git a/drivers/bluetooth/hci_intel.c b/drivers/bluetooth/hci_intel.c
index acac48d..2053d73 100644
--- a/drivers/bluetooth/hci_intel.c
+++ b/drivers/bluetooth/hci_intel.c
@@ -33,6 +33,7 @@
#include <linux/acpi.h>
#include <linux/interrupt.h>
#include <linux/pm_runtime.h>
+#include <asm/unaligned.h>

#include <net/bluetooth/bluetooth.h>
#include <net/bluetooth/hci_core.h>
@@ -562,8 +563,11 @@ static int intel_setup(struct hci_uart *hu)
hu->hdev->set_diag = btintel_set_diag;
hu->hdev->set_bdaddr = btintel_set_bdaddr;

- /* Default boot parameter */
- boot_param = 0x00040800;
+ /* Set the default boot parameter to 0x0 and it is updated to
+ * SKU specific boot parameter after reading Intel_Write_Boot_Params
+ * command while downloading the firmware.
+ */
+ boot_param = 0x00000000;

calltime = ktime_get();

@@ -824,6 +828,21 @@ static int intel_setup(struct hci_uart *hu)
while (fw_ptr - fw->data < fw->size) {
struct hci_command_hdr *cmd = (void *)(fw_ptr + frag_len);

+ /* Each SKU has a different reset parameter to use in the
+ * HCI_Intel_Reset command and it is embedded in the firmware
+ * data. So, instead of using static value per SKU, check
+ * the firmware data and save it for later use.
+ */
+ if (cmd->opcode == 0xfc0e) {
+
+ /* The boot parameter is the first 32-bit value
+ * and rest of 3 octets are reserved.
+ */
+ boot_param = get_unaligned_le32(fw_ptr + sizeof(*cmd));
+
+ bt_dev_dbg(hdev, "boot_param=0x%x", boot_param);
+ }
+
frag_len += sizeof(*cmd) + cmd->plen;

bt_dev_dbg(hdev, "Patching %td/%zu", (fw_ptr - fw->data),
--
2.7.4


2018-01-24 03:17:48

by Tedd Ho-Jeong An

[permalink] [raw]
Subject: [PATCH 4/5] Bluetooth: btintel: Create common Intel Read Boot Params function

The Intel_Read_Boot_Params command is used to read boot parameters
from the bootloader and this is Intel generic command used in USB
and UART drivers.

Signed-off-by: Tedd Ho-Jeong An <[email protected]>
---
drivers/bluetooth/btintel.c | 51 +++++++++++++++++++++++++++++++++++++++++
drivers/bluetooth/btintel.h | 8 +++++++
drivers/bluetooth/btusb.c | 53 ++++++++-----------------------------------
drivers/bluetooth/hci_intel.c | 48 +++++++--------------------------------
4 files changed, 76 insertions(+), 84 deletions(-)

diff --git a/drivers/bluetooth/btintel.c b/drivers/bluetooth/btintel.c
index 067df4e..46f0e3e 100644
--- a/drivers/bluetooth/btintel.c
+++ b/drivers/bluetooth/btintel.c
@@ -589,6 +589,57 @@ int btintel_send_intel_reset(struct hci_dev *hdev, u32 boot_param)
}
EXPORT_SYMBOL_GPL(btintel_send_intel_reset);

+int btintel_read_boot_params(struct hci_dev *hdev,
+ struct intel_boot_params *params)
+{
+ struct sk_buff *skb;
+
+ skb = __hci_cmd_sync(hdev, 0xfc0d, 0, NULL, HCI_INIT_TIMEOUT);
+ if (IS_ERR(skb)) {
+ bt_dev_err(hdev, "Reading Intel boot parameters failed (%ld)",
+ PTR_ERR(skb));
+ return PTR_ERR(skb);
+ }
+
+ if (skb->len != sizeof(*params)) {
+ bt_dev_err(hdev, "Intel boot parameters size mismatch");
+ kfree_skb(skb);
+ return -EILSEQ;
+ }
+
+ memcpy(params, skb->data, sizeof(*params));
+
+ kfree_skb(skb);
+
+ if (params->status) {
+ bt_dev_err(hdev, "Intel boot parameters command failed (%02x)",
+ params->status);
+ return -bt_to_errno(params->status);
+ }
+
+ bt_dev_info(hdev, "Device revision is %u",
+ le16_to_cpu(params->dev_revid));
+
+ bt_dev_info(hdev, "Secure boot is %s",
+ params->secure_boot ? "enabled" : "disabled");
+
+ bt_dev_info(hdev, "OTP lock is %s",
+ params->otp_lock ? "enabled" : "disabled");
+
+ bt_dev_info(hdev, "API lock is %s",
+ params->api_lock ? "enabled" : "disabled");
+
+ bt_dev_info(hdev, "Debug lock is %s",
+ params->debug_lock ? "enabled" : "disabled");
+
+ bt_dev_info(hdev, "Minimum firmware build %u week %u %u",
+ params->min_fw_build_nn, params->min_fw_build_cw,
+ 2000 + params->min_fw_build_yy);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(btintel_read_boot_params);
+
MODULE_AUTHOR("Marcel Holtmann <[email protected]>");
MODULE_DESCRIPTION("Bluetooth support for Intel devices ver " VERSION);
MODULE_VERSION(VERSION);
diff --git a/drivers/bluetooth/btintel.h b/drivers/bluetooth/btintel.h
index 3ef2db7..28727b2 100644
--- a/drivers/bluetooth/btintel.h
+++ b/drivers/bluetooth/btintel.h
@@ -98,6 +98,8 @@ int btintel_read_version(struct hci_dev *hdev, struct intel_version *ver);
struct regmap *btintel_regmap_init(struct hci_dev *hdev, u16 opcode_read,
u16 opcode_write);
int btintel_send_intel_reset(struct hci_dev *hdev, u32 boot_param);
+int btintel_read_boot_params(struct hci_dev *hdev,
+ struct intel_boot_params *params);

#else

@@ -180,4 +182,10 @@ static inline int btintel_send_intel_reset(struct hci_dev *hdev,
{
return -EOPNOTSUPP;
}
+
+static inline int btintel_read_boot_params(struct hci_dev *hdev,
+ struct intel_boot_params *params)
+{
+ return -EOPNOTSUPP;
+}
#endif
diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c
index 979d530..808c245 100644
--- a/drivers/bluetooth/btusb.c
+++ b/drivers/bluetooth/btusb.c
@@ -2010,9 +2010,8 @@ static int btusb_send_frame_intel(struct hci_dev *hdev, struct sk_buff *skb)
static int btusb_setup_intel_new(struct hci_dev *hdev)
{
struct btusb_data *data = hci_get_drvdata(hdev);
- struct sk_buff *skb;
struct intel_version ver;
- struct intel_boot_params *params;
+ struct intel_boot_params params;
const struct firmware *fw;
const u8 *fw_ptr;
u32 frag_len;
@@ -2100,55 +2099,24 @@ static int btusb_setup_intel_new(struct hci_dev *hdev)
/* Read the secure boot parameters to identify the operating
* details of the bootloader.
*/
- skb = __hci_cmd_sync(hdev, 0xfc0d, 0, NULL, HCI_INIT_TIMEOUT);
- if (IS_ERR(skb)) {
- BT_ERR("%s: Reading Intel boot parameters failed (%ld)",
- hdev->name, PTR_ERR(skb));
- return PTR_ERR(skb);
- }
-
- if (skb->len != sizeof(*params)) {
- BT_ERR("%s: Intel boot parameters size mismatch", hdev->name);
- kfree_skb(skb);
- return -EILSEQ;
- }
-
- params = (struct intel_boot_params *)skb->data;
-
- bt_dev_info(hdev, "Device revision is %u",
- le16_to_cpu(params->dev_revid));
-
- bt_dev_info(hdev, "Secure boot is %s",
- params->secure_boot ? "enabled" : "disabled");
-
- bt_dev_info(hdev, "OTP lock is %s",
- params->otp_lock ? "enabled" : "disabled");
-
- bt_dev_info(hdev, "API lock is %s",
- params->api_lock ? "enabled" : "disabled");
-
- bt_dev_info(hdev, "Debug lock is %s",
- params->debug_lock ? "enabled" : "disabled");
-
- bt_dev_info(hdev, "Minimum firmware build %u week %u %u",
- params->min_fw_build_nn, params->min_fw_build_cw,
- 2000 + params->min_fw_build_yy);
+ err = btintel_read_boot_params(hdev, &params);
+ if (err)
+ return err;

/* It is required that every single firmware fragment is acknowledged
* with a command complete event. If the boot parameters indicate
* that this bootloader does not send them, then abort the setup.
*/
- if (params->limited_cce != 0x00) {
+ if (params.limited_cce != 0x00) {
BT_ERR("%s: Unsupported Intel firmware loading method (%u)",
- hdev->name, params->limited_cce);
- kfree_skb(skb);
+ hdev->name, params.limited_cce);
return -EINVAL;
}

/* If the OTP has no valid Bluetooth device address, then there will
* also be no valid address for the operational firmware.
*/
- if (!bacmp(&params->otp_bdaddr, BDADDR_ANY)) {
+ if (!bacmp(&params.otp_bdaddr, BDADDR_ANY)) {
bt_dev_info(hdev, "No device address configured");
set_bit(HCI_QUIRK_INVALID_BDADDR, &hdev->quirks);
}
@@ -2179,7 +2147,7 @@ static int btusb_setup_intel_new(struct hci_dev *hdev)
case 0x0c: /* WsP */
snprintf(fwname, sizeof(fwname), "intel/ibt-%u-%u.sfi",
le16_to_cpu(ver.hw_variant),
- le16_to_cpu(params->dev_revid));
+ le16_to_cpu(params.dev_revid));
break;
case 0x11: /* JfP */
case 0x12: /* ThP */
@@ -2197,7 +2165,6 @@ static int btusb_setup_intel_new(struct hci_dev *hdev)
if (err < 0) {
BT_ERR("%s: Failed to load Intel firmware file (%d)",
hdev->name, err);
- kfree_skb(skb);
return err;
}

@@ -2211,7 +2178,7 @@ static int btusb_setup_intel_new(struct hci_dev *hdev)
case 0x0c: /* WsP */
snprintf(fwname, sizeof(fwname), "intel/ibt-%u-%u.ddc",
le16_to_cpu(ver.hw_variant),
- le16_to_cpu(params->dev_revid));
+ le16_to_cpu(params.dev_revid));
break;
case 0x11: /* JfP */
case 0x12: /* ThP */
@@ -2225,8 +2192,6 @@ static int btusb_setup_intel_new(struct hci_dev *hdev)
return -EINVAL;
}

- kfree_skb(skb);
-
if (fw->size < 644) {
BT_ERR("%s: Invalid size of firmware file (%zu)",
hdev->name, fw->size);
diff --git a/drivers/bluetooth/hci_intel.c b/drivers/bluetooth/hci_intel.c
index 2053d73..f83b9da 100644
--- a/drivers/bluetooth/hci_intel.c
+++ b/drivers/bluetooth/hci_intel.c
@@ -545,7 +545,7 @@ static int intel_setup(struct hci_uart *hu)
struct hci_dev *hdev = hu->hdev;
struct sk_buff *skb;
struct intel_version ver;
- struct intel_boot_params *params;
+ struct intel_boot_params params;
struct list_head *p;
const struct firmware *fw;
const u8 *fw_ptr;
@@ -662,53 +662,24 @@ static int intel_setup(struct hci_uart *hu)
/* Read the secure boot parameters to identify the operating
* details of the bootloader.
*/
- skb = __hci_cmd_sync(hdev, 0xfc0d, 0, NULL, HCI_CMD_TIMEOUT);
- if (IS_ERR(skb)) {
- bt_dev_err(hdev, "Reading Intel boot parameters failed (%ld)",
- PTR_ERR(skb));
- return PTR_ERR(skb);
- }
-
- if (skb->len != sizeof(*params)) {
- bt_dev_err(hdev, "Intel boot parameters size mismatch");
- kfree_skb(skb);
- return -EILSEQ;
- }
-
- params = (struct intel_boot_params *)skb->data;
- if (params->status) {
- bt_dev_err(hdev, "Intel boot parameters command failure (%02x)",
- params->status);
- err = -bt_to_errno(params->status);
- kfree_skb(skb);
+ err = btintel_read_boot_params(hdev, &params);
+ if (err)
return err;
- }
-
- bt_dev_info(hdev, "Device revision is %u",
- le16_to_cpu(params->dev_revid));
-
- bt_dev_info(hdev, "Secure boot is %s",
- params->secure_boot ? "enabled" : "disabled");
-
- bt_dev_info(hdev, "Minimum firmware build %u week %u %u",
- params->min_fw_build_nn, params->min_fw_build_cw,
- 2000 + params->min_fw_build_yy);

/* It is required that every single firmware fragment is acknowledged
* with a command complete event. If the boot parameters indicate
* that this bootloader does not send them, then abort the setup.
*/
- if (params->limited_cce != 0x00) {
+ if (params.limited_cce != 0x00) {
bt_dev_err(hdev, "Unsupported Intel firmware loading method (%u)",
- params->limited_cce);
- kfree_skb(skb);
+ params.limited_cce);
return -EINVAL;
}

/* If the OTP has no valid Bluetooth device address, then there will
* also be no valid address for the operational firmware.
*/
- if (!bacmp(&params->otp_bdaddr, BDADDR_ANY)) {
+ if (!bacmp(&params.otp_bdaddr, BDADDR_ANY)) {
bt_dev_info(hdev, "No device address configured");
set_bit(HCI_QUIRK_INVALID_BDADDR, &hdev->quirks);
}
@@ -738,7 +709,7 @@ static int intel_setup(struct hci_uart *hu)
case 0x0c: /* WsP */
snprintf(fwname, sizeof(fwname), "intel/ibt-%u-%u.sfi",
le16_to_cpu(ver.hw_variant),
- le16_to_cpu(params->dev_revid));
+ le16_to_cpu(params.dev_revid));
break;
case 0x12: /* ThP */
snprintf(fwname, sizeof(fwname), "intel/ibt-%u-%u-%u.sfi",
@@ -756,7 +727,6 @@ static int intel_setup(struct hci_uart *hu)
if (err < 0) {
bt_dev_err(hdev, "Failed to load Intel firmware file (%d)",
err);
- kfree_skb(skb);
return err;
}

@@ -768,7 +738,7 @@ static int intel_setup(struct hci_uart *hu)
case 0x0c: /* WsP */
snprintf(fwname, sizeof(fwname), "intel/ibt-%u-%u.ddc",
le16_to_cpu(ver.hw_variant),
- le16_to_cpu(params->dev_revid));
+ le16_to_cpu(params.dev_revid));
break;
case 0x12: /* ThP */
snprintf(fwname, sizeof(fwname), "intel/ibt-%u-%u-%u.ddc",
@@ -782,8 +752,6 @@ static int intel_setup(struct hci_uart *hu)
return -EINVAL;
}

- kfree_skb(skb);
-
if (fw->size < 644) {
bt_dev_err(hdev, "Invalid size of firmware file (%zu)",
fw->size);
--
2.7.4