AI Trajectory


Trajectory: (Expand/Collapse All)
Seq Timestamp Type Name Duration
0/0 2026/10/13 12:43 flow patch-triage
1m Args:
null

Results:
{
  "EnableConfigs": null,
  "FocusSymbols": [],
  "KMSANReasoning": "",
  "NeedsKMSAN": false,
  "Reasoning": "The patch series modifies the btintel_pcie driver and adds btintel_pcie_debug for Intel PCIe Bluetooth devices (YoYo debug configuration support). This driver requires specific physical Intel PCIe hardware (such as Intel BlazarI, Lunar Lake, Panther Lake, Nova Lake PCIe Bluetooth adapters) that is not emulated in standard QEMU or GCE virtualized environments. Because there is no virtual bus or emulation support for these PCIe devices in standard fuzzing environments, the modified code is structurally unreachable.",
  "WorthFuzzing": false
}

1/1 2026/10/13 12:43 action read-patch-diff
0m Args:
null

Results:
{
  "PatchDiff": "commit 9798fc7492d7a728059de5992f4fa132720e3f2e\nAuthor: syz-cluster \u003ctriage@syzkaller.com\u003e\nDate:   Tue Oct 13 12:43:08 2026 +0000\n\n    syz-cluster: applied patch under review\n\ndiff --git a/drivers/bluetooth/Makefile b/drivers/bluetooth/Makefile\nindex d5eb2568af2e9..7d933755b2916 100644\n--- a/drivers/bluetooth/Makefile\n+++ b/drivers/bluetooth/Makefile\n@@ -14,7 +14,7 @@ obj-$(CONFIG_BT_HCIBTUSB)\t+= btusb.o\n obj-$(CONFIG_BT_HCIBTSDIO)\t+= btsdio.o\n \n obj-$(CONFIG_BT_INTEL)\t\t+= btintel.o\n-obj-$(CONFIG_BT_INTEL_PCIE)\t+= btintel_pcie.o btintel.o\n+obj-$(CONFIG_BT_INTEL_PCIE)\t+= btintel_pcie.o btintel.o btintel_pcie_debug.o\n obj-$(CONFIG_BT_ATH3K)\t\t+= ath3k.o\n obj-$(CONFIG_BT_MRVL)\t\t+= btmrvl.o\n obj-$(CONFIG_BT_MRVL_SDIO)\t+= btmrvl_sdio.o\ndiff --git a/drivers/bluetooth/btintel_pcie.c b/drivers/bluetooth/btintel_pcie.c\nindex 3a555aa50c873..b85e8229d5d77 100644\n--- a/drivers/bluetooth/btintel_pcie.c\n+++ b/drivers/bluetooth/btintel_pcie.c\n@@ -203,6 +203,90 @@ static inline bool btintel_pcie_dbg_to_wifi(struct btintel_pcie_data *data)\n \treturn data-\u003edbg_path_cache != BTINTEL_PCIE_DRAM;\n }\n \n+#define BTINTEL_PCIE_DBG_INI_FILE \"ibt_bt_dbg_cfg.ini\"\n+\n+/*\n+ * Loads optional \"DBG_PATH=\u003cvalue\u003e\" and \"ENABLE_INI=\u003cvalue\u003e\" overrides from\n+ * BTINTEL_PCIE_DBG_INI_FILE and applies them to dbg_path_cache and enable_ini.\n+ *\n+ * DBG_PATH accepts WiFi DBGC (0x06) or legacy host DRAM (0x01); ENABLE_INI\n+ * accepts 1 (enabled) or 0 (disabled). Missing or invalid entries leave the\n+ * values set by the caller unchanged.\n+ */\n+static void btintel_pcie_load_dbg_path_from_ini(struct btintel_pcie_data *data)\n+{\n+\tconst struct firmware *fw;\n+\tconst char *ini_file = BTINTEL_PCIE_DBG_INI_FILE;\n+\tchar *buf, *cursor, *line;\n+\tbool dbg_path_applied = false;\n+\tint err;\n+\n+\terr = request_firmware_direct(\u0026fw, ini_file, \u0026data-\u003epdev-\u003edev);\n+\tif (err \u003c 0) {\n+\t\tBT_ERR(\"%s not found (%d), using dbg_path=0x%02x\", ini_file,\n+\t\t       err, data-\u003edbg_path_cache);\n+\t\treturn;\n+\t}\n+\n+\tbuf = kmemdup_nul(fw-\u003edata, fw-\u003esize, GFP_KERNEL);\n+\trelease_firmware(fw);\n+\tif (!buf)\n+\t\treturn;\n+\n+\tcursor = buf;\n+\twhile ((line = strsep(\u0026cursor, \"\\n\"))) {\n+\t\tchar *eq, *val;\n+\t\tunsigned int parsed;\n+\n+\t\tline = strim(line);\n+\t\tif (!line[0] || line[0] == '#' || line[0] == ';')\n+\t\t\tcontinue;\n+\n+\t\teq = strchr(line, '=');\n+\t\tif (!eq)\n+\t\t\tcontinue;\n+\n+\t\t*eq = '\\0';\n+\t\tline = strim(line);\n+\t\tval = strim(eq + 1);\n+\n+\t\tif (!strcasecmp(line, \"DBG_PATH\")) {\n+\t\t\tBT_DBG(\"Read DBG_PATH from %s: '%s'\", ini_file, val);\n+\n+\t\t\tif (!kstrtouint(val, 0, \u0026parsed) \u0026\u0026\n+\t\t\t    (parsed == BTINTEL_PCIE_DRAM ||\n+\t\t\t     parsed == BTINTEL_PCIE_WIFI_DBGC)) {\n+\t\t\t\tdata-\u003edbg_path_cache = parsed;\n+\t\t\t\tdbg_path_applied = true;\n+\t\t\t\tBT_DBG(\"YoYo: DBG_PATH=0x%02x\", data-\u003edbg_path_cache);\n+\t\t\t} else {\n+\t\t\t\tBT_ERR(\"Invalid DBG_PATH='%s' in %s, using dbg_path=0x%02x\",\n+\t\t\t\t       val, ini_file, data-\u003edbg_path_cache);\n+\t\t\t}\n+\t\t} else if (!strcasecmp(line, \"ENABLE_INI\")) {\n+\t\t\tBT_DBG(\"Read ENABLE_INI from %s: '%s'\", ini_file, val);\n+\n+\t\t\tif (!kstrtouint(val, 0, \u0026parsed) \u0026\u0026 parsed \u003c= 1) {\n+\t\t\t\tdata-\u003eenable_ini = !!parsed;\n+\t\t\t\tBT_DBG(\"YoYo: ENABLE_INI=%u\", data-\u003eenable_ini);\n+\t\t\t} else {\n+\t\t\t\tBT_ERR(\"Invalid ENABLE_INI='%s' in %s, using enable_ini=%u\",\n+\t\t\t\t       val, ini_file, data-\u003eenable_ini);\n+\t\t\t}\n+\t\t}\n+\t}\n+\n+\tif (dbg_path_applied)\n+\t\tBT_DBG(\"Loaded dbg_path=0x%02x from %s\", data-\u003edbg_path_cache,\n+\t\t       ini_file);\n+\telse\n+\t\tBT_ERR(\"No valid DBG_PATH in %s, dbg_path=0x%02x\", ini_file,\n+\t\t       data-\u003edbg_path_cache);\n+\n+\tBT_DBG(\"ENABLE_INI effective state: %u\", data-\u003eenable_ini);\n+\tkfree(buf);\n+}\n+\n /* Helper function to allocate and setup a debug buffer group\n  * @data: driver data structure\n  * @buf: pointer to data_buf array pointer\n@@ -218,7 +302,8 @@ static int btintel_pcie_alloc_dbgc_buf(struct btintel_pcie_data *data,\n \t\t\t\t       void **v_addr,\n \t\t\t\t       struct btintel_pcie_dbgc_ctxt_buf *frag,\n \t\t\t\t       u32 buf_index,\n-\t\t\t\t       u32 buf_count)\n+\t\t\t\t       u32 buf_count,\n+\t\t\t\t       u32 per_buf_size)\n {\n \tstruct data_buf *b;\n \tint i;\n@@ -231,8 +316,7 @@ static int btintel_pcie_alloc_dbgc_buf(struct btintel_pcie_data *data,\n \t}\n \n \t*v_addr = dmam_alloc_coherent(\u0026data-\u003epdev-\u003edev,\n-\t\t\t\t      buf_count *\n-\t\t\t\t\tBTINTEL_PCIE_DBGC_BUFFER_SIZE,\n+\t\t\t\t      buf_count * per_buf_size,\n \t\t\t\t\tp_addr,\n \t\t\t\t\tGFP_KERNEL | __GFP_NOWARN);\n \tif (!*v_addr) {\n@@ -242,16 +326,37 @@ static int btintel_pcie_alloc_dbgc_buf(struct btintel_pcie_data *data,\n \n \tfor (i = 0; i \u003c buf_count; i++) {\n \t\tb = \u0026(*buf)[i];\n-\t\tb-\u003edata_p_addr = *p_addr + i * BTINTEL_PCIE_DBGC_BUFFER_SIZE;\n-\t\tb-\u003edata = *v_addr + i * BTINTEL_PCIE_DBGC_BUFFER_SIZE;\n+\t\tb-\u003edata_p_addr = *p_addr + i * per_buf_size;\n+\t\tb-\u003edata = *v_addr + i * per_buf_size;\n \t\tfrag[i].buf_addr_lsb = lower_32_bits(b-\u003edata_p_addr);\n \t\tfrag[i].buf_addr_msb = upper_32_bits(b-\u003edata_p_addr);\n-\t\tfrag[i].buf_size = BTINTEL_PCIE_DBGC_BUFFER_SIZE;\n+\t\tfrag[i].buf_size = per_buf_size;\n \t}\n+\tBT_INFO(\"DBGC allocation %u: fragments=%u fragment_size=%u total=%u\",\n+\t\tbuf_index + 1, buf_count, per_buf_size, buf_count * per_buf_size);\n \n \treturn 0;\n }\n \n+static bool btintel_pcie_get_mdbgc_cfg(struct btintel_pcie_data *data,\n+\t\t\t\t       u32 alloc_id, u32 *count, u32 *size)\n+{\n+\tconst struct btintel_pcie_buf_alloc *alloc;\n+\n+\talloc = btintel_pcie_yoyo_get_buf_alloc(\u0026data-\u003eyoyo, alloc_id);\n+\tif (alloc) {\n+\t\t*count = alloc-\u003emax_num_frags;\n+\t\t*size = alloc-\u003ereq_buf_size / alloc-\u003emax_num_frags;\n+\t\treturn true;\n+\t}\n+\tif (data-\u003eyoyo.enabled)\n+\t\treturn false;\n+\n+\t*count = BTINTEL_PCIE_DBGC_BUFFER_COUNT;\n+\t*size = BTINTEL_PCIE_DBGC_BUFFER_SIZE;\n+\treturn true;\n+}\n+\n /* This function initializes the memory for MDBGC buffers and formats the\n  * DBGC fragment which consists header info and DBGC buffer's LSB, MSB and\n  * size as the payload\n@@ -261,10 +366,9 @@ static int btintel_pcie_setup_mdbgc(struct btintel_pcie_data *data)\n \tstruct btintel_pcie_mdbgc_ctxt db_frag;\n \tu32 frag_size = sizeof(db_frag);\n \tvoid *frag_v_addr;\n+\tu32 buf_count, buf_size;\n \tint err;\n \n-\tdata-\u003emdbgc.count = BTINTEL_PCIE_DBGC_BUFFER_COUNT;\n-\n \t/* Allocate fragment context structure */\n \tfrag_v_addr = dmam_alloc_coherent(\u0026data-\u003epdev-\u003edev, frag_size,\n \t\t\t\t\t  \u0026data-\u003emdbgc.frag_p_addr,\n@@ -283,46 +387,56 @@ static int btintel_pcie_setup_mdbgc(struct btintel_pcie_data *data)\n \tdb_frag.ver = BTINTEL_PCIE_MDBGC_FRAG_VERSION;\n \n \t/* Allocate DBGC buffer 1 */\n-\tdb_frag.buf1_index = BTINTEL_PCIE_MDBGC_ALLOCATIONID_1;\n-\tdb_frag.buf1_count = data-\u003emdbgc.count;\n-\terr = btintel_pcie_alloc_dbgc_buf(data,\n-\t\t\t\t\t  \u0026data-\u003emdbgc.buf1,\n-\t\t\t\t\t  \u0026data-\u003emdbgc.buf1_p_addr,\n-\t\t\t\t\t  \u0026data-\u003emdbgc.buf1_v_addr,\n-\t\t\t\t\t  db_frag.buf1,\n-\t\t\t\t\t  0,\n-\t\t\t\t\t  data-\u003emdbgc.count);\n-\tif (err)\n-\t\treturn err;\n+\tif (btintel_pcie_get_mdbgc_cfg(data, BTINTEL_PCIE_ALLOC_ID_DBGC1,\n+\t\t\t\t       \u0026buf_count, \u0026buf_size)) {\n+\t\tdb_frag.buf1_index = BTINTEL_PCIE_MDBGC_ALLOCATIONID_1;\n+\t\tdb_frag.buf1_count = buf_count;\n+\t\tdata-\u003emdbgc.buf1_count = buf_count;\n+\t\tdata-\u003emdbgc.buf1_size = buf_size;\n+\t\terr = btintel_pcie_alloc_dbgc_buf(data, \u0026data-\u003emdbgc.buf1,\n+\t\t\t\t\t\t  \u0026data-\u003emdbgc.buf1_p_addr,\n+\t\t\t\t\t  \u0026data-\u003emdbgc.buf1_v_addr, db_frag.buf1,\n+\t\t\t\t\t  0, buf_count, buf_size);\n+\t\tif (err)\n+\t\t\treturn err;\n+\t}\n \n \t/* Allocate DBGC buffer 2 */\n-\tdb_frag.buf2_index = BTINTEL_PCIE_MDBGC_ALLOCATIONID_2;\n-\tdb_frag.buf2_count = data-\u003emdbgc.count;\n-\terr = btintel_pcie_alloc_dbgc_buf(data,\n-\t\t\t\t\t  \u0026data-\u003emdbgc.buf2,\n-\t\t\t\t\t  \u0026data-\u003emdbgc.buf2_p_addr,\n-\t\t\t\t\t  \u0026data-\u003emdbgc.buf2_v_addr,\n-\t\t\t\t\t  db_frag.buf2,\n-\t\t\t\t\t  1,\n-\t\t\t\t\t  data-\u003emdbgc.count);\n-\tif (err)\n-\t\treturn err;\n+\tif (btintel_pcie_get_mdbgc_cfg(data, BTINTEL_PCIE_ALLOC_ID_DBGC2,\n+\t\t\t\t       \u0026buf_count, \u0026buf_size)) {\n+\t\tdb_frag.buf2_index = BTINTEL_PCIE_MDBGC_ALLOCATIONID_2;\n+\t\tdb_frag.buf2_count = buf_count;\n+\t\tdata-\u003emdbgc.buf2_count = buf_count;\n+\t\tdata-\u003emdbgc.buf2_size = buf_size;\n+\t\terr = btintel_pcie_alloc_dbgc_buf(data, \u0026data-\u003emdbgc.buf2,\n+\t\t\t\t\t\t  \u0026data-\u003emdbgc.buf2_p_addr,\n+\t\t\t\t\t  \u0026data-\u003emdbgc.buf2_v_addr, db_frag.buf2,\n+\t\t\t\t\t  1, buf_count, buf_size);\n+\t\tif (err)\n+\t\t\treturn err;\n+\t}\n \n \t/* Allocate DBGC buffer 3 */\n-\tdb_frag.buf3_index = BTINTEL_PCIE_MDBGC_ALLOCATIONID_3;\n-\tdb_frag.buf3_count = data-\u003emdbgc.count;\n-\terr = btintel_pcie_alloc_dbgc_buf(data,\n-\t\t\t\t\t  \u0026data-\u003emdbgc.buf3,\n-\t\t\t\t\t  \u0026data-\u003emdbgc.buf3_p_addr,\n-\t\t\t\t\t  \u0026data-\u003emdbgc.buf3_v_addr,\n-\t\t\t\t\t  db_frag.buf3,\n-\t\t\t\t\t  2,\n-\t\t\t\t\t  data-\u003emdbgc.count);\n-\tif (err)\n-\t\treturn err;\n+\tif (btintel_pcie_get_mdbgc_cfg(data, BTINTEL_PCIE_ALLOC_ID_DBGC3,\n+\t\t\t\t       \u0026buf_count, \u0026buf_size)) {\n+\t\tdb_frag.buf3_index = BTINTEL_PCIE_MDBGC_ALLOCATIONID_3;\n+\t\tdb_frag.buf3_count = buf_count;\n+\t\tdata-\u003emdbgc.buf3_count = buf_count;\n+\t\tdata-\u003emdbgc.buf3_size = buf_size;\n+\t\terr = btintel_pcie_alloc_dbgc_buf(data, \u0026data-\u003emdbgc.buf3,\n+\t\t\t\t\t\t  \u0026data-\u003emdbgc.buf3_p_addr,\n+\t\t\t\t\t  \u0026data-\u003emdbgc.buf3_v_addr, db_frag.buf3,\n+\t\t\t\t\t  2, buf_count, buf_size);\n+\t\tif (err)\n+\t\t\treturn err;\n+\t}\n \n \t/* Copy fragment to DMA coherent memory */\n \tmemcpy(data-\u003emdbgc.frag_v_addr, \u0026db_frag, sizeof(db_frag));\n+\tBT_INFO(\"MDBGC fragments: DBGC1=%u/%u DBGC2=%u/%u DBGC3=%u/%u\",\n+\t\tdb_frag.buf1_count, data-\u003emdbgc.buf1_size,\n+\t\tdb_frag.buf2_count, data-\u003emdbgc.buf2_size,\n+\t\tdb_frag.buf3_count, data-\u003emdbgc.buf3_size);\n \treturn 0;\n }\n \n@@ -334,9 +448,17 @@ static int btintel_pcie_setup_dbgc(struct btintel_pcie_data *data)\n {\n \tstruct btintel_pcie_dbgc_ctxt db_frag;\n \tu32 frag_size = sizeof(db_frag);\n+\tconst struct btintel_pcie_buf_alloc *alloc;\n+\tu32 buf_count, buf_size;\n \tint err;\n \n-\tdata-\u003edbgc.count = BTINTEL_PCIE_DBGC_BUFFER_COUNT;\n+\talloc = btintel_pcie_yoyo_get_buf_alloc(\u0026data-\u003eyoyo,\n+\t\t\t\t\t\tBTINTEL_PCIE_ALLOC_ID_DBGC1);\n+\tbuf_count = alloc ? alloc-\u003emax_num_frags : BTINTEL_PCIE_DBGC_BUFFER_COUNT;\n+\tbuf_size = alloc ? alloc-\u003ereq_buf_size / alloc-\u003emax_num_frags :\n+\t\tBTINTEL_PCIE_DBGC_BUFFER_SIZE;\n+\tdata-\u003edbgc.count = buf_count;\n+\tdata-\u003edbgc.buf_size = buf_size;\n \n \t/* Allocate fragment context structure */\n \tdata-\u003edbgc.frag_v_addr = dmam_alloc_coherent(\u0026data-\u003epdev-\u003edev,\n@@ -354,8 +476,9 @@ static int btintel_pcie_setup_dbgc(struct btintel_pcie_data *data)\n \tmemset(\u0026db_frag, 0, sizeof(db_frag));\n \tdb_frag.magic_num = BTINTEL_PCIE_MAGIC_NUM;\n \tdb_frag.ver = BTINTEL_PCIE_DBGC_FRAG_VERSION;\n-\tdb_frag.total_size = BTINTEL_PCIE_DBGC_FRAG_PAYLOAD_SIZE;\n-\tdb_frag.num_buf = BTINTEL_PCIE_DBGC_FRAG_BUFFER_COUNT;\n+\tdb_frag.total_size = sizeof(db_frag.num_buf) +\n+\t\t\t     buf_count * sizeof(db_frag.bufs[0]);\n+\tdb_frag.num_buf = buf_count;\n \n \t/* Allocate DBGC buffers */\n \terr = btintel_pcie_alloc_dbgc_buf(data,\n@@ -364,7 +487,8 @@ static int btintel_pcie_setup_dbgc(struct btintel_pcie_data *data)\n \t\t\t\t\t  \u0026data-\u003edbgc.buf_v_addr,\n \t\t\t\t\t  db_frag.bufs,\n \t\t\t\t\t  0,\n-\t\t\t\t\t  data-\u003edbgc.count);\n+\t\t\t\t\t  buf_count,\n+\t\t\t\t\t  buf_size);\n \tif (err)\n \t\treturn err;\n \n@@ -857,7 +981,8 @@ static u32 btintel_pcie_dump_list_total_size(struct list_head *list)\n }\n \n static int btintel_pcie_dump_dram(struct list_head *list,\n-\t\t\t\t  u8 count, struct data_buf *bufs,\n+\t\t\t\t  u8 count, u32 buf_size,\n+\t\t\t\t  struct data_buf *bufs,\n \t\t\t\t  u32 write_ptr, u32 wrap_ctr, u32 cur_frag,\n \t\t\t\t  u32 region_id, const char *name)\n {\n@@ -869,7 +994,7 @@ static int btintel_pcie_dump_dram(struct list_head *list,\n \tint i;\n \n \tmon_hdr_size = sizeof(*mon_dump);\n-\tranges_size = count * (sizeof(*range) + BTINTEL_PCIE_DBGC_BUFFER_SIZE);\n+\tranges_size = count * (sizeof(*range) + buf_size);\n \tpayload_size = mon_hdr_size + ranges_size;\n \ttotal_size = sizeof(*dump_data) + payload_size;\n \n@@ -898,12 +1023,10 @@ static int btintel_pcie_dump_dram(struct list_head *list,\n \n \trange = (void *)mon_dump-\u003edata;\n \tfor (i = 0; i \u003c count; i++) {\n-\t\trange-\u003erange_data_size =\n-\t\t\tcpu_to_le32(BTINTEL_PCIE_DBGC_BUFFER_SIZE);\n+\t\trange-\u003erange_data_size = cpu_to_le32(buf_size);\n \t\trange-\u003edram_base_addr = cpu_to_le64(bufs[i].data_p_addr);\n-\t\tmemcpy(range-\u003edata, bufs[i].data,\n-\t\t       BTINTEL_PCIE_DBGC_BUFFER_SIZE);\n-\t\trange = (void *)range-\u003edata + BTINTEL_PCIE_DBGC_BUFFER_SIZE;\n+\t\tmemcpy(range-\u003edata, bufs[i].data, buf_size);\n+\t\trange = (void *)range-\u003edata + buf_size;\n \t}\n \n \tlist_add_tail(\u0026entry-\u003elist, list);\n@@ -913,6 +1036,7 @@ static int btintel_pcie_dump_dram(struct list_head *list,\n static int\n btintel_pcie_dump_dram_monitor(struct btintel_pcie_data *data,\n \t\t\t       struct list_head *list, u8 count,\n+\t\t\t       u32 buf_size,\n \t\t\t       struct data_buf *bufs, u32 status_reg,\n \t\t\t       u32 wrap_reg, u8 allocation_id, u32 region_id,\n \t\t\t       const char *name)\n@@ -920,6 +1044,9 @@ btintel_pcie_dump_dram_monitor(struct btintel_pcie_data *data,\n \tu32 allocation_offset, write_ptr, wrap_ctr, wr_ptr_status;\n \tu8 cur_frag;\n \n+\tif (!count)\n+\t\treturn -ENOENT;\n+\n \tallocation_offset = allocation_id *\n \t\t\t    BTINTEL_PCIE_DBGC_ALLOCATION_OFFSET;\n \twr_ptr_status = btintel_pcie_rd_dev_mem(data, status_reg +\n@@ -941,8 +1068,8 @@ btintel_pcie_dump_dram_monitor(struct btintel_pcie_data *data,\n \t\t   \"allocation=%u wr_ptr_status=0x%08x write_ptr=0x%06x cur_frag=%u wrap_ctr=0x%08x\",\n \t\t   allocation_id, wr_ptr_status, write_ptr, cur_frag, wrap_ctr);\n \n-\treturn btintel_pcie_dump_dram(list, count, bufs, write_ptr, wrap_ctr,\n-\t\t\t\t      cur_frag, region_id, name);\n+\treturn btintel_pcie_dump_dram(list, count, buf_size, bufs, write_ptr,\n+\t\t\t\t      wrap_ctr, cur_frag, region_id, name);\n }\n \n static int btintel_pcie_dump_target_region(struct btintel_pcie_data *data,\n@@ -1223,6 +1350,7 @@ static int btintel_pcie_read_debug_regions(struct btintel_pcie_data *data)\n \tu8 hw_variant;\n \tu32 file_len;\n \tu8 count;\n+\tu32 buf_size;\n \tint ret;\n \tLIST_HEAD(dump_list);\n \n@@ -1231,10 +1359,10 @@ static int btintel_pcie_read_debug_regions(struct btintel_pcie_data *data)\n \n \tif (btintel_pcie_is_mdbgc_supported(data)) {\n \t\tmdbgc = \u0026data-\u003emdbgc;\n-\t\tcount = mdbgc-\u003ecount;\n \t} else {\n \t\tdbgc = \u0026data-\u003edbgc;\n \t\tcount = dbgc-\u003ecount;\n+\t\tbuf_size = dbgc-\u003ebuf_size;\n \t}\n \n \thw_variant = INTEL_HW_VARIANT(data-\u003ecnvi);\n@@ -1254,7 +1382,9 @@ static int btintel_pcie_read_debug_regions(struct btintel_pcie_data *data)\n \t}\n \n \tif (btintel_pcie_is_mdbgc_supported(data)) {\n-\t\tret = btintel_pcie_dump_dram_monitor(data, \u0026dump_list, count,\n+\t\tret = btintel_pcie_dump_dram_monitor(data, \u0026dump_list,\n+\t\t\t\t\t\t     mdbgc-\u003ebuf1_count,\n+\t\t\t\t\t\t     mdbgc-\u003ebuf1_size,\n \t\t\t\t\t\t     mdbgc-\u003ebuf1, status_reg,\n \t\t\t\t\t\t     wrap_reg,\n \t\t\t\t\t\t     BTINTEL_PCIE_MDBGC_ALLOCATIONID_1,\n@@ -1263,10 +1393,12 @@ static int btintel_pcie_read_debug_regions(struct btintel_pcie_data *data)\n \t\tif (!ret)\n \t\t\tregions_mask |=\n \t\t\t\tBIT_ULL(BTINTEL_PCIE_INI_ID_DRAM_MONITOR1);\n-\t\telse\n+\t\telse if (ret != -ENOENT)\n \t\t\tbt_dev_warn(hdev, \"Failed to dump DRAM buf1: %d\", ret);\n \n-\t\tret = btintel_pcie_dump_dram_monitor(data, \u0026dump_list, count,\n+\t\tret = btintel_pcie_dump_dram_monitor(data, \u0026dump_list,\n+\t\t\t\t\t\t     mdbgc-\u003ebuf2_count,\n+\t\t\t\t\t\t     mdbgc-\u003ebuf2_size,\n \t\t\t\t\t\t     mdbgc-\u003ebuf2, status_reg,\n \t\t\t\t\t\t     wrap_reg,\n \t\t\t\t\t\t     BTINTEL_PCIE_MDBGC_ALLOCATIONID_2,\n@@ -1275,10 +1407,12 @@ static int btintel_pcie_read_debug_regions(struct btintel_pcie_data *data)\n \t\tif (!ret)\n \t\t\tregions_mask |=\n \t\t\t\tBIT_ULL(BTINTEL_PCIE_INI_ID_DRAM_MONITOR2);\n-\t\telse\n+\t\telse if (ret != -ENOENT)\n \t\t\tbt_dev_warn(hdev, \"Failed to dump DRAM buf2: %d\", ret);\n \n-\t\tret = btintel_pcie_dump_dram_monitor(data, \u0026dump_list, count,\n+\t\tret = btintel_pcie_dump_dram_monitor(data, \u0026dump_list,\n+\t\t\t\t\t\t     mdbgc-\u003ebuf3_count,\n+\t\t\t\t\t\t     mdbgc-\u003ebuf3_size,\n \t\t\t\t\t\t     mdbgc-\u003ebuf3, status_reg,\n \t\t\t\t\t\t     wrap_reg,\n \t\t\t\t\t\t     BTINTEL_PCIE_MDBGC_ALLOCATIONID_3,\n@@ -1287,11 +1421,12 @@ static int btintel_pcie_read_debug_regions(struct btintel_pcie_data *data)\n \t\tif (!ret)\n \t\t\tregions_mask |=\n \t\t\t\tBIT_ULL(BTINTEL_PCIE_INI_ID_DRAM_MONITOR3);\n-\t\telse\n+\t\telse if (ret != -ENOENT)\n \t\t\tbt_dev_warn(hdev, \"Failed to dump DRAM buf3: %d\", ret);\n \t} else {\n \t\tret = btintel_pcie_dump_dram_monitor(data, \u0026dump_list, count,\n-\t\t\t\t\t\t     dbgc-\u003ebufs, status_reg,\n+\t\t\t\t\t\t     buf_size, dbgc-\u003ebufs,\n+\t\t\t\t\t\t     status_reg,\n \t\t\t\t\t\t     wrap_reg,\n \t\t\t\t\t\t     BTINTEL_PCIE_MDBGC_ALLOCATIONID_1,\n \t\t\t\t\t\t     BTINTEL_PCIE_INI_ID_DRAM_MONITOR1,\n@@ -4101,6 +4236,22 @@ static int btintel_pcie_probe(struct pci_dev *pdev,\n \t * initialized\n \t */\n \tdata-\u003ereset_type = BTINTEL_PCIE_IOSF_PRR_FLR;\n+\tdata-\u003eenable_ini = false;\n+\tbtintel_pcie_yoyo_init(\u0026data-\u003eyoyo);\n+\tbtintel_pcie_load_dbg_path_from_ini(data);\n+\n+\t/* YoYo configuration is supported only with host DRAM debug routing. */\n+\tif (data-\u003edbg_path_cache != BTINTEL_PCIE_DRAM)\n+\t\tdata-\u003eenable_ini = false;\n+\n+\tif (data-\u003eenable_ini) {\n+\t\terr = btintel_pcie_yoyo_load_and_parse(\u0026data-\u003eyoyo, \u0026pdev-\u003edev);\n+\t\tif (err) {\n+\t\t\tBT_WARN(\"YoYo configuration is invalid (%d); keeping legacy defaults\",\n+\t\t\t\terr);\n+\t\t\tbtintel_pcie_yoyo_cleanup(\u0026data-\u003eyoyo);\n+\t\t}\n+\t}\n \terr = btintel_pcie_config_pcie(pdev, data);\n \tif (err)\n \t\tgoto exit_error;\n@@ -4128,11 +4279,14 @@ static int btintel_pcie_probe(struct pci_dev *pdev,\n \tif (err)\n \t\tgoto exit_error;\n \n+\tdata-\u003eyoyo.hdev = data-\u003ehdev;\n \tbt_dev_dbg(data-\u003ehdev, \"cnvi: 0x%8.8x cnvr: 0x%8.8x\", data-\u003ecnvi,\n \t\t   data-\u003ecnvr);\n \treturn 0;\n \n exit_error:\n+\tbtintel_pcie_yoyo_cleanup(\u0026data-\u003eyoyo);\n+\n \t/* reset device before exit */\n \tbtintel_pcie_reset_bt(data);\n \n@@ -4173,6 +4327,8 @@ static void btintel_pcie_remove(struct pci_dev *pdev)\n \tif (current_work() != \u0026data-\u003ereset_work)\n \t\tdisable_work_sync(\u0026data-\u003ereset_work);\n \n+\tbtintel_pcie_yoyo_cleanup(\u0026data-\u003eyoyo);\n+\n \tbtintel_pcie_disable_interrupts(data);\n \n \tbtintel_pcie_synchronize_irqs(data);\ndiff --git a/drivers/bluetooth/btintel_pcie.h b/drivers/bluetooth/btintel_pcie.h\nindex 3030b4e8b7503..3827527c5b4d5 100644\n--- a/drivers/bluetooth/btintel_pcie.h\n+++ b/drivers/bluetooth/btintel_pcie.h\n@@ -6,6 +6,8 @@\n  *  Copyright (C) 2024  Intel Corporation\n  */\n \n+#include \"btintel_pcie_debug.h\"\n+\n /* Control and Status Register(BTINTEL_PCIE_CSR) */\n #define BTINTEL_PCIE_CSR_BASE\t\t\t(0x000)\n #define BTINTEL_PCIE_CSR_FUNC_CTRL_REG\t\t(BTINTEL_PCIE_CSR_BASE + 0x024)\n@@ -466,6 +468,7 @@ struct rxq {\n  */\n struct btintel_pcie_dbgc {\n \tu16\t\tcount;\n+\tu32\t\tbuf_size;\n \n \tvoid\t\t*frag_v_addr;\n \tdma_addr_t\tfrag_p_addr;\n@@ -477,7 +480,12 @@ struct btintel_pcie_dbgc {\n };\n \n struct btintel_pcie_mdbgc {\n-\tu32\t\tcount;\n+\tu32\t\tbuf1_count;\n+\tu32\t\tbuf1_size;\n+\tu32\t\tbuf2_count;\n+\tu32\t\tbuf2_size;\n+\tu32\t\tbuf3_count;\n+\tu32\t\tbuf3_size;\n \n \tvoid\t\t*frag_v_addr;\n \tdma_addr_t\tfrag_p_addr;\n@@ -737,6 +745,7 @@ struct btintel_pcie_data {\n \tu32\tboot_stage_cache;\n \tu32\timg_resp_cache;\n \tu32\tdbg_path_cache;\n+\tbool\tenable_ini;\n \n \tu32\tcnvi;\n \tu32\tcnvr;\n@@ -778,6 +787,7 @@ struct btintel_pcie_data {\n \tu32\tdebug_table_size;\n \tstruct btintel_pcie_dump_mem_info\tdump_info;\n \tstruct btintel_pcie_mbox\tmbox;\n+\tstruct btintel_pcie_yoyo_ctx yoyo;\n \n \t/* Wait queue for mbox_worker to wait for GP0 alive interrupt */\n \twait_queue_head_t\tmbox_parse_wait_q;\ndiff --git a/drivers/bluetooth/btintel_pcie_debug.c b/drivers/bluetooth/btintel_pcie_debug.c\nnew file mode 100644\nindex 0000000000000..806017b222093\n--- /dev/null\n+++ b/drivers/bluetooth/btintel_pcie_debug.c\n@@ -0,0 +1,271 @@\n+// SPDX-License-Identifier: GPL-2.0-only\n+/* Intel Bluetooth PCIe YoYo debug configuration support. */\n+\n+#include \u003clinux/errno.h\u003e\n+#include \u003clinux/firmware.h\u003e\n+#include \u003clinux/module.h\u003e\n+#include \u003clinux/stddef.h\u003e\n+#include \u003clinux/string.h\u003e\n+#include \u003clinux/unaligned.h\u003e\n+#include \u003cnet/bluetooth/bluetooth.h\u003e\n+\n+#include \"btintel_pcie_debug.h\"\n+\n+static int btintel_pcie_yoyo_parse_dbg_info(struct btintel_pcie_yoyo_ctx *ctx,\n+\t\t\t\t\t    const struct btintel_pcie_tlv_dbg_info *info,\n+\t\t\t\t\t    u32 len)\n+{\n+\tconst u8 *data = (const u8 *)info;\n+\tu32 domain, image_type, core_type, version;\n+\n+\tif (len != sizeof(*info) - sizeof(struct btintel_pcie_tlv_hdr))\n+\t\treturn -EBADMSG;\n+\n+\timage_type = get_unaligned_le32(data +\n+\t\t\t\t       offsetof(struct btintel_pcie_tlv_dbg_info,\n+\t\t\t\t\t\timage_type));\n+\tcore_type = get_unaligned_le32(data +\n+\t\t\t\t      offsetof(struct btintel_pcie_tlv_dbg_info,\n+\t\t\t\t\t       core_type));\n+\tdomain = get_unaligned_le32(data +\n+\t\t\t\t   offsetof(struct btintel_pcie_tlv_dbg_info,\n+\t\t\t\t\t    dbg_hdr.domain));\n+\tversion = get_unaligned_le32(data +\n+\t\t\t\t     offsetof(struct btintel_pcie_tlv_dbg_info,\n+\t\t\t\t\t      dbg_hdr.tlv_data_version));\n+\n+\tif (domain != BTINTEL_PCIE_DOMAIN_BT ||\n+\t    version != BTINTEL_PCIE_DBG_INFO_TLV_VERSION) {\n+\t\tBT_WARN(\"YoYo: unsupported domain/version (%u/%u), disabling\",\n+\t\t\tdomain, version);\n+\t\treturn -EINVAL;\n+\t}\n+\tif (image_type != BTINTEL_PCIE_IMAGE_TLV_TYPE_EXTERNAL) {\n+\t\tBT_WARN(\"YoYo: unsupported image_type 0x%x, disabling\", image_type);\n+\t\treturn -EINVAL;\n+\t}\n+\tif (core_type != BTINTEL_PCIE_CORE_TYPE_BT) {\n+\t\tBT_WARN(\"YoYo: non-Bluetooth core_type %u, disabling\", core_type);\n+\t\treturn -EINVAL;\n+\t}\n+\n+\tctx-\u003edbg_info_present = true;\n+\tBT_DBG(\"YoYo: config='%.64s' image=%u core=%u\",\n+\t       info-\u003econfig_name, image_type, core_type);\n+\treturn 0;\n+}\n+\n+static int btintel_pcie_yoyo_parse_buf_alloc(struct btintel_pcie_yoyo_ctx *ctx,\n+\t\t\t\t\t     const struct btintel_pcie_tlv_buf_alloc *tlv,\n+\t\t\t\t\t     u32 len)\n+{\n+\tu32 alloc_id, buf_location, domain, idx, max_num_frags, min_buf_size;\n+\tu32 req_buf_size, version;\n+\n+\tif (len != sizeof(*tlv) - sizeof(struct btintel_pcie_tlv_hdr)) {\n+\t\tBT_WARN(\"YoYo: unexpected buffer allocation TLV length %u\", len);\n+\t\treturn -EBADMSG;\n+\t}\n+\n+\tdomain = get_unaligned_le32(\u0026tlv-\u003edbg_hdr.domain);\n+\tversion = get_unaligned_le32(\u0026tlv-\u003edbg_hdr.tlv_data_version);\n+\tif (domain != BTINTEL_PCIE_DOMAIN_BT ||\n+\t    version != BTINTEL_PCIE_BUF_ALLOC_TLV_VERSION) {\n+\t\tBT_WARN(\"YoYo: unsupported buffer allocation domain/version (%u/%u)\",\n+\t\t\tdomain, version);\n+\t\treturn -EINVAL;\n+\t}\n+\n+\talloc_id = get_unaligned_le32(\u0026tlv-\u003ealloc_id);\n+\tif (alloc_id \u003c BTINTEL_PCIE_ALLOC_ID_DBGC1 ||\n+\t    alloc_id \u003e BTINTEL_PCIE_ALLOC_ID_DBGC3) {\n+\t\tBT_WARN(\"YoYo: invalid buffer allocation ID %u\", alloc_id);\n+\t\treturn -EINVAL;\n+\t}\n+\n+\tidx = alloc_id - BTINTEL_PCIE_ALLOC_ID_DBGC1;\n+\tbuf_location = get_unaligned_le32(\u0026tlv-\u003ebuf_location);\n+\tmax_num_frags = get_unaligned_le32(\u0026tlv-\u003emax_num_frags);\n+\tmin_buf_size = get_unaligned_le32(\u0026tlv-\u003emin_buf_size);\n+\treq_buf_size = get_unaligned_le32(\u0026tlv-\u003ereq_buf_size);\n+\tif (buf_location != BTINTEL_PCIE_BUF_LOC_DRAM) {\n+\t\tBT_WARN(\"YoYo: allocation %u requests unsupported location %u\",\n+\t\t\talloc_id, buf_location);\n+\t\treturn -EINVAL;\n+\t}\n+\n+\tif (!max_num_frags || max_num_frags \u003e BTINTEL_PCIE_MAX_BUF_FRAGS ||\n+\t    min_buf_size \u003c BTINTEL_PCIE_MIN_BUF_SIZE ||\n+\t    min_buf_size \u003e BTINTEL_PCIE_MAX_BUF_SIZE ||\n+\t    req_buf_size \u003e BTINTEL_PCIE_MAX_BUF_SIZE ||\n+\t    req_buf_size % max_num_frags ||\n+\t    req_buf_size / max_num_frags \u003c min_buf_size) {\n+\t\tBT_WARN(\"YoYo: invalid allocation %u size=%u fragments=%u minimum=%u\",\n+\t\t\talloc_id, req_buf_size, max_num_frags, min_buf_size);\n+\t\treturn -EINVAL;\n+\t}\n+\n+\tctx-\u003ebuf_alloc[idx].alloc_id = alloc_id;\n+\tctx-\u003ebuf_alloc[idx].buf_location = buf_location;\n+\tctx-\u003ebuf_alloc[idx].req_buf_size = req_buf_size;\n+\tctx-\u003ebuf_alloc[idx].max_num_frags = max_num_frags;\n+\tctx-\u003ebuf_alloc[idx].min_buf_size = min_buf_size;\n+\tctx-\u003ebuf_alloc[idx].present = true;\n+\tctx-\u003enum_buf_allocs = max(ctx-\u003enum_buf_allocs, idx + 1);\n+\tBT_DBG(\"YoYo: allocation %u location=%u size=%u fragments=%u minimum=%u\",\n+\t       alloc_id, buf_location, req_buf_size, max_num_frags, min_buf_size);\n+\treturn 0;\n+}\n+\n+static int btintel_pcie_yoyo_parse_tlv_buffer(struct btintel_pcie_yoyo_ctx *ctx,\n+\t\t\t\t\t      const u8 *buf, size_t buf_len)\n+{\n+\tconst u8 *ptr = buf;\n+\tsize_t remaining = buf_len;\n+\tu32 count = 0;\n+\tint err;\n+\n+\tif (!ctx || !buf)\n+\t\treturn -EINVAL;\n+\n+\twhile (remaining \u003e= sizeof(struct btintel_pcie_tlv_hdr)) {\n+\t\tu32 type = get_unaligned_le32(ptr);\n+\t\tu32 len = get_unaligned_le32(ptr + sizeof(__le32));\n+\n+\t\tif (len \u003e remaining - sizeof(struct btintel_pcie_tlv_hdr)) {\n+\t\t\tBT_ERR(\"YoYo: TLV %u truncated (len=%u remaining=%zu)\",\n+\t\t\t       count, len, remaining);\n+\t\t\treturn -EBADMSG;\n+\t\t}\n+\n+\t\tswitch (type) {\n+\t\tcase BTINTEL_PCIE_TLV_TYPE_DBG_INFO:\n+\t\t\terr = btintel_pcie_yoyo_parse_dbg_info(ctx,\n+\t\t\t\t\t\t\t       (const void *)ptr,\n+\t\t\t\t\t\t\t\t       len);\n+\t\t\tif (err) {\n+\t\t\t\tctx-\u003edbg_info_present = false;\n+\t\t\t\treturn err;\n+\t\t\t}\n+\t\t\tbreak;\n+\t\tcase BTINTEL_PCIE_TLV_TYPE_DBG_BUF_ALLOC:\n+\t\t\terr = btintel_pcie_yoyo_parse_buf_alloc(ctx,\n+\t\t\t\t\t\t\t\t(const void *)ptr,\n+\t\t\t\t\t\t\t\t       len);\n+\t\t\tif (err)\n+\t\t\t\treturn err;\n+\t\t\tbreak;\n+\t\tcase BTINTEL_PCIE_TLV_TYPE_DBG_REGION:\n+\t\tcase BTINTEL_PCIE_TLV_TYPE_DBG_TRIGGER:\n+\t\tcase BTINTEL_PCIE_TLV_TYPE_DBG_HCMD:\n+\t\tcase BTINTEL_PCIE_TLV_TYPE_DBG_CONFIG_SET:\n+\t\tcase BTINTEL_PCIE_TLV_TYPE_DBG_PRESET_OVERRIDE:\n+\t\t\tBT_DBG(\"YoYo: recognized TLV type 0x%x len=%u\", type, len);\n+\t\t\tbreak;\n+\t\tdefault:\n+\t\t\tBT_DBG(\"YoYo: unknown TLV type 0x%x len=%u\", type, len);\n+\t\t\tbreak;\n+\t\t}\n+\n+\t\tptr += sizeof(struct btintel_pcie_tlv_hdr) + len;\n+\t\tremaining -= sizeof(struct btintel_pcie_tlv_hdr) + len;\n+\t\tcount++;\n+\t}\n+\n+\tif (remaining || !count) {\n+\t\tBT_ERR(\"YoYo: invalid TLV stream (%zu trailing bytes, %u TLVs)\",\n+\t\t       remaining, count);\n+\t\treturn -EBADMSG;\n+\t}\n+\tif (!ctx-\u003edbg_info_present) {\n+\t\tBT_ERR(\"YoYo: mandatory DEBUG_INFO TLV missing\");\n+\t\treturn -EBADMSG;\n+\t}\n+\tif (!ctx-\u003enum_buf_allocs) {\n+\t\tBT_ERR(\"YoYo: mandatory buffer allocation TLV missing\");\n+\t\treturn -EBADMSG;\n+\t}\n+\treturn 0;\n+}\n+\n+int btintel_pcie_yoyo_init(struct btintel_pcie_yoyo_ctx *ctx)\n+{\n+\tif (!ctx)\n+\t\treturn -EINVAL;\n+\n+\tmemset(ctx, 0, sizeof(*ctx));\n+\tINIT_LIST_HEAD(\u0026ctx-\u003eregion_list);\n+\tINIT_LIST_HEAD(\u0026ctx-\u003etrigger_list);\n+\tINIT_LIST_HEAD(\u0026ctx-\u003ehcmd_list);\n+\tINIT_LIST_HEAD(\u0026ctx-\u003econfig_set_list);\n+\treturn 0;\n+}\n+EXPORT_SYMBOL_GPL(btintel_pcie_yoyo_init);\n+\n+void btintel_pcie_yoyo_cleanup(struct btintel_pcie_yoyo_ctx *ctx)\n+{\n+\tif (!ctx)\n+\t\treturn;\n+\n+\tctx-\u003eenabled = false;\n+\tctx-\u003edbg_info_present = false;\n+\tctx-\u003enum_buf_allocs = 0;\n+\tmemset(ctx-\u003ebuf_alloc, 0, sizeof(ctx-\u003ebuf_alloc));\n+}\n+EXPORT_SYMBOL_GPL(btintel_pcie_yoyo_cleanup);\n+\n+int btintel_pcie_yoyo_load_and_parse(struct btintel_pcie_yoyo_ctx *ctx,\n+\t\t\t\t     struct device *dev)\n+{\n+\tconst struct firmware *fw;\n+\tint err;\n+\n+\tif (!ctx || !dev)\n+\t\treturn -EINVAL;\n+\n+\terr = request_firmware_direct(\u0026fw, BTINTEL_PCIE_YOYO_FW_NAME, dev);\n+\tif (err) {\n+\t\tBT_ERR(\"YoYo: failed to load %s (%d)\",\n+\t\t       BTINTEL_PCIE_YOYO_FW_NAME, err);\n+\t\treturn err;\n+\t}\n+\n+\tif (fw-\u003esize \u003c sizeof(struct btintel_pcie_tlv_hdr))\n+\t\terr = -EBADMSG;\n+\telse\n+\t\terr = btintel_pcie_yoyo_parse_tlv_buffer(ctx, fw-\u003edata, fw-\u003esize);\n+\n+\trelease_firmware(fw);\n+\tif (err) {\n+\t\tBT_ERR(\"YoYo: TLV parsing failed (%d)\", err);\n+\t\treturn err;\n+\t}\n+\tif (!ctx-\u003edbg_info_present) {\n+\t\tBT_ERR(\"YoYo: mandatory DEBUG_INFO TLV missing; using legacy defaults\");\n+\t\treturn -EBADMSG;\n+\t}\n+\tctx-\u003eenabled = true;\n+\tBT_INFO(\"YoYo: configuration loaded and validated\");\n+\treturn 0;\n+}\n+EXPORT_SYMBOL_GPL(btintel_pcie_yoyo_load_and_parse);\n+\n+const struct btintel_pcie_buf_alloc *\n+btintel_pcie_yoyo_get_buf_alloc(struct btintel_pcie_yoyo_ctx *ctx, u32 alloc_id)\n+{\n+\tu32 idx;\n+\n+\tif (!ctx || !ctx-\u003eenabled ||\n+\t    alloc_id \u003c BTINTEL_PCIE_ALLOC_ID_DBGC1 ||\n+\t    alloc_id \u003e BTINTEL_PCIE_ALLOC_ID_DBGC3)\n+\t\treturn NULL;\n+\n+\tidx = alloc_id - BTINTEL_PCIE_ALLOC_ID_DBGC1;\n+\tif (!ctx-\u003ebuf_alloc[idx].present)\n+\t\treturn NULL;\n+\treturn \u0026ctx-\u003ebuf_alloc[idx];\n+}\n+EXPORT_SYMBOL_GPL(btintel_pcie_yoyo_get_buf_alloc);\n+\n+MODULE_DESCRIPTION(\"Intel Bluetooth PCIe YoYo debug configuration support\");\n+MODULE_LICENSE(\"GPL\");\ndiff --git a/drivers/bluetooth/btintel_pcie_debug.h b/drivers/bluetooth/btintel_pcie_debug.h\nnew file mode 100644\nindex 0000000000000..531a24c905b00\n--- /dev/null\n+++ b/drivers/bluetooth/btintel_pcie_debug.h\n@@ -0,0 +1,114 @@\n+/* SPDX-License-Identifier: GPL-2.0-only */\n+/* Intel Bluetooth PCIe YoYo debug configuration support. */\n+\n+#ifndef __BTINTEL_PCIE_DEBUG_H__\n+#define __BTINTEL_PCIE_DEBUG_H__\n+\n+#include \u003clinux/device.h\u003e\n+#include \u003clinux/list.h\u003e\n+#include \u003clinux/types.h\u003e\n+\n+#define BTINTEL_PCIE_YOYO_FW_NAME \"intel/ibt_debug_yoyo.bin\"\n+\n+#define BTINTEL_PCIE_TLV_TYPE_DBG_INFO\t\t0x01000005\n+#define BTINTEL_PCIE_TLV_TYPE_DBG_BUF_ALLOC\t0x01000006\n+#define BTINTEL_PCIE_TLV_TYPE_DBG_HCMD\t\t0x01000007\n+#define BTINTEL_PCIE_TLV_TYPE_DBG_REGION\t\t0x01000008\n+#define BTINTEL_PCIE_TLV_TYPE_DBG_TRIGGER\t0x01000009\n+#define BTINTEL_PCIE_TLV_TYPE_DBG_CONFIG_SET\t0x0100000a\n+#define BTINTEL_PCIE_TLV_TYPE_DBG_PRESET_OVERRIDE 0x0100000b\n+\n+#define BTINTEL_PCIE_DBG_INFO_TLV_VERSION\t2\n+#define BTINTEL_PCIE_BUF_ALLOC_TLV_VERSION\t1\n+#define BTINTEL_PCIE_CONFIG_NAME_LEN\t\t64\n+#define BTINTEL_PCIE_DOMAIN_BT\t\t\t0\n+#define BTINTEL_PCIE_CORE_TYPE_BT\t\t1\n+#define BTINTEL_PCIE_MAX_BUF_ALLOC\t\t3\n+#define BTINTEL_PCIE_MAX_BUF_FRAGS\t\t16\n+#define BTINTEL_PCIE_MIN_BUF_SIZE\t\t(32 * 1024)\n+#define BTINTEL_PCIE_MAX_BUF_SIZE\t\t(4 * 1024 * 1024)\n+\n+enum btintel_pcie_image_tlv_type {\n+\tBTINTEL_PCIE_IMAGE_TLV_TYPE_EXTERNAL = 0x1,\n+\tBTINTEL_PCIE_IMAGE_TLV_TYPE_INTERNAL = 0x2,\n+\tBTINTEL_PCIE_IMAGE_TLV_TYPE_UNKNOWN = 0xff,\n+};\n+\n+enum btintel_dbg_alloc_id {\n+\tBTINTEL_PCIE_ALLOC_ID_INVALID = 0,\n+\tBTINTEL_PCIE_ALLOC_ID_DBGC1 = 1,\n+\tBTINTEL_PCIE_ALLOC_ID_DBGC2 = 2,\n+\tBTINTEL_PCIE_ALLOC_ID_DBGC3 = 3,\n+\tBTINTEL_PCIE_ALLOC_ID_MAX,\n+};\n+\n+enum btintel_dbg_buf_location {\n+\tBTINTEL_PCIE_BUF_LOC_INVALID = 0,\n+\tBTINTEL_PCIE_BUF_LOC_SRAM = 1,\n+\tBTINTEL_PCIE_BUF_LOC_DRAM = 2,\n+\tBTINTEL_PCIE_BUF_LOC_NPK = 3,\n+\tBTINTEL_PCIE_BUF_LOC_MAX,\n+};\n+\n+struct btintel_pcie_tlv_hdr {\n+\t__le32 type;\n+\t__le32 length;\n+} __packed;\n+\n+struct btintel_pcie_dbg_hdr {\n+\t__le32 tlv_data_version;\n+\t__le32 domain;\n+} __packed;\n+\n+struct btintel_pcie_addr_value {\n+\t__le32 address;\n+\t__le32 value;\n+} __packed;\n+\n+struct btintel_pcie_tlv_dbg_info {\n+\tstruct btintel_pcie_tlv_hdr hdr;\n+\tstruct btintel_pcie_dbg_hdr dbg_hdr;\n+\t__le32 image_type;\n+\t__le32 core_type;\n+\tu8 config_name[BTINTEL_PCIE_CONFIG_NAME_LEN];\n+} __packed;\n+\n+struct btintel_pcie_tlv_buf_alloc {\n+\tstruct btintel_pcie_tlv_hdr hdr;\n+\tstruct btintel_pcie_dbg_hdr dbg_hdr;\n+\t__le32 alloc_id;\n+\t__le32 buf_location;\n+\t__le32 req_buf_size;\n+\t__le32 max_num_frags;\n+\t__le32 min_buf_size;\n+} __packed;\n+\n+struct btintel_pcie_buf_alloc {\n+\tu32 alloc_id;\n+\tu32 buf_location;\n+\tu32 req_buf_size;\n+\tu32 max_num_frags;\n+\tu32 min_buf_size;\n+\tbool present;\n+};\n+\n+struct btintel_pcie_yoyo_ctx {\n+\tbool enabled;\n+\tbool dbg_info_present;\n+\tstruct btintel_pcie_buf_alloc buf_alloc[BTINTEL_PCIE_MAX_BUF_ALLOC];\n+\tu32 num_buf_allocs;\n+\tstruct list_head region_list;\n+\tstruct list_head trigger_list;\n+\tstruct list_head hcmd_list;\n+\tstruct list_head config_set_list;\n+\tstruct hci_dev *hdev;\n+};\n+\n+int btintel_pcie_yoyo_init(struct btintel_pcie_yoyo_ctx *ctx);\n+void btintel_pcie_yoyo_cleanup(struct btintel_pcie_yoyo_ctx *ctx);\n+int btintel_pcie_yoyo_load_and_parse(struct btintel_pcie_yoyo_ctx *ctx,\n+\t\t\t\t     struct device *dev);\n+const struct btintel_pcie_buf_alloc *\n+btintel_pcie_yoyo_get_buf_alloc(struct btintel_pcie_yoyo_ctx *ctx, u32 alloc_id);\n+\n+#endif /* __BTINTEL_PCIE_DEBUG_H__ */\n"
}

2/1 2026/10/13 12:43 agent patch-evaluator
1m Model:
core

Args:
null

Results:
{
  "EnableConfigs": null,
  "FocusSymbols": [],
  "Reasoning": "The patch series modifies the btintel_pcie driver and adds btintel_pcie_debug for Intel PCIe Bluetooth devices (YoYo debug configuration support). This driver requires specific physical Intel PCIe hardware (such as Intel BlazarI, Lunar Lake, Panther Lake, Nova Lake PCIe Bluetooth adapters) that is not emulated in standard QEMU or GCE virtualized environments. Because there is no virtual bus or emulation support for these PCIe devices in standard fuzzing environments, the modified code is structurally unreachable.",
  "WorthFuzzing": false
}

Instruction:
You are an expert Linux kernel maintainer and security engineer.
Your job is to review a provided patch series and evaluate whether it warrants fuzzing with syzkaller.

IMPORTANT: The changes have ALREADY been applied and committed as the HEAD commit in
your workspace. Do NOT rely on internal assumptions. You must actively use your code access
tools to inspect the actual source code, callers, and surrounding context.

================================================================================
1. CORE TRIAGE PHILOSOPHY
================================================================================
The goal of patch fuzzing is to discover crashes, regressions, exposed latent bugs,
and newly triggered assertions introduced by the patch series.

- REACHABILITY IS THE PRIMARY GATE:
  Fuzzing can only discover bugs in code that can actually execute in standard virtualized
  environments (GCE or QEMU, utilizing software-emulated devices like USB gadgets, netdev, tun/tap).
  If the modified code is structurally unreachable (see Section 2), it MUST NOT be fuzzed,
  regardless of whether it adds assertions or complex logic.

- DO NOT BLINDLY TRUST "NO FUNCTIONAL CHANGE" (NFCI) OR "REFACTORING" CLAIMS:
  Patch authors routinely label changes as "cleanups", "refactorings", or state
  "No functional change intended". Do NOT take these claims at face value.
  Code refactorings that rearrange logic, introduce helper functions, or alter state management
  in core subsystems frequently introduce subtle semantic shifts or uncover latent kernel bugs.
  If reachable executable code is modified or refactored, it MUST be fuzzed.

- NEW OR MODIFIED ASSERTIONS IN REACHABLE CODE MUST BE FUZZED:
  When a patch introduces or modifies runtime checks or assertions (e.g., WARN_ON*, VM_WARN_ON*,
  BUG_ON*, lockdep_assert*) in reachable code paths, it enforces new or stricter invariants.
  Even if the author believes the invariant always holds, fuzzing is essential to verify whether
  an unusual sequence of operations can violate it.

================================================================================
2. WHEN TO RETURN WorthFuzzing=false (NEGATIVE CRITERIA)
================================================================================
Return WorthFuzzing=false ONLY IF all modified code falls strictly into one or more of these categories:

- Non-kernel and non-executable changes:
  * Modifications to Documentation/, comments, or spelling fixes.
  * User-space directories, self-tests, samples, or scripts (e.g., tools/, samples/, scripts/, usr/)
    that do not affect the compiled kernel image (vmlinux) or kernel modules.
  * Purely decorative logging (e.g., message strings in pr_err, printk, dev_info) or tracepoints
    that do not alter control flow or data structures.
  * Build system or Kconfig changes that do not alter compiled C logic.
- Structurally unreachable hardware:
  * Vendor-specific PCIe switches, SmartNICs, or GPU drivers (e.g., mlxsw, pds_core, qed,
    ionic, amdgpu) requiring physical ASIC/PCIe cards not emulated in standard QEMU.
- Unreachable execution paths:
  * Driver teardown callbacks (.remove, .shutdown, pci_unregister_driver) executed only during
    physical PCI hot-unplug or manual sysfs driver unbinding.
  * Code paths exclusive to architectures other than the target architecture.

================================================================================
3. WHEN TO RETURN WorthFuzzing=true (POSITIVE CRITERIA)
================================================================================
Return WorthFuzzing=true whenever the patch touches reachable executable code, including:
- Core Subsystems:
  * Any logic modifications in memory management (mm/), synchronization/locking (kernel/locking/),
    BPF, scheduler, core networking, VFS, or syscall handling.
- Refactorings and Code Cleanups:
  * Any restructuring of reachable data structures, helper abstractions, or algorithm flows.
- Runtime Assertions and Defensive Checks:
  * Any introduction or alteration of assertions (WARN_ON*, VM_WARN_ON*, BUG_ON*, etc.) in reachable paths.
- Reachable Drivers and Protocols:
  * Drivers accessible via virtual buses (virtio, USB gadget, loopback, netlink, binder, sockets, etc.).

================================================================================
4. EXTRACTING FocusSymbols (PREVENTING DILUTION)
================================================================================
When WorthFuzzing=true, you must extract specific kernel functions into FocusSymbols to guide the fuzzer:

- AVOID UBIQUITOUS LIFECYCLE HOT-PATHS:
  Do NOT list generic, ubiquitous functions called by almost every program in the corpus
  (including, but not limited to: general memory allocators and deallocators, page fault
  and trap handlers, or core synchronization primitives; this is not an exhaustive list).
  Listing ubiquitous functions causes the fuzzer to classify thousands of unrelated tests as "focused",
  which severely dilutes fuzzing effort away from the actual changes.

- TARGET SPECIFIC FEATURE LOGIC AND ENTRYPOINTS:
  List functions that specifically implement the logic being added or altered, or direct API entrypoints
  for the subsystem feature under review.

- HANDLING STATIC INLINE FUNCTIONS IN HEADERS (.h):
  Compiler-inlined static functions (such as static inlines in mm/*.h or include/linux/*.h) lack
  distinct symbol addresses in vmlinux and cannot be targeted directly by symbol coverage filters.
  If the changes are primarily in static inline helpers, identify non-static, feature-specific caller
  functions in .c files that exercise them (avoiding ubiquitous lifecycle wrappers).

================================================================================
5. IDENTIFYING EnableConfigs
================================================================================
Identify any specific CONFIG_ options required to properly compile and reach the modified code:
- Inspect Kconfig files and #ifdef guards; do not make assumptions.
- Check "depends on" lines in Kconfig to include any non-standard parent subsystem configs needed.
- Strip any 'CONFIG_' prefix (e.g., return "NET_IPV4" instead of "CONFIG_NET_IPV4").
Prefer calling several tools at the same time to save round-trips.


Use set-results tool to provide results of the analysis.
It must be called exactly once before the final reply.
Ignore results of this tool.

Prompt:
Target architecture: amd64

For your convenience, here is the diff of the changes:
commit 9798fc7492d7a728059de5992f4fa132720e3f2e
Author: syz-cluster <triage@syzkaller.com>
Date:   Tue Oct 13 12:43:08 2026 +0000

    syz-cluster: applied patch under review

diff --git a/drivers/bluetooth/Makefile b/drivers/bluetooth/Makefile
index d5eb2568af2e9..7d933755b2916 100644
--- a/drivers/bluetooth/Makefile
+++ b/drivers/bluetooth/Makefile
@@ -14,7 +14,7 @@ obj-$(CONFIG_BT_HCIBTUSB)	+= btusb.o
 obj-$(CONFIG_BT_HCIBTSDIO)	+= btsdio.o
 
 obj-$(CONFIG_BT_INTEL)		+= btintel.o
-obj-$(CONFIG_BT_INTEL_PCIE)	+= btintel_pcie.o btintel.o
+obj-$(CONFIG_BT_INTEL_PCIE)	+= btintel_pcie.o btintel.o btintel_pcie_debug.o
 obj-$(CONFIG_BT_ATH3K)		+= ath3k.o
 obj-$(CONFIG_BT_MRVL)		+= btmrvl.o
 obj-$(CONFIG_BT_MRVL_SDIO)	+= btmrvl_sdio.o
diff --git a/drivers/bluetooth/btintel_pcie.c b/drivers/bluetooth/btintel_pcie.c
index 3a555aa50c873..b85e8229d5d77 100644
--- a/drivers/bluetooth/btintel_pcie.c
+++ b/drivers/bluetooth/btintel_pcie.c
@@ -203,6 +203,90 @@ static inline bool btintel_pcie_dbg_to_wifi(struct btintel_pcie_data *data)
 	return data->dbg_path_cache != BTINTEL_PCIE_DRAM;
 }
 
+#define BTINTEL_PCIE_DBG_INI_FILE "ibt_bt_dbg_cfg.ini"
+
+/*
+ * Loads optional "DBG_PATH=<value>" and "ENABLE_INI=<value>" overrides from
+ * BTINTEL_PCIE_DBG_INI_FILE and applies them to dbg_path_cache and enable_ini.
+ *
+ * DBG_PATH accepts WiFi DBGC (0x06) or legacy host DRAM (0x01); ENABLE_INI
+ * accepts 1 (enabled) or 0 (disabled). Missing or invalid entries leave the
+ * values set by the caller 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;
+	int err;
+
+	err = request_firmware_direct(&fw, ini_file, &data->pdev->dev);
+	if (err < 0) {
+		BT_ERR("%s not found (%d), using dbg_path=0x%02x", ini_file,
+		       err, data->dbg_path_cache);
+		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, *val;
+		unsigned int 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);
+
+		if (!strcasecmp(line, "DBG_PATH")) {
+			BT_DBG("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_DBG("YoYo: DBG_PATH=0x%02x", data->dbg_path_cache);
+			} else {
+				BT_ERR("Invalid DBG_PATH='%s' in %s, using dbg_path=0x%02x",
+				       val, ini_file, data->dbg_path_cache);
+			}
+		} else if (!strcasecmp(line, "ENABLE_INI")) {
+			BT_DBG("Read ENABLE_INI from %s: '%s'", ini_file, val);
+
+			if (!kstrtouint(val, 0, &parsed) && parsed <= 1) {
+				data->enable_ini = !!parsed;
+				BT_DBG("YoYo: ENABLE_INI=%u", data->enable_ini);
+			} else {
+				BT_ERR("Invalid ENABLE_INI='%s' in %s, using enable_ini=%u",
+				       val, ini_file, data->enable_ini);
+			}
+		}
+	}
+
+	if (dbg_path_applied)
+		BT_DBG("Loaded dbg_path=0x%02x from %s", data->dbg_path_cache,
+		       ini_file);
+	else
+		BT_ERR("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);
+	kfree(buf);
+}
+
 /* Helper function to allocate and setup a debug buffer group
  * @data: driver data structure
  * @buf: pointer to data_buf array pointer
@@ -218,7 +302,8 @@ static int btintel_pcie_alloc_dbgc_buf(struct btintel_pcie_data *data,
 				       void **v_addr,
 				       struct btintel_pcie_dbgc_ctxt_buf *frag,
 				       u32 buf_index,
-				       u32 buf_count)
+				       u32 buf_count,
+				       u32 per_buf_size)
 {
 	struct data_buf *b;
 	int i;
@@ -231,8 +316,7 @@ static int btintel_pcie_alloc_dbgc_buf(struct btintel_pcie_data *data,
 	}
 
 	*v_addr = dmam_alloc_coherent(&data->pdev->dev,
-				      buf_count *
-					BTINTEL_PCIE_DBGC_BUFFER_SIZE,
+				      buf_count * per_buf_size,
 					p_addr,
 					GFP_KERNEL | __GFP_NOWARN);
 	if (!*v_addr) {
@@ -242,16 +326,37 @@ static int btintel_pcie_alloc_dbgc_buf(struct btintel_pcie_data *data,
 
 	for (i = 0; i < buf_count; i++) {
 		b = &(*buf)[i];
-		b->data_p_addr = *p_addr + i * BTINTEL_PCIE_DBGC_BUFFER_SIZE;
-		b->data = *v_addr + i * BTINTEL_PCIE_DBGC_BUFFER_SIZE;
+		b->data_p_addr = *p_addr + i * per_buf_size;
+		b->data = *v_addr + i * per_buf_size;
 		frag[i].buf_addr_lsb = lower_32_bits(b->data_p_addr);
 		frag[i].buf_addr_msb = upper_32_bits(b->data_p_addr);
-		frag[i].buf_size = BTINTEL_PCIE_DBGC_BUFFER_SIZE;
+		frag[i].buf_size = per_buf_size;
 	}
+	BT_INFO("DBGC allocation %u: fragments=%u fragment_size=%u total=%u",
+		buf_index + 1, buf_count, per_buf_size, buf_count * per_buf_size);
 
 	return 0;
 }
 
+static bool btintel_pcie_get_mdbgc_cfg(struct btintel_pcie_data *data,
+				       u32 alloc_id, u32 *count, u32 *size)
+{
+	const struct btintel_pcie_buf_alloc *alloc;
+
+	alloc = btintel_pcie_yoyo_get_buf_alloc(&data->yoyo, alloc_id);
+	if (alloc) {
+		*count = alloc->max_num_frags;
+		*size = alloc->req_buf_size / alloc->max_num_frags;
+		return true;
+	}
+	if (data->yoyo.enabled)
+		return false;
+
+	*count = BTINTEL_PCIE_DBGC_BUFFER_COUNT;
+	*size = BTINTEL_PCIE_DBGC_BUFFER_SIZE;
+	return true;
+}
+
 /* This function initializes the memory for MDBGC buffers and formats the
  * DBGC fragment which consists header info and DBGC buffer's LSB, MSB and
  * size as the payload
@@ -261,10 +366,9 @@ static int btintel_pcie_setup_mdbgc(struct btintel_pcie_data *data)
 	struct btintel_pcie_mdbgc_ctxt db_frag;
 	u32 frag_size = sizeof(db_frag);
 	void *frag_v_addr;
+	u32 buf_count, buf_size;
 	int err;
 
-	data->mdbgc.count = BTINTEL_PCIE_DBGC_BUFFER_COUNT;
-
 	/* Allocate fragment context structure */
 	frag_v_addr = dmam_alloc_coherent(&data->pdev->dev, frag_size,
 					  &data->mdbgc.frag_p_addr,
@@ -283,46 +387,56 @@ static int btintel_pcie_setup_mdbgc(struct btintel_pcie_data *data)
 	db_frag.ver = BTINTEL_PCIE_MDBGC_FRAG_VERSION;
 
 	/* Allocate DBGC buffer 1 */
-	db_frag.buf1_index = BTINTEL_PCIE_MDBGC_ALLOCATIONID_1;
-	db_frag.buf1_count = data->mdbgc.count;
-	err = btintel_pcie_alloc_dbgc_buf(data,
-					  &data->mdbgc.buf1,
-					  &data->mdbgc.buf1_p_addr,
-					  &data->mdbgc.buf1_v_addr,
-					  db_frag.buf1,
-					  0,
-					  data->mdbgc.count);
-	if (err)
-		return err;
+	if (btintel_pcie_get_mdbgc_cfg(data, BTINTEL_PCIE_ALLOC_ID_DBGC1,
+				       &buf_count, &buf_size)) {
+		db_frag.buf1_index = BTINTEL_PCIE_MDBGC_ALLOCATIONID_1;
+		db_frag.buf1_count = buf_count;
+		data->mdbgc.buf1_count = buf_count;
+		data->mdbgc.buf1_size = buf_size;
+		err = btintel_pcie_alloc_dbgc_buf(data, &data->mdbgc.buf1,
+						  &data->mdbgc.buf1_p_addr,
+					  &data->mdbgc.buf1_v_addr, db_frag.buf1,
+					  0, buf_count, buf_size);
+		if (err)
+			return err;
+	}
 
 	/* Allocate DBGC buffer 2 */
-	db_frag.buf2_index = BTINTEL_PCIE_MDBGC_ALLOCATIONID_2;
-	db_frag.buf2_count = data->mdbgc.count;
-	err = btintel_pcie_alloc_dbgc_buf(data,
-					  &data->mdbgc.buf2,
-					  &data->mdbgc.buf2_p_addr,
-					  &data->mdbgc.buf2_v_addr,
-					  db_frag.buf2,
-					  1,
-					  data->mdbgc.count);
-	if (err)
-		return err;
+	if (btintel_pcie_get_mdbgc_cfg(data, BTINTEL_PCIE_ALLOC_ID_DBGC2,
+				       &buf_count, &buf_size)) {
+		db_frag.buf2_index = BTINTEL_PCIE_MDBGC_ALLOCATIONID_2;
+		db_frag.buf2_count = buf_count;
+		data->mdbgc.buf2_count = buf_count;
+		data->mdbgc.buf2_size = buf_size;
+		err = btintel_pcie_alloc_dbgc_buf(data, &data->mdbgc.buf2,
+						  &data->mdbgc.buf2_p_addr,
+					  &data->mdbgc.buf2_v_addr, db_frag.buf2,
+					  1, buf_count, buf_size);
+		if (err)
+			return err;
+	}
 
 	/* Allocate DBGC buffer 3 */
-	db_frag.buf3_index = BTINTEL_PCIE_MDBGC_ALLOCATIONID_3;
-	db_frag.buf3_count = data->mdbgc.count;
-	err = btintel_pcie_alloc_dbgc_buf(data,
-					  &data->mdbgc.buf3,
-					  &data->mdbgc.buf3_p_addr,
-					  &data->mdbgc.buf3_v_addr,
-					  db_frag.buf3,
-					  2,
-					  data->mdbgc.count);
-	if (err)
-		return err;
+	if (btintel_pcie_get_mdbgc_cfg(data, BTINTEL_PCIE_ALLOC_ID_DBGC3,
+				       &buf_count, &buf_size)) {
+		db_frag.buf3_index = BTINTEL_PCIE_MDBGC_ALLOCATIONID_3;
+		db_frag.buf3_count = buf_count;
+		data->mdbgc.buf3_count = buf_count;
+		data->mdbgc.buf3_size = buf_size;
+		err = btintel_pcie_alloc_dbgc_buf(data, &data->mdbgc.buf3,
+						  &data->mdbgc.buf3_p_addr,
+					  &data->mdbgc.buf3_v_addr, db_frag.buf3,
+					  2, buf_count, buf_size);
+		if (err)
+			return err;
+	}
 
 	/* Copy fragment to DMA coherent memory */
 	memcpy(data->mdbgc.frag_v_addr, &db_frag, sizeof(db_frag));
+	BT_INFO("MDBGC fragments: DBGC1=%u/%u DBGC2=%u/%u DBGC3=%u/%u",
+		db_frag.buf1_count, data->mdbgc.buf1_size,
+		db_frag.buf2_count, data->mdbgc.buf2_size,
+		db_frag.buf3_count, data->mdbgc.buf3_size);
 	return 0;
 }
 
@@ -334,9 +448,17 @@ static int btintel_pcie_setup_dbgc(struct btintel_pcie_data *data)
 {
 	struct btintel_pcie_dbgc_ctxt db_frag;
 	u32 frag_size = sizeof(db_frag);
+	const struct btintel_pcie_buf_alloc *alloc;
+	u32 buf_count, buf_size;
 	int err;
 
-	data->dbgc.count = BTINTEL_PCIE_DBGC_BUFFER_COUNT;
+	alloc = btintel_pcie_yoyo_get_buf_alloc(&data->yoyo,
+						BTINTEL_PCIE_ALLOC_ID_DBGC1);
+	buf_count = alloc ? alloc->max_num_frags : BTINTEL_PCIE_DBGC_BUFFER_COUNT;
+	buf_size = alloc ? alloc->req_buf_size / alloc->max_num_frags :
+		BTINTEL_PCIE_DBGC_BUFFER_SIZE;
+	data->dbgc.count = buf_count;
+	data->dbgc.buf_size = buf_size;
 
 	/* Allocate fragment context structure */
 	data->dbgc.frag_v_addr = dmam_alloc_coherent(&data->pdev->dev,
@@ -354,8 +476,9 @@ static int btintel_pcie_setup_dbgc(struct btintel_pcie_data *data)
 	memset(&db_frag, 0, sizeof(db_frag));
 	db_frag.magic_num = BTINTEL_PCIE_MAGIC_NUM;
 	db_frag.ver = BTINTEL_PCIE_DBGC_FRAG_VERSION;
-	db_frag.total_size = BTINTEL_PCIE_DBGC_FRAG_PAYLOAD_SIZE;
-	db_frag.num_buf = BTINTEL_PCIE_DBGC_FRAG_BUFFER_COUNT;
+	db_frag.total_size = sizeof(db_frag.num_buf) +
+			     buf_count * sizeof(db_frag.bufs[0]);
+	db_frag.num_buf = buf_count;
 
 	/* Allocate DBGC buffers */
 	err = btintel_pcie_alloc_dbgc_buf(data,
@@ -364,7 +487,8 @@ static int btintel_pcie_setup_dbgc(struct btintel_pcie_data *data)
 					  &data->dbgc.buf_v_addr,
 					  db_frag.bufs,
 					  0,
-					  data->dbgc.count);
+					  buf_count,
+					  buf_size);
 	if (err)
 		return err;
 
@@ -857,7 +981,8 @@ static u32 btintel_pcie_dump_list_total_size(struct list_head *list)
 }
 
 static int btintel_pcie_dump_dram(struct list_head *list,
-				  u8 count, struct data_buf *bufs,
+				  u8 count, u32 buf_size,
+				  struct data_buf *bufs,
 				  u32 write_ptr, u32 wrap_ctr, u32 cur_frag,
 				  u32 region_id, const char *name)
 {
@@ -869,7 +994,7 @@ static int btintel_pcie_dump_dram(struct list_head *list,
 	int i;
 
 	mon_hdr_size = sizeof(*mon_dump);
-	ranges_size = count * (sizeof(*range) + BTINTEL_PCIE_DBGC_BUFFER_SIZE);
+	ranges_size = count * (sizeof(*range) + buf_size);
 	payload_size = mon_hdr_size + ranges_size;
 	total_size = sizeof(*dump_data) + payload_size;
 
@@ -898,12 +1023,10 @@ static int btintel_pcie_dump_dram(struct list_head *list,
 
 	range = (void *)mon_dump->data;
 	for (i = 0; i < count; i++) {
-		range->range_data_size =
-			cpu_to_le32(BTINTEL_PCIE_DBGC_BUFFER_SIZE);
+		range->range_data_size = cpu_to_le32(buf_size);
 		range->dram_base_addr = cpu_to_le64(bufs[i].data_p_addr);
-		memcpy(range->data, bufs[i].data,
-		       BTINTEL_PCIE_DBGC_BUFFER_SIZE);
-		range = (void *)range->data + BTINTEL_PCIE_DBGC_BUFFER_SIZE;
+		memcpy(range->data, bufs[i].data, buf_size);
+		range = (void *)range->data + buf_size;
 	}
 
 	list_add_tail(&entry->list, list);
@@ -913,6 +1036,7 @@ static int btintel_pcie_dump_dram(struct list_head *list,
 static int
 btintel_pcie_dump_dram_monitor(struct btintel_pcie_data *data,
 			       struct list_head *list, u8 count,
+			       u32 buf_size,
 			       struct data_buf *bufs, u32 status_reg,
 			       u32 wrap_reg, u8 allocation_id, u32 region_id,
 			       const char *name)
@@ -920,6 +1044,9 @@ btintel_pcie_dump_dram_monitor(struct btintel_pcie_data *data,
 	u32 allocation_offset, write_ptr, wrap_ctr, wr_ptr_status;
 	u8 cur_frag;
 
+	if (!count)
+		return -ENOENT;
+
 	allocation_offset = allocation_id *
 			    BTINTEL_PCIE_DBGC_ALLOCATION_OFFSET;
 	wr_ptr_status = btintel_pcie_rd_dev_mem(data, status_reg +
@@ -941,8 +1068,8 @@ btintel_pcie_dump_dram_monitor(struct btintel_pcie_data *data,
 		   "allocation=%u wr_ptr_status=0x%08x write_ptr=0x%06x cur_frag=%u wrap_ctr=0x%08x",
 		   allocation_id, wr_ptr_status, write_ptr, cur_frag, wrap_ctr);
 
-	return btintel_pcie_dump_dram(list, count, bufs, write_ptr, wrap_ctr,
-				      cur_frag, region_id, name);
+	return btintel_pcie_dump_dram(list, count, buf_size, bufs, write_ptr,
+				      wrap_ctr, cur_frag, region_id, name);
 }
 
 static int btintel_pcie_dump_target_region(struct btintel_pcie_data *data,
@@ -1223,6 +1350,7 @@ static int btintel_pcie_read_debug_regions(struct btintel_pcie_data *data)
 	u8 hw_variant;
 	u32 file_len;
 	u8 count;
+	u32 buf_size;
 	int ret;
 	LIST_HEAD(dump_list);
 
@@ -1231,10 +1359,10 @@ static int btintel_pcie_read_debug_regions(struct btintel_pcie_data *data)
 
 	if (btintel_pcie_is_mdbgc_supported(data)) {
 		mdbgc = &data->mdbgc;
-		count = mdbgc->count;
 	} else {
 		dbgc = &data->dbgc;
 		count = dbgc->count;
+		buf_size = dbgc->buf_size;
 	}
 
 	hw_variant = INTEL_HW_VARIANT(data->cnvi);
@@ -1254,7 +1382,9 @@ static int btintel_pcie_read_debug_regions(struct btintel_pcie_data *data)
 	}
 
 	if (btintel_pcie_is_mdbgc_supported(data)) {
-		ret = btintel_pcie_dump_dram_monitor(data, &dump_list, count,
+		ret = btintel_pcie_dump_dram_monitor(data, &dump_list,
+						     mdbgc->buf1_count,
+						     mdbgc->buf1_size,
 						     mdbgc->buf1, status_reg,
 						     wrap_reg,
 						     BTINTEL_PCIE_MDBGC_ALLOCATIONID_1,
@@ -1263,10 +1393,12 @@ static int btintel_pcie_read_debug_regions(struct btintel_pcie_data *data)
 		if (!ret)
 			regions_mask |=
 				BIT_ULL(BTINTEL_PCIE_INI_ID_DRAM_MONITOR1);
-		else
+		else if (ret != -ENOENT)
 			bt_dev_warn(hdev, "Failed to dump DRAM buf1: %d", ret);
 
-		ret = btintel_pcie_dump_dram_monitor(data, &dump_list, count,
+		ret = btintel_pcie_dump_dram_monitor(data, &dump_list,
+						     mdbgc->buf2_count,
+						     mdbgc->buf2_size,
 						     mdbgc->buf2, status_reg,
 						     wrap_reg,
 						     BTINTEL_PCIE_MDBGC_ALLOCATIONID_2,
@@ -1275,10 +1407,12 @@ static int btintel_pcie_read_debug_regions(struct btintel_pcie_data *data)
 		if (!ret)
 			regions_mask |=
 				BIT_ULL(BTINTEL_PCIE_INI_ID_DRAM_MONITOR2);
-		else
+		else if (ret != -ENOENT)
 			bt_dev_warn(hdev, "Failed to dump DRAM buf2: %d", ret);
 
-		ret = btintel_pcie_dump_dram_monitor(data, &dump_list, count,
+		ret = btintel_pcie_dump_dram_monitor(data, &dump_list,
+						     mdbgc->buf3_count,
+						     mdbgc->buf3_size,
 						     mdbgc->buf3, status_reg,
 						     wrap_reg,
 						     BTINTEL_PCIE_MDBGC_ALLOCATIONID_3,
@@ -1287,11 +1421,12 @@ static int btintel_pcie_read_debug_regions(struct btintel_pcie_data *data)
 		if (!ret)
 			regions_mask |=
 				BIT_ULL(BTINTEL_PCIE_INI_ID_DRAM_MONITOR3);
-		else
+		else if (ret != -ENOENT)
 			bt_dev_warn(hdev, "Failed to dump DRAM buf3: %d", ret);
 	} else {
 		ret = btintel_pcie_dump_dram_monitor(data, &dump_list, count,
-						     dbgc->bufs, status_reg,
+						     buf_size, dbgc->bufs,
+						     status_reg,
 						     wrap_reg,
 						     BTINTEL_PCIE_MDBGC_ALLOCATIONID_1,
 						     BTINTEL_PCIE_INI_ID_DRAM_MONITOR1,
@@ -4101,6 +4236,22 @@ static int btintel_pcie_probe(struct pci_dev *pdev,
 	 * initialized
 	 */
 	data->reset_type = BTINTEL_PCIE_IOSF_PRR_FLR;
+	data->enable_ini = false;
+	btintel_pcie_yoyo_init(&data->yoyo);
+	btintel_pcie_load_dbg_path_from_ini(data);
+
+	/* YoYo configuration is supported only with host DRAM debug routing. */
+	if (data->dbg_path_cache != BTINTEL_PCIE_DRAM)
+		data->enable_ini = false;
+
+	if (data->enable_ini) {
+		err = btintel_pcie_yoyo_load_and_parse(&data->yoyo, &pdev->dev);
+		if (err) {
+			BT_WARN("YoYo configuration is invalid (%d); keeping legacy defaults",
+				err);
+			btintel_pcie_yoyo_cleanup(&data->yoyo);
+		}
+	}
 	err = btintel_pcie_config_pcie(pdev, data);
 	if (err)
 		goto exit_error;
@@ -4128,11 +4279,14 @@ static int btintel_pcie_probe(struct pci_dev *pdev,
 	if (err)
 		goto exit_error;
 
+	data->yoyo.hdev = data->hdev;
 	bt_dev_dbg(data->hdev, "cnvi: 0x%8.8x cnvr: 0x%8.8x", data->cnvi,
 		   data->cnvr);
 	return 0;
 
 exit_error:
+	btintel_pcie_yoyo_cleanup(&data->yoyo);
+
 	/* reset device before exit */
 	btintel_pcie_reset_bt(data);
 
@@ -4173,6 +4327,8 @@ static void btintel_pcie_remove(struct pci_dev *pdev)
 	if (current_work() != &data->reset_work)
 		disable_work_sync(&data->reset_work);
 
+	btintel_pcie_yoyo_cleanup(&data->yoyo);
+
 	btintel_pcie_disable_interrupts(data);
 
 	btintel_pcie_synchronize_irqs(data);
diff --git a/drivers/bluetooth/btintel_pcie.h b/drivers/bluetooth/btintel_pcie.h
index 3030b4e8b7503..3827527c5b4d5 100644
--- a/drivers/bluetooth/btintel_pcie.h
+++ b/drivers/bluetooth/btintel_pcie.h
@@ -6,6 +6,8 @@
  *  Copyright (C) 2024  Intel Corporation
  */
 
+#include "btintel_pcie_debug.h"
+
 /* Control and Status Register(BTINTEL_PCIE_CSR) */
 #define BTINTEL_PCIE_CSR_BASE			(0x000)
 #define BTINTEL_PCIE_CSR_FUNC_CTRL_REG		(BTINTEL_PCIE_CSR_BASE + 0x024)
@@ -466,6 +468,7 @@ struct rxq {
  */
 struct btintel_pcie_dbgc {
 	u16		count;
+	u32		buf_size;
 
 	void		*frag_v_addr;
 	dma_addr_t	frag_p_addr;
@@ -477,7 +480,12 @@ struct btintel_pcie_dbgc {
 };
 
 struct btintel_pcie_mdbgc {
-	u32		count;
+	u32		buf1_count;
+	u32		buf1_size;
+	u32		buf2_count;
+	u32		buf2_size;
+	u32		buf3_count;
+	u32		buf3_size;
 
 	void		*frag_v_addr;
 	dma_addr_t	frag_p_addr;
@@ -737,6 +745,7 @@ struct btintel_pcie_data {
 	u32	boot_stage_cache;
 	u32	img_resp_cache;
 	u32	dbg_path_cache;
+	bool	enable_ini;
 
 	u32	cnvi;
 	u32	cnvr;
@@ -778,6 +787,7 @@ struct btintel_pcie_data {
 	u32	debug_table_size;
 	struct btintel_pcie_dump_mem_info	dump_info;
 	struct btintel_pcie_mbox	mbox;
+	struct btintel_pcie_yoyo_ctx yoyo;
 
 	/* Wait queue for mbox_worker to wait for GP0 alive interrupt */
 	wait_queue_head_t	mbox_parse_wait_q;
diff --git a/drivers/bluetooth/btintel_pcie_debug.c b/drivers/bluetooth/btintel_pcie_debug.c
new file mode 100644
index 0000000000000..806017b222093
--- /dev/null
+++ b/drivers/bluetooth/btintel_pcie_debug.c
@@ -0,0 +1,271 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/* Intel Bluetooth PCIe YoYo debug configuration support. */
+
+#include <linux/errno.h>
+#include <linux/firmware.h>
+#include <linux/module.h>
+#include <linux/stddef.h>
+#include <linux/string.h>
+#include <linux/unaligned.h>
+#include <net/bluetooth/bluetooth.h>
+
+#include "btintel_pcie_debug.h"
+
+static int btintel_pcie_yoyo_parse_dbg_info(struct btintel_pcie_yoyo_ctx *ctx,
+					    const struct btintel_pcie_tlv_dbg_info *info,
+					    u32 len)
+{
+	const u8 *data = (const u8 *)info;
+	u32 domain, image_type, core_type, version;
+
+	if (len != sizeof(*info) - sizeof(struct btintel_pcie_tlv_hdr))
+		return -EBADMSG;
+
+	image_type = get_unaligned_le32(data +
+				       offsetof(struct btintel_pcie_tlv_dbg_info,
+						image_type));
+	core_type = get_unaligned_le32(data +
+				      offsetof(struct btintel_pcie_tlv_dbg_info,
+					       core_type));
+	domain = get_unaligned_le32(data +
+				   offsetof(struct btintel_pcie_tlv_dbg_info,
+					    dbg_hdr.domain));
+	version = get_unaligned_le32(data +
+				     offsetof(struct btintel_pcie_tlv_dbg_info,
+					      dbg_hdr.tlv_data_version));
+
+	if (domain != BTINTEL_PCIE_DOMAIN_BT ||
+	    version != BTINTEL_PCIE_DBG_INFO_TLV_VERSION) {
+		BT_WARN("YoYo: unsupported domain/version (%u/%u), disabling",
+			domain, version);
+		return -EINVAL;
+	}
+	if (image_type != BTINTEL_PCIE_IMAGE_TLV_TYPE_EXTERNAL) {
+		BT_WARN("YoYo: unsupported image_type 0x%x, disabling", image_type);
+		return -EINVAL;
+	}
+	if (core_type != BTINTEL_PCIE_CORE_TYPE_BT) {
+		BT_WARN("YoYo: non-Bluetooth core_type %u, disabling", core_type);
+		return -EINVAL;
+	}
+
+	ctx->dbg_info_present = true;
+	BT_DBG("YoYo: config='%.64s' image=%u core=%u",
+	       info->config_name, image_type, core_type);
+	return 0;
+}
+
+static int btintel_pcie_yoyo_parse_buf_alloc(struct btintel_pcie_yoyo_ctx *ctx,
+					     const struct btintel_pcie_tlv_buf_alloc *tlv,
+					     u32 len)
+{
+	u32 alloc_id, buf_location, domain, idx, max_num_frags, min_buf_size;
+	u32 req_buf_size, version;
+
+	if (len != sizeof(*tlv) - sizeof(struct btintel_pcie_tlv_hdr)) {
+		BT_WARN("YoYo: unexpected buffer allocation TLV length %u", len);
+		return -EBADMSG;
+	}
+
+	domain = get_unaligned_le32(&tlv->dbg_hdr.domain);
+	version = get_unaligned_le32(&tlv->dbg_hdr.tlv_data_version);
+	if (domain != BTINTEL_PCIE_DOMAIN_BT ||
+	    version != BTINTEL_PCIE_BUF_ALLOC_TLV_VERSION) {
+		BT_WARN("YoYo: unsupported buffer allocation domain/version (%u/%u)",
+			domain, version);
+		return -EINVAL;
+	}
+
+	alloc_id = get_unaligned_le32(&tlv->alloc_id);
+	if (alloc_id < BTINTEL_PCIE_ALLOC_ID_DBGC1 ||
+	    alloc_id > BTINTEL_PCIE_ALLOC_ID_DBGC3) {
+		BT_WARN("YoYo: invalid buffer allocation ID %u", alloc_id);
+		return -EINVAL;
+	}
+
+	idx = alloc_id - BTINTEL_PCIE_ALLOC_ID_DBGC1;
+	buf_location = get_unaligned_le32(&tlv->buf_location);
+	max_num_frags = get_unaligned_le32(&tlv->max_num_frags);
+	min_buf_size = get_unaligned_le32(&tlv->min_buf_size);
+	req_buf_size = get_unaligned_le32(&tlv->req_buf_size);
+	if (buf_location != BTINTEL_PCIE_BUF_LOC_DRAM) {
+		BT_WARN("YoYo: allocation %u requests unsupported location %u",
+			alloc_id, buf_location);
+		return -EINVAL;
+	}
+
+	if (!max_num_frags || max_num_frags > BTINTEL_PCIE_MAX_BUF_FRAGS ||
+	    min_buf_size < BTINTEL_PCIE_MIN_BUF_SIZE ||
+	    min_buf_size > BTINTEL_PCIE_MAX_BUF_SIZE ||
+	    req_buf_size > BTINTEL_PCIE_MAX_BUF_SIZE ||
+	    req_buf_size % max_num_frags ||
+	    req_buf_size / max_num_frags < min_buf_size) {
+		BT_WARN("YoYo: invalid allocation %u size=%u fragments=%u minimum=%u",
+			alloc_id, req_buf_size, max_num_frags, min_buf_size);
+		return -EINVAL;
+	}
+
+	ctx->buf_alloc[idx].alloc_id = alloc_id;
+	ctx->buf_alloc[idx].buf_location = buf_location;
+	ctx->buf_alloc[idx].req_buf_size = req_buf_size;
+	ctx->buf_alloc[idx].max_num_frags = max_num_frags;
+	ctx->buf_alloc[idx].min_buf_size = min_buf_size;
+	ctx->buf_alloc[idx].present = true;
+	ctx->num_buf_allocs = max(ctx->num_buf_allocs, idx + 1);
+	BT_DBG("YoYo: allocation %u location=%u size=%u fragments=%u minimum=%u",
+	       alloc_id, buf_location, req_buf_size, max_num_frags, min_buf_size);
+	return 0;
+}
+
+static int btintel_pcie_yoyo_parse_tlv_buffer(struct btintel_pcie_yoyo_ctx *ctx,
+					      const u8 *buf, size_t buf_len)
+{
+	const u8 *ptr = buf;
+	size_t remaining = buf_len;
+	u32 count = 0;
+	int err;
+
+	if (!ctx || !buf)
+		return -EINVAL;
+
+	while (remaining >= sizeof(struct btintel_pcie_tlv_hdr)) {
+		u32 type = get_unaligned_le32(ptr);
+		u32 len = get_unaligned_le32(ptr + sizeof(__le32));
+
+		if (len > remaining - sizeof(struct btintel_pcie_tlv_hdr)) {
+			BT_ERR("YoYo: TLV %u truncated (len=%u remaining=%zu)",
+			       count, len, remaining);
+			return -EBADMSG;
+		}
+
+		switch (type) {
+		case BTINTEL_PCIE_TLV_TYPE_DBG_INFO:
+			err = btintel_pcie_yoyo_parse_dbg_info(ctx,
+							       (const void *)ptr,
+								       len);
+			if (err) {
+				ctx->dbg_info_present = false;
+				return err;
+			}
+			break;
+		case BTINTEL_PCIE_TLV_TYPE_DBG_BUF_ALLOC:
+			err = btintel_pcie_yoyo_parse_buf_alloc(ctx,
+								(const void *)ptr,
+								       len);
+			if (err)
+				return err;
+			break;
+		case BTINTEL_PCIE_TLV_TYPE_DBG_REGION:
+		case BTINTEL_PCIE_TLV_TYPE_DBG_TRIGGER:
+		case BTINTEL_PCIE_TLV_TYPE_DBG_HCMD:
+		case BTINTEL_PCIE_TLV_TYPE_DBG_CONFIG_SET:
+		case BTINTEL_PCIE_TLV_TYPE_DBG_PRESET_OVERRIDE:
+			BT_DBG("YoYo: recognized TLV type 0x%x len=%u", type, len);
+			break;
+		default:
+			BT_DBG("YoYo: unknown TLV type 0x%x len=%u", type, len);
+			break;
+		}
+
+		ptr += sizeof(struct btintel_pcie_tlv_hdr) + len;
+		remaining -= sizeof(struct btintel_pcie_tlv_hdr) + len;
+		count++;
+	}
+
+	if (remaining || !count) {
+		BT_ERR("YoYo: invalid TLV stream (%zu trailing bytes, %u TLVs)",
+		       remaining, count);
+		return -EBADMSG;
+	}
+	if (!ctx->dbg_info_present) {
+		BT_ERR("YoYo: mandatory DEBUG_INFO TLV missing");
+		return -EBADMSG;
+	}
+	if (!ctx->num_buf_allocs) {
+		BT_ERR("YoYo: mandatory buffer allocation TLV missing");
+		return -EBADMSG;
+	}
+	return 0;
+}
+
+int btintel_pcie_yoyo_init(struct btintel_pcie_yoyo_ctx *ctx)
+{
+	if (!ctx)
+		return -EINVAL;
+
+	memset(ctx, 0, sizeof(*ctx));
+	INIT_LIST_HEAD(&ctx->region_list);
+	INIT_LIST_HEAD(&ctx->trigger_list);
+	INIT_LIST_HEAD(&ctx->hcmd_list);
+	INIT_LIST_HEAD(&ctx->config_set_list);
+	return 0;
+}
+EXPORT_SYMBOL_GPL(btintel_pcie_yoyo_init);
+
+void btintel_pcie_yoyo_cleanup(struct btintel_pcie_yoyo_ctx *ctx)
+{
+	if (!ctx)
+		return;
+
+	ctx->enabled = false;
+	ctx->dbg_info_present = false;
+	ctx->num_buf_allocs = 0;
+	memset(ctx->buf_alloc, 0, sizeof(ctx->buf_alloc));
+}
+EXPORT_SYMBOL_GPL(btintel_pcie_yoyo_cleanup);
+
+int btintel_pcie_yoyo_load_and_parse(struct btintel_pcie_yoyo_ctx *ctx,
+				     struct device *dev)
+{
+	const struct firmware *fw;
+	int err;
+
+	if (!ctx || !dev)
+		return -EINVAL;
+
+	err = request_firmware_direct(&fw, BTINTEL_PCIE_YOYO_FW_NAME, dev);
+	if (err) {
+		BT_ERR("YoYo: failed to load %s (%d)",
+		       BTINTEL_PCIE_YOYO_FW_NAME, err);
+		return err;
+	}
+
+	if (fw->size < sizeof(struct btintel_pcie_tlv_hdr))
+		err = -EBADMSG;
+	else
+		err = btintel_pcie_yoyo_parse_tlv_buffer(ctx, fw->data, fw->size);
+
+	release_firmware(fw);
+	if (err) {
+		BT_ERR("YoYo: TLV parsing failed (%d)", err);
+		return err;
+	}
+	if (!ctx->dbg_info_present) {
+		BT_ERR("YoYo: mandatory DEBUG_INFO TLV missing; using legacy defaults");
+		return -EBADMSG;
+	}
+	ctx->enabled = true;
+	BT_INFO("YoYo: configuration loaded and validated");
+	return 0;
+}
+EXPORT_SYMBOL_GPL(btintel_pcie_yoyo_load_and_parse);
+
+const struct btintel_pcie_buf_alloc *
+btintel_pcie_yoyo_get_buf_alloc(struct btintel_pcie_yoyo_ctx *ctx, u32 alloc_id)
+{
+	u32 idx;
+
+	if (!ctx || !ctx->enabled ||
+	    alloc_id < BTINTEL_PCIE_ALLOC_ID_DBGC1 ||
+	    alloc_id > BTINTEL_PCIE_ALLOC_ID_DBGC3)
+		return NULL;
+
+	idx = alloc_id - BTINTEL_PCIE_ALLOC_ID_DBGC1;
+	if (!ctx->buf_alloc[idx].present)
+		return NULL;
+	return &ctx->buf_alloc[idx];
+}
+EXPORT_SYMBOL_GPL(btintel_pcie_yoyo_get_buf_alloc);
+
+MODULE_DESCRIPTION("Intel Bluetooth PCIe YoYo debug configuration support");
+MODULE_LICENSE("GPL");
diff --git a/drivers/bluetooth/btintel_pcie_debug.h b/drivers/bluetooth/btintel_pcie_debug.h
new file mode 100644
index 0000000000000..531a24c905b00
--- /dev/null
+++ b/drivers/bluetooth/btintel_pcie_debug.h
@@ -0,0 +1,114 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/* Intel Bluetooth PCIe YoYo debug configuration support. */
+
+#ifndef __BTINTEL_PCIE_DEBUG_H__
+#define __BTINTEL_PCIE_DEBUG_H__
+
+#include <linux/device.h>
+#include <linux/list.h>
+#include <linux/types.h>
+
+#define BTINTEL_PCIE_YOYO_FW_NAME "intel/ibt_debug_yoyo.bin"
+
+#define BTINTEL_PCIE_TLV_TYPE_DBG_INFO		0x01000005
+#define BTINTEL_PCIE_TLV_TYPE_DBG_BUF_ALLOC	0x01000006
+#define BTINTEL_PCIE_TLV_TYPE_DBG_HCMD		0x01000007
+#define BTINTEL_PCIE_TLV_TYPE_DBG_REGION		0x01000008
+#define BTINTEL_PCIE_TLV_TYPE_DBG_TRIGGER	0x01000009
+#define BTINTEL_PCIE_TLV_TYPE_DBG_CONFIG_SET	0x0100000a
+#define BTINTEL_PCIE_TLV_TYPE_DBG_PRESET_OVERRIDE 0x0100000b
+
+#define BTINTEL_PCIE_DBG_INFO_TLV_VERSION	2
+#define BTINTEL_PCIE_BUF_ALLOC_TLV_VERSION	1
+#define BTINTEL_PCIE_CONFIG_NAME_LEN		64
+#define BTINTEL_PCIE_DOMAIN_BT			0
+#define BTINTEL_PCIE_CORE_TYPE_BT		1
+#define BTINTEL_PCIE_MAX_BUF_ALLOC		3
+#define BTINTEL_PCIE_MAX_BUF_FRAGS		16
+#define BTINTEL_PCIE_MIN_BUF_SIZE		(32 * 1024)
+#define BTINTEL_PCIE_MAX_BUF_SIZE		(4 * 1024 * 1024)
+
+enum btintel_pcie_image_tlv_type {
+	BTINTEL_PCIE_IMAGE_TLV_TYPE_EXTERNAL = 0x1,
+	BTINTEL_PCIE_IMAGE_TLV_TYPE_INTERNAL = 0x2,
+	BTINTEL_PCIE_IMAGE_TLV_TYPE_UNKNOWN = 0xff,
+};
+
+enum btintel_dbg_alloc_id {
+	BTINTEL_PCIE_ALLOC_ID_INVALID = 0,
+	BTINTEL_PCIE_ALLOC_ID_DBGC1 = 1,
+	BTINTEL_PCIE_ALLOC_ID_DBGC2 = 2,
+	BTINTEL_PCIE_ALLOC_ID_DBGC3 = 3,
+	BTINTEL_PCIE_ALLOC_ID_MAX,
+};
+
+enum btintel_dbg_buf_location {
+	BTINTEL_PCIE_BUF_LOC_INVALID = 0,
+	BTINTEL_PCIE_BUF_LOC_SRAM = 1,
+	BTINTEL_PCIE_BUF_LOC_DRAM = 2,
+	BTINTEL_PCIE_BUF_LOC_NPK = 3,
+	BTINTEL_PCIE_BUF_LOC_MAX,
+};
+
+struct btintel_pcie_tlv_hdr {
+	__le32 type;
+	__le32 length;
+} __packed;
+
+struct btintel_pcie_dbg_hdr {
+	__le32 tlv_data_version;
+	__le32 domain;
+} __packed;
+
+struct btintel_pcie_addr_value {
+	__le32 address;
+	__le32 value;
+} __packed;
+
+struct btintel_pcie_tlv_dbg_info {
+	struct btintel_pcie_tlv_hdr hdr;
+	struct btintel_pcie_dbg_hdr dbg_hdr;
+	__le32 image_type;
+	__le32 core_type;
+	u8 config_name[BTINTEL_PCIE_CONFIG_NAME_LEN];
+} __packed;
+
+struct btintel_pcie_tlv_buf_alloc {
+	struct btintel_pcie_tlv_hdr hdr;
+	struct btintel_pcie_dbg_hdr dbg_hdr;
+	__le32 alloc_id;
+	__le32 buf_location;
+	__le32 req_buf_size;
+	__le32 max_num_frags;
+	__le32 min_buf_size;
+} __packed;
+
+struct btintel_pcie_buf_alloc {
+	u32 alloc_id;
+	u32 buf_location;
+	u32 req_buf_size;
+	u32 max_num_frags;
+	u32 min_buf_size;
+	bool present;
+};
+
+struct btintel_pcie_yoyo_ctx {
+	bool enabled;
+	bool dbg_info_present;
+	struct btintel_pcie_buf_alloc buf_alloc[BTINTEL_PCIE_MAX_BUF_ALLOC];
+	u32 num_buf_allocs;
+	struct list_head region_list;
+	struct list_head trigger_list;
+	struct list_head hcmd_list;
+	struct list_head config_set_list;
+	struct hci_dev *hdev;
+};
+
+int btintel_pcie_yoyo_init(struct btintel_pcie_yoyo_ctx *ctx);
+void btintel_pcie_yoyo_cleanup(struct btintel_pcie_yoyo_ctx *ctx);
+int btintel_pcie_yoyo_load_and_parse(struct btintel_pcie_yoyo_ctx *ctx,
+				     struct device *dev);
+const struct btintel_pcie_buf_alloc *
+btintel_pcie_yoyo_get_buf_alloc(struct btintel_pcie_yoyo_ctx *ctx, u32 alloc_id);
+
+#endif /* __BTINTEL_PCIE_DEBUG_H__ */

3/2 2026/10/13 12:43 llm patch-evaluator
0m Model:
gemini-3.8-flash

Args:
null

Results:
null

Tokens:
							input: 16350
							output: 45
							thoughts: 232
						

Thoughts:
**Analyzing a Kernel Patch Series: Initial Assessment**

Okay, so I've got this kernel patch series to review. My first step is always to understand the scope and intent. Let's dig in and see what's being modified. The diff touches the Bluetooth subsystem specifically, hitting files like `Makefile`, `btintel_pcie.c`, `btintel_pcie.h`, and the corresponding debug files. That narrows the focus considerably. I can already tell this is centered around the `btintel_pcie` driver, so my immediate thought is "Intel PCIe Bluetooth."

Now, let's get into the nitty-gritty. What are the hardware implications here? Does this driver have specific hardware requirements? Does it play nice in virtualized environments? Or does it *require* a physical Intel PCIe Bluetooth card? I need to check `btintel_pcie.c` for clues. I'll be looking for how the driver binds. Specifically, I'll be searching for how it identifies its compatible devices. I'll be looking for things like `pci_device_id` definitions. That will tell me a great deal, initially.



4/2 2026/10/13 12:43 tool grepper
0m Args:
{
  "Expression": "btintel_pcie_driver|MODULE_DEVICE_TABLE",
  "PathPrefixes": [
    "drivers/bluetooth/btintel_pcie.c"
  ]
}

Results:
{
  "Output": "drivers/bluetooth/btintel_pcie.c=46=static const struct pci_device_id btintel_pcie_table[] = {\n--\ndrivers/bluetooth/btintel_pcie.c-63-};\ndrivers/bluetooth/btintel_pcie.c:64:MODULE_DEVICE_TABLE(pci, btintel_pcie_table);\ndrivers/bluetooth/btintel_pcie.c-65-\n--\ndrivers/bluetooth/btintel_pcie.c=4580=static const struct dev_pm_ops btintel_pcie_pm_ops = {\n--\ndrivers/bluetooth/btintel_pcie.c-4588-\ndrivers/bluetooth/btintel_pcie.c:4589:static struct pci_driver btintel_pcie_driver = {\ndrivers/bluetooth/btintel_pcie.c-4590-\t.name = KBUILD_MODNAME,\n--\ndrivers/bluetooth/btintel_pcie.c=4601=static int __init btintel_pcie_init(void)\ndrivers/bluetooth/btintel_pcie.c-4602-{\ndrivers/bluetooth/btintel_pcie.c:4603:\treturn pci_register_driver(\u0026btintel_pcie_driver);\ndrivers/bluetooth/btintel_pcie.c-4604-}\n--\ndrivers/bluetooth/btintel_pcie.c=4606=static void __exit btintel_pcie_exit(void)\ndrivers/bluetooth/btintel_pcie.c-4607-{\ndrivers/bluetooth/btintel_pcie.c:4608:\tpci_unregister_driver(\u0026btintel_pcie_driver);\ndrivers/bluetooth/btintel_pcie.c-4609-\tbtintel_pcie_free_restart_list();\n"
}

5/2 2026/10/13 12:43 llm patch-evaluator
0m Model:
gemini-3.8-flash

Args:
null

Results:
null

Tokens:
							input: 17329
							output: 38
							thoughts: 27
						

Thoughts:
Okay, let's dive into this. Here's my summary, presented as my own thought process, given my expertise:

**Inspecting the Bluetooth Intel PCIe Initialization**

Alright, I need to get to the bottom of this. My first move is to head straight for the `btintel_pcie_table` data structure. I'm thinking the likely starting point is within the `drivers/bluetooth/btintel_pcie.c` file. This table almost certainly contains the initial configuration data – the base addresses, interrupt lines, potentially the firmware loading specifics – that's crucial for getting this Intel PCIe Bluetooth controller up and running. I'll need to understand how this table is structured, what the various fields represent, and how they're used during the PCIe initialization sequence. I'm expecting to find the key parameters for hardware detection and configuration. Knowing the layout of this data is fundamental for understanding any issues related to driver loading, resource allocation, or, for that matter, any kind of unexpected device behavior. Let's see what we can find.



6/2 2026/10/13 12:43 tool read-file
0m Args:
{
  "File": "drivers/bluetooth/btintel_pcie.c",
  "FirstLine": 45,
  "LineCount": 30
}

Results:
{
  "Contents": "  45:\t/* Intel Bluetooth PCIe device id table */\n  46:\tstatic const struct pci_device_id btintel_pcie_table[] = {\n  47:\t\t/* BlazarI, Wildcat Lake */\n  48:\t\t{ BTINTEL_PCI_DEVICE(0x4D76, PCI_ANY_ID) },\n  49:\t\t/* BlazarI, Lunar Lake */\n  50:\t\t{ BTINTEL_PCI_DEVICE(0xA876, PCI_ANY_ID) },\n  51:\t\t/* Scorpious, Panther Lake-H484 */\n  52:\t\t{ BTINTEL_PCI_DEVICE(0xE376, PCI_ANY_ID) },\n  53:\t\t /* Scorpious, Panther Lake-H404 */\n  54:\t\t{ BTINTEL_PCI_DEVICE(0xE476, PCI_ANY_ID) },\n  55:\t\t /* Scorpious2, Nova Lake-PCD-H */\n  56:\t\t{ BTINTEL_PCI_DEVICE(0xD346, PCI_ANY_ID) },\n  57:\t\t /* Scorpious2, Nova Lake-PCD-S */\n  58:\t\t{ BTINTEL_PCI_DEVICE(0x6E74, PCI_ANY_ID) },\n  59:\t\t /* Draco */\n  60:\t\t{ BTINTEL_PCI_DEVICE(0x2731, PCI_ANY_ID) },\n  61:\t\t{ BTINTEL_PCI_DEVICE(0x2732, PCI_ANY_ID) },\n  62:\t\t{ 0 }\n  63:\t};\n  64:\tMODULE_DEVICE_TABLE(pci, btintel_pcie_table);\n  65:\t\n  66:\tstruct btintel_pcie_dev_recovery {\n  67:\t\tstruct list_head list;\n  68:\t\tu8 count;\n  69:\t\ttime64_t last_error;\n  70:\t\tchar name[];\n  71:\t};\n  72:\t\n  73:\t/* Intel PCIe uses 4 bytes of HCI type instead of 1 byte BT SIG HCI type */\n  74:\t#define BTINTEL_PCIE_HCI_TYPE_LEN\t4\n"
}

7/2 2026/10/13 12:43 llm patch-evaluator
0m Model:
gemini-3.8-flash

Args:
null

Results:
null

Tokens:
							input: 18183
							output: 43
							thoughts: 810
						

Thoughts:
**WorthFuzzing Decision for `btintel_pcie`**

Okay, here's the situation. I need to figure out if this patch to `btintel_pcie` is worth fuzzing. The first thing I'm doing is checking if syzkaller/QEMU can even *reach* this code. Let's revisit those guidelines. The negative criteria are the things to avoid fuzzing and the positive are the things we want to fuzz. Okay, negative criteria states: "Structurally unreachable hardware: Vendor-specific PCIe switches, SmartNICs, or GPU drivers... requiring physical ASIC/PCIe cards not emulated in standard QEMU."

Now, is `btintel_pcie` one of those? I need to know. Based on the PCI device IDs, it looks like this is an Intel PCIe Wi-Fi/Bluetooth driver, specific to CNVi or discrete PCIe Wi-Fi/BT adapters (like BE200, etc.). Hold on... is this hardware emulated in QEMU, or even Google Compute Engine? No, QEMU's standard devices are like e1000, rtl8139, virtio-*, USB, etc. QEMU does not emulate Intel PCIe Bluetooth controllers.

But can syzkaller emulate arbitrary PCI devices? No, that's a no. Unlike USB Raw Gadget for arbitrary USB, syzkaller does not have a generic PCI emulation framework. Wait, what about `vhci`? But the `btintel_pcie` driver is NOT HCI over vhci. I know, because it's a PCI device driver. The driver struct shows it's a PCI driver: `.probe = btintel_pcie_probe`, `.remove = btintel_pcie_remove`, and so on.

Okay, does it register an HCI device? Yes, that's what I have to check in `btintel_pcie_probe` within `drivers/bluetooth/btintel_pcie.c`. I have to dig further to see if there is a path through which I can access it.



8/2 2026/10/13 12:43 tool grepper
0m Args:
{
  "Expression": "hci_alloc_dev|hci_register_dev",
  "PathPrefixes": [
    "drivers/bluetooth/btintel_pcie.c"
  ]
}

Results:
{
  "Output": "drivers/bluetooth/btintel_pcie.c=4145=static int btintel_pcie_setup_hdev(struct btintel_pcie_data *data)\n--\ndrivers/bluetooth/btintel_pcie.c-4149-\ndrivers/bluetooth/btintel_pcie.c:4150:\thdev = hci_alloc_dev_priv(sizeof(struct btintel_data));\ndrivers/bluetooth/btintel_pcie.c-4151-\tif (!hdev)\n--\ndrivers/bluetooth/btintel_pcie.c-4171-\ndrivers/bluetooth/btintel_pcie.c:4172:\terr = hci_register_dev(hdev);\ndrivers/bluetooth/btintel_pcie.c-4173-\tif (err \u003c 0) {\n"
}

9/2 2026/10/13 12:43 llm patch-evaluator
0m Model:
gemini-3.8-flash

Args:
null

Results:
null

Tokens:
							input: 19693
							output: 30
							thoughts: 466
						

Thoughts:
**Analyzing the Reachability of `btintel_pcie` for Fuzzing**

Okay, let's break this down. My initial thought was, "Can I probe `btintel_pcie` without any physical hardware?" The answer, as I expected, is no. It's a PCI driver, so it relies on those specific vendor:device IDs (`btintel_pcie_table`) being present on the PCI bus. QEMU or GCE, without PCI passthrough, aren't going to magically emulate those IDs like 8086:4d76, or any of those others.

Then I had a flicker of an idea – could I use `new_id` in sysfs (`/sys/bus/pci/drivers/btintel_pcie/new_id`) to force a binding? But even if I could write to it, there'd still need to *be* a PCI device there to bind to. And even *then*, the `btintel_pcie_probe` function is going to try to configure PCIe, read device memory, request firmware, and all sorts of things that depend on the physical hardware. Standard VMs just don't have matching, or even dummy, PCI devices for this. And Syzkaller definitely doesn't do that kind of dynamic ID binding.

Then I reviewed the guidelines and that clinched it. The fuzzing philosophy is all about *reachability*. This is structurally unreachable hardware. The guidelines are crystal clear: only fuzz code that *can* actually execute in standard VMs. The text here explicitly calls out vendor-specific PCIe stuff like this, requiring physical cards not emulated in QEMU.

So, `btintel_pcie` is clearly a vendor-specific driver for Intel's discrete or integrated PCIe Bluetooth adapters (BlazarI, Scorpious, Draco). Now, let's explore if any other part of the code relies on `btintel_pcie_debug.c`.



10/2 2026/10/13 12:43 tool grepper
0m Args:
{
  "Expression": "btintel_pcie_debug",
  "PathPrefixes": [
    "drivers/"
  ]
}

Results:
{
  "Output": "drivers/bluetooth/Makefile=16=obj-$(CONFIG_BT_INTEL)\t\t+= btintel.o\ndrivers/bluetooth/Makefile:17:obj-$(CONFIG_BT_INTEL_PCIE)\t+= btintel_pcie.o btintel.o btintel_pcie_debug.o\ndrivers/bluetooth/Makefile-18-obj-$(CONFIG_BT_ATH3K)\t\t+= ath3k.o\n--\ndrivers/bluetooth/btintel_pcie.h-8-\ndrivers/bluetooth/btintel_pcie.h:9:#include \"btintel_pcie_debug.h\"\ndrivers/bluetooth/btintel_pcie.h-10-\n--\ndrivers/bluetooth/btintel_pcie_debug.c-11-\ndrivers/bluetooth/btintel_pcie_debug.c:12:#include \"btintel_pcie_debug.h\"\ndrivers/bluetooth/btintel_pcie_debug.c-13-\n"
}

11/2 2026/10/13 12:44 llm patch-evaluator
0m Model:
gemini-3.8-flash

Args:
null

Results:
null

Tokens:
							input: 20846
							output: 31
							thoughts: 39
						

Thoughts:
Okay, here's my summary, considering my expertise:

**Checking Function Call Scope**

Alright, let's zero in on this. I need to quickly ascertain the scope of those `btintel_pcie_yoyo_*` and `btintel_pcie_*` functions. My immediate concern is whether any of those are being called from outside of `btintel_pcie.c`. That would be the critical piece of information I need to confirm right away. This will help me assess the modularity and potential for unexpected dependencies or interactions. This quickly helps me determine if I need to look into this more deeply.



12/2 2026/10/13 12:44 tool grepper
0m Args:
{
  "Expression": "btintel_pcie_yoyo",
  "PathPrefixes": [
    "drivers/"
  ]
}

Results:
{
  "Output": "drivers/bluetooth/btintel_pcie.c=341=static bool btintel_pcie_get_mdbgc_cfg(struct btintel_pcie_data *data,\n--\ndrivers/bluetooth/btintel_pcie.c-345-\ndrivers/bluetooth/btintel_pcie.c:346:\talloc = btintel_pcie_yoyo_get_buf_alloc(\u0026data-\u003eyoyo, alloc_id);\ndrivers/bluetooth/btintel_pcie.c-347-\tif (alloc) {\n--\ndrivers/bluetooth/btintel_pcie.c=447=static int btintel_pcie_setup_dbgc(struct btintel_pcie_data *data)\n--\ndrivers/bluetooth/btintel_pcie.c-454-\ndrivers/bluetooth/btintel_pcie.c:455:\talloc = btintel_pcie_yoyo_get_buf_alloc(\u0026data-\u003eyoyo,\ndrivers/bluetooth/btintel_pcie.c-456-\t\t\t\t\t\tBTINTEL_PCIE_ALLOC_ID_DBGC1);\n--\ndrivers/bluetooth/btintel_pcie.c=4188=static int btintel_pcie_probe(struct pci_dev *pdev,\n--\ndrivers/bluetooth/btintel_pcie.c-4239-\tdata-\u003eenable_ini = false;\ndrivers/bluetooth/btintel_pcie.c:4240:\tbtintel_pcie_yoyo_init(\u0026data-\u003eyoyo);\ndrivers/bluetooth/btintel_pcie.c-4241-\tbtintel_pcie_load_dbg_path_from_ini(data);\n--\ndrivers/bluetooth/btintel_pcie.c-4247-\tif (data-\u003eenable_ini) {\ndrivers/bluetooth/btintel_pcie.c:4248:\t\terr = btintel_pcie_yoyo_load_and_parse(\u0026data-\u003eyoyo, \u0026pdev-\u003edev);\ndrivers/bluetooth/btintel_pcie.c-4249-\t\tif (err) {\n--\ndrivers/bluetooth/btintel_pcie.c-4251-\t\t\t\terr);\ndrivers/bluetooth/btintel_pcie.c:4252:\t\t\tbtintel_pcie_yoyo_cleanup(\u0026data-\u003eyoyo);\ndrivers/bluetooth/btintel_pcie.c-4253-\t\t}\n--\ndrivers/bluetooth/btintel_pcie.c-4287-exit_error:\ndrivers/bluetooth/btintel_pcie.c:4288:\tbtintel_pcie_yoyo_cleanup(\u0026data-\u003eyoyo);\ndrivers/bluetooth/btintel_pcie.c-4289-\n--\ndrivers/bluetooth/btintel_pcie.c=4302=static void btintel_pcie_remove(struct pci_dev *pdev)\n--\ndrivers/bluetooth/btintel_pcie.c-4329-\ndrivers/bluetooth/btintel_pcie.c:4330:\tbtintel_pcie_yoyo_cleanup(\u0026data-\u003eyoyo);\ndrivers/bluetooth/btintel_pcie.c-4331-\n--\ndrivers/bluetooth/btintel_pcie.h=725=struct btintel_pcie_data {\n--\ndrivers/bluetooth/btintel_pcie.h-789-\tstruct btintel_pcie_mbox\tmbox;\ndrivers/bluetooth/btintel_pcie.h:790:\tstruct btintel_pcie_yoyo_ctx yoyo;\ndrivers/bluetooth/btintel_pcie.h-791-\n--\ndrivers/bluetooth/btintel_pcie_debug.c-13-\ndrivers/bluetooth/btintel_pcie_debug.c:14:static int btintel_pcie_yoyo_parse_dbg_info(struct btintel_pcie_yoyo_ctx *ctx,\ndrivers/bluetooth/btintel_pcie_debug.c-15-\t\t\t\t\t    const struct btintel_pcie_tlv_dbg_info *info,\n--\ndrivers/bluetooth/btintel_pcie_debug.c-57-\ndrivers/bluetooth/btintel_pcie_debug.c:58:static int btintel_pcie_yoyo_parse_buf_alloc(struct btintel_pcie_yoyo_ctx *ctx,\ndrivers/bluetooth/btintel_pcie_debug.c-59-\t\t\t\t\t     const struct btintel_pcie_tlv_buf_alloc *tlv,\n--\ndrivers/bluetooth/btintel_pcie_debug.c-119-\ndrivers/bluetooth/btintel_pcie_debug.c:120:static int btintel_pcie_yoyo_parse_tlv_buffer(struct btintel_pcie_yoyo_ctx *ctx,\ndrivers/bluetooth/btintel_pcie_debug.c-121-\t\t\t\t\t      const u8 *buf, size_t buf_len)\n--\ndrivers/bluetooth/btintel_pcie_debug.c-142-\t\tcase BTINTEL_PCIE_TLV_TYPE_DBG_INFO:\ndrivers/bluetooth/btintel_pcie_debug.c:143:\t\t\terr = btintel_pcie_yoyo_parse_dbg_info(ctx,\ndrivers/bluetooth/btintel_pcie_debug.c-144-\t\t\t\t\t\t\t       (const void *)ptr,\n--\ndrivers/bluetooth/btintel_pcie_debug.c-151-\t\tcase BTINTEL_PCIE_TLV_TYPE_DBG_BUF_ALLOC:\ndrivers/bluetooth/btintel_pcie_debug.c:152:\t\t\terr = btintel_pcie_yoyo_parse_buf_alloc(ctx,\ndrivers/bluetooth/btintel_pcie_debug.c-153-\t\t\t\t\t\t\t\t(const void *)ptr,\n--\ndrivers/bluetooth/btintel_pcie_debug.c-190-\ndrivers/bluetooth/btintel_pcie_debug.c:191:int btintel_pcie_yoyo_init(struct btintel_pcie_yoyo_ctx *ctx)\ndrivers/bluetooth/btintel_pcie_debug.c-192-{\n--\ndrivers/bluetooth/btintel_pcie_debug.c-202-}\ndrivers/bluetooth/btintel_pcie_debug.c:203:EXPORT_SYMBOL_GPL(btintel_pcie_yoyo_init);\ndrivers/bluetooth/btintel_pcie_debug.c-204-\ndrivers/bluetooth/btintel_pcie_debug.c:205:void btintel_pcie_yoyo_cleanup(struct btintel_pcie_yoyo_ctx *ctx)\ndrivers/bluetooth/btintel_pcie_debug.c-206-{\n--\ndrivers/bluetooth/btintel_pcie_debug.c-214-}\ndrivers/bluetooth/btintel_pcie_debug.c:215:EXPORT_SYMBOL_GPL(btintel_pcie_yoyo_cleanup);\ndrivers/bluetooth/btintel_pcie_debug.c-216-\ndrivers/bluetooth/btintel_pcie_debug.c:217:int btintel_pcie_yoyo_load_and_parse(struct btintel_pcie_yoyo_ctx *ctx,\ndrivers/bluetooth/btintel_pcie_debug.c-218-\t\t\t\t     struct device *dev)\n--\ndrivers/bluetooth/btintel_pcie_debug.c-235-\telse\ndrivers/bluetooth/btintel_pcie_debug.c:236:\t\terr = btintel_pcie_yoyo_parse_tlv_buffer(ctx, fw-\u003edata, fw-\u003esize);\ndrivers/bluetooth/btintel_pcie_debug.c-237-\n--\ndrivers/bluetooth/btintel_pcie_debug.c-250-}\ndrivers/bluetooth/btintel_pcie_debug.c:251:EXPORT_SYMBOL_GPL(btintel_pcie_yoyo_load_and_parse);\ndrivers/bluetooth/btintel_pcie_debug.c-252-\ndrivers/bluetooth/btintel_pcie_debug.c=253=const struct btintel_pcie_buf_alloc *\ndrivers/bluetooth/btintel_pcie_debug.c:254:btintel_pcie_yoyo_get_buf_alloc(struct btintel_pcie_yoyo_ctx *ctx, u32 alloc_id)\ndrivers/bluetooth/btintel_pcie_debug.c-255-{\n--\ndrivers/bluetooth/btintel_pcie_debug.c-267-}\ndrivers/bluetooth/btintel_pcie_debug.c:268:EXPORT_SYMBOL_GPL(btintel_pcie_yoyo_get_buf_alloc);\ndrivers/bluetooth/btintel_pcie_debug.c-269-\n--\ndrivers/bluetooth/btintel_pcie_debug.h=86=struct btintel_pcie_buf_alloc {\n--\ndrivers/bluetooth/btintel_pcie_debug.h-94-\ndrivers/bluetooth/btintel_pcie_debug.h:95:struct btintel_pcie_yoyo_ctx {\ndrivers/bluetooth/btintel_pcie_debug.h-96-\tbool enabled;\n--\ndrivers/bluetooth/btintel_pcie_debug.h-106-\ndrivers/bluetooth/btintel_pcie_debug.h:107:int btintel_pcie_yoyo_init(struct btintel_pcie_yoyo_ctx *ctx);\ndrivers/bluetooth/btintel_pcie_debug.h:108:void btintel_pcie_yoyo_cleanup(struct btintel_pcie_yoyo_ctx *ctx);\ndrivers/bluetooth/btintel_pcie_debug.h:109:int btintel_pcie_yoyo_load_and_parse(struct btintel_pcie_yoyo_ctx *ctx,\ndrivers/bluetooth/btintel_pcie_debug.h-110-\t\t\t\t     struct device *dev);\ndrivers/bluetooth/btintel_pcie_debug.h=111=const struct btintel_pcie_buf_alloc *\ndrivers/bluetooth/btintel_pcie_debug.h:112:btintel_pcie_yoyo_get_buf_alloc(struct btintel_pcie_yoyo_ctx *ctx, u32 alloc_id);\ndrivers/bluetooth/btintel_pcie_debug.h-113-\n"
}

13/2 2026/10/13 12:44 llm patch-evaluator
0m Model:
gemini-3.8-flash

Args:
null

Results:
null

Tokens:
							input: 23596
							output: 134
							thoughts: 823
						

Thoughts:
**Analysis of `btintel_pcie` for Fuzzing Suitability**

Okay, let's break this down. My initial assessment is that `btintel_pcie` is unlikely to be a good fuzzing target. Let's see why, systematically:

First, `btintel_pcie` is only triggered during PCI probe of Intel Bluetooth PCIe devices. I'm seeing calls like `btintel_pcie_load_dbg_path_from_ini`, but that's only in `btintel_pcie_probe`. Similarly, `btintel_pcie_setup_mdbgc` is called within `btintel_pcie_setup_dbgc_mem`, which itself is only called from either `btintel_pcie_start` or `btintel_pcie_probe`. Functions for debug dumps, such as `btintel_pcie_dump_dram` and `btintel_pcie_read_debug_regions`, are called within `btintel_pcie`'s context. In short: all the modified code here is directly tied to this specific driver. Critically, we are dealing with a PCI driver for Intel Bluetooth PCIe hardware (e.g., BE200, AX211, etc.).

Now, back to the instructions. Section 2 explicitly flags "Structurally unreachable hardware." Specifically, drivers that need specific hardware not emulated in standard QEMU. That list of examples really hits home, and now I need to confirm:

Is Intel Bluetooth PCIe supported in a standard QEMU environment? No. My understanding is that QEMU doesn't emulate these specific devices. This is a vendor-specific PCI device driver! Given this, it cannot be reached in a standard virtualized environment like GCE or QEMU, because the required PCI device IDs are simply not present in any standard virtualized fuzzing setup. I'm talking about 0x4D76, 0xA876, 0xE376, 0xE476, 0xD346, 0x6E74, 0x2731, 0x2732. These IDs, and the associated Intel hardware, are the key to this driver being active.

Therefore, `WorthFuzzing` should definitely be `false`. Now, let's verify everything is in order:

When `WorthFuzzing` is set to `false`, my reasoning needs to be crisp: The modified code is isolated within `btintel_pcie` and its debug helpers. This is an Intel PCIe Bluetooth driver that specifically requires physical Intel PCIe hardware (BlazarI, Scorpious, Draco). These are *not* emulated in standard QEMU or GCE virtualized environments, making them structurally unreachable for Syzkaller fuzzing.

Let's double-check the code changes. The patch only touches files within the `drivers/bluetooth/` directory: specifically, `Makefile`, `btintel_pcie.c`, `btintel_pcie.h`, `btintel_pcie_debug.c`, and `btintel_pcie_debug.h`. It does *not* touch core Bluetooth subsystem code, virtual HCI drivers, or USB gadget drivers. Everything is strictly within the `btintel_pcie` driver. This driver specifically binds to certain Intel PCIe device IDs through `pci_driver btintel_pcie_driver`. Since standard QEMU/GCE environments don't emulate these devices, the code is indeed structurally unreachable. I've got a tight argument, and I'm ready to call `set-results`.



14/2 2026/10/13 12:44 tool set-results
0m Args:
{
  "EnableConfigs": [],
  "FocusSymbols": [],
  "Reasoning": "The patch series modifies the btintel_pcie driver and adds btintel_pcie_debug for Intel PCIe Bluetooth devices (YoYo debug configuration support). This driver requires specific physical Intel PCIe hardware (such as Intel BlazarI, Lunar Lake, Panther Lake, Nova Lake PCIe Bluetooth adapters) that is not emulated in standard QEMU or GCE virtualized environments. Because there is no virtual bus or emulation support for these PCIe devices in standard fuzzing environments, the modified code is structurally unreachable.",
  "WorthFuzzing": false
}

Results:
{
  "EnableConfigs": null,
  "FocusSymbols": [],
  "Reasoning": "The patch series modifies the btintel_pcie driver and adds btintel_pcie_debug for Intel PCIe Bluetooth devices (YoYo debug configuration support). This driver requires specific physical Intel PCIe hardware (such as Intel BlazarI, Lunar Lake, Panther Lake, Nova Lake PCIe Bluetooth adapters) that is not emulated in standard QEMU or GCE virtualized environments. Because there is no virtual bus or emulation support for these PCIe devices in standard fuzzing environments, the modified code is structurally unreachable.",
  "WorthFuzzing": false
}

15/1 2026/10/13 12:44 action If
0m Args:
{
  "WorthFuzzing": false
}

Results:
null

LLM Calls Summary:
Total Calls Total Tokens Avg Tokens Total Duration (Seconds) Avg Duration (Seconds)
Tool Calls Summary:
Total Calls Total Duration (Seconds) Avg Duration (Seconds)