All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 1/2] Bluetooth: btintel: Add TOP silent reset hooks
@ 2026-10-14 11:47 Chandrashekar Devegowda
  2026-10-14 11:47 ` [PATCH 2/2] Bluetooth: btintel_pcie: Add TOP silent reset support Chandrashekar Devegowda
  2026-10-14 12:55 ` [1/2] Bluetooth: btintel: Add TOP silent reset hooks bluez.test.bot
  0 siblings, 2 replies; 3+ messages in thread
From: Chandrashekar Devegowda @ 2026-10-14 11:47 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: chethan.tumkur.narayan, kiran.k, Chandrashekar Devegowda

Add an INTEL_TOP_RESET flag so btintel_boot() can abort with
-ECANCELED and let the caller substitute its own reset sequence,
and cache boot_addr in struct btintel_data so that sequence can
replay btintel_send_intel_reset() without re-parsing firmware.
Preserve the flag across the reset in btintel_bootloader_setup_tlv().

Inert on its own; used by the follow-up btintel_pcie patch.

Signed-off-by: Chandrashekar Devegowda <chandrashekar.devegowda@intel.com>
---
 drivers/bluetooth/btintel.c | 68 +++++++++++++++++++++++++++++++++----
 drivers/bluetooth/btintel.h |  2 ++
 2 files changed, 64 insertions(+), 6 deletions(-)

diff --git a/drivers/bluetooth/btintel.c b/drivers/bluetooth/btintel.c
index 0709fb3212f9..f48cda37ffa0 100644
--- a/drivers/bluetooth/btintel.c
+++ b/drivers/bluetooth/btintel.c
@@ -1238,6 +1238,17 @@ static bool btintel_firmware_version(struct hci_dev *hdev,
 {
 	const u8 *fw_ptr;
 
+	/* Invalidate any previously cached boot_addr up front so that if
+	 * this firmware image lacks CMD_WRITE_BOOT_PARAMS below, the TOP
+	 * silent reset replay path in btintel_pcie does not reuse a stale
+	 * address from an earlier firmware load.
+	 */
+	if (hdev->bus == HCI_PCI) {
+		struct btintel_data *data = hci_get_priv(hdev);
+
+		data->boot_addr = 0;
+	}
+
 	fw_ptr = fw->data;
 
 	while (fw_ptr - fw->data < fw->size) {
@@ -1255,6 +1266,18 @@ static bool btintel_firmware_version(struct hci_dev *hdev,
 
 			*boot_addr = le32_to_cpu(params->boot_addr);
 
+			/* boot_addr is cached only for the PCIe TOP silent
+			 * reset replay path. UART (hci_intel) devices have no
+			 * struct btintel_data allocated as hci_dev private
+			 * data, so hci_get_priv(hdev) would return memory past
+			 * the end of hdev; skip the cache write there.
+			 */
+			if (hdev->bus == HCI_PCI) {
+				struct btintel_data *data = hci_get_priv(hdev);
+
+				data->boot_addr = *boot_addr;
+			}
+
 			bt_dev_info(hdev, "Boot Address: 0x%x", *boot_addr);
 
 			bt_dev_info(hdev, "Firmware Version: %u-%u.%u",
@@ -2059,11 +2082,30 @@ static int btintel_boot_wait_d0(struct hci_dev *hdev, ktime_t calltime,
 	return 0;
 }
 
+/* Returns true when a TOP silent reset is pending on this hdev and the
+ * caller must cancel whatever FW-download/boot step it was about to run
+ * instead of proceeding, so the reset dispatch in btintel_pcie_setup()
+ * is not bypassed.
+ */
+static bool btintel_top_reset_pending(struct hci_dev *hdev)
+{
+	if (hdev->bus == HCI_PCI && btintel_test_flag(hdev, INTEL_TOP_RESET)) {
+		bt_dev_info(hdev, "INTEL_TOP_RESET flag set, cancel boot");
+		return true;
+	}
+
+	return false;
+}
+
 static int btintel_boot(struct hci_dev *hdev, u32 boot_addr)
 {
 	ktime_t calltime;
 	int err;
 
+	/* TOP reset flag set, abort FW download before sending Intel soft reset */
+	if (btintel_top_reset_pending(hdev))
+		return -ECANCELED;
+
 	calltime = ktime_get();
 
 	btintel_set_flag(hdev, INTEL_BOOTING);
@@ -3543,12 +3585,13 @@ static int btintel_try_load_unlocker(struct hci_dev *hdev,
 int btintel_bootloader_setup_tlv(struct hci_dev *hdev,
 				 struct intel_version_tlv *ver)
 {
-	u32 boot_param;
-	char ddcname[64];
-	int err;
-	struct intel_version_tlv new_ver;
 	struct btintel_data *data = hci_get_priv(hdev);
 	u8 hw_variant = INTEL_HW_VARIANT(ver->cnvi_bt);
+	struct intel_version_tlv new_ver;
+	bool backup = false;
+	char ddcname[64];
+	u32 boot_param;
+	int err, i;
 
 	bt_dev_dbg(hdev, "");
 
@@ -3562,9 +3605,15 @@ int btintel_bootloader_setup_tlv(struct hci_dev *hdev,
 	 * same hdev instance if there is any error on firmware download.
 	 * Need to clear stale bits of previous firmware download attempt.
 	 */
-	for (int i = 0; i < __INTEL_NUM_FLAGS; i++)
+	if (btintel_test_flag(hdev, INTEL_TOP_RESET))
+		backup = true;
+
+	for (i = 0; i < __INTEL_NUM_FLAGS; i++)
 		btintel_clear_flag(hdev, i);
 
+	if (backup)
+		btintel_set_flag(hdev, INTEL_TOP_RESET);
+
 	btintel_set_flag(hdev, INTEL_BOOTLOADER);
 
 	data->unlocker = false;
@@ -3597,8 +3646,15 @@ int btintel_bootloader_setup_tlv(struct hci_dev *hdev,
 		return err;
 
 	/* check if controller is already having an operational firmware */
-	if (ver->img_type == BTINTEL_IMG_OP)
+	if (ver->img_type == BTINTEL_IMG_OP) {
+		/* A pending TOP reset must still be dispatched by the
+		 * caller even though there is no bootloader stage to run
+		 * through btintel_boot() in this case.
+		 */
+		if (btintel_top_reset_pending(hdev))
+			return -ECANCELED;
 		goto finish;
+	}
 
 	err = btintel_boot(hdev, boot_param);
 	if (err)
diff --git a/drivers/bluetooth/btintel.h b/drivers/bluetooth/btintel.h
index 9526acf65959..97fbe0ddf2d3 100644
--- a/drivers/bluetooth/btintel.h
+++ b/drivers/bluetooth/btintel.h
@@ -257,6 +257,7 @@ enum {
 	INTEL_ROM_LEGACY_NO_WBS_SUPPORT,
 	INTEL_ACPI_RESET_ACTIVE,
 	INTEL_WAIT_FOR_D0,
+	INTEL_TOP_RESET,
 
 	__INTEL_NUM_FLAGS,
 };
@@ -265,6 +266,7 @@ struct btintel_data {
 	DECLARE_BITMAP(flags, __INTEL_NUM_FLAGS);
 	int (*acpi_reset_method)(struct hci_dev *hdev);
 	u32 cnvi_bt;
+	u32 boot_addr;
 	bool	unlocker;
 };
 
-- 
2.43.0


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

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

Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-10-14 11:47 [PATCH 1/2] Bluetooth: btintel: Add TOP silent reset hooks Chandrashekar Devegowda
2026-10-14 11:47 ` [PATCH 2/2] Bluetooth: btintel_pcie: Add TOP silent reset support Chandrashekar Devegowda
2026-10-14 12:55 ` [1/2] Bluetooth: btintel: Add TOP silent reset hooks bluez.test.bot

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.