Linux bluetooth development
 help / color / mirror / Atom feed
* [PATCH v3 0/2] Bluetooth: btintel_pcie: debug INI rework and fatal error injection
@ 2026-11-02 17:37 Sai Teja Aluvala
  2026-11-02 17:37 ` [PATCH v3 1/2] Bluetooth: btintel_pcie: Move debug INI parsing to debug file Sai Teja Aluvala
  2026-11-02 17:37 ` [PATCH v3 2/2] Bluetooth: btintel_pcie: Add fatal error injection test mode Sai Teja Aluvala
  0 siblings, 2 replies; 5+ messages in thread
From: Sai Teja Aluvala @ 2026-11-02 17:37 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: kiran.k, chethan.tumkur.narayan, Sai Teja Aluvala

This series moves the btintel_pcie debug INI parsing into the debug
file and adds a test mode for injecting firmware exceptions.

Patch 1 moves the debug INI parser (DBG_PATH, ENABLE_INI, LOG_MASK)
from btintel_pcie.c to btintel_pcie_debug.c, so that all debug INI
handling lives in one file. The parsing behaviour is unchanged.

Patch 2 adds the FATAL_ERR_TESTMODE debug INI option. It injects a
firmware exception for testing. The INI value selects the exception
type and the injection context (thread, IRQ or rfkill). Whether the
exception is expected to trigger recovery depends on its type. The
test mode is disabled when the OPFW API lock is set, unless the
unlocker firmware was loaded.

v3:
 - Fall back to the normal rfkill handling when HCI is down, so the
   test mode no longer suppresses it.
 - Send the deferred post-setup notification when HCI is opened again.

v2:
 - Drop the btintel "Zero-initialize new_ver" patch, as
   btintel_read_version_tlv() already clears the structure.
 - Arm the post-setup injection before setting SETUP_DONE, so the rfkill
   work cannot inject ahead of it.
 - Keep the post-setup injection pending if HCI is down when the rfkill
   work runs.
 - Document that the test mode intentionally injects on every rfkill
   assertion and skips the initial rfkill check after the post-setup
   injection, and that the api_lock check uses the operational firmware
   version.

Sai Teja Aluvala (2):
  Bluetooth: btintel_pcie: Move debug INI parsing to debug file
  Bluetooth: btintel_pcie: Add fatal error injection test mode

 drivers/bluetooth/btintel.c            |   5 +-
 drivers/bluetooth/btintel.h            |   1 +
 drivers/bluetooth/btintel_pcie.c       | 160 ++++---------
 drivers/bluetooth/btintel_pcie.h       |   5 +-
 drivers/bluetooth/btintel_pcie_debug.c | 296 ++++++++++++++++++++++++-
 drivers/bluetooth/btintel_pcie_debug.h |  33 ++-
 6 files changed, 372 insertions(+), 128 deletions(-)

-- 
2.53.0


^ permalink raw reply	[flat|nested] 5+ messages in thread
* [PATCH v4 1/2] Bluetooth: btintel_pcie: Move debug INI parsing to debug file
@ 2026-11-03  6:28 Sai Teja Aluvala
  2026-11-03  8:45 ` Bluetooth: btintel_pcie: debug INI rework and fatal error injection bluez.test.bot
  0 siblings, 1 reply; 5+ messages in thread
From: Sai Teja Aluvala @ 2026-11-03  6:28 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: kiran.k, chethan.tumkur.narayan, Sai Teja Aluvala

Move the debug INI parser from btintel_pcie.c to
btintel_pcie_debug.c so that all debug INI handling lives in one
file. DBG_PATH, ENABLE_INI and LOG_MASK behave as before.

Signed-off-by: Sai Teja Aluvala <aluvala.sai.teja@intel.com>
---
 drivers/bluetooth/btintel_pcie.c       | 122 ---------------------
 drivers/bluetooth/btintel_pcie_debug.c | 142 ++++++++++++++++++++++++-
 drivers/bluetooth/btintel_pcie_debug.h |   8 +-
 3 files changed, 146 insertions(+), 126 deletions(-)

diff --git a/drivers/bluetooth/btintel_pcie.c b/drivers/bluetooth/btintel_pcie.c
index 7d84c8106cf1..8b991ad2a107 100644
--- a/drivers/bluetooth/btintel_pcie.c
+++ b/drivers/bluetooth/btintel_pcie.c
@@ -274,128 +274,6 @@ static inline bool btintel_pcie_dbg_to_wifi(struct btintel_pcie_data *data)
 	return data->dbg_path_cache != BTINTEL_PCIE_DRAM;
 }
 
-/* Name of the optional INI file used to override the default dbg_path
- * (data->dbg_path_cache), yoyo ini settings and runtime log_mask.
- */
-#define BTINTEL_PCIE_DBG_INI_FILE "ibt_bt_dbg_cfg.ini"
-
-/* Loads optional "DBG_PATH=<value>", "ENABLE_INI=<value>" and "LOG_MASK=<value>"
- * overrides from BTINTEL_PCIE_DBG_INI_FILE
- * and applies them to data->dbg_path_cache, data->enable_ini and data->log_mask.
- *
- * DBG_PATH accepts BTINTEL_PCIE_WIFI_DBGC (0x06, default) and
- * BTINTEL_PCIE_DRAM (0x01, legacy); an invalid or missing entry leaves
- * the cached value set by the caller unchanged.
- *
- * ENABLE_INI accepts 1 (enabled) or 0 (disabled); an invalid or missing
- * entry leaves data->enable_ini unchanged.
- *
- * LOG_MASK accepts any u32 bitmask (see BTINTEL_PCIE_DUMP_TX and friends).
- * The default enables alive interrupt and Sx logging; an invalid or missing
- * entry leaves data->log_mask unchanged.
- */
-static void btintel_pcie_load_dbg_path_from_ini(struct btintel_pcie_data *data)
-{
-	const struct firmware *fw;
-	const char *ini_file = BTINTEL_PCIE_DBG_INI_FILE;
-	char *buf, *cursor, *line;
-	bool dbg_path_applied = false;
-	bool log_mask_applied = false;
-	int err;
-
-	err = request_firmware_direct(&fw, ini_file, &data->pdev->dev);
-	if (err < 0) {
-		BT_DBG("%s not found (%d), using dbg_path=0x%02x log_mask=0x%08x",
-		       ini_file, err, data->dbg_path_cache, data->log_mask);
-		if (data->dbg_path_cache != BTINTEL_PCIE_DRAM)
-			data->enable_ini = false;
-		return;
-	}
-
-	buf = kmemdup_nul(fw->data, fw->size, GFP_KERNEL);
-	release_firmware(fw);
-	if (!buf)
-		return;
-
-	cursor = buf;
-	while ((line = strsep(&cursor, "\n"))) {
-		char *eq;
-		char *val;
-		uint parsed;
-
-		line = strim(line);
-		if (!line[0] || line[0] == '#' || line[0] == ';')
-			continue;
-
-		eq = strchr(line, '=');
-		if (!eq)
-			continue;
-
-		*eq = '\0';
-		line = strim(line);
-		val = strim(eq + 1);
-
-		/* Keys are case-insensitive. */
-		if (!strcasecmp(line, "DBG_PATH")) {
-			BT_INFO("Read DBG_PATH from %s: '%s'", ini_file, val);
-
-			/* base 0 lets kstrtouint accept "0x06", "6", etc. */
-			if (kstrtouint(val, 0, &parsed) == 0 &&
-			    (parsed == BTINTEL_PCIE_DRAM ||
-			     parsed == BTINTEL_PCIE_WIFI_DBGC)) {
-				data->dbg_path_cache = parsed;
-				dbg_path_applied = true;
-				BT_INFO("WRT dbg_path accepted: 0x%02x",
-					data->dbg_path_cache);
-			} else {
-				BT_WARN("Invalid DBG_PATH='%s' in %s, using dbg_path=0x%02x",
-					val, ini_file, data->dbg_path_cache);
-			}
-		} else if (!strcasecmp(line, "LOG_MASK")) {
-			BT_INFO("Read LOG_MASK from %s: '%s'", ini_file, val);
-
-			if (kstrtouint(val, 0, &parsed) == 0) {
-				data->log_mask = parsed;
-				log_mask_applied = true;
-				BT_INFO("WRT log_mask accepted: 0x%08x",
-					data->log_mask);
-			} else {
-				BT_WARN("Invalid LOG_MASK='%s' in %s, using log_mask=0x%08x",
-					val, ini_file, data->log_mask);
-			}
-		} else if (!strcasecmp(line, "ENABLE_INI")) {
-			BT_INFO("Read ENABLE_INI from %s: '%s'", ini_file, val);
-
-			if (kstrtouint(val, 0, &parsed) == 0 &&
-			    (parsed == 0 || parsed == 1)) {
-				data->enable_ini = !!parsed;
-				BT_INFO("WRT enable_ini accepted: %u",
-					data->enable_ini);
-			} else {
-				BT_WARN("Invalid ENABLE_INI='%s' in %s, using enable_ini=%u",
-					val, ini_file, data->enable_ini);
-			}
-		}
-	}
-
-	if (data->dbg_path_cache != BTINTEL_PCIE_DRAM)
-		data->enable_ini = false;
-
-	if (dbg_path_applied)
-		BT_DBG("Loaded dbg_path=0x%02x from %s", data->dbg_path_cache, ini_file);
-	else
-		BT_WARN("No valid DBG_PATH in %s, dbg_path=0x%02x", ini_file, data->dbg_path_cache);
-
-	BT_DBG("ENABLE_INI effective state: %u", data->enable_ini);
-
-	if (log_mask_applied)
-		BT_DBG("Loaded log_mask=0x%08x from %s", data->log_mask, ini_file);
-	else
-		BT_DBG("No valid LOG_MASK in %s, log_mask=0x%08x", ini_file, data->log_mask);
-
-	kfree(buf);
-}
-
 /* Helper function to allocate and setup a debug buffer group
  * @data: driver data structure
  * @buf: pointer to data_buf array pointer
diff --git a/drivers/bluetooth/btintel_pcie_debug.c b/drivers/bluetooth/btintel_pcie_debug.c
index 9f2d3f32bd99..f3350fc9b08a 100644
--- a/drivers/bluetooth/btintel_pcie_debug.c
+++ b/drivers/bluetooth/btintel_pcie_debug.c
@@ -1,22 +1,158 @@
 // SPDX-License-Identifier: GPL-2.0-only
 /*
- * Intel Bluetooth YoYo Debug Framework
+ * Intel Bluetooth PCIe Debug Framework
  *
  * Copyright (C) 2026 Intel Corporation
  *
  * Runtime-configurable TLV-based debug collection framework for loading and
  * parsing the optional YoYo firmware configuration used to enable debug
- * regions, triggers, HCI commands, and configuration sets.
+ * regions, triggers, HCI commands, and configuration sets. Also provides
+ * debug INI configuration.
  */
 
 #include <linux/errno.h>
 #include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/slab.h>
 #include <linux/stddef.h>
 #include <linux/string.h>
 #include <linux/unaligned.h>
 #include <net/bluetooth/bluetooth.h>
+#include "btintel_pcie.h"
 #include "btintel_pcie_debug.h"
 
+static char *btintel_pcie_read_debug_ini(struct btintel_pcie_data *data)
+{
+	const struct firmware *fw;
+	char *buf;
+	int err;
+
+	err = request_firmware_direct(&fw, BTINTEL_PCIE_DBG_INI_FILE,
+				      &data->pdev->dev);
+	if (err)
+		return ERR_PTR(err);
+
+	buf = kmemdup_nul(fw->data, fw->size, GFP_KERNEL);
+	release_firmware(fw);
+	if (!buf)
+		return ERR_PTR(-ENOMEM);
+
+	return buf;
+}
+
+static char *btintel_pcie_ini_next(char **cursor, char **key)
+{
+	char *line, *eq;
+
+	while ((line = strsep(cursor, "\n"))) {
+		line = strim(line);
+		if (!line[0] || line[0] == '#' || line[0] == ';')
+			continue;
+
+		eq = strchr(line, '=');
+		if (!eq)
+			continue;
+
+		*eq = '\0';
+		*key = strim(line);
+		return strim(eq + 1);
+	}
+
+	return NULL;
+}
+
+/* Loads optional "DBG_PATH=<value>", "ENABLE_INI=<value>" and
+ * "LOG_MASK=<value>" overrides from BTINTEL_PCIE_DBG_INI_FILE and applies
+ * them to data->dbg_path_cache, data->enable_ini and data->log_mask.
+ *
+ * DBG_PATH accepts BTINTEL_PCIE_WIFI_DBGC (0x06, default) and
+ * BTINTEL_PCIE_DRAM (0x01, legacy); an invalid or missing entry leaves
+ * the cached value set by the caller unchanged.
+ *
+ * ENABLE_INI accepts 1 (enabled) or 0 (disabled); an invalid or missing
+ * entry leaves data->enable_ini unchanged.
+ *
+ * LOG_MASK accepts any u32 bitmask (see BTINTEL_PCIE_DUMP_TX and friends).
+ * The default enables alive interrupt and Sx logging; an invalid or missing
+ * entry leaves data->log_mask unchanged.
+ */
+void btintel_pcie_load_dbg_path_from_ini(struct btintel_pcie_data *data)
+{
+	const char *ini_file = BTINTEL_PCIE_DBG_INI_FILE;
+	char *buf, *cursor, *key, *val;
+	bool dbg_path_applied = false;
+	bool log_mask_applied = false;
+
+	buf = btintel_pcie_read_debug_ini(data);
+	if (IS_ERR(buf)) {
+		BT_DBG("%s not found (%ld), using dbg_path=0x%02x log_mask=0x%08x",
+		       ini_file, PTR_ERR(buf), data->dbg_path_cache,
+		       data->log_mask);
+		if (data->dbg_path_cache != BTINTEL_PCIE_DRAM)
+			data->enable_ini = false;
+		return;
+	}
+
+	cursor = buf;
+	while ((val = btintel_pcie_ini_next(&cursor, &key))) {
+		unsigned int parsed;
+
+		if (!strcasecmp(key, "DBG_PATH")) {
+			BT_INFO("Read DBG_PATH from %s: '%s'", ini_file, val);
+			if (!kstrtouint(val, 0, &parsed) &&
+			    (parsed == BTINTEL_PCIE_DRAM ||
+			     parsed == BTINTEL_PCIE_WIFI_DBGC)) {
+				data->dbg_path_cache = parsed;
+				dbg_path_applied = true;
+				BT_INFO("WRT dbg_path accepted: 0x%02x",
+					data->dbg_path_cache);
+			} else {
+				BT_WARN("Invalid DBG_PATH='%s' in %s, using dbg_path=0x%02x",
+					val, ini_file, data->dbg_path_cache);
+			}
+		} else if (!strcasecmp(key, "LOG_MASK")) {
+			BT_INFO("Read LOG_MASK from %s: '%s'", ini_file, val);
+			if (!kstrtouint(val, 0, &parsed)) {
+				data->log_mask = parsed;
+				log_mask_applied = true;
+				BT_INFO("WRT log_mask accepted: 0x%08x",
+					data->log_mask);
+			} else {
+				BT_WARN("Invalid LOG_MASK='%s' in %s, using log_mask=0x%08x",
+					val, ini_file, data->log_mask);
+			}
+		} else if (!strcasecmp(key, "ENABLE_INI")) {
+			BT_INFO("Read ENABLE_INI from %s: '%s'", ini_file, val);
+			if (!kstrtouint(val, 0, &parsed) && parsed <= 1) {
+				data->enable_ini = !!parsed;
+				BT_INFO("WRT enable_ini accepted: %u",
+					data->enable_ini);
+			} else {
+				BT_WARN("Invalid ENABLE_INI='%s' in %s, using enable_ini=%u",
+					val, ini_file, data->enable_ini);
+			}
+		}
+	}
+
+	if (data->dbg_path_cache != BTINTEL_PCIE_DRAM)
+		data->enable_ini = false;
+
+	if (dbg_path_applied)
+		BT_DBG("Loaded dbg_path=0x%02x from %s", data->dbg_path_cache, ini_file);
+	else
+		BT_WARN("No valid DBG_PATH in %s, dbg_path=0x%02x", ini_file, data->dbg_path_cache);
+
+	BT_DBG("ENABLE_INI effective state: %u", data->enable_ini);
+
+	if (log_mask_applied)
+		BT_DBG("Loaded log_mask=0x%08x from %s", data->log_mask, ini_file);
+	else
+		BT_DBG("No valid LOG_MASK in %s, log_mask=0x%08x", ini_file, data->log_mask);
+
+	kfree(buf);
+}
+EXPORT_SYMBOL_GPL(btintel_pcie_load_dbg_path_from_ini);
+
 /* TLV-specific parser DEBUG_INFO TLV type */
 static int btintel_pcie_yoyo_parse_dbg_info(struct btintel_pcie_yoyo_ctx *ctx,
 					    const struct btintel_pcie_tlv_dbg_info *info,
@@ -327,5 +463,5 @@ btintel_pcie_yoyo_get_buf_alloc(struct btintel_pcie_yoyo_ctx *ctx, u32 alloc_id)
 }
 EXPORT_SYMBOL_GPL(btintel_pcie_yoyo_get_buf_alloc);
 
-MODULE_DESCRIPTION("Intel Bluetooth yoyo debug framework");
+MODULE_DESCRIPTION("Intel Bluetooth PCIe Debug Framework");
 MODULE_LICENSE("GPL");
diff --git a/drivers/bluetooth/btintel_pcie_debug.h b/drivers/bluetooth/btintel_pcie_debug.h
index 5ed368fb13d1..04cfcef6f65b 100644
--- a/drivers/bluetooth/btintel_pcie_debug.h
+++ b/drivers/bluetooth/btintel_pcie_debug.h
@@ -1,6 +1,6 @@
 /* SPDX-License-Identifier: GPL-2.0-only */
 /*
- * Intel Bluetooth YoYo Debug Framework
+ * Intel Bluetooth PCIe Debug Framework
  *
  * Copyright (C) 2026 Intel Corporation
  *
@@ -14,6 +14,12 @@
 #include <linux/device.h>
 #include <linux/firmware.h>
 
+struct btintel_pcie_data;
+
+#define BTINTEL_PCIE_DBG_INI_FILE	"ibt_bt_dbg_cfg.ini"
+
+void btintel_pcie_load_dbg_path_from_ini(struct btintel_pcie_data *data);
+
 /* External YoYo binary file */
 #define BTINTEL_PCIE_YOYO_FW_NAME	"intel/ibt_debug_yoyo.bin"
 
-- 
2.53.0


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

end of thread, other threads:[~2026-11-03  8:45 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-11-02 17:37 [PATCH v3 0/2] Bluetooth: btintel_pcie: debug INI rework and fatal error injection Sai Teja Aluvala
2026-11-02 17:37 ` [PATCH v3 1/2] Bluetooth: btintel_pcie: Move debug INI parsing to debug file Sai Teja Aluvala
2026-11-02 19:25   ` Bluetooth: btintel_pcie: debug INI rework and fatal error injection bluez.test.bot
2026-11-02 17:37 ` [PATCH v3 2/2] Bluetooth: btintel_pcie: Add fatal error injection test mode Sai Teja Aluvala
  -- strict thread matches above, loose matches on Subject: below --
2026-11-03  6:28 [PATCH v4 1/2] Bluetooth: btintel_pcie: Move debug INI parsing to debug file Sai Teja Aluvala
2026-11-03  8:45 ` Bluetooth: btintel_pcie: debug INI rework and fatal error injection bluez.test.bot

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