Linux bluetooth development
 help / color / mirror / Atom feed
* [PATCH v1] Bluetooth: btintel: check FIPS status before firmware download
@ 2026-10-21 13:04 Kiran K
  2026-10-21 18:07 ` [v1] " bluez.test.bot
  2026-10-23 21:49 ` [PATCH v1] " Luiz Augusto von Dentz
  0 siblings, 2 replies; 4+ messages in thread
From: Kiran K @ 2026-10-21 13:04 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: chethan.tumkur.narayan, chandrashekar.devegowda, Kiran K

Intel Bluetooth controllers (PCIe and USB) from Scorpius Peak2 onwards
report bootloader self-test results (CRC, security, patch) in the
INTEL_TLV_FIPS_STS TLV of the Intel Read Version event. Act on them
before firmware download:

  1. CRC failure      -> abort download.
  2. Security failure -> abort on USB / HW reset and retry on PCIe.
  3. Patch failure    -> abort on USB / HW reset and retry on PCIe.

Signed-off-by: Kiran K <kiran.k@intel.com>
---
 drivers/bluetooth/btintel.c      | 66 +++++++++++++++++++++++++++++++-
 drivers/bluetooth/btintel.h      | 10 +++++
 drivers/bluetooth/btintel_pcie.c | 18 ++++++++-
 3 files changed, 90 insertions(+), 4 deletions(-)

diff --git a/drivers/bluetooth/btintel.c b/drivers/bluetooth/btintel.c
index 0709fb3212f9..f6deb3d7c5a0 100644
--- a/drivers/bluetooth/btintel.c
+++ b/drivers/bluetooth/btintel.c
@@ -485,10 +485,18 @@ int btintel_read_version(struct hci_dev *hdev, struct intel_version *ver)
 }
 EXPORT_SYMBOL_GPL(btintel_read_version);
 
+/* FIPS self-test status is only reported by ScP2 onwards, except BlazarIW */
+static bool btintel_fips_status_supported(u8 hw_variant)
+{
+	return hw_variant >= BTINTEL_HWID_SCP2 && hw_variant != BTINTEL_HWID_BZRIW;
+}
+
 int btintel_version_info_tlv(struct hci_dev *hdev,
 			     struct intel_version_tlv *version)
 {
 	const char *variant;
+	bool fips_status = false;
+	u8 hw_variant;
 
 	/* The hardware platform number has a fixed value of 0x37 and
 	 * for now only accept this single value.
@@ -505,7 +513,8 @@ int btintel_version_info_tlv(struct hci_dev *hdev,
 	 * This check has been put in place to ensure correct forward
 	 * compatibility options when newer hardware variants come along.
 	 */
-	switch (INTEL_HW_VARIANT(version->cnvi_bt)) {
+	hw_variant = INTEL_HW_VARIANT(version->cnvi_bt);
+	switch (hw_variant) {
 	case 0x17:	/* TyP */
 	case 0x18:	/* Slr */
 	case 0x19:	/* Slr-F */
@@ -521,10 +530,13 @@ int btintel_version_info_tlv(struct hci_dev *hdev,
 		break;
 	default:
 		bt_dev_err(hdev, "Unsupported Intel hardware variant (0x%x)",
-			   INTEL_HW_VARIANT(version->cnvi_bt));
+			   hw_variant);
 		return -EINVAL;
 	}
 
+	fips_status = btintel_fips_status_supported(hw_variant) &&
+		version->img_type == BTINTEL_IMG_BOOTLOADER;
+
 	switch (version->img_type) {
 	case BTINTEL_IMG_BOOTLOADER:
 		variant = "Bootloader";
@@ -584,6 +596,9 @@ int btintel_version_info_tlv(struct hci_dev *hdev,
 
 	bt_dev_info(hdev, "Unlock policy: 0x%2.2x", version->unlock_policy);
 
+	if (fips_status)
+		bt_dev_info(hdev, "crc status: %u security status: %u patch status: %u",
+			    version->crc_sts, version->sec_sts, version->patch_sts);
 	return 0;
 }
 EXPORT_SYMBOL_GPL(btintel_version_info_tlv);
@@ -612,6 +627,7 @@ static u8 btintel_version_tlv_min_len(u8 type)
 	case INTEL_TLV_UNLOCK_POLICY:
 		return sizeof(u8);
 	case INTEL_TLV_MIN_FW:
+	case INTEL_TLV_FIPS_STS:
 		return 3;
 	case INTEL_TLV_OTP_BDADDR:
 		return sizeof(bdaddr_t);
@@ -720,6 +736,11 @@ int btintel_parse_version_tlv(struct hci_dev *hdev,
 		case INTEL_TLV_GIT_SHA1:
 			version->git_sha1 = get_unaligned_le32(tlv->val);
 			break;
+		case INTEL_TLV_FIPS_STS:
+			version->crc_sts = tlv->val[0];
+			version->sec_sts = tlv->val[1];
+			version->patch_sts = tlv->val[2];
+			break;
 		case INTEL_TLV_FW_ID:
 			snprintf(version->fw_id, sizeof(version->fw_id),
 				 "%.*s", tlv->len, tlv->val);
@@ -3831,6 +3852,43 @@ void btintel_print_fseq_info(struct hci_dev *hdev)
 }
 EXPORT_SYMBOL_GPL(btintel_print_fseq_info);
 
+int btintel_check_fips_status(struct hci_dev *hdev,
+			      struct intel_version_tlv *ver)
+{
+	u8 hw_variant;
+
+	/* FIPS status is reported only in the bootloader image */
+	if (ver->img_type != BTINTEL_IMG_BOOTLOADER)
+		return 0;
+
+	hw_variant = INTEL_HW_VARIANT(ver->cnvi_bt);
+
+	if (!btintel_fips_status_supported(hw_variant))
+		return 0;
+
+	/* 0 -> Test not executed
+	 * 1 -> Test executed and it passed
+	 * any other value -> Test failed
+	 */
+	if (ver->crc_sts > 1) {
+		bt_dev_err(hdev, "crc test failed: %u", ver->crc_sts);
+		return -ENOEXEC;
+	}
+
+	if (ver->sec_sts > 1) {
+		bt_dev_err(hdev, "security test failed: %u", ver->sec_sts);
+		return -EAGAIN;
+	}
+
+	if (ver->patch_sts > 1) {
+		bt_dev_err(hdev, "patch test failed: %u", ver->patch_sts);
+		return -EAGAIN;
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(btintel_check_fips_status);
+
 static int btintel_setup_combined(struct hci_dev *hdev)
 {
 	const u8 param[1] = { 0xFF };
@@ -4055,6 +4113,10 @@ static int btintel_setup_combined(struct hci_dev *hdev)
 		/* Display version information of TLV type */
 		btintel_version_info_tlv(hdev, &ver_tlv);
 
+		err = btintel_check_fips_status(hdev, &ver_tlv);
+		if (err)
+			goto exit_error;
+
 		/* Apply the device specific HCI quirks for TLV based devices
 		 *
 		 * All TLV based devices support WBS
diff --git a/drivers/bluetooth/btintel.h b/drivers/bluetooth/btintel.h
index 9526acf65959..d5e125ec5168 100644
--- a/drivers/bluetooth/btintel.h
+++ b/drivers/bluetooth/btintel.h
@@ -43,6 +43,7 @@ enum {
 	INTEL_TLV_OTP_BDADDR,
 	INTEL_TLV_UNLOCKED_STATE,
 	INTEL_TLV_GIT_SHA1,
+	INTEL_TLV_FIPS_STS = 0x3b,
 	INTEL_TLV_UNLOCK_POLICY = 0x3c,
 	INTEL_TLV_PLATFORM_ID = 0x3d,
 	INTEL_TLV_FW_ID = 0x50
@@ -112,6 +113,7 @@ struct intel_version_tlv {
 	bdaddr_t otp_bd_addr;
 	u8	unlock_policy;
 	u8	platform_id[6];
+	u8	crc_sts, sec_sts, patch_sts;
 };
 
 struct intel_version {
@@ -331,6 +333,8 @@ int btintel_shutdown_combined(struct hci_dev *hdev);
 void btintel_hw_error(struct hci_dev *hdev, u8 code);
 void btintel_print_fseq_info(struct hci_dev *hdev);
 int btintel_acpi_reset_method(struct hci_dev *hdev);
+int btintel_check_fips_status(struct hci_dev *hdev,
+			      struct intel_version_tlv *ver);
 #else
 
 static inline int btintel_check_bdaddr(struct hci_dev *hdev)
@@ -468,4 +472,10 @@ static inline int btintel_acpi_reset_method(struct hci_dev *hdev)
 {
 	return -ENODEV;
 }
+
+static inline int btintel_check_fips_status(struct hci_dev *hdev,
+					    struct intel_version_tlv *ver)
+{
+	return -EOPNOTSUPP;
+}
 #endif
diff --git a/drivers/bluetooth/btintel_pcie.c b/drivers/bluetooth/btintel_pcie.c
index df95d16a163c..73822ba2acbb 100644
--- a/drivers/bluetooth/btintel_pcie.c
+++ b/drivers/bluetooth/btintel_pcie.c
@@ -3786,7 +3786,8 @@ static int btintel_pcie_get_debug_info_addr(struct hci_dev *hdev)
 	return err;
 }
 
-static int btintel_pcie_setup_internal(struct hci_dev *hdev)
+static int btintel_pcie_setup_internal(struct hci_dev *hdev,
+				       bool *fips_crc_failed)
 {
 	struct btintel_pcie_data *data = hci_get_drvdata(hdev);
 	const u8 param[1] = { 0xFF };
@@ -3794,6 +3795,8 @@ static int btintel_pcie_setup_internal(struct hci_dev *hdev)
 	struct sk_buff *skb;
 	int err;
 
+	*fips_crc_failed = false;
+
 	BT_DBG("%s", hdev->name);
 
 	skb = __hci_cmd_sync(hdev, 0xfc05, 1, param, HCI_CMD_TIMEOUT);
@@ -3855,6 +3858,12 @@ static int btintel_pcie_setup_internal(struct hci_dev *hdev)
 		/* Display version information of TLV type */
 		btintel_version_info_tlv(hdev, &ver_tlv);
 
+		err = btintel_check_fips_status(hdev, &ver_tlv);
+		if (err) {
+			*fips_crc_failed = (err == -ENOEXEC);
+			goto exit_error;
+		}
+
 		/* Apply the device specific HCI quirks for TLV based devices
 		 *
 		 * All TLV based devices support WBS
@@ -3900,8 +3909,13 @@ static int btintel_pcie_setup(struct hci_dev *hdev)
 {
 	int err, fw_dl_retry = 0;
 	struct btintel_pcie_data *data = hci_get_drvdata(hdev);
+	bool fips_crc_failed;
+
+	while ((err = btintel_pcie_setup_internal(hdev, &fips_crc_failed)) &&
+	       fw_dl_retry++ < 1) {
+		if (fips_crc_failed)
+			break;
 
-	while ((err = btintel_pcie_setup_internal(hdev)) && fw_dl_retry++ < 1) {
 		bt_dev_err(hdev, "Firmware download retry count: %d",
 			   fw_dl_retry);
 		btintel_pcie_dump_debug_registers(hdev);
-- 
2.54.0


^ permalink raw reply related	[flat|nested] 4+ messages in thread

* RE: [v1] Bluetooth: btintel: check FIPS status before firmware download
  2026-10-21 13:04 [PATCH v1] Bluetooth: btintel: check FIPS status before firmware download Kiran K
@ 2026-10-21 18:07 ` bluez.test.bot
  2026-10-23 21:49 ` [PATCH v1] " Luiz Augusto von Dentz
  1 sibling, 0 replies; 4+ messages in thread
From: bluez.test.bot @ 2026-10-21 18:07 UTC (permalink / raw)
  To: linux-bluetooth, kiran.k

[-- Attachment #1: Type: text/plain, Size: 1019 bytes --]

This is automated email and please do not reply to this email!

Dear submitter,

Thank you for submitting the patches to the linux bluetooth mailing list.
This is a CI test results with your patch series:
PW Link:https://patchwork.kernel.org/series/1190499/

---Test result---

Test Summary:
CheckPatch                    PASS      1.17 seconds
VerifyFixes                   PASS      0.09 seconds
VerifySignedoff               PASS      7.16 seconds
GitLint                       PASS      0.27 seconds
SubjectPrefix                 PASS      0.09 seconds
BuildKernel                   PASS      30.84 seconds
CheckAllWarning               PASS      35.19 seconds
CheckSparse                   PASS      38.01 seconds
BuildKernel32                 PASS      30.63 seconds
CheckKernelLLVM               PASS      35.04 seconds
TestRunnerSetup               PASS      720.87 seconds
IncrementalBuild              PASS      35.13 seconds



https://github.com/bluez/bluetooth-next/pull/973

---
Regards,
Linux Bluetooth


^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [PATCH v1] Bluetooth: btintel: check FIPS status before firmware download
  2026-10-21 13:04 [PATCH v1] Bluetooth: btintel: check FIPS status before firmware download Kiran K
  2026-10-21 18:07 ` [v1] " bluez.test.bot
@ 2026-10-23 21:49 ` Luiz Augusto von Dentz
  2026-10-27 12:56   ` K, Kiran
  1 sibling, 1 reply; 4+ messages in thread
From: Luiz Augusto von Dentz @ 2026-10-23 21:49 UTC (permalink / raw)
  To: Kiran K; +Cc: linux-bluetooth, chethan.tumkur.narayan, chandrashekar.devegowda

Hi Kiran,

On Wed, Oct 21, 2026 at 9:02 AM Kiran K <kiran.k@intel.com> wrote:
>
> Intel Bluetooth controllers (PCIe and USB) from Scorpius Peak2 onwards
> report bootloader self-test results (CRC, security, patch) in the
> INTEL_TLV_FIPS_STS TLV of the Intel Read Version event. Act on them
> before firmware download:
>
>   1. CRC failure      -> abort download.
>   2. Security failure -> abort on USB / HW reset and retry on PCIe.
>   3. Patch failure    -> abort on USB / HW reset and retry on PCIe.
>
> Signed-off-by: Kiran K <kiran.k@intel.com>
> ---
>  drivers/bluetooth/btintel.c      | 66 +++++++++++++++++++++++++++++++-
>  drivers/bluetooth/btintel.h      | 10 +++++
>  drivers/bluetooth/btintel_pcie.c | 18 ++++++++-
>  3 files changed, 90 insertions(+), 4 deletions(-)
>
> diff --git a/drivers/bluetooth/btintel.c b/drivers/bluetooth/btintel.c
> index 0709fb3212f9..f6deb3d7c5a0 100644
> --- a/drivers/bluetooth/btintel.c
> +++ b/drivers/bluetooth/btintel.c
> @@ -485,10 +485,18 @@ int btintel_read_version(struct hci_dev *hdev, struct intel_version *ver)
>  }
>  EXPORT_SYMBOL_GPL(btintel_read_version);
>
> +/* FIPS self-test status is only reported by ScP2 onwards, except BlazarIW */
> +static bool btintel_fips_status_supported(u8 hw_variant)
> +{
> +       return hw_variant >= BTINTEL_HWID_SCP2 && hw_variant != BTINTEL_HWID_BZRIW;
> +}
> +
>  int btintel_version_info_tlv(struct hci_dev *hdev,
>                              struct intel_version_tlv *version)
>  {
>         const char *variant;
> +       bool fips_status = false;
> +       u8 hw_variant;
>
>         /* The hardware platform number has a fixed value of 0x37 and
>          * for now only accept this single value.
> @@ -505,7 +513,8 @@ int btintel_version_info_tlv(struct hci_dev *hdev,
>          * This check has been put in place to ensure correct forward
>          * compatibility options when newer hardware variants come along.
>          */
> -       switch (INTEL_HW_VARIANT(version->cnvi_bt)) {
> +       hw_variant = INTEL_HW_VARIANT(version->cnvi_bt);
> +       switch (hw_variant) {
>         case 0x17:      /* TyP */
>         case 0x18:      /* Slr */
>         case 0x19:      /* Slr-F */
> @@ -521,10 +530,13 @@ int btintel_version_info_tlv(struct hci_dev *hdev,
>                 break;
>         default:
>                 bt_dev_err(hdev, "Unsupported Intel hardware variant (0x%x)",
> -                          INTEL_HW_VARIANT(version->cnvi_bt));
> +                          hw_variant);
>                 return -EINVAL;
>         }
>
> +       fips_status = btintel_fips_status_supported(hw_variant) &&
> +               version->img_type == BTINTEL_IMG_BOOTLOADER;
> +
>         switch (version->img_type) {
>         case BTINTEL_IMG_BOOTLOADER:
>                 variant = "Bootloader";
> @@ -584,6 +596,9 @@ int btintel_version_info_tlv(struct hci_dev *hdev,
>
>         bt_dev_info(hdev, "Unlock policy: 0x%2.2x", version->unlock_policy);
>
> +       if (fips_status)
> +               bt_dev_info(hdev, "crc status: %u security status: %u patch status: %u",
> +                           version->crc_sts, version->sec_sts, version->patch_sts);
>         return 0;
>  }
>  EXPORT_SYMBOL_GPL(btintel_version_info_tlv);
> @@ -612,6 +627,7 @@ static u8 btintel_version_tlv_min_len(u8 type)
>         case INTEL_TLV_UNLOCK_POLICY:
>                 return sizeof(u8);
>         case INTEL_TLV_MIN_FW:
> +       case INTEL_TLV_FIPS_STS:
>                 return 3;
>         case INTEL_TLV_OTP_BDADDR:
>                 return sizeof(bdaddr_t);
> @@ -720,6 +736,11 @@ int btintel_parse_version_tlv(struct hci_dev *hdev,
>                 case INTEL_TLV_GIT_SHA1:
>                         version->git_sha1 = get_unaligned_le32(tlv->val);
>                         break;
> +               case INTEL_TLV_FIPS_STS:
> +                       version->crc_sts = tlv->val[0];
> +                       version->sec_sts = tlv->val[1];
> +                       version->patch_sts = tlv->val[2];
> +                       break;
>                 case INTEL_TLV_FW_ID:
>                         snprintf(version->fw_id, sizeof(version->fw_id),
>                                  "%.*s", tlv->len, tlv->val);
> @@ -3831,6 +3852,43 @@ void btintel_print_fseq_info(struct hci_dev *hdev)
>  }
>  EXPORT_SYMBOL_GPL(btintel_print_fseq_info);
>
> +int btintel_check_fips_status(struct hci_dev *hdev,
> +                             struct intel_version_tlv *ver)
> +{
> +       u8 hw_variant;
> +
> +       /* FIPS status is reported only in the bootloader image */
> +       if (ver->img_type != BTINTEL_IMG_BOOTLOADER)
> +               return 0;
> +
> +       hw_variant = INTEL_HW_VARIANT(ver->cnvi_bt);
> +
> +       if (!btintel_fips_status_supported(hw_variant))
> +               return 0;
> +
> +       /* 0 -> Test not executed
> +        * 1 -> Test executed and it passed
> +        * any other value -> Test failed
> +        */
> +       if (ver->crc_sts > 1) {
> +               bt_dev_err(hdev, "crc test failed: %u", ver->crc_sts);
> +               return -ENOEXEC;
> +       }
> +
> +       if (ver->sec_sts > 1) {
> +               bt_dev_err(hdev, "security test failed: %u", ver->sec_sts);
> +               return -EAGAIN;
> +       }
> +
> +       if (ver->patch_sts > 1) {
> +               bt_dev_err(hdev, "patch test failed: %u", ver->patch_sts);
> +               return -EAGAIN;
> +       }
> +
> +       return 0;
> +}
> +EXPORT_SYMBOL_GPL(btintel_check_fips_status);
> +
>  static int btintel_setup_combined(struct hci_dev *hdev)
>  {
>         const u8 param[1] = { 0xFF };
> @@ -4055,6 +4113,10 @@ static int btintel_setup_combined(struct hci_dev *hdev)
>                 /* Display version information of TLV type */
>                 btintel_version_info_tlv(hdev, &ver_tlv);
>
> +               err = btintel_check_fips_status(hdev, &ver_tlv);
> +               if (err)
> +                       goto exit_error;
> +
>                 /* Apply the device specific HCI quirks for TLV based devices
>                  *
>                  * All TLV based devices support WBS
> diff --git a/drivers/bluetooth/btintel.h b/drivers/bluetooth/btintel.h
> index 9526acf65959..d5e125ec5168 100644
> --- a/drivers/bluetooth/btintel.h
> +++ b/drivers/bluetooth/btintel.h
> @@ -43,6 +43,7 @@ enum {
>         INTEL_TLV_OTP_BDADDR,
>         INTEL_TLV_UNLOCKED_STATE,
>         INTEL_TLV_GIT_SHA1,
> +       INTEL_TLV_FIPS_STS = 0x3b,
>         INTEL_TLV_UNLOCK_POLICY = 0x3c,
>         INTEL_TLV_PLATFORM_ID = 0x3d,
>         INTEL_TLV_FW_ID = 0x50
> @@ -112,6 +113,7 @@ struct intel_version_tlv {
>         bdaddr_t otp_bd_addr;
>         u8      unlock_policy;
>         u8      platform_id[6];
> +       u8      crc_sts, sec_sts, patch_sts;
>  };
>
>  struct intel_version {
> @@ -331,6 +333,8 @@ int btintel_shutdown_combined(struct hci_dev *hdev);
>  void btintel_hw_error(struct hci_dev *hdev, u8 code);
>  void btintel_print_fseq_info(struct hci_dev *hdev);
>  int btintel_acpi_reset_method(struct hci_dev *hdev);
> +int btintel_check_fips_status(struct hci_dev *hdev,
> +                             struct intel_version_tlv *ver);
>  #else
>
>  static inline int btintel_check_bdaddr(struct hci_dev *hdev)
> @@ -468,4 +472,10 @@ static inline int btintel_acpi_reset_method(struct hci_dev *hdev)
>  {
>         return -ENODEV;
>  }
> +
> +static inline int btintel_check_fips_status(struct hci_dev *hdev,
> +                                           struct intel_version_tlv *ver)
> +{
> +       return -EOPNOTSUPP;
> +}
>  #endif
> diff --git a/drivers/bluetooth/btintel_pcie.c b/drivers/bluetooth/btintel_pcie.c
> index df95d16a163c..73822ba2acbb 100644
> --- a/drivers/bluetooth/btintel_pcie.c
> +++ b/drivers/bluetooth/btintel_pcie.c
> @@ -3786,7 +3786,8 @@ static int btintel_pcie_get_debug_info_addr(struct hci_dev *hdev)
>         return err;
>  }
>
> -static int btintel_pcie_setup_internal(struct hci_dev *hdev)
> +static int btintel_pcie_setup_internal(struct hci_dev *hdev,
> +                                      bool *fips_crc_failed)
>  {
>         struct btintel_pcie_data *data = hci_get_drvdata(hdev);
>         const u8 param[1] = { 0xFF };
> @@ -3794,6 +3795,8 @@ static int btintel_pcie_setup_internal(struct hci_dev *hdev)
>         struct sk_buff *skb;
>         int err;
>
> +       *fips_crc_failed = false;
> +
>         BT_DBG("%s", hdev->name);
>
>         skb = __hci_cmd_sync(hdev, 0xfc05, 1, param, HCI_CMD_TIMEOUT);
> @@ -3855,6 +3858,12 @@ static int btintel_pcie_setup_internal(struct hci_dev *hdev)
>                 /* Display version information of TLV type */
>                 btintel_version_info_tlv(hdev, &ver_tlv);
>
> +               err = btintel_check_fips_status(hdev, &ver_tlv);
> +               if (err) {
> +                       *fips_crc_failed = (err == -ENOEXEC);
> +                       goto exit_error;
> +               }
> +
>                 /* Apply the device specific HCI quirks for TLV based devices
>                  *
>                  * All TLV based devices support WBS
> @@ -3900,8 +3909,13 @@ static int btintel_pcie_setup(struct hci_dev *hdev)
>  {
>         int err, fw_dl_retry = 0;
>         struct btintel_pcie_data *data = hci_get_drvdata(hdev);
> +       bool fips_crc_failed;
> +
> +       while ((err = btintel_pcie_setup_internal(hdev, &fips_crc_failed)) &&
> +              fw_dl_retry++ < 1) {
> +               if (fips_crc_failed)
> +                       break;
>
> -       while ((err = btintel_pcie_setup_internal(hdev)) && fw_dl_retry++ < 1) {
>                 bt_dev_err(hdev, "Firmware download retry count: %d",
>                            fw_dl_retry);
>                 btintel_pcie_dump_debug_registers(hdev);
> --
> 2.54.0

Looks like the second instance of sashiko from netdev catch a problem:

https://netdev-ai.bots.linux.dev/sashiko/#/patchset/20261021130424.3042597-1-kiran.k%40intel.com

-- 
Luiz Augusto von Dentz

^ permalink raw reply	[flat|nested] 4+ messages in thread

* RE: [PATCH v1] Bluetooth: btintel: check FIPS status before firmware download
  2026-10-23 21:49 ` [PATCH v1] " Luiz Augusto von Dentz
@ 2026-10-27 12:56   ` K, Kiran
  0 siblings, 0 replies; 4+ messages in thread
From: K, Kiran @ 2026-10-27 12:56 UTC (permalink / raw)
  To: Luiz Augusto von Dentz
  Cc: linux-bluetooth@vger.kernel.org, Tumkur Narayan, Chethan,
	Devegowda, Chandrashekar

Hi Luiz,

>Subject: Re: [PATCH v1] Bluetooth: btintel: check FIPS status before firmware
>download
>
>Hi Kiran,
>
>On Wed, Oct 21, 2026 at 9:02 AM Kiran K <kiran.k@intel.com> wrote:
>>
>> Intel Bluetooth controllers (PCIe and USB) from Scorpius Peak2 onwards
>> report bootloader self-test results (CRC, security, patch) in the
>> INTEL_TLV_FIPS_STS TLV of the Intel Read Version event. Act on them
>> before firmware download:
>>
>>   1. CRC failure      -> abort download.
>>   2. Security failure -> abort on USB / HW reset and retry on PCIe.
>>   3. Patch failure    -> abort on USB / HW reset and retry on PCIe.
>>
>> Signed-off-by: Kiran K <kiran.k@intel.com>
>> ---
>>  drivers/bluetooth/btintel.c      | 66 +++++++++++++++++++++++++++++++-
>>  drivers/bluetooth/btintel.h      | 10 +++++
>>  drivers/bluetooth/btintel_pcie.c | 18 ++++++++-
>>  3 files changed, 90 insertions(+), 4 deletions(-)
>>
>> diff --git a/drivers/bluetooth/btintel.c b/drivers/bluetooth/btintel.c
>> index 0709fb3212f9..f6deb3d7c5a0 100644
>> --- a/drivers/bluetooth/btintel.c
>> +++ b/drivers/bluetooth/btintel.c
>> @@ -485,10 +485,18 @@ int btintel_read_version(struct hci_dev *hdev,
>> struct intel_version *ver)  }
>> EXPORT_SYMBOL_GPL(btintel_read_version);
>>
>> +/* FIPS self-test status is only reported by ScP2 onwards, except
>> +BlazarIW */ static bool btintel_fips_status_supported(u8 hw_variant)
>> +{
>> +       return hw_variant >= BTINTEL_HWID_SCP2 && hw_variant !=
>> +BTINTEL_HWID_BZRIW; }
>> +
>>  int btintel_version_info_tlv(struct hci_dev *hdev,
>>                              struct intel_version_tlv *version)  {
>>         const char *variant;
>> +       bool fips_status = false;
>> +       u8 hw_variant;
>>
>>         /* The hardware platform number has a fixed value of 0x37 and
>>          * for now only accept this single value.
>> @@ -505,7 +513,8 @@ int btintel_version_info_tlv(struct hci_dev *hdev,
>>          * This check has been put in place to ensure correct forward
>>          * compatibility options when newer hardware variants come along.
>>          */
>> -       switch (INTEL_HW_VARIANT(version->cnvi_bt)) {
>> +       hw_variant = INTEL_HW_VARIANT(version->cnvi_bt);
>> +       switch (hw_variant) {
>>         case 0x17:      /* TyP */
>>         case 0x18:      /* Slr */
>>         case 0x19:      /* Slr-F */
>> @@ -521,10 +530,13 @@ int btintel_version_info_tlv(struct hci_dev *hdev,
>>                 break;
>>         default:
>>                 bt_dev_err(hdev, "Unsupported Intel hardware variant (0x%x)",
>> -                          INTEL_HW_VARIANT(version->cnvi_bt));
>> +                          hw_variant);
>>                 return -EINVAL;
>>         }
>>
>> +       fips_status = btintel_fips_status_supported(hw_variant) &&
>> +               version->img_type == BTINTEL_IMG_BOOTLOADER;
>> +
>>         switch (version->img_type) {
>>         case BTINTEL_IMG_BOOTLOADER:
>>                 variant = "Bootloader"; @@ -584,6 +596,9 @@ int
>> btintel_version_info_tlv(struct hci_dev *hdev,
>>
>>         bt_dev_info(hdev, "Unlock policy: 0x%2.2x",
>> version->unlock_policy);
>>
>> +       if (fips_status)
>> +               bt_dev_info(hdev, "crc status: %u security status: %u patch status:
>%u",
>> +                           version->crc_sts, version->sec_sts,
>> + version->patch_sts);
>>         return 0;
>>  }
>>  EXPORT_SYMBOL_GPL(btintel_version_info_tlv);
>> @@ -612,6 +627,7 @@ static u8 btintel_version_tlv_min_len(u8 type)
>>         case INTEL_TLV_UNLOCK_POLICY:
>>                 return sizeof(u8);
>>         case INTEL_TLV_MIN_FW:
>> +       case INTEL_TLV_FIPS_STS:
>>                 return 3;
>>         case INTEL_TLV_OTP_BDADDR:
>>                 return sizeof(bdaddr_t); @@ -720,6 +736,11 @@ int
>> btintel_parse_version_tlv(struct hci_dev *hdev,
>>                 case INTEL_TLV_GIT_SHA1:
>>                         version->git_sha1 = get_unaligned_le32(tlv->val);
>>                         break;
>> +               case INTEL_TLV_FIPS_STS:
>> +                       version->crc_sts = tlv->val[0];
>> +                       version->sec_sts = tlv->val[1];
>> +                       version->patch_sts = tlv->val[2];
>> +                       break;
>>                 case INTEL_TLV_FW_ID:
>>                         snprintf(version->fw_id, sizeof(version->fw_id),
>>                                  "%.*s", tlv->len, tlv->val); @@
>> -3831,6 +3852,43 @@ void btintel_print_fseq_info(struct hci_dev *hdev)
>> }  EXPORT_SYMBOL_GPL(btintel_print_fseq_info);
>>
>> +int btintel_check_fips_status(struct hci_dev *hdev,
>> +                             struct intel_version_tlv *ver) {
>> +       u8 hw_variant;
>> +
>> +       /* FIPS status is reported only in the bootloader image */
>> +       if (ver->img_type != BTINTEL_IMG_BOOTLOADER)
>> +               return 0;
>> +
>> +       hw_variant = INTEL_HW_VARIANT(ver->cnvi_bt);
>> +
>> +       if (!btintel_fips_status_supported(hw_variant))
>> +               return 0;
>> +
>> +       /* 0 -> Test not executed
>> +        * 1 -> Test executed and it passed
>> +        * any other value -> Test failed
>> +        */
>> +       if (ver->crc_sts > 1) {
>> +               bt_dev_err(hdev, "crc test failed: %u", ver->crc_sts);
>> +               return -ENOEXEC;
>> +       }
>> +
>> +       if (ver->sec_sts > 1) {
>> +               bt_dev_err(hdev, "security test failed: %u", ver->sec_sts);
>> +               return -EAGAIN;
>> +       }
>> +
>> +       if (ver->patch_sts > 1) {
>> +               bt_dev_err(hdev, "patch test failed: %u", ver->patch_sts);
>> +               return -EAGAIN;
>> +       }
>> +
>> +       return 0;
>> +}
>> +EXPORT_SYMBOL_GPL(btintel_check_fips_status);
>> +
>>  static int btintel_setup_combined(struct hci_dev *hdev)  {
>>         const u8 param[1] = { 0xFF };
>> @@ -4055,6 +4113,10 @@ static int btintel_setup_combined(struct hci_dev
>*hdev)
>>                 /* Display version information of TLV type */
>>                 btintel_version_info_tlv(hdev, &ver_tlv);
>>
>> +               err = btintel_check_fips_status(hdev, &ver_tlv);
>> +               if (err)
>> +                       goto exit_error;
>> +
>>                 /* Apply the device specific HCI quirks for TLV based devices
>>                  *
>>                  * All TLV based devices support WBS diff --git
>> a/drivers/bluetooth/btintel.h b/drivers/bluetooth/btintel.h index
>> 9526acf65959..d5e125ec5168 100644
>> --- a/drivers/bluetooth/btintel.h
>> +++ b/drivers/bluetooth/btintel.h
>> @@ -43,6 +43,7 @@ enum {
>>         INTEL_TLV_OTP_BDADDR,
>>         INTEL_TLV_UNLOCKED_STATE,
>>         INTEL_TLV_GIT_SHA1,
>> +       INTEL_TLV_FIPS_STS = 0x3b,
>>         INTEL_TLV_UNLOCK_POLICY = 0x3c,
>>         INTEL_TLV_PLATFORM_ID = 0x3d,
>>         INTEL_TLV_FW_ID = 0x50
>> @@ -112,6 +113,7 @@ struct intel_version_tlv {
>>         bdaddr_t otp_bd_addr;
>>         u8      unlock_policy;
>>         u8      platform_id[6];
>> +       u8      crc_sts, sec_sts, patch_sts;
>>  };
>>
>>  struct intel_version {
>> @@ -331,6 +333,8 @@ int btintel_shutdown_combined(struct hci_dev
>> *hdev);  void btintel_hw_error(struct hci_dev *hdev, u8 code);  void
>> btintel_print_fseq_info(struct hci_dev *hdev);  int
>> btintel_acpi_reset_method(struct hci_dev *hdev);
>> +int btintel_check_fips_status(struct hci_dev *hdev,
>> +                             struct intel_version_tlv *ver);
>>  #else
>>
>>  static inline int btintel_check_bdaddr(struct hci_dev *hdev) @@
>> -468,4 +472,10 @@ static inline int btintel_acpi_reset_method(struct
>> hci_dev *hdev)  {
>>         return -ENODEV;
>>  }
>> +
>> +static inline int btintel_check_fips_status(struct hci_dev *hdev,
>> +                                           struct intel_version_tlv
>> +*ver) {
>> +       return -EOPNOTSUPP;
>> +}
>>  #endif
>> diff --git a/drivers/bluetooth/btintel_pcie.c
>> b/drivers/bluetooth/btintel_pcie.c
>> index df95d16a163c..73822ba2acbb 100644
>> --- a/drivers/bluetooth/btintel_pcie.c
>> +++ b/drivers/bluetooth/btintel_pcie.c
>> @@ -3786,7 +3786,8 @@ static int btintel_pcie_get_debug_info_addr(struct
>hci_dev *hdev)
>>         return err;
>>  }
>>
>> -static int btintel_pcie_setup_internal(struct hci_dev *hdev)
>> +static int btintel_pcie_setup_internal(struct hci_dev *hdev,
>> +                                      bool *fips_crc_failed)
>>  {
>>         struct btintel_pcie_data *data = hci_get_drvdata(hdev);
>>         const u8 param[1] = { 0xFF };
>> @@ -3794,6 +3795,8 @@ static int btintel_pcie_setup_internal(struct hci_dev
>*hdev)
>>         struct sk_buff *skb;
>>         int err;
>>
>> +       *fips_crc_failed = false;
>> +
>>         BT_DBG("%s", hdev->name);
>>
>>         skb = __hci_cmd_sync(hdev, 0xfc05, 1, param, HCI_CMD_TIMEOUT);
>> @@ -3855,6 +3858,12 @@ static int btintel_pcie_setup_internal(struct
>hci_dev *hdev)
>>                 /* Display version information of TLV type */
>>                 btintel_version_info_tlv(hdev, &ver_tlv);
>>
>> +               err = btintel_check_fips_status(hdev, &ver_tlv);
>> +               if (err) {
>> +                       *fips_crc_failed = (err == -ENOEXEC);
>> +                       goto exit_error;
>> +               }
>> +
>>                 /* Apply the device specific HCI quirks for TLV based devices
>>                  *
>>                  * All TLV based devices support WBS @@ -3900,8
>> +3909,13 @@ static int btintel_pcie_setup(struct hci_dev *hdev)  {
>>         int err, fw_dl_retry = 0;
>>         struct btintel_pcie_data *data = hci_get_drvdata(hdev);
>> +       bool fips_crc_failed;
>> +
>> +       while ((err = btintel_pcie_setup_internal(hdev, &fips_crc_failed)) &&
>> +              fw_dl_retry++ < 1) {
>> +               if (fips_crc_failed)
>> +                       break;
>>
>> -       while ((err = btintel_pcie_setup_internal(hdev)) && fw_dl_retry++ < 1) {
>>                 bt_dev_err(hdev, "Firmware download retry count: %d",
>>                            fw_dl_retry);
>>                 btintel_pcie_dump_debug_registers(hdev);
>> --
>> 2.54.0
>
>Looks like the second instance of sashiko from netdev catch a problem:
>
>https://netdev-
>ai.bots.linux.dev/sashiko/#/patchset/20261021130424.3042597-1-
>kiran.k%40intel.com

Ack. Looks like the commit message needs an update to fix this. I will publish v2 version.
>
>--
>Luiz Augusto von Dentz

Thanks,
Kiran


^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2026-10-27 12:56 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-10-21 13:04 [PATCH v1] Bluetooth: btintel: check FIPS status before firmware download Kiran K
2026-10-21 18:07 ` [v1] " bluez.test.bot
2026-10-23 21:49 ` [PATCH v1] " Luiz Augusto von Dentz
2026-10-27 12:56   ` K, Kiran

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox