]> git.proxmox.com Git - mirror_ubuntu-eoan-kernel.git/commitdiff
Bluetooth: btintel: Create common function for firmware download
authorTedd Ho-Jeong An <tedd.an@linux.intel.com>
Wed, 24 Jan 2018 17:19:21 +0000 (09:19 -0800)
committerMarcel Holtmann <marcel@holtmann.org>
Thu, 25 Jan 2018 08:28:40 +0000 (09:28 +0100)
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 <tedd.an@linux.intel.com>
Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
drivers/bluetooth/btintel.c
drivers/bluetooth/btintel.h
drivers/bluetooth/btusb.c
drivers/bluetooth/hci_intel.c

index da47f6dccd386d0744fe889a2a00423ffc7554ec..5270d55132015a467b15aba8887b944585893b91 100644 (file)
@@ -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,89 @@ 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 (le16_to_cpu(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 <marcel@holtmann.org>");
 MODULE_DESCRIPTION("Bluetooth support for Intel devices ver " VERSION);
 MODULE_VERSION(VERSION);
index 0391e7aba03b794037d8404a46f18b70aedbb68d..41c642cc523fcc63a42262cafc3616d90249f233 100644 (file)
@@ -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
index 6ea21d503eaf346f63fda9a7c16cc0a598cad457..2a55380ad730713fa4f26807294e9a9a0b5fa1b5 100644 (file)
@@ -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,78 +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);
 
index cf7438512d21a9f7c6238956f7d4688c5d08640c..7c166e3b308b76ee9964bc005f9c4f2acf25083f 100644 (file)
@@ -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,84 +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);