* [PATCH v2 0/6] Add support for IPQ5018 Bluetooth
@ 2026-06-29 13:01 George Moussalem via B4 Relay
2026-06-29 13:01 ` [PATCH v2 1/6] dt-bindings: net: bluetooth: Document Qualcomm IPQ5018 Bluetooth controller George Moussalem via B4 Relay
` (5 more replies)
0 siblings, 6 replies; 27+ messages in thread
From: George Moussalem via B4 Relay @ 2026-06-29 13:01 UTC (permalink / raw)
To: Jens Axboe, Ulf Hansson, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Johannes Berg, Jeff Johnson, Bartosz Golaszewski,
Marcel Holtmann, Luiz Augusto von Dentz, Balakrishna Godavarthi,
Rocky Liao, Saravana Kannan, Andrew Lunn, Heiner Kallweit,
Russell King, David S. Miller, Eric Dumazet, Jakub Kicinski,
Paolo Abeni, Simon Horman, Bjorn Andersson, Konrad Dybcio,
Mathieu Poirier, Philipp Zabel
Cc: linux-block, linux-kernel, linux-mmc, devicetree, linux-wireless,
ath10k, linux-arm-msm, linux-bluetooth, netdev, linux-remoteproc,
George Moussalem
Hello,
This patch series introduces Bluetooth support for IPQ5018.
Bluetooth firmware is loaded by the host into a dedicated reserved
memory carveout and authenticated by TrustZone. A Secure Channel Manager
(SCM) call safely brings the peripheral core out of reset.
A shared memory ring buffer topology handles runtime data frame
transport between the host APSS and the Bluetooth controller.
An outgoing APCS IPC bit and an incoming GIC interrupt handle
host/guest signaling.
This series has been tested and verified on various IPQ5018 router
boards utilizing firmware extracted from GPL distributions, using both
mdt and mbn file formats.
[ 14.781511] Bluetooth: hci0: QCA Product ID :0x00000016
[ 14.781583] Bluetooth: hci0: QCA SOC Version :0x20180100
[ 14.785926] Bluetooth: hci0: QCA ROM Version :0x00000100
[ 14.791546] Bluetooth: hci0: QCA Patch Version:0x00003ded
[ 14.796698] Bluetooth: hci0: QCA controller version 0x01000100
[ 14.802217] Bluetooth: hci0: QCA Downloading qca/mpnv10.bin
[ 16.393850] Bluetooth: hci0: QCA Build Info: BTFW.MAPLE.1.0.0-00102-MPL_ROM_PATCHZ-1
Best regards,
George Moussalem
Signed-off-by: George Moussalem <george.moussalem@outlook.com>
---
Changes in v2:
- removed unused struct member btss_reset from m0_btss struct.
- used devm_reset_control_get_exclusive_deasserted to acquire and
deassert btss_reset in one call. No need to explicitly assert upon
unbind since devres will handle it.
- As per Bjorn's comments, collapsed the rproc and BT driver into one
which now handles firmware loading and transport.
- As per further review comments and above change, squashed the two
devicetree bindings into one to represent the Bluetooth controller
- Added new SCM call to drive Bluetooth power modes. Based on testing on
more router boards, this is required during start/stop sequences to
avoid the controller hanging. This is only supported on relatively
newer QSEE versions, so the SCM call is checked for availability
before use.
- Refactored resource lifecycle management in the driver so that IRQ and
work queue are managed at the driver level (probe/remove) while FW
loading and powering on/off the controller is handled upon hdev
open/close.
- Consolidated TX send functions for custom IPC and HCI frames into one
and solved a potential NULL pointer dereference issue under TX
pressure.
- Replace code to load and initialize firmware metadate by existing
qcom_mdt_pas_init function.
- Solved an off byone calculation error in the RX parser.
- Added entry to MAINTAINERS file
- Link to v1: https://lore.kernel.org/r/20260625-ipq5018-bluetooth-v1-0-d999be0e04f7@outlook.com
---
George Moussalem (6):
dt-bindings: net: bluetooth: Document Qualcomm IPQ5018 Bluetooth controller
Bluetooth: btqca: Add IPQ5018 support
firmware: qcom: scm: Add support for setting Bluetooth power modes
Bluetooth: Introduce Qualcomm IPQ5018 IPC based HCI driver
arm64: dts: qcom: ipq5018: add nodes required for Bluetooth support
MAINTAINERS: Add entry for Qualcomm IPQ5018 Bluetooth driver
.../bindings/net/bluetooth/qcom,ipq5018-bt.yaml | 86 ++
MAINTAINERS | 7 +
arch/arm64/boot/dts/qcom/ipq5018.dtsi | 25 +-
drivers/bluetooth/Kconfig | 11 +
drivers/bluetooth/Makefile | 1 +
drivers/bluetooth/btqca.c | 16 +
drivers/bluetooth/btqca.h | 3 +
drivers/bluetooth/btqcomipc.c | 1052 ++++++++++++++++++++
drivers/firmware/qcom/qcom_scm.c | 49 +
drivers/firmware/qcom/qcom_scm.h | 1 +
include/linux/firmware/qcom/qcom_scm.h | 1 +
11 files changed, 1251 insertions(+), 1 deletion(-)
---
base-commit: 4d1ab324fcb7d20df5a071edb0304461846fdc12
change-id: 20260625-ipq5018-bluetooth-06ff66c9d753
prerequisite-message-id: <20260612-block-as-nvmem-v5-0-95e0b30fff90@oss.qualcomm.com>
prerequisite-patch-id: 6ce8686c1683f468d86b4502f5ec9d19c392a382
prerequisite-patch-id: e362f7fcbacff716b7ef720e6780786a7d88c013
prerequisite-patch-id: 9168930e40551e842c8171d5433a6f39ad4b78a4
prerequisite-patch-id: 64fecfbd1e085d7d2ab0ae23295ca34ec8e14c5e
prerequisite-patch-id: 566804aaa690ee9aa285d0fd75fd16d94fbadebf
prerequisite-patch-id: dc18bec338f54b3051f4523f9d1d3c0566a20ccd
prerequisite-patch-id: b6b3eb46429936ab49423d295433daf47981db0f
prerequisite-patch-id: 75caa99e3bbcdf41b6462b9f5f703bea1d4a65fa
prerequisite-patch-id: 35e9968f482f78ca233eb0306d9c5fdbff093175
Best regards,
--
George Moussalem <george.moussalem@outlook.com>
^ permalink raw reply [flat|nested] 27+ messages in thread
* [PATCH v2 1/6] dt-bindings: net: bluetooth: Document Qualcomm IPQ5018 Bluetooth controller
2026-06-29 13:01 [PATCH v2 0/6] Add support for IPQ5018 Bluetooth George Moussalem via B4 Relay
@ 2026-06-29 13:01 ` George Moussalem via B4 Relay
2026-06-30 7:15 ` Krzysztof Kozlowski
2026-06-30 8:20 ` Krzysztof Kozlowski
2026-06-29 13:01 ` [PATCH v2 2/6] Bluetooth: btqca: Add IPQ5018 support George Moussalem via B4 Relay
` (4 subsequent siblings)
5 siblings, 2 replies; 27+ messages in thread
From: George Moussalem via B4 Relay @ 2026-06-29 13:01 UTC (permalink / raw)
To: Jens Axboe, Ulf Hansson, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Johannes Berg, Jeff Johnson, Bartosz Golaszewski,
Marcel Holtmann, Luiz Augusto von Dentz, Balakrishna Godavarthi,
Rocky Liao, Saravana Kannan, Andrew Lunn, Heiner Kallweit,
Russell King, David S. Miller, Eric Dumazet, Jakub Kicinski,
Paolo Abeni, Simon Horman, Bjorn Andersson, Konrad Dybcio,
Mathieu Poirier, Philipp Zabel
Cc: linux-block, linux-kernel, linux-mmc, devicetree, linux-wireless,
ath10k, linux-arm-msm, linux-bluetooth, netdev, linux-remoteproc,
George Moussalem
From: George Moussalem <george.moussalem@outlook.com>
Document the Qualcomm IPQ5018 Bluetooth controller.
Signed-off-by: George Moussalem <george.moussalem@outlook.com>
---
.../bindings/net/bluetooth/qcom,ipq5018-bt.yaml | 86 ++++++++++++++++++++++
1 file changed, 86 insertions(+)
diff --git a/Documentation/devicetree/bindings/net/bluetooth/qcom,ipq5018-bt.yaml b/Documentation/devicetree/bindings/net/bluetooth/qcom,ipq5018-bt.yaml
new file mode 100644
index 000000000000..2119162994e0
--- /dev/null
+++ b/Documentation/devicetree/bindings/net/bluetooth/qcom,ipq5018-bt.yaml
@@ -0,0 +1,86 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/net/bluetooth/qcom,ipq5018-bt.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Qualcomm IPQ5018 Bluetooth
+
+maintainers:
+ - George Moussalem <george.moussalem@outlook.com>
+
+properties:
+ compatible:
+ enum:
+ - qcom,ipq5018-bt
+
+ clocks:
+ items:
+ - description: Bluetooth Subsystem low power oscillator clock
+
+ clock-names:
+ items:
+ - const: lpo
+
+ firmware-name:
+ maxItems: 1
+
+ memory-region:
+ items:
+ - description: |
+ Reserved memory carveout for firmware loading and runtime data
+ transport between the host and the Bluetooth controller.
+
+ interrupts:
+ maxItems: 1
+
+ qcom,ipc:
+ $ref: /schemas/types.yaml#/definitions/phandle-array
+ items:
+ - items:
+ - description: syscon node representing the APCS registers
+ - description: offset to the register within the syscon
+ - description: IPC bit within the register
+ description: |
+ The outgoing IPC bit used for signaling the Bluetooth controller of a host
+ event or for sending an ACK if the remote processor expects it.
+
+ resets:
+ items:
+ - description: Bluetooth Subsystem reset
+
+required:
+ - compatible
+ - clocks
+ - clock-names
+ - firmware-name
+ - interrupts
+ - qcom,ipc
+ - resets
+
+allOf:
+ - $ref: bluetooth-controller.yaml#
+ - $ref: qcom,bluetooth-common.yaml
+
+unevaluatedProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/clock/qcom,gcc-ipq5018.h>
+ #include <dt-bindings/interrupt-controller/arm-gic.h>
+ #include <dt-bindings/reset/qcom,gcc-ipq5018.h>
+
+ bluetooth {
+ compatible = "qcom,ipq5018-bt";
+
+ firmware-name = "qca/bt_fw_patch.mbn";
+
+ clocks = <&gcc GCC_BTSS_LPO_CLK>;
+ clock-names = "lpo";
+ resets = <&gcc GCC_BTSS_BCR>;
+
+ qcom,ipc = <&apcs_glb 8 23>;
+ interrupts = <GIC_SPI 162 IRQ_TYPE_EDGE_RISING>;
+
+ memory-region = <&btss_region>;
+ };
--
2.53.0
^ permalink raw reply related [flat|nested] 27+ messages in thread
* [PATCH v2 2/6] Bluetooth: btqca: Add IPQ5018 support
2026-06-29 13:01 [PATCH v2 0/6] Add support for IPQ5018 Bluetooth George Moussalem via B4 Relay
2026-06-29 13:01 ` [PATCH v2 1/6] dt-bindings: net: bluetooth: Document Qualcomm IPQ5018 Bluetooth controller George Moussalem via B4 Relay
@ 2026-06-29 13:01 ` George Moussalem via B4 Relay
2026-07-01 9:59 ` Bartosz Golaszewski
2026-06-29 13:01 ` [PATCH v2 3/6] firmware: qcom: scm: Add support for setting Bluetooth power modes George Moussalem via B4 Relay
` (3 subsequent siblings)
5 siblings, 1 reply; 27+ messages in thread
From: George Moussalem via B4 Relay @ 2026-06-29 13:01 UTC (permalink / raw)
To: Jens Axboe, Ulf Hansson, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Johannes Berg, Jeff Johnson, Bartosz Golaszewski,
Marcel Holtmann, Luiz Augusto von Dentz, Balakrishna Godavarthi,
Rocky Liao, Saravana Kannan, Andrew Lunn, Heiner Kallweit,
Russell King, David S. Miller, Eric Dumazet, Jakub Kicinski,
Paolo Abeni, Simon Horman, Bjorn Andersson, Konrad Dybcio,
Mathieu Poirier, Philipp Zabel
Cc: linux-block, linux-kernel, linux-mmc, devicetree, linux-wireless,
ath10k, linux-arm-msm, linux-bluetooth, netdev, linux-remoteproc,
George Moussalem
From: George Moussalem <george.moussalem@outlook.com>
Add the IPQ5018 SoC type and support for loading its firmware.
The firmware tested has been taken from GPL sources of various router
boards. Firmware files needed are:
- qca/bt_fw_patch.mbn
- qca/mpnv10.bin
Signed-off-by: George Moussalem <george.moussalem@outlook.com>
---
drivers/bluetooth/btqca.c | 16 ++++++++++++++++
drivers/bluetooth/btqca.h | 3 +++
2 files changed, 19 insertions(+)
diff --git a/drivers/bluetooth/btqca.c b/drivers/bluetooth/btqca.c
index 04ebe290bc78..e136e91976cf 100644
--- a/drivers/bluetooth/btqca.c
+++ b/drivers/bluetooth/btqca.c
@@ -380,6 +380,9 @@ static int qca_tlv_check_data(struct hci_dev *hdev,
break;
case TLV_TYPE_NVM:
+ if (soc_type == QCA_IPQ5018)
+ break;
+
if (fw_size < sizeof(struct tlv_type_hdr))
return -EINVAL;
@@ -794,6 +797,9 @@ int qca_uart_setup(struct hci_dev *hdev, uint8_t baudrate,
else
rom_ver = ((soc_ver & 0x00000f00) >> 0x04) | (soc_ver & 0x0000000f);
+ if (soc_type == QCA_IPQ5018)
+ goto download_nvm;
+
if (soc_type == QCA_WCN6750)
qca_send_patch_config_cmd(hdev);
@@ -881,6 +887,7 @@ int qca_uart_setup(struct hci_dev *hdev, uint8_t baudrate,
if (soc_type == QCA_QCA2066 || soc_type == QCA_WCN7850)
qca_read_fw_board_id(hdev, &boardid);
+download_nvm:
/* Download NVM configuration */
config.type = TLV_TYPE_NVM;
if (firmware_name) {
@@ -939,6 +946,10 @@ int qca_uart_setup(struct hci_dev *hdev, uint8_t baudrate,
qca_get_nvm_name_by_board(config.fwname, sizeof(config.fwname),
"hmtnv", soc_type, ver, rom_ver, boardid);
break;
+ case QCA_IPQ5018:
+ snprintf(config.fwname, sizeof(config.fwname),
+ "qca/mpnv%02x.bin", rom_ver);
+ break;
default:
snprintf(config.fwname, sizeof(config.fwname),
"qca/nvm_%08x.bin", soc_ver);
@@ -958,6 +969,9 @@ int qca_uart_setup(struct hci_dev *hdev, uint8_t baudrate,
return err;
}
+ if (soc_type == QCA_IPQ5018)
+ msleep(NVM_READY_DELAY_MS);
+
switch (soc_type) {
case QCA_QCA2066:
case QCA_QCA6390:
@@ -965,6 +979,7 @@ int qca_uart_setup(struct hci_dev *hdev, uint8_t baudrate,
case QCA_WCN6750:
case QCA_WCN6855:
case QCA_WCN7850:
+ case QCA_IPQ5018:
err = qca_disable_soc_logging(hdev);
if (err < 0)
return err;
@@ -1001,6 +1016,7 @@ int qca_uart_setup(struct hci_dev *hdev, uint8_t baudrate,
case QCA_WCN6750:
case QCA_WCN6855:
case QCA_WCN7850:
+ case QCA_IPQ5018:
/* get fw build info */
err = qca_read_fw_build_info(hdev);
if (err < 0)
diff --git a/drivers/bluetooth/btqca.h b/drivers/bluetooth/btqca.h
index 8f3c1b1c77b3..343cd62d1137 100644
--- a/drivers/bluetooth/btqca.h
+++ b/drivers/bluetooth/btqca.h
@@ -54,6 +54,8 @@
#define QCA_HSP_GF_SOC_ID 0x1200
#define QCA_HSP_GF_SOC_MASK 0x0000ff00
+#define NVM_READY_DELAY_MS 1500
+
enum qca_baudrate {
QCA_BAUDRATE_115200 = 0,
QCA_BAUDRATE_57600,
@@ -158,6 +160,7 @@ enum qca_btsoc_type {
QCA_WCN6750,
QCA_WCN6855,
QCA_WCN7850,
+ QCA_IPQ5018,
};
#if IS_ENABLED(CONFIG_BT_QCA)
--
2.53.0
^ permalink raw reply related [flat|nested] 27+ messages in thread
* [PATCH v2 3/6] firmware: qcom: scm: Add support for setting Bluetooth power modes
2026-06-29 13:01 [PATCH v2 0/6] Add support for IPQ5018 Bluetooth George Moussalem via B4 Relay
2026-06-29 13:01 ` [PATCH v2 1/6] dt-bindings: net: bluetooth: Document Qualcomm IPQ5018 Bluetooth controller George Moussalem via B4 Relay
2026-06-29 13:01 ` [PATCH v2 2/6] Bluetooth: btqca: Add IPQ5018 support George Moussalem via B4 Relay
@ 2026-06-29 13:01 ` George Moussalem via B4 Relay
2026-06-30 13:02 ` sashiko-bot
` (2 more replies)
2026-06-29 13:01 ` [PATCH v2 4/6] Bluetooth: Introduce Qualcomm IPQ5018 IPC based HCI driver George Moussalem via B4 Relay
` (2 subsequent siblings)
5 siblings, 3 replies; 27+ messages in thread
From: George Moussalem via B4 Relay @ 2026-06-29 13:01 UTC (permalink / raw)
To: Jens Axboe, Ulf Hansson, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Johannes Berg, Jeff Johnson, Bartosz Golaszewski,
Marcel Holtmann, Luiz Augusto von Dentz, Balakrishna Godavarthi,
Rocky Liao, Saravana Kannan, Andrew Lunn, Heiner Kallweit,
Russell King, David S. Miller, Eric Dumazet, Jakub Kicinski,
Paolo Abeni, Simon Horman, Bjorn Andersson, Konrad Dybcio,
Mathieu Poirier, Philipp Zabel
Cc: linux-block, linux-kernel, linux-mmc, devicetree, linux-wireless,
ath10k, linux-arm-msm, linux-bluetooth, netdev, linux-remoteproc,
George Moussalem
From: George Moussalem <george.moussalem@outlook.com>
The Bluetooth subsystem (BTSS) on the IPQ5018 SoC supports setting power
modes which are required to be configured through a Secure Channel
Manager (SCM) call to TrustZone. However, not all Trusted Execution
Environment (QSEE) images support this call, so first check if the call
is available.
Signed-off-by: George Moussalem <george.moussalem@outlook.com>
---
drivers/firmware/qcom/qcom_scm.c | 49 ++++++++++++++++++++++++++++++++++
drivers/firmware/qcom/qcom_scm.h | 1 +
include/linux/firmware/qcom/qcom_scm.h | 1 +
3 files changed, 51 insertions(+)
diff --git a/drivers/firmware/qcom/qcom_scm.c b/drivers/firmware/qcom/qcom_scm.c
index 6b601a4b89db..e26f54e5033b 100644
--- a/drivers/firmware/qcom/qcom_scm.c
+++ b/drivers/firmware/qcom/qcom_scm.c
@@ -1094,6 +1094,55 @@ bool qcom_scm_pas_supported(u32 pas_id)
}
EXPORT_SYMBOL_GPL(qcom_scm_pas_supported);
+static int __qcom_scm_pas_set_bluetooth_power_mode(u32 pas_id, u32 val)
+{
+ struct qcom_scm_desc desc = {
+ .svc = QCOM_SCM_SVC_PIL,
+ .cmd = QCOM_SCM_PIL_PAS_BT_PWR_MODE,
+ .arginfo = QCOM_SCM_ARGS(2),
+ .args[0] = pas_id,
+ .args[1] = val,
+ .owner = ARM_SMCCC_OWNER_SIP,
+ };
+ struct qcom_scm_res res;
+ int ret;
+
+ ret = qcom_scm_clk_enable();
+ if (ret)
+ return ret;
+
+ ret = qcom_scm_bw_enable();
+ if (ret)
+ goto disable_clk;
+
+ ret = qcom_scm_call(__scm->dev, &desc, &res);
+ qcom_scm_bw_disable();
+
+disable_clk:
+ qcom_scm_clk_disable();
+
+ return ret ? : res.result[0];
+}
+
+/**
+ * qcom_scm_pas_set_bluetooth_power_mode() - Configure power optimization mode
+ * for the Bluetooth subsystem (BTSS)
+ * @pas_id: peripheral authentication service id
+ * @val: 0x0 for normal operation, 0x4 for ECO mode
+ *
+ * Return: 0 on success, negative errno on failure.
+ * Returns -EOPNOTSUPP if the firmware configuration call is unavailable.
+ */
+int qcom_scm_pas_set_bluetooth_power_mode(u32 pas_id, u32 val)
+{
+ if (!__qcom_scm_is_call_available(__scm->dev, QCOM_SCM_SVC_PIL,
+ QCOM_SCM_PIL_PAS_BT_PWR_MODE))
+ return -EOPNOTSUPP;
+
+ return __qcom_scm_pas_set_bluetooth_power_mode(pas_id, val);
+}
+EXPORT_SYMBOL_GPL(qcom_scm_pas_set_bluetooth_power_mode);
+
static int __qcom_scm_pas_mss_reset(struct device *dev, bool reset)
{
struct qcom_scm_desc desc = {
diff --git a/drivers/firmware/qcom/qcom_scm.h b/drivers/firmware/qcom/qcom_scm.h
index caab80a73e17..5579df5a2aca 100644
--- a/drivers/firmware/qcom/qcom_scm.h
+++ b/drivers/firmware/qcom/qcom_scm.h
@@ -105,6 +105,7 @@ int qcom_scm_shm_bridge_enable(struct device *scm_dev);
#define QCOM_SCM_PIL_PAS_SHUTDOWN 0x06
#define QCOM_SCM_PIL_PAS_IS_SUPPORTED 0x07
#define QCOM_SCM_PIL_PAS_MSS_RESET 0x0a
+#define QCOM_SCM_PIL_PAS_BT_PWR_MODE 0x21
#define QCOM_SCM_PIL_PAS_GET_RSCTABLE 0x21
#define QCOM_SCM_SVC_IO 0x05
diff --git a/include/linux/firmware/qcom/qcom_scm.h b/include/linux/firmware/qcom/qcom_scm.h
index 5747bd191bf1..76de4b69580b 100644
--- a/include/linux/firmware/qcom/qcom_scm.h
+++ b/include/linux/firmware/qcom/qcom_scm.h
@@ -93,6 +93,7 @@ struct resource_table *qcom_scm_pas_get_rsc_table(struct qcom_scm_pas_context *c
size_t *output_rt_size);
int qcom_scm_pas_prepare_and_auth_reset(struct qcom_scm_pas_context *ctx);
+int qcom_scm_pas_set_bluetooth_power_mode(u32 pas_id, u32 val);
int qcom_scm_io_readl(phys_addr_t addr, unsigned int *val);
int qcom_scm_io_writel(phys_addr_t addr, unsigned int val);
--
2.53.0
^ permalink raw reply related [flat|nested] 27+ messages in thread
* [PATCH v2 4/6] Bluetooth: Introduce Qualcomm IPQ5018 IPC based HCI driver
2026-06-29 13:01 [PATCH v2 0/6] Add support for IPQ5018 Bluetooth George Moussalem via B4 Relay
` (2 preceding siblings ...)
2026-06-29 13:01 ` [PATCH v2 3/6] firmware: qcom: scm: Add support for setting Bluetooth power modes George Moussalem via B4 Relay
@ 2026-06-29 13:01 ` George Moussalem via B4 Relay
2026-06-30 13:02 ` sashiko-bot
2026-07-01 11:19 ` Konrad Dybcio
2026-06-29 13:01 ` [PATCH v2 5/6] arm64: dts: qcom: ipq5018: add nodes required for Bluetooth support George Moussalem via B4 Relay
2026-06-29 13:01 ` [PATCH v2 6/6] MAINTAINERS: Add entry for Qualcomm IPQ5018 Bluetooth driver George Moussalem via B4 Relay
5 siblings, 2 replies; 27+ messages in thread
From: George Moussalem via B4 Relay @ 2026-06-29 13:01 UTC (permalink / raw)
To: Jens Axboe, Ulf Hansson, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Johannes Berg, Jeff Johnson, Bartosz Golaszewski,
Marcel Holtmann, Luiz Augusto von Dentz, Balakrishna Godavarthi,
Rocky Liao, Saravana Kannan, Andrew Lunn, Heiner Kallweit,
Russell King, David S. Miller, Eric Dumazet, Jakub Kicinski,
Paolo Abeni, Simon Horman, Bjorn Andersson, Konrad Dybcio,
Mathieu Poirier, Philipp Zabel
Cc: linux-block, linux-kernel, linux-mmc, devicetree, linux-wireless,
ath10k, linux-arm-msm, linux-bluetooth, netdev, linux-remoteproc,
George Moussalem
From: George Moussalem <george.moussalem@outlook.com>
Add support for the Bluetooth controller found in the IPQ5018 SoC.
This driver implements firmware loading and the transport layer between
the HCI core and the Bluetooth controller.
The firmware is loaded by the host into the dedicated reserved memory
carveout and authenticated by TrustZone. A Secure Channel Manager (SCM)
call safely brings the peripheral core out of reset.
A shared memory ring buffer topology handles runtime data frame
transport between the host APSS and the controller.
An outgoing APCS IPC bit and an incoming GIC interrupt handle host/guest
signaling.
Signed-off-by: George Moussalem <george.moussalem@outlook.com>
---
drivers/bluetooth/Kconfig | 11 +
drivers/bluetooth/Makefile | 1 +
drivers/bluetooth/btqcomipc.c | 1052 +++++++++++++++++++++++++++++++++++++++++
3 files changed, 1064 insertions(+)
diff --git a/drivers/bluetooth/Kconfig b/drivers/bluetooth/Kconfig
index 4e8c24d757e9..c9785f43c87c 100644
--- a/drivers/bluetooth/Kconfig
+++ b/drivers/bluetooth/Kconfig
@@ -413,6 +413,17 @@ config BT_MTKUART
Say Y here to compile support for MediaTek Bluetooth UART devices
into the kernel or say M to compile it as module (btmtkuart).
+config BT_QCOMIPC
+ tristate "Qualcomm IPQ5018 IPC based HCI support"
+ select BT_QCA
+ help
+ Qualcomm IPQ5018 IPC based HCI driver.
+ This driver is used to load firmware and bridge HCI data onto shared
+ memory between the host and the Bluetooth controller.
+
+ Say Y here to compile support for HCI over Qualcomm IPC into the
+ kernel or say M to compile as a module.
+
config BT_QCOMSMD
tristate "Qualcomm SMD based HCI support"
depends on RPMSG || (COMPILE_TEST && RPMSG=n)
diff --git a/drivers/bluetooth/Makefile b/drivers/bluetooth/Makefile
index e6b1c1180d1d..05f19047bed0 100644
--- a/drivers/bluetooth/Makefile
+++ b/drivers/bluetooth/Makefile
@@ -20,6 +20,7 @@ obj-$(CONFIG_BT_MRVL) += btmrvl.o
obj-$(CONFIG_BT_MRVL_SDIO) += btmrvl_sdio.o
obj-$(CONFIG_BT_MTKSDIO) += btmtksdio.o
obj-$(CONFIG_BT_MTKUART) += btmtkuart.o
+obj-$(CONFIG_BT_QCOMIPC) += btqcomipc.o
obj-$(CONFIG_BT_QCOMSMD) += btqcomsmd.o
obj-$(CONFIG_BT_BCM) += btbcm.o
obj-$(CONFIG_BT_RTL) += btrtl.o
diff --git a/drivers/bluetooth/btqcomipc.c b/drivers/bluetooth/btqcomipc.c
new file mode 100644
index 000000000000..16bc59e4edae
--- /dev/null
+++ b/drivers/bluetooth/btqcomipc.c
@@ -0,0 +1,1052 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2020 The Linux Foundation. All rights reserved.
+ */
+
+#include <linux/bits.h>
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/elf.h>
+#include <linux/firmware.h>
+#include <linux/firmware/qcom/qcom_scm.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/mfd/syscon.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_irq.h>
+#include <linux/of_reserved_mem.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+#include <linux/reset.h>
+#include <linux/skbuff.h>
+#include <linux/slab.h>
+#include <linux/soc/qcom/mdt_loader.h>
+#include <linux/types.h>
+#include <linux/workqueue.h>
+
+#include <net/bluetooth/bluetooth.h>
+#include <net/bluetooth/hci_core.h>
+
+#include "btqca.h"
+
+/** Message header format.
+ *
+ * ----------------------------------------------------------------
+ * BitPos | 15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7 - 0 |
+ * ---------------------------------------------------------------
+ * Field | long_msg |ACK | RFU | pkt_type | cmd |
+ * ----------------------------------------------------------------
+ *
+ * - long_msg : If set, indicates that the payload is larger than the
+ * IPC_MSG_PLD_SZ. The payload instead contains a pointer to the
+ * long message buffer in the shared BTSS memory space.
+ *
+ * - ACK : Set if sending ACK if required by sending acknowledegement
+ * to sender i.e. send an ack IPC interrupt if set.
+ *
+ * - RFU : Reserved for future use.
+ *
+ * - pkt_type : IPC Packet Type
+ *
+ * - cmd : Contains unique command ID
+ */
+
+#define IPC_MSG_HDR_SZ 4
+#define IPC_MSG_PLD_SZ 40
+#define IPC_TOTAL_MSG_SZ (IPC_MSG_HDR_SZ + IPC_MSG_PLD_SZ)
+
+/* Message Header */
+#define IPC_HDR_LONG_MSG BIT(15)
+#define IPC_HDR_REQ_ACK BIT(14)
+#define IPC_HDR_PKT_TYPE_MASK GENMASK(9, 8)
+#define IPC_HDR_PKT_TYPE_CUST 0
+#define IPC_HDR_PKT_TYPE_HCI 1
+#define IPC_HDR_PKT_TYPE_AUDIO 2
+#define IPC_HDR_PKT_TYPE_RFU 3
+#define IPC_HDR_CMD_MASK GENMASK(7, 0)
+
+#define IPC_CMD_STOP 1
+#define IPC_CMD_SWITCH_TO_UART 2
+#define IPC_CMD_PREPARE_DUMP 3
+#define IPC_CMD_COLLECT_DUMP 4
+#define IPC_CMD_START 5
+
+#define IPC_TX_QSIZE 32
+
+#define TO_APPS_ADDR(a) (desc->mem_region + (int)(uintptr_t)a)
+#define TO_BT_ADDR(a) (a - desc->mem_region)
+#define IPC_LBUF_SZ(w, x, y, z) (((TO_BT_ADDR((void *)w) + w->x) - w->y) / w->z)
+
+#define GET_NO_OF_BLOCKS(a, b) ((a + b - 1) / b)
+
+#define GET_RX_INDEX_FROM_BUF(x, y) ((x - desc->rx_ctxt->lring_buf) / y)
+
+#define GET_TX_INDEX_FROM_BUF(x, y) ((x - desc->tx_ctxt->lring_buf) / y)
+
+#define IS_RX_MEM_NON_CONTIGIOUS(buf, len, sz) \
+ ((buf + len) > (desc->rx_ctxt->lring_buf + \
+ (sz * desc->rx_ctxt->lmsg_buf_cnt)))
+
+#define BTSS_PAS_ID 0xc
+
+#define BTSS_PWR_STATE_ACTIVE 0x0
+#define BTSS_PWR_STATE_ECO 0x4
+#define BTSS_PWR_CTRL_DELAY_MS 50
+
+struct long_msg_info {
+ __le16 smsg_free_cnt;
+ __le16 lmsg_free_cnt;
+ u8 ridx;
+ u8 widx;
+} __packed;
+
+struct ipc_aux_ptr {
+ __le32 len;
+ __le32 buf;
+} __packed;
+
+struct ring_buffer {
+ __le16 msg_hdr;
+ __le16 len;
+ union {
+ u8 smsg_data[IPC_MSG_PLD_SZ];
+ __le32 lmsg_data;
+ } payload;
+} __packed;
+
+struct ring_buffer_info {
+ __le32 rbuf;
+ u8 ring_buf_cnt;
+ u8 ridx;
+ u8 widx;
+ u8 tidx;
+ __le32 next;
+} __packed;
+
+struct context_info {
+ __le16 total_size;
+ u8 lmsg_buf_cnt;
+ u8 smsg_buf_cnt;
+ struct ring_buffer_info sring_buf_info;
+ __le32 sring_buf;
+ __le32 lring_buf;
+ __le32 reserved;
+} __packed;
+
+struct qcom_btss {
+ struct device *dev;
+ struct hci_dev *hdev;
+
+ struct regmap *regmap;
+ u32 offset;
+ u32 bit;
+ int irq;
+
+ const char *firmware;
+ void *mem_region;
+ phys_addr_t mem_phys;
+ phys_addr_t mem_reloc;
+ size_t mem_size;
+
+ struct sk_buff_head tx_q;
+ struct workqueue_struct *wq;
+ struct work_struct work;
+ wait_queue_head_t wait_q;
+ spinlock_t lock;
+
+ struct context_info *tx_ctxt;
+ struct context_info *rx_ctxt;
+ struct long_msg_info lmsg_ctxt;
+
+ bool running;
+};
+
+static void btqcomipc_update_stats(struct hci_dev *hdev, struct sk_buff *skb);
+
+static void *btss_alloc_lmsg(struct qcom_btss *desc, u32 len,
+ struct ipc_aux_ptr *aux_ptr, bool *is_lbuf_full)
+{
+ struct device *dev = desc->dev;
+ u8 idx, blks, blks_consumed;
+ void *ret_ptr;
+ u32 lsz;
+
+ if (desc->tx_ctxt->lring_buf == 0) {
+ dev_err(dev, "no long message buffer initialized\n");
+ return ERR_PTR(-ENODEV);
+ }
+
+ lsz = IPC_LBUF_SZ(desc->tx_ctxt, total_size, lring_buf, lmsg_buf_cnt);
+ blks = GET_NO_OF_BLOCKS(len, lsz);
+
+ if (!desc->lmsg_ctxt.lmsg_free_cnt ||
+ (blks > desc->lmsg_ctxt.lmsg_free_cnt))
+ return ERR_PTR(-EAGAIN);
+
+ idx = desc->lmsg_ctxt.widx;
+
+ if ((desc->lmsg_ctxt.widx + blks) > desc->tx_ctxt->lmsg_buf_cnt) {
+ blks_consumed = desc->tx_ctxt->lmsg_buf_cnt - idx;
+ aux_ptr->len = len - (blks_consumed * lsz);
+ aux_ptr->buf = desc->tx_ctxt->lring_buf;
+ }
+
+ desc->lmsg_ctxt.widx = (desc->lmsg_ctxt.widx + blks) %
+ desc->tx_ctxt->lmsg_buf_cnt;
+
+ desc->lmsg_ctxt.lmsg_free_cnt -= blks;
+
+ if (desc->lmsg_ctxt.lmsg_free_cnt <=
+ ((desc->tx_ctxt->lmsg_buf_cnt * 20) / 100))
+ *is_lbuf_full = true;
+
+ ret_ptr = TO_APPS_ADDR(desc->tx_ctxt->lring_buf) + (idx * lsz);
+
+ return ret_ptr;
+}
+
+static struct ring_buffer_info *btss_get_tx_rbuf(struct qcom_btss *desc,
+ bool *is_sbuf_full)
+{
+ u8 idx;
+ struct ring_buffer_info *rinfo;
+
+ for (rinfo = &(desc->tx_ctxt->sring_buf_info); rinfo != NULL;
+ rinfo = (struct ring_buffer_info *)(uintptr_t)(rinfo->next)) {
+ idx = (rinfo->widx + 1) % (desc->tx_ctxt->smsg_buf_cnt);
+
+ if (idx != rinfo->tidx) {
+ desc->lmsg_ctxt.smsg_free_cnt--;
+
+ if (desc->lmsg_ctxt.smsg_free_cnt <=
+ ((desc->tx_ctxt->smsg_buf_cnt * 20) / 100))
+ *is_sbuf_full = true;
+
+ return rinfo;
+ }
+ }
+
+ return ERR_PTR(-EAGAIN);
+}
+
+static int btss_send(struct qcom_btss *desc, u16 msg_hdr,
+ struct sk_buff *skb)
+{
+ struct hci_dev *hdev = desc->hdev;
+ struct ring_buffer_info *rinfo;
+ struct ipc_aux_ptr aux_ptr;
+ struct ring_buffer *rbuf;
+ bool is_lbuf_full = false;
+ bool is_sbuf_full = false;
+ u16 hdr = msg_hdr;
+ void *ptr_buf;
+ u32 len;
+
+ /* Account for HCI packet type as it's not included in the skb payload */
+ len = (skb) ? skb->len + 1 : 0;
+ memset(&aux_ptr, 0, sizeof(struct ipc_aux_ptr));
+
+ if (len > IPC_MSG_PLD_SZ) {
+ hdr |= IPC_HDR_LONG_MSG;
+
+ ptr_buf = btss_alloc_lmsg(desc, len,
+ &aux_ptr, &is_lbuf_full);
+ if (IS_ERR(ptr_buf)) {
+ bt_dev_err(hdev, "TX long buffers full");
+ hdev->stat.err_tx++;
+ return PTR_ERR(ptr_buf);
+ }
+ }
+
+ rinfo = btss_get_tx_rbuf(desc, &is_sbuf_full);
+ if (IS_ERR(rinfo)) {
+ bt_dev_err(hdev, "TX short buffers full");
+ hdev->stat.err_tx++;
+ return PTR_ERR(rinfo);
+ }
+
+ rbuf = &((struct ring_buffer *)(TO_APPS_ADDR(rinfo->rbuf)))[rinfo->widx];
+
+ if (!skb)
+ goto complete_tx;
+
+ if (len > IPC_MSG_PLD_SZ)
+ rbuf->payload.lmsg_data = cpu_to_le32(TO_BT_ADDR(ptr_buf));
+ else
+ ptr_buf = rbuf->payload.smsg_data;
+
+ /* if it's a short message, the aux len and buf are NULL */
+ memcpy_toio(ptr_buf, &hci_skb_pkt_type(skb), 1);
+ memcpy_toio((u8 *)ptr_buf + 1, skb->data, skb->len - aux_ptr.len);
+ if (aux_ptr.buf) {
+ memcpy_toio(TO_APPS_ADDR(aux_ptr.buf),
+ (skb->data + (skb->len - aux_ptr.len)),
+ aux_ptr.len);
+ }
+
+ /*
+ * if free buffer count is low, send ACK request to signal to the
+ * firmware to process and free up queued buffers in the TX ring.
+ */
+ if (is_sbuf_full || is_lbuf_full)
+ hdr |= IPC_HDR_REQ_ACK;
+
+complete_tx:
+ rbuf->msg_hdr = cpu_to_le16(hdr);
+ rbuf->len = cpu_to_le16(len);
+
+ rinfo->widx = (rinfo->widx + 1) % desc->tx_ctxt->smsg_buf_cnt;
+
+ regmap_set_bits(desc->regmap, desc->offset, BIT(desc->bit));
+
+ return 0;
+}
+
+static void btss_process_tx_queue(struct qcom_btss *desc)
+{
+ struct sk_buff *skb;
+ u16 hdr;
+ int ret;
+
+ while ((skb = skb_dequeue(&desc->tx_q))) {
+ hdr = FIELD_PREP(IPC_HDR_PKT_TYPE_MASK, IPC_HDR_PKT_TYPE_HCI);
+
+ ret = btss_send(desc, hdr, skb);
+ if (ret) {
+ bt_dev_err(desc->hdev, "Failed to send message");
+ skb_queue_head(&desc->tx_q, skb);
+ break;
+ }
+
+ btqcomipc_update_stats(desc->hdev, skb);
+ kfree_skb(skb);
+ }
+}
+
+static void btss_free_lmsg(struct qcom_btss *desc, u32 lmsg, u16 len)
+{
+ u8 idx;
+ u8 blks;
+ u32 lsz = IPC_LBUF_SZ(desc->tx_ctxt, total_size, lring_buf,
+ lmsg_buf_cnt);
+
+ idx = GET_TX_INDEX_FROM_BUF(lmsg, lsz);
+
+ if (idx != desc->lmsg_ctxt.ridx)
+ return;
+
+ blks = GET_NO_OF_BLOCKS(len, lsz);
+
+ desc->lmsg_ctxt.ridx = (desc->lmsg_ctxt.ridx + blks) %
+ desc->tx_ctxt->lmsg_buf_cnt;
+
+ desc->lmsg_ctxt.lmsg_free_cnt += blks;
+}
+
+static int btss_recv_cust_frame(struct qcom_btss *desc, u8 cmd)
+{
+ u16 msg_hdr = 0;
+ int ret;
+
+ switch (cmd) {
+ case IPC_CMD_STOP:
+ spin_unlock(&desc->lock);
+ ret = qcom_scm_pas_set_bluetooth_power_mode(BTSS_PAS_ID,
+ BTSS_PWR_STATE_ECO);
+ spin_lock(&desc->lock);
+ if (ret && ret != -EOPNOTSUPP) {
+ bt_dev_err(desc->hdev,
+ "Failed to apply BTSS power-save mode: %d",
+ ret);
+ return ret;
+ }
+
+ WRITE_ONCE(desc->running, false);
+
+ msg_hdr |= cmd;
+ ret = btss_send(desc, msg_hdr, NULL);
+ if (ret)
+ bt_dev_err(desc->hdev,
+ "Failed to send control message");
+ break;
+ case IPC_CMD_START:
+ spin_unlock(&desc->lock);
+ ret = qcom_scm_pas_set_bluetooth_power_mode(BTSS_PAS_ID,
+ BTSS_PWR_STATE_ACTIVE);
+ spin_lock(&desc->lock);
+ if (ret && ret != -EOPNOTSUPP) {
+ bt_dev_err(desc->hdev,
+ "Failed to apply BTSS active power mode: %d",
+ ret);
+ return ret;
+ }
+
+ desc->tx_ctxt = (struct context_info *)((void *)desc->rx_ctxt +
+ le16_to_cpu(desc->rx_ctxt->total_size));
+ desc->lmsg_ctxt.widx = 0;
+ desc->lmsg_ctxt.ridx = 0;
+ desc->lmsg_ctxt.smsg_free_cnt = desc->tx_ctxt->smsg_buf_cnt;
+ desc->lmsg_ctxt.lmsg_free_cnt = desc->tx_ctxt->lmsg_buf_cnt;
+ WRITE_ONCE(desc->running, true);
+ wake_up(&desc->wait_q);
+ break;
+ default:
+ bt_dev_err(desc->hdev, "Unsupported CMD ID: %u", cmd);
+ return -EOPNOTSUPP;
+ }
+
+ return 0;
+}
+
+static inline int btss_recv_hci_frame(struct qcom_btss *desc, const u8 *data,
+ size_t len)
+{
+ unsigned char pkt_type;
+ struct sk_buff *skb;
+ size_t pkt_len;
+
+ if (len < 1)
+ return -EPROTO;
+
+ pkt_type = data[0];
+
+ switch (pkt_type) {
+ case HCI_EVENT_PKT:
+ {
+ if (len < 1 + HCI_EVENT_HDR_SIZE)
+ return -EILSEQ;
+ struct hci_event_hdr *hdr = (struct hci_event_hdr *)(data + 1);
+
+ pkt_len = HCI_EVENT_HDR_SIZE + hdr->plen;
+ break;
+ }
+ case HCI_COMMAND_PKT: {
+ if (len < 1 + HCI_COMMAND_HDR_SIZE)
+ return -EILSEQ;
+ struct hci_command_hdr *hdr = (struct hci_command_hdr *)(data + 1);
+
+ pkt_len = HCI_COMMAND_HDR_SIZE + le16_to_cpu(hdr->plen);
+ break;
+ }
+ case HCI_ACLDATA_PKT:
+ {
+ if (len < 1 + HCI_ACL_HDR_SIZE)
+ return -EILSEQ;
+ struct hci_acl_hdr *hdr = (struct hci_acl_hdr *)(data + 1);
+
+ pkt_len = HCI_ACL_HDR_SIZE + le16_to_cpu(hdr->dlen);
+ break;
+ }
+ case HCI_SCODATA_PKT:
+ {
+ if (len < 1 + HCI_SCO_HDR_SIZE)
+ return -EILSEQ;
+ struct hci_sco_hdr *hdr = (struct hci_sco_hdr *)(data + 1);
+
+ pkt_len = HCI_SCO_HDR_SIZE + hdr->dlen;
+ break;
+ }
+ default:
+ return -EPROTO;
+ }
+
+ if (pkt_len + 1 > len)
+ return -EINVAL;
+
+ skb = bt_skb_alloc(pkt_len, GFP_ATOMIC);
+ if (!skb) {
+ desc->hdev->stat.err_rx++;
+ return -ENOMEM;
+ }
+
+ skb->dev = (void *)desc->hdev;
+ hci_skb_pkt_type(skb) = pkt_type;
+ skb_put_data(skb, data + 1, pkt_len);
+
+ hci_recv_frame(desc->hdev, skb);
+ desc->hdev->stat.byte_rx += pkt_len;
+
+ return 0;
+}
+
+static inline int btss_process_rx(struct qcom_btss *desc,
+ struct ring_buffer_info *rinfo,
+ bool *ack, u8 *rx_count)
+{
+ u8 ridx, lbuf_idx, blks_consumed, pkt_type, cmd;
+ struct ipc_aux_ptr aux_ptr;
+ struct ring_buffer *rbuf;
+ uint8_t *rxbuf = NULL;
+ unsigned char *buf;
+ u32 lsz;
+ int ret;
+
+ ridx = rinfo->ridx;
+
+ while (ridx != rinfo->widx) {
+ memset(&aux_ptr, 0, sizeof(struct ipc_aux_ptr));
+
+ rbuf = &((struct ring_buffer *)(TO_APPS_ADDR(rinfo->rbuf)))[ridx];
+
+ if (rbuf->msg_hdr & IPC_HDR_LONG_MSG) {
+ rxbuf = TO_APPS_ADDR(rbuf->payload.lmsg_data);
+ lsz = IPC_LBUF_SZ(desc->rx_ctxt, total_size, lring_buf,
+ lmsg_buf_cnt);
+
+ if (IS_RX_MEM_NON_CONTIGIOUS(rbuf->payload.lmsg_data,
+ rbuf->len, lsz)) {
+ lbuf_idx = GET_RX_INDEX_FROM_BUF(
+ rbuf->payload.lmsg_data, lsz);
+
+ blks_consumed = desc->rx_ctxt->lmsg_buf_cnt -
+ lbuf_idx;
+ aux_ptr.len = rbuf->len - (blks_consumed * lsz);
+ aux_ptr.buf = desc->rx_ctxt->lring_buf;
+ }
+ } else {
+ rxbuf = rbuf->payload.smsg_data;
+ }
+
+ *ack = (rbuf->msg_hdr & IPC_HDR_REQ_ACK);
+
+ pkt_type = FIELD_GET(IPC_HDR_PKT_TYPE_MASK, rbuf->msg_hdr);
+
+ switch (pkt_type) {
+ case IPC_HDR_PKT_TYPE_HCI:
+ buf = kmalloc(rbuf->len, GFP_ATOMIC);
+ if (!buf) {
+ rinfo->ridx = ridx;
+ return -ENOMEM;
+ }
+
+ memcpy_fromio(buf, rxbuf, rbuf->len - aux_ptr.len);
+
+ if (aux_ptr.buf)
+ memcpy_fromio(buf + (rbuf->len - aux_ptr.len),
+ TO_APPS_ADDR(aux_ptr.buf),
+ aux_ptr.len);
+
+ ret = btss_recv_hci_frame(desc, buf, rbuf->len);
+ if (ret)
+ bt_dev_err(desc->hdev,
+ "Failed to process HCI frame: %d",
+ ret);
+ kfree(buf);
+ break;
+ case IPC_HDR_PKT_TYPE_CUST:
+ cmd = FIELD_GET(IPC_HDR_CMD_MASK, rbuf->msg_hdr);
+ ret = btss_recv_cust_frame(desc, cmd);
+ if (ret)
+ bt_dev_warn(desc->hdev,
+ "Failed to process custom frame: %d",
+ ret);
+ break;
+ default:
+ break;
+ }
+
+ ridx = (ridx + 1) % rinfo->ring_buf_cnt;
+
+ if (rx_count)
+ (*rx_count)++;
+
+ rinfo->ridx = ridx;
+ }
+
+ return 0;
+}
+
+static void btss_process_ack(struct qcom_btss *desc)
+{
+ struct ring_buffer_info *rinfo;
+ struct ring_buffer *rbuf;
+ u8 tidx;
+
+ for (rinfo = &desc->tx_ctxt->sring_buf_info; rinfo != NULL;
+ rinfo = (struct ring_buffer_info *)(uintptr_t)(rinfo->next)) {
+ tidx = rinfo->tidx;
+ rbuf = (struct ring_buffer *)TO_APPS_ADDR(rinfo->rbuf);
+
+ while (tidx != rinfo->ridx) {
+ if (rbuf[tidx].msg_hdr & IPC_HDR_LONG_MSG) {
+ btss_free_lmsg(desc,
+ rbuf[tidx].payload.lmsg_data,
+ rbuf[tidx].len);
+ }
+
+ tidx = (tidx + 1) % desc->tx_ctxt->smsg_buf_cnt;
+ desc->lmsg_ctxt.smsg_free_cnt++;
+ }
+
+ rinfo->tidx = tidx;
+
+ btss_process_tx_queue(desc);
+ }
+}
+
+static void btss_worker(struct work_struct *work)
+{
+ struct qcom_btss *desc = container_of(work, struct qcom_btss, work);
+ struct ring_buffer_info *rinfo;
+ bool ack = false;
+ u32 offset;
+ int ret;
+
+ spin_lock(&desc->lock);
+
+ if (unlikely(!READ_ONCE(desc->running))) {
+ /*
+ * FW sets offset of RX context info at the start of the memory
+ * region upon boot
+ */
+ offset = readl(desc->mem_region);
+ dev_dbg(desc->dev, "offset after firmware boot: 0x%08x\n",
+ offset);
+ desc->rx_ctxt = (struct context_info *)(desc->mem_region + offset);
+ } else {
+ btss_process_ack(desc);
+ }
+
+ for (rinfo = &(desc->rx_ctxt->sring_buf_info);
+ rinfo != NULL;
+ rinfo = (struct ring_buffer_info *)(uintptr_t)(rinfo->next)) {
+ ret = btss_process_rx(desc, rinfo, &ack,
+ &desc->rx_ctxt->smsg_buf_cnt);
+ if (ret) {
+ bt_dev_err(desc->hdev,
+ "Failed to process peer msgs: %d", ret);
+ goto spin_unlock;
+ }
+ }
+
+ if (ack)
+ regmap_set_bits(desc->regmap, desc->offset, BIT(desc->bit));
+
+spin_unlock:
+ spin_unlock(&desc->lock);
+}
+
+static irqreturn_t btss_irq_handler(int irq, void *data)
+{
+ struct qcom_btss *desc = data;
+
+ queue_work(desc->wq, &desc->work);
+
+ return IRQ_HANDLED;
+}
+
+static void btqcomipc_update_stats(struct hci_dev *hdev, struct sk_buff *skb)
+{
+ u8 pkt_type = hci_skb_pkt_type(skb);
+
+ hdev->stat.byte_tx += skb->len;
+ switch (pkt_type) {
+ case HCI_COMMAND_PKT:
+ hdev->stat.cmd_tx++;
+ break;
+ case HCI_ACLDATA_PKT:
+ hdev->stat.acl_tx++;
+ break;
+ case HCI_SCODATA_PKT:
+ hdev->stat.sco_tx++;
+ break;
+ default:
+ break;
+ }
+}
+
+static int btcomqipc_firmware_load(struct qcom_btss *desc)
+{
+ const struct elf32_phdr *phdrs;
+ const struct firmware *seg_fw;
+ const struct elf32_phdr *phdr;
+ const struct elf32_hdr *ehdr;
+ const struct firmware *fw;
+ int i, ret;
+
+ ret = request_firmware(&fw, desc->firmware, desc->dev);
+ if (ret) {
+ dev_err(desc->dev, "Failed to request firmware: %d\n",
+ ret);
+ return ret;
+ }
+
+ ehdr = (const struct elf32_hdr *)fw->data;
+ phdrs = (const struct elf32_phdr *)(ehdr + 1);
+
+ ret = qcom_mdt_pas_init(desc->dev, fw, desc->firmware,
+ BTSS_PAS_ID, desc->mem_phys, NULL);
+ if (ret) {
+ dev_err(desc->dev, "PAS init failed: %d\n", ret);
+ goto release_fw;
+ }
+
+ for (i = 0; i < ehdr->e_phnum; i++) {
+ char *seg_name __free(kfree) = kstrdup(desc->firmware,
+ GFP_KERNEL);
+ if (!seg_name) {
+ ret = -ENOMEM;
+ goto release_fw;
+ }
+
+ phdr = &phdrs[i];
+
+ /* Only process valid loadable data segments */
+ if (phdr->p_type != PT_LOAD || !phdr->p_memsz)
+ continue;
+
+ if (phdr->p_vaddr + phdr->p_filesz > desc->mem_size) {
+ dev_err(desc->dev,
+ "Segment data exceeds the reserved memory area!\n");
+ goto release_fw;
+ }
+
+ /* Check if firmware is split across multiple segment files */
+ if (phdr->p_offset > fw->size ||
+ phdr->p_offset + phdr->p_filesz > fw->size) {
+ sprintf(seg_name + strlen(seg_name) - 3, "b%02d", i);
+ ret = request_firmware(&seg_fw, seg_name,
+ desc->dev);
+ if (ret) {
+ dev_err(desc->dev,
+ "Could not find split segment binary: %s\n",
+ seg_name);
+ goto release_fw;
+ }
+
+ /*
+ * Use the virtual instead of the physical address as
+ * the offset
+ */
+ memcpy_toio(desc->mem_region + phdr->p_vaddr,
+ seg_fw->data, phdr->p_filesz);
+
+ release_firmware(seg_fw);
+ } else {
+ memcpy_toio(desc->mem_region + phdr->p_vaddr,
+ fw->data + phdr->p_offset, phdr->p_filesz);
+ }
+ }
+
+release_fw:
+ release_firmware(fw);
+ return ret;
+}
+
+static int btqcomipc_open(struct hci_dev *hdev)
+{
+ struct qcom_btss *desc = hci_get_drvdata(hdev);
+ int ret;
+
+ if (!qcom_scm_pas_supported(BTSS_PAS_ID)) {
+ bt_dev_err(hdev,
+ "PAS is not available for peripheral: 0x%x",
+ BTSS_PAS_ID);
+ return -ENODEV;
+ }
+
+ ret = btcomqipc_firmware_load(desc);
+ if (ret) {
+ bt_dev_err(hdev, "Failed to load firmware: %d", ret);
+ return ret;
+ }
+
+ /* Boot firmware */
+ ret = qcom_scm_pas_auth_and_reset(BTSS_PAS_ID);
+ if (ret) {
+ bt_dev_err(hdev, "Failed to boot firmware: %d", ret);
+ return ret;
+ }
+
+ msleep(BTSS_PWR_CTRL_DELAY_MS);
+ ret = wait_event_timeout(desc->wait_q, READ_ONCE(desc->running),
+ msecs_to_jiffies(1000));
+
+ if (!ret) {
+ bt_dev_err(hdev, "Timeout waiting for BTSS start");
+ return -ETIMEDOUT;
+ }
+
+ return 0;
+}
+
+static int btqcomipc_close(struct hci_dev *hdev)
+{
+ int ret;
+
+ ret = qcom_scm_pas_shutdown(BTSS_PAS_ID);
+ if (ret) {
+ bt_dev_err(hdev, "Failed to stop firmware: %d", ret);
+ return ret;
+ }
+
+ msleep(BTSS_PWR_CTRL_DELAY_MS);
+
+ return 0;
+}
+
+static int btqcomipc_setup(struct hci_dev *hdev)
+{
+ struct qca_btsoc_version ver;
+ int ret;
+
+ /*
+ * Enable controller to do both LE scan and BR/EDR inquiry
+ * simultaneously.
+ */
+ hci_set_quirk(hdev, HCI_QUIRK_SIMULTANEOUS_DISCOVERY);
+
+ /*
+ * Enable NON_PERSISTENT_SETUP QUIRK to ensure to execute
+ * setup for every hci up.
+ */
+ hci_set_quirk(hdev, HCI_QUIRK_NON_PERSISTENT_SETUP);
+ ret = qca_read_soc_version(hdev, &ver, QCA_IPQ5018);
+ if (ret)
+ return -EINVAL;
+
+ ret = qca_uart_setup(hdev, 0, QCA_IPQ5018, ver, NULL);
+ if (ret) {
+ bt_dev_err(hdev, "Failed to setup UART: %d\n", ret);
+ return ret;
+ }
+
+ bt_dev_info(hdev, "QCA Build Info: %s", hdev->fw_info);
+
+ /* Obtain and set BD address from NVMEM cell */
+ hci_set_quirk(hdev, HCI_QUIRK_USE_BDADDR_NVMEM);
+ hci_set_quirk(hdev, HCI_QUIRK_BDADDR_NVMEM_BE);
+
+ return 0;
+}
+
+static int btqcomipc_send(struct hci_dev *hdev, struct sk_buff *skb)
+{
+ u16 hdr = FIELD_PREP(IPC_HDR_PKT_TYPE_MASK, IPC_HDR_PKT_TYPE_HCI);
+ struct qcom_btss *desc = hci_get_drvdata(hdev);
+ int ret;
+
+ if (unlikely(!READ_ONCE(desc->running))) {
+ bt_dev_err(hdev,
+ "BTSS not initialized, failed to send message");
+ ret = -ENODEV;
+ goto free_skb;
+ }
+
+ ret = btss_send(desc, hdr, skb);
+ if (ret) {
+ if (ret == -EAGAIN) {
+ if (skb_queue_len(&desc->tx_q) >= IPC_TX_QSIZE) {
+ bt_dev_err(hdev,
+ "TX queue full, dropping message");
+ hdev->stat.err_tx++;
+ ret = -ENOBUFS;
+ } else {
+ skb_queue_tail(&desc->tx_q, skb);
+ return 0;
+ }
+ } else {
+ bt_dev_err(hdev, "Failed to send message: %d", ret);
+ hdev->stat.err_tx++;
+ }
+ }
+
+ btqcomipc_update_stats(desc->hdev, skb);
+
+free_skb:
+ kfree_skb(skb);
+
+ return ret;
+}
+
+static int btqcomipc_flush(struct hci_dev *hdev)
+{
+ struct qcom_btss *desc = hci_get_drvdata(hdev);
+
+ skb_queue_purge(&desc->tx_q);
+ return 0;
+}
+
+static int btqcomipc_init(struct qcom_btss *desc)
+{
+ struct device *dev = desc->dev;
+ int ret;
+
+ init_waitqueue_head(&desc->wait_q);
+ spin_lock_init(&desc->lock);
+ skb_queue_head_init(&desc->tx_q);
+
+ desc->wq = create_singlethread_workqueue("btss_wq");
+ if (!desc->wq) {
+ dev_err(dev, "Failed to initialize workqueue\n");
+ return -EAGAIN;
+ }
+
+ INIT_WORK(&desc->work, btss_worker);
+
+ ret = devm_request_threaded_irq(dev, desc->irq, NULL, btss_irq_handler,
+ IRQF_TRIGGER_RISING | IRQF_ONESHOT,
+ "btss_irq", desc);
+
+ if (ret)
+ dev_err(dev, "error registering irq[%d] ret = %d\n",
+ desc->irq, ret);
+
+ return ret;
+}
+
+static void btqcomipc_deinit(struct qcom_btss *desc)
+{
+ disable_irq(desc->irq);
+ if (desc->wq != NULL) {
+ flush_workqueue(desc->wq);
+ skb_queue_purge(&desc->tx_q);
+ destroy_workqueue(desc->wq);
+ desc->wq = NULL;
+ }
+}
+
+static int btqcomipc_alloc_memory_region(struct qcom_btss *desc)
+{
+ struct device *dev = desc->dev;
+ struct resource res;
+ int ret;
+
+ ret = of_reserved_mem_region_to_resource(dev->of_node, 0, &res);
+ if (ret) {
+ dev_err(dev, "unable to acquire memory-region resource\n");
+ return ret;
+ }
+
+ desc->mem_phys = res.start;
+ desc->mem_reloc = res.start;
+ desc->mem_size = resource_size(&res);
+ desc->mem_region = devm_ioremap(dev, desc->mem_phys, desc->mem_size);
+ if (!desc->mem_region) {
+ dev_err(dev, "unable to map memory region: %pR\n", &res);
+ return -ENOMEM;
+ }
+
+ return 0;
+}
+
+static int btqcomipc_probe(struct platform_device *pdev)
+{
+ struct reset_control *btss_reset;
+ struct device *dev = &pdev->dev;
+ struct qcom_btss *desc;
+ struct hci_dev *hdev;
+ unsigned int args[2];
+ struct clk *lpo_clk;
+ int ret;
+
+ desc = devm_kzalloc(dev, sizeof(*desc), GFP_KERNEL);
+ if (!desc)
+ return -ENOMEM;
+
+ desc->dev = dev;
+
+ ret = of_property_read_string(dev->of_node, "firmware-name",
+ &desc->firmware);
+ if (ret < 0)
+ return ret;
+
+ ret = btqcomipc_alloc_memory_region(desc);
+ if (ret)
+ return ret;
+
+ desc->regmap = syscon_regmap_lookup_by_phandle_args(dev->of_node,
+ "qcom,ipc",
+ 2, args);
+ if (IS_ERR(desc->regmap))
+ return PTR_ERR(desc->regmap);
+
+ desc->offset = args[0];
+ desc->bit = args[1];
+
+ lpo_clk = devm_clk_get_enabled(dev, "lpo");
+ if (IS_ERR(lpo_clk))
+ return dev_err_probe(dev, PTR_ERR(lpo_clk),
+ "Failed to get lpo clock\n");
+
+ btss_reset = devm_reset_control_get_exclusive_deasserted(dev, NULL);
+ if (IS_ERR_OR_NULL(btss_reset))
+ return dev_err_probe(dev, PTR_ERR(btss_reset),
+ "unable to deassert reset\n");
+
+ desc->irq = platform_get_irq(pdev, 0);
+ if (desc->irq < 0)
+ return dev_err_probe(dev, desc->irq, "Failed to acquire IRQ\n");
+
+ ret = btqcomipc_init(desc);
+ if (ret)
+ return dev_err_probe(dev, ret, "Failed to initialize\n");
+
+ hdev = hci_alloc_dev();
+ if (!hdev) {
+ btqcomipc_deinit(desc);
+ return -ENOMEM;
+ }
+
+ hci_set_drvdata(hdev, desc);
+ desc->hdev = hdev;
+ SET_HCIDEV_DEV(hdev, &pdev->dev);
+ hdev->bus = HCI_IPC;
+
+ hdev->open = btqcomipc_open;
+ hdev->close = btqcomipc_close;
+ hdev->setup = btqcomipc_setup;
+ hdev->send = btqcomipc_send;
+ hdev->flush = btqcomipc_flush;
+ hdev->set_bdaddr = qca_set_bdaddr;
+
+ ret = hci_register_dev(hdev);
+ if (ret < 0) {
+ btqcomipc_deinit(desc);
+ hci_free_dev(hdev);
+ return dev_err_probe(dev, -EBUSY, "Failed to register hdev\n");
+ }
+
+ platform_set_drvdata(pdev, desc);
+
+ return 0;
+}
+
+static void btqcomipc_remove(struct platform_device *pdev)
+{
+ struct qcom_btss *desc = platform_get_drvdata(pdev);
+
+ if (!desc)
+ return;
+
+ btqcomipc_deinit(desc);
+
+ if (desc->hdev) {
+ hci_unregister_dev(desc->hdev);
+ hci_free_dev(desc->hdev);
+ }
+}
+
+static const struct of_device_id btqcomipc_of_match[] = {
+ { .compatible = "qcom,ipq5018-bt" },
+ { /* sentinel */},
+};
+MODULE_DEVICE_TABLE(of, btqcomipc_of_match);
+
+static struct platform_driver btqcomipc_driver = {
+ .probe = btqcomipc_probe,
+ .remove = btqcomipc_remove,
+ .driver = {
+ .name = "btqcomipc",
+ .of_match_table = btqcomipc_of_match,
+ },
+};
+
+module_platform_driver(btqcomipc_driver);
+
+MODULE_DESCRIPTION("Qualcomm Bluetooth IPC Driver");
+MODULE_LICENSE("GPL");
--
2.53.0
^ permalink raw reply related [flat|nested] 27+ messages in thread
* [PATCH v2 5/6] arm64: dts: qcom: ipq5018: add nodes required for Bluetooth support
2026-06-29 13:01 [PATCH v2 0/6] Add support for IPQ5018 Bluetooth George Moussalem via B4 Relay
` (3 preceding siblings ...)
2026-06-29 13:01 ` [PATCH v2 4/6] Bluetooth: Introduce Qualcomm IPQ5018 IPC based HCI driver George Moussalem via B4 Relay
@ 2026-06-29 13:01 ` George Moussalem via B4 Relay
2026-06-30 11:40 ` Konrad Dybcio
2026-06-30 13:02 ` sashiko-bot
2026-06-29 13:01 ` [PATCH v2 6/6] MAINTAINERS: Add entry for Qualcomm IPQ5018 Bluetooth driver George Moussalem via B4 Relay
5 siblings, 2 replies; 27+ messages in thread
From: George Moussalem via B4 Relay @ 2026-06-29 13:01 UTC (permalink / raw)
To: Jens Axboe, Ulf Hansson, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Johannes Berg, Jeff Johnson, Bartosz Golaszewski,
Marcel Holtmann, Luiz Augusto von Dentz, Balakrishna Godavarthi,
Rocky Liao, Saravana Kannan, Andrew Lunn, Heiner Kallweit,
Russell King, David S. Miller, Eric Dumazet, Jakub Kicinski,
Paolo Abeni, Simon Horman, Bjorn Andersson, Konrad Dybcio,
Mathieu Poirier, Philipp Zabel
Cc: linux-block, linux-kernel, linux-mmc, devicetree, linux-wireless,
ath10k, linux-arm-msm, linux-bluetooth, netdev, linux-remoteproc,
George Moussalem
From: George Moussalem <george.moussalem@outlook.com>
Add nodes for the reserved memory carveout and Bluetooth.
Signed-off-by: George Moussalem <george.moussalem@outlook.com>
---
arch/arm64/boot/dts/qcom/ipq5018.dtsi | 25 ++++++++++++++++++++++++-
1 file changed, 24 insertions(+), 1 deletion(-)
diff --git a/arch/arm64/boot/dts/qcom/ipq5018.dtsi b/arch/arm64/boot/dts/qcom/ipq5018.dtsi
index 6f8004a22a1f..65a47ba7d3a3 100644
--- a/arch/arm64/boot/dts/qcom/ipq5018.dtsi
+++ b/arch/arm64/boot/dts/qcom/ipq5018.dtsi
@@ -17,6 +17,23 @@ / {
#address-cells = <2>;
#size-cells = <2>;
+ bluetooth: bluetooth {
+ compatible = "qcom,ipq5018-bt";
+
+ firmware-name = "qca/bt_fw_patch.mbn";
+
+ clocks = <&gcc GCC_BTSS_LPO_CLK>;
+ clock-names = "lpo";
+ resets = <&gcc GCC_BTSS_BCR>;
+
+ qcom,ipc = <&apcs_glb 8 23>;
+ interrupts = <GIC_SPI 162 IRQ_TYPE_EDGE_RISING>;
+
+ memory-region = <&btss_region>;
+
+ status = "disabled";
+ };
+
clocks {
gephy_rx_clk: gephy-rx-clk {
compatible = "fixed-clock";
@@ -136,6 +153,11 @@ reserved-memory {
#size-cells = <2>;
ranges;
+ btss_region: bluetooth@7000000 {
+ reg = <0x0 0x07000000 0x0 0x58000>;
+ no-map;
+ };
+
bootloader@4a800000 {
reg = <0x0 0x4a800000 0x0 0x200000>;
no-map;
@@ -647,7 +669,8 @@ watchdog: watchdog@b017000 {
apcs_glb: mailbox@b111000 {
compatible = "qcom,ipq5018-apcs-apps-global",
- "qcom,ipq6018-apcs-apps-global";
+ "qcom,ipq6018-apcs-apps-global",
+ "syscon";
reg = <0x0b111000 0x1000>;
#clock-cells = <1>;
clocks = <&a53pll>, <&xo_board_clk>, <&gcc GPLL0>;
--
2.53.0
^ permalink raw reply related [flat|nested] 27+ messages in thread
* [PATCH v2 6/6] MAINTAINERS: Add entry for Qualcomm IPQ5018 Bluetooth driver
2026-06-29 13:01 [PATCH v2 0/6] Add support for IPQ5018 Bluetooth George Moussalem via B4 Relay
` (4 preceding siblings ...)
2026-06-29 13:01 ` [PATCH v2 5/6] arm64: dts: qcom: ipq5018: add nodes required for Bluetooth support George Moussalem via B4 Relay
@ 2026-06-29 13:01 ` George Moussalem via B4 Relay
5 siblings, 0 replies; 27+ messages in thread
From: George Moussalem via B4 Relay @ 2026-06-29 13:01 UTC (permalink / raw)
To: Jens Axboe, Ulf Hansson, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Johannes Berg, Jeff Johnson, Bartosz Golaszewski,
Marcel Holtmann, Luiz Augusto von Dentz, Balakrishna Godavarthi,
Rocky Liao, Saravana Kannan, Andrew Lunn, Heiner Kallweit,
Russell King, David S. Miller, Eric Dumazet, Jakub Kicinski,
Paolo Abeni, Simon Horman, Bjorn Andersson, Konrad Dybcio,
Mathieu Poirier, Philipp Zabel
Cc: linux-block, linux-kernel, linux-mmc, devicetree, linux-wireless,
ath10k, linux-arm-msm, linux-bluetooth, netdev, linux-remoteproc,
George Moussalem
From: George Moussalem <george.moussalem@outlook.com>
Add maintainers entry for Qualcomm IPQ5018 Bluetooth driver.
Signed-off-by: George Moussalem <george.moussalem@outlook.com>
---
MAINTAINERS | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/MAINTAINERS b/MAINTAINERS
index 0b9d7c8276ac..60f7251d1a16 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -22289,6 +22289,13 @@ S: Maintained
F: Documentation/devicetree/bindings/regulator/vqmmc-ipq4019-regulator.yaml
F: drivers/regulator/vqmmc-ipq4019-regulator.c
+QUALCOMM IPQ5018 BLUETOOTH DRIVER
+M: George Moussalem <george.moussalem@outlook.com>
+L: linux-bluetooth@vger.kernel.org
+S: Maintained
+F: Documentation/devicetree/bindings/net/bluetooth/qcom,ipq5018-bt.yaml
+F: drivers/bluetooth/btqcomipc.c
+
QUALCOMM IRIS VIDEO ACCELERATOR DRIVER
M: Vikash Garodia <vikash.garodia@oss.qualcomm.com>
M: Dikshita Agarwal <dikshita.agarwal@oss.qualcomm.com>
--
2.53.0
^ permalink raw reply related [flat|nested] 27+ messages in thread
* Re: [PATCH v2 1/6] dt-bindings: net: bluetooth: Document Qualcomm IPQ5018 Bluetooth controller
2026-06-29 13:01 ` [PATCH v2 1/6] dt-bindings: net: bluetooth: Document Qualcomm IPQ5018 Bluetooth controller George Moussalem via B4 Relay
@ 2026-06-30 7:15 ` Krzysztof Kozlowski
2026-06-30 7:31 ` George Moussalem
2026-06-30 9:06 ` Konrad Dybcio
2026-06-30 8:20 ` Krzysztof Kozlowski
1 sibling, 2 replies; 27+ messages in thread
From: Krzysztof Kozlowski @ 2026-06-30 7:15 UTC (permalink / raw)
To: George Moussalem
Cc: Jens Axboe, Ulf Hansson, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Johannes Berg, Jeff Johnson, Bartosz Golaszewski,
Marcel Holtmann, Luiz Augusto von Dentz, Balakrishna Godavarthi,
Rocky Liao, Saravana Kannan, Andrew Lunn, Heiner Kallweit,
Russell King, David S. Miller, Eric Dumazet, Jakub Kicinski,
Paolo Abeni, Simon Horman, Bjorn Andersson, Konrad Dybcio,
Mathieu Poirier, Philipp Zabel, linux-block, linux-kernel,
linux-mmc, devicetree, linux-wireless, ath10k, linux-arm-msm,
linux-bluetooth, netdev, linux-remoteproc
On Mon, Jun 29, 2026 at 05:01:44PM +0400, George Moussalem wrote:
> +unevaluatedProperties: false
> +
> +examples:
> + - |
> + #include <dt-bindings/clock/qcom,gcc-ipq5018.h>
> + #include <dt-bindings/interrupt-controller/arm-gic.h>
> + #include <dt-bindings/reset/qcom,gcc-ipq5018.h>
> +
> + bluetooth {
Don't send new versions while discussion is still going. I need to
repeat my question - what bus does that sit on?
Device nodes represent real devices. Real devices sit on a bus, usually.
Do you have here a bus?
> + compatible = "qcom,ipq5018-bt";
Best regards,
Krzysztof
^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: [PATCH v2 1/6] dt-bindings: net: bluetooth: Document Qualcomm IPQ5018 Bluetooth controller
2026-06-30 7:15 ` Krzysztof Kozlowski
@ 2026-06-30 7:31 ` George Moussalem
2026-06-30 7:40 ` Krzysztof Kozlowski
2026-06-30 9:06 ` Konrad Dybcio
1 sibling, 1 reply; 27+ messages in thread
From: George Moussalem @ 2026-06-30 7:31 UTC (permalink / raw)
To: Krzysztof Kozlowski
Cc: Jens Axboe, Ulf Hansson, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Johannes Berg, Jeff Johnson, Bartosz Golaszewski,
Marcel Holtmann, Luiz Augusto von Dentz, Balakrishna Godavarthi,
Rocky Liao, Saravana Kannan, Andrew Lunn, Heiner Kallweit,
Russell King, David S. Miller, Eric Dumazet, Jakub Kicinski,
Paolo Abeni, Simon Horman, Bjorn Andersson, Konrad Dybcio,
Mathieu Poirier, Philipp Zabel, linux-block, linux-kernel,
linux-mmc, devicetree, linux-wireless, ath10k, linux-arm-msm,
linux-bluetooth, netdev, linux-remoteproc
On 6/30/26 11:15, Krzysztof Kozlowski wrote:
> On Mon, Jun 29, 2026 at 05:01:44PM +0400, George Moussalem wrote:
>> +unevaluatedProperties: false
>> +
>> +examples:
>> + - |
>> + #include <dt-bindings/clock/qcom,gcc-ipq5018.h>
>> + #include <dt-bindings/interrupt-controller/arm-gic.h>
>> + #include <dt-bindings/reset/qcom,gcc-ipq5018.h>
>> +
>> + bluetooth {
>
> Don't send new versions while discussion is still going. I need to
> repeat my question - what bus does that sit on?
>
> Device nodes represent real devices. Real devices sit on a bus, usually.
> Do you have here a bus?
I'm afraid I don't have a definitive answer. Again, my understanding
based on downstream code is that the 'controller' is basically a Cortex
M0 processor running Bluetooth firmware connected to an RF. Data
transport is over a shared memory carveout with APPS signaling the
controller through writes to an IPC mailbox register, while the
controller has an interrupt line back to signal APPS.
>
>> + compatible = "qcom,ipq5018-bt";
>
> Best regards,
> Krzysztof
>
Best regards,
George
^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: [PATCH v2 1/6] dt-bindings: net: bluetooth: Document Qualcomm IPQ5018 Bluetooth controller
2026-06-30 7:31 ` George Moussalem
@ 2026-06-30 7:40 ` Krzysztof Kozlowski
2026-06-30 7:55 ` George Moussalem
0 siblings, 1 reply; 27+ messages in thread
From: Krzysztof Kozlowski @ 2026-06-30 7:40 UTC (permalink / raw)
To: George Moussalem
Cc: Jens Axboe, Ulf Hansson, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Johannes Berg, Jeff Johnson, Bartosz Golaszewski,
Marcel Holtmann, Luiz Augusto von Dentz, Balakrishna Godavarthi,
Rocky Liao, Saravana Kannan, Andrew Lunn, Heiner Kallweit,
Russell King, David S. Miller, Eric Dumazet, Jakub Kicinski,
Paolo Abeni, Simon Horman, Bjorn Andersson, Konrad Dybcio,
Mathieu Poirier, Philipp Zabel, linux-block, linux-kernel,
linux-mmc, devicetree, linux-wireless, ath10k, linux-arm-msm,
linux-bluetooth, netdev, linux-remoteproc
On 30/06/2026 09:31, George Moussalem wrote:
> On 6/30/26 11:15, Krzysztof Kozlowski wrote:
>> On Mon, Jun 29, 2026 at 05:01:44PM +0400, George Moussalem wrote:
>>> +unevaluatedProperties: false
>>> +
>>> +examples:
>>> + - |
>>> + #include <dt-bindings/clock/qcom,gcc-ipq5018.h>
>>> + #include <dt-bindings/interrupt-controller/arm-gic.h>
>>> + #include <dt-bindings/reset/qcom,gcc-ipq5018.h>
>>> +
>>> + bluetooth {
>>
>> Don't send new versions while discussion is still going. I need to
>> repeat my question - what bus does that sit on?
>>
>> Device nodes represent real devices. Real devices sit on a bus, usually.
>> Do you have here a bus?
>
> I'm afraid I don't have a definitive answer. Again, my understanding
> based on downstream code is that the 'controller' is basically a Cortex
> M0 processor running Bluetooth firmware connected to an RF. Data
> transport is over a shared memory carveout with APPS signaling the
> controller through writes to an IPC mailbox register, while the
> controller has an interrupt line back to signal APPS.
So this looks like should be squashed into remoteproc node. There is no
reason or no data to express it as two separate device nodes.
Best regards,
Krzysztof
^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: [PATCH v2 1/6] dt-bindings: net: bluetooth: Document Qualcomm IPQ5018 Bluetooth controller
2026-06-30 7:40 ` Krzysztof Kozlowski
@ 2026-06-30 7:55 ` George Moussalem
2026-06-30 8:20 ` Krzysztof Kozlowski
0 siblings, 1 reply; 27+ messages in thread
From: George Moussalem @ 2026-06-30 7:55 UTC (permalink / raw)
To: Krzysztof Kozlowski
Cc: Jens Axboe, Ulf Hansson, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Johannes Berg, Jeff Johnson, Bartosz Golaszewski,
Marcel Holtmann, Luiz Augusto von Dentz, Balakrishna Godavarthi,
Rocky Liao, Saravana Kannan, Andrew Lunn, Heiner Kallweit,
Russell King, David S. Miller, Eric Dumazet, Jakub Kicinski,
Paolo Abeni, Simon Horman, Bjorn Andersson, Konrad Dybcio,
Mathieu Poirier, Philipp Zabel, linux-block, linux-kernel,
linux-mmc, devicetree, linux-wireless, ath10k, linux-arm-msm,
linux-bluetooth, netdev, linux-remoteproc
On 6/30/26 11:40, Krzysztof Kozlowski wrote:
> On 30/06/2026 09:31, George Moussalem wrote:
>> On 6/30/26 11:15, Krzysztof Kozlowski wrote:
>>> On Mon, Jun 29, 2026 at 05:01:44PM +0400, George Moussalem wrote:
>>>> +unevaluatedProperties: false
>>>> +
>>>> +examples:
>>>> + - |
>>>> + #include <dt-bindings/clock/qcom,gcc-ipq5018.h>
>>>> + #include <dt-bindings/interrupt-controller/arm-gic.h>
>>>> + #include <dt-bindings/reset/qcom,gcc-ipq5018.h>
>>>> +
>>>> + bluetooth {
>>>
>>> Don't send new versions while discussion is still going. I need to
>>> repeat my question - what bus does that sit on?
>>>
>>> Device nodes represent real devices. Real devices sit on a bus, usually.
>>> Do you have here a bus?
>>
>> I'm afraid I don't have a definitive answer. Again, my understanding
>> based on downstream code is that the 'controller' is basically a Cortex
>> M0 processor running Bluetooth firmware connected to an RF. Data
>> transport is over a shared memory carveout with APPS signaling the
>> controller through writes to an IPC mailbox register, while the
>> controller has an interrupt line back to signal APPS.
>
> So this looks like should be squashed into remoteproc node. There is no
> reason or no data to express it as two separate device nodes.
In this version, I've squashed them into one already but as a Bluetooth
controller as that's what the 'processor' is dedicated to, also in line
with Bjorn's guidance to manage the lifecycle of this processor and all
other resources in one. Kindly let me know if this approach is satisfactory.
>
> Best regards,
> Krzysztof
Best regards,
George
^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: [PATCH v2 1/6] dt-bindings: net: bluetooth: Document Qualcomm IPQ5018 Bluetooth controller
2026-06-30 7:55 ` George Moussalem
@ 2026-06-30 8:20 ` Krzysztof Kozlowski
0 siblings, 0 replies; 27+ messages in thread
From: Krzysztof Kozlowski @ 2026-06-30 8:20 UTC (permalink / raw)
To: George Moussalem
Cc: Jens Axboe, Ulf Hansson, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Johannes Berg, Jeff Johnson, Bartosz Golaszewski,
Marcel Holtmann, Luiz Augusto von Dentz, Balakrishna Godavarthi,
Rocky Liao, Saravana Kannan, Andrew Lunn, Heiner Kallweit,
Russell King, David S. Miller, Eric Dumazet, Jakub Kicinski,
Paolo Abeni, Simon Horman, Bjorn Andersson, Konrad Dybcio,
Mathieu Poirier, Philipp Zabel, linux-block, linux-kernel,
linux-mmc, devicetree, linux-wireless, ath10k, linux-arm-msm,
linux-bluetooth, netdev, linux-remoteproc
On 30/06/2026 09:55, George Moussalem wrote:
> On 6/30/26 11:40, Krzysztof Kozlowski wrote:
>> On 30/06/2026 09:31, George Moussalem wrote:
>>> On 6/30/26 11:15, Krzysztof Kozlowski wrote:
>>>> On Mon, Jun 29, 2026 at 05:01:44PM +0400, George Moussalem wrote:
>>>>> +unevaluatedProperties: false
>>>>> +
>>>>> +examples:
>>>>> + - |
>>>>> + #include <dt-bindings/clock/qcom,gcc-ipq5018.h>
>>>>> + #include <dt-bindings/interrupt-controller/arm-gic.h>
>>>>> + #include <dt-bindings/reset/qcom,gcc-ipq5018.h>
>>>>> +
>>>>> + bluetooth {
>>>>
>>>> Don't send new versions while discussion is still going. I need to
>>>> repeat my question - what bus does that sit on?
>>>>
>>>> Device nodes represent real devices. Real devices sit on a bus, usually.
>>>> Do you have here a bus?
>>>
>>> I'm afraid I don't have a definitive answer. Again, my understanding
>>> based on downstream code is that the 'controller' is basically a Cortex
>>> M0 processor running Bluetooth firmware connected to an RF. Data
>>> transport is over a shared memory carveout with APPS signaling the
>>> controller through writes to an IPC mailbox register, while the
>>> controller has an interrupt line back to signal APPS.
>>
>> So this looks like should be squashed into remoteproc node. There is no
>> reason or no data to express it as two separate device nodes.
>
> In this version, I've squashed them into one already but as a Bluetooth
> controller as that's what the 'processor' is dedicated to, also in line
> with Bjorn's guidance to manage the lifecycle of this processor and all
> other resources in one. Kindly let me know if this approach is satisfactory.
>
I read changelog twice and only then found it mentions squashing it. I
suggest writing concise entries and drop all boiler plate like "As per
further review comments". I just ignore such paragraphs.
Best regards,
Krzysztof
^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: [PATCH v2 1/6] dt-bindings: net: bluetooth: Document Qualcomm IPQ5018 Bluetooth controller
2026-06-29 13:01 ` [PATCH v2 1/6] dt-bindings: net: bluetooth: Document Qualcomm IPQ5018 Bluetooth controller George Moussalem via B4 Relay
2026-06-30 7:15 ` Krzysztof Kozlowski
@ 2026-06-30 8:20 ` Krzysztof Kozlowski
1 sibling, 0 replies; 27+ messages in thread
From: Krzysztof Kozlowski @ 2026-06-30 8:20 UTC (permalink / raw)
To: george.moussalem, Jens Axboe, Ulf Hansson, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Johannes Berg, Jeff Johnson,
Bartosz Golaszewski, Marcel Holtmann, Luiz Augusto von Dentz,
Balakrishna Godavarthi, Rocky Liao, Saravana Kannan, Andrew Lunn,
Heiner Kallweit, Russell King, David S. Miller, Eric Dumazet,
Jakub Kicinski, Paolo Abeni, Simon Horman, Bjorn Andersson,
Konrad Dybcio, Mathieu Poirier, Philipp Zabel
Cc: linux-block, linux-kernel, linux-mmc, devicetree, linux-wireless,
ath10k, linux-arm-msm, linux-bluetooth, netdev, linux-remoteproc
On 29/06/2026 15:01, George Moussalem via B4 Relay wrote:
> From: George Moussalem <george.moussalem@outlook.com>
>
> Document the Qualcomm IPQ5018 Bluetooth controller.
>
> Signed-off-by: George Moussalem <george.moussalem@outlook.com>
> ---
> .../bindings/net/bluetooth/qcom,ipq5018-bt.yaml | 86 ++++++++++++++++++++++
> 1 file changed, 86 insertions(+)
Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski@oss.qualcomm.com>
Best regards,
Krzysztof
^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: [PATCH v2 1/6] dt-bindings: net: bluetooth: Document Qualcomm IPQ5018 Bluetooth controller
2026-06-30 7:15 ` Krzysztof Kozlowski
2026-06-30 7:31 ` George Moussalem
@ 2026-06-30 9:06 ` Konrad Dybcio
2026-06-30 9:09 ` Krzysztof Kozlowski
1 sibling, 1 reply; 27+ messages in thread
From: Konrad Dybcio @ 2026-06-30 9:06 UTC (permalink / raw)
To: Krzysztof Kozlowski, George Moussalem, Kathiravan Thirumoorthy
Cc: Jens Axboe, Ulf Hansson, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Johannes Berg, Jeff Johnson, Bartosz Golaszewski,
Marcel Holtmann, Luiz Augusto von Dentz, Balakrishna Godavarthi,
Rocky Liao, Saravana Kannan, Andrew Lunn, Heiner Kallweit,
Russell King, David S. Miller, Eric Dumazet, Jakub Kicinski,
Paolo Abeni, Simon Horman, Bjorn Andersson, Konrad Dybcio,
Mathieu Poirier, Philipp Zabel, linux-block, linux-kernel,
linux-mmc, devicetree, linux-wireless, ath10k, linux-arm-msm,
linux-bluetooth, netdev, linux-remoteproc
On 6/30/26 9:15 AM, Krzysztof Kozlowski wrote:
> On Mon, Jun 29, 2026 at 05:01:44PM +0400, George Moussalem wrote:
>> +unevaluatedProperties: false
>> +
>> +examples:
>> + - |
>> + #include <dt-bindings/clock/qcom,gcc-ipq5018.h>
>> + #include <dt-bindings/interrupt-controller/arm-gic.h>
>> + #include <dt-bindings/reset/qcom,gcc-ipq5018.h>
>> +
>> + bluetooth {
>
> Don't send new versions while discussion is still going. I need to
> repeat my question - what bus does that sit on?
>
> Device nodes represent real devices. Real devices sit on a bus, usually.
> Do you have here a bus?
+Kathiravan would you know what the remoteproc-driven bluetooth is
connected over on IPQ5018?
Konrad
^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: [PATCH v2 1/6] dt-bindings: net: bluetooth: Document Qualcomm IPQ5018 Bluetooth controller
2026-06-30 9:06 ` Konrad Dybcio
@ 2026-06-30 9:09 ` Krzysztof Kozlowski
0 siblings, 0 replies; 27+ messages in thread
From: Krzysztof Kozlowski @ 2026-06-30 9:09 UTC (permalink / raw)
To: Konrad Dybcio, George Moussalem, Kathiravan Thirumoorthy
Cc: Jens Axboe, Ulf Hansson, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Johannes Berg, Jeff Johnson, Bartosz Golaszewski,
Marcel Holtmann, Luiz Augusto von Dentz, Balakrishna Godavarthi,
Rocky Liao, Saravana Kannan, Andrew Lunn, Heiner Kallweit,
Russell King, David S. Miller, Eric Dumazet, Jakub Kicinski,
Paolo Abeni, Simon Horman, Bjorn Andersson, Konrad Dybcio,
Mathieu Poirier, Philipp Zabel, linux-block, linux-kernel,
linux-mmc, devicetree, linux-wireless, ath10k, linux-arm-msm,
linux-bluetooth, netdev, linux-remoteproc
On 30/06/2026 11:06, Konrad Dybcio wrote:
> On 6/30/26 9:15 AM, Krzysztof Kozlowski wrote:
>> On Mon, Jun 29, 2026 at 05:01:44PM +0400, George Moussalem wrote:
>>> +unevaluatedProperties: false
>>> +
>>> +examples:
>>> + - |
>>> + #include <dt-bindings/clock/qcom,gcc-ipq5018.h>
>>> + #include <dt-bindings/interrupt-controller/arm-gic.h>
>>> + #include <dt-bindings/reset/qcom,gcc-ipq5018.h>
>>> +
>>> + bluetooth {
>>
>> Don't send new versions while discussion is still going. I need to
>> repeat my question - what bus does that sit on?
>>
>> Device nodes represent real devices. Real devices sit on a bus, usually.
>> Do you have here a bus?
>
> +Kathiravan would you know what the remoteproc-driven bluetooth is
> connected over on IPQ5018?
No need, this got resolved. I missed that this was merged with
remoteproc and remoteprocs we represent in top-level as it uses non-bus
way (APCS IPC or whatever its called). We could fix that and maybe this
should be a child of APCS... but maybe not and it feels like out of
scope of this patchset.
Best regards,
Krzysztof
^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: [PATCH v2 5/6] arm64: dts: qcom: ipq5018: add nodes required for Bluetooth support
2026-06-29 13:01 ` [PATCH v2 5/6] arm64: dts: qcom: ipq5018: add nodes required for Bluetooth support George Moussalem via B4 Relay
@ 2026-06-30 11:40 ` Konrad Dybcio
2026-06-30 12:09 ` George Moussalem
2026-06-30 13:02 ` sashiko-bot
1 sibling, 1 reply; 27+ messages in thread
From: Konrad Dybcio @ 2026-06-30 11:40 UTC (permalink / raw)
To: george.moussalem, Jens Axboe, Ulf Hansson, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Johannes Berg, Jeff Johnson,
Bartosz Golaszewski, Marcel Holtmann, Luiz Augusto von Dentz,
Balakrishna Godavarthi, Rocky Liao, Saravana Kannan, Andrew Lunn,
Heiner Kallweit, Russell King, David S. Miller, Eric Dumazet,
Jakub Kicinski, Paolo Abeni, Simon Horman, Bjorn Andersson,
Konrad Dybcio, Mathieu Poirier, Philipp Zabel
Cc: linux-block, linux-kernel, linux-mmc, devicetree, linux-wireless,
ath10k, linux-arm-msm, linux-bluetooth, netdev, linux-remoteproc
On 6/29/26 3:01 PM, George Moussalem via B4 Relay wrote:
> From: George Moussalem <george.moussalem@outlook.com>
>
> Add nodes for the reserved memory carveout and Bluetooth.
>
> Signed-off-by: George Moussalem <george.moussalem@outlook.com>
> ---
> arch/arm64/boot/dts/qcom/ipq5018.dtsi | 25 ++++++++++++++++++++++++-
> 1 file changed, 24 insertions(+), 1 deletion(-)
>
> diff --git a/arch/arm64/boot/dts/qcom/ipq5018.dtsi b/arch/arm64/boot/dts/qcom/ipq5018.dtsi
> index 6f8004a22a1f..65a47ba7d3a3 100644
> --- a/arch/arm64/boot/dts/qcom/ipq5018.dtsi
> +++ b/arch/arm64/boot/dts/qcom/ipq5018.dtsi
> @@ -17,6 +17,23 @@ / {
> #address-cells = <2>;
> #size-cells = <2>;
>
> + bluetooth: bluetooth {
> + compatible = "qcom,ipq5018-bt";
> +
> + firmware-name = "qca/bt_fw_patch.mbn";
Is this fw vendor-signed?
Konrad
^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: [PATCH v2 5/6] arm64: dts: qcom: ipq5018: add nodes required for Bluetooth support
2026-06-30 11:40 ` Konrad Dybcio
@ 2026-06-30 12:09 ` George Moussalem
2026-06-30 12:12 ` Konrad Dybcio
0 siblings, 1 reply; 27+ messages in thread
From: George Moussalem @ 2026-06-30 12:09 UTC (permalink / raw)
To: Konrad Dybcio, Jens Axboe, Ulf Hansson, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Johannes Berg, Jeff Johnson,
Bartosz Golaszewski, Marcel Holtmann, Luiz Augusto von Dentz,
Balakrishna Godavarthi, Rocky Liao, Saravana Kannan, Andrew Lunn,
Heiner Kallweit, Russell King, David S. Miller, Eric Dumazet,
Jakub Kicinski, Paolo Abeni, Simon Horman, Bjorn Andersson,
Konrad Dybcio, Mathieu Poirier, Philipp Zabel
Cc: linux-block, linux-kernel, linux-mmc, devicetree, linux-wireless,
ath10k, linux-arm-msm, linux-bluetooth, netdev, linux-remoteproc
On 6/30/26 15:40, Konrad Dybcio wrote:
> On 6/29/26 3:01 PM, George Moussalem via B4 Relay wrote:
>> From: George Moussalem <george.moussalem@outlook.com>
>>
>> Add nodes for the reserved memory carveout and Bluetooth.
>>
>> Signed-off-by: George Moussalem <george.moussalem@outlook.com>
>> ---
>> arch/arm64/boot/dts/qcom/ipq5018.dtsi | 25 ++++++++++++++++++++++++-
>> 1 file changed, 24 insertions(+), 1 deletion(-)
>>
>> diff --git a/arch/arm64/boot/dts/qcom/ipq5018.dtsi b/arch/arm64/boot/dts/qcom/ipq5018.dtsi
>> index 6f8004a22a1f..65a47ba7d3a3 100644
>> --- a/arch/arm64/boot/dts/qcom/ipq5018.dtsi
>> +++ b/arch/arm64/boot/dts/qcom/ipq5018.dtsi
>> @@ -17,6 +17,23 @@ / {
>> #address-cells = <2>;
>> #size-cells = <2>;
>>
>> + bluetooth: bluetooth {
>> + compatible = "qcom,ipq5018-bt";
>> +
>> + firmware-name = "qca/bt_fw_patch.mbn";
>
> Is this fw vendor-signed?
I've just analyzed the mbn file (and the mdt + b0x files): it only
contains hashes for the mdt and b02 segments, no signature/certs at all.
I've used your pil squasher to create the mbn file. Here are the FW files:
https://github.com/georgemoussalem/openwrt/tree/ipq50xx-bluetooth/package/firmware/qca-bt-firmware/files
Perhaps you can double check?
>
> Konrad
Best regards,
George
^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: [PATCH v2 5/6] arm64: dts: qcom: ipq5018: add nodes required for Bluetooth support
2026-06-30 12:09 ` George Moussalem
@ 2026-06-30 12:12 ` Konrad Dybcio
0 siblings, 0 replies; 27+ messages in thread
From: Konrad Dybcio @ 2026-06-30 12:12 UTC (permalink / raw)
To: George Moussalem, Jens Axboe, Ulf Hansson, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Johannes Berg, Jeff Johnson,
Bartosz Golaszewski, Marcel Holtmann, Luiz Augusto von Dentz,
Balakrishna Godavarthi, Rocky Liao, Saravana Kannan, Andrew Lunn,
Heiner Kallweit, Russell King, David S. Miller, Eric Dumazet,
Jakub Kicinski, Paolo Abeni, Simon Horman, Bjorn Andersson,
Konrad Dybcio, Mathieu Poirier, Philipp Zabel
Cc: linux-block, linux-kernel, linux-mmc, devicetree, linux-wireless,
ath10k, linux-arm-msm, linux-bluetooth, netdev, linux-remoteproc
On 6/30/26 2:09 PM, George Moussalem wrote:
> On 6/30/26 15:40, Konrad Dybcio wrote:
>> On 6/29/26 3:01 PM, George Moussalem via B4 Relay wrote:
>>> From: George Moussalem <george.moussalem@outlook.com>
>>>
>>> Add nodes for the reserved memory carveout and Bluetooth.
>>>
>>> Signed-off-by: George Moussalem <george.moussalem@outlook.com>
>>> ---
>>> arch/arm64/boot/dts/qcom/ipq5018.dtsi | 25 ++++++++++++++++++++++++-
>>> 1 file changed, 24 insertions(+), 1 deletion(-)
>>>
>>> diff --git a/arch/arm64/boot/dts/qcom/ipq5018.dtsi b/arch/arm64/boot/dts/qcom/ipq5018.dtsi
>>> index 6f8004a22a1f..65a47ba7d3a3 100644
>>> --- a/arch/arm64/boot/dts/qcom/ipq5018.dtsi
>>> +++ b/arch/arm64/boot/dts/qcom/ipq5018.dtsi
>>> @@ -17,6 +17,23 @@ / {
>>> #address-cells = <2>;
>>> #size-cells = <2>;
>>>
>>> + bluetooth: bluetooth {
>>> + compatible = "qcom,ipq5018-bt";
>>> +
>>> + firmware-name = "qca/bt_fw_patch.mbn";
>>
>> Is this fw vendor-signed?
>
> I've just analyzed the mbn file (and the mdt + b0x files): it only
> contains hashes for the mdt and b02 segments, no signature/certs at all.
> I've used your pil squasher to create the mbn file. Here are the FW files:
> https://github.com/georgemoussalem/openwrt/tree/ipq50xx-bluetooth/package/firmware/qca-bt-firmware/files
>
> Perhaps you can double check?
Using the not very sophisticated but very quick method of running
strings on it, there's no certificate identifiers indeed
Konrad
^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: [PATCH v2 4/6] Bluetooth: Introduce Qualcomm IPQ5018 IPC based HCI driver
2026-06-29 13:01 ` [PATCH v2 4/6] Bluetooth: Introduce Qualcomm IPQ5018 IPC based HCI driver George Moussalem via B4 Relay
@ 2026-06-30 13:02 ` sashiko-bot
2026-07-01 11:19 ` Konrad Dybcio
1 sibling, 0 replies; 27+ messages in thread
From: sashiko-bot @ 2026-06-30 13:02 UTC (permalink / raw)
To: George Moussalem via B4 Relay; +Cc: conor+dt, devicetree, robh
Thank you for your contribution! Sashiko AI review found 22 potential issue(s) to consider:
- [High] Vulnerability / Integer Overflow in Firmware ELF Parsing
- [High] Vulnerability / Heap Buffer Overflow in Firmware Splitting
- [High] Vulnerability / Invalid Pointer Dereference in Ring Buffer Iteration
- [High] Vulnerability / Divide by Zero from Untrusted Firmware Memory
- [High] Concurrency / Data Race in TX Ring Buffer
- [High] Vulnerability / Out-of-Bounds Read in Split Firmware Segment Loading
- [High] Logic Error / Endianness Conversion Missing on Shared Structures
- [High] Race Condition / NULL Pointer Dereference on Early IRQ
- [High] Logic Bug / State Machine Failure on Device Close
- [High] Logic Error / Endianness Issue in Packet Length Conversion
- [High] Vulnerability / Out-of-Bounds Read on Short Messages
- [High] Teardown Ordering / Hanging and Resource Leak on Driver Unbind
- [High] Vulnerability / Heap Buffer Overflow due to Integer Underflow
- [High] Vulnerability / Denial of Service via Linked List Cycle
- [High] I/O Memory Access Violation and Missing Memory Barriers
- [High] Logic Error / Ring Buffer Configuration Memory Corruption
- [Medium] Resource Leak / Leaked Workqueue on Probe Error
- [Medium] Resource Leak / Missing TrustZone PAS Shutdown on Open Timeout
- [Low] Build Failure / Missing Dependencies
- [Low] Code Style / Cleanup Rule Violation (Goto Mixing)
- [Low] API Misuse / Incorrect Free Function for Success Path
- [Low] Logic Error / Statistics Corruption on Failed Transmissions
--
commit ec79eeaa3b7302e6db1f42d811d3977beecf78c1
Author: George Moussalem <george.moussalem@outlook.com>
Bluetooth: Introduce Qualcomm IPQ5018 IPC based HCI driver
Add support for the Bluetooth controller found in the IPQ5018 SoC.
This driver implements firmware loading and the transport layer between
the HCI core and the Bluetooth controller.
> diff --git a/drivers/bluetooth/Kconfig b/drivers/bluetooth/Kconfig
> --- a/drivers/bluetooth/Kconfig
> +++ b/drivers/bluetooth/Kconfig
> @@ -453,6 +453,17 @@ config BT_MTKUART
> Say Y here to compile support for MediaTek Bluetooth UART devices
> into the kernel or say M to compile it as module (btmtkuart).
>
> +config BT_QCOMIPC
> + tristate "Qualcomm IPQ5018 IPC based HCI support"
> + select BT_QCA
[Severity: Low]
Does this Kconfig entry miss required dependencies? It appears that
select QCOM_MDT_LOADER and depends on QCOM_SCM are required to successfully
compile and link the driver.
[ ... ]
> diff --git a/drivers/bluetooth/btqcomipc.c b/drivers/bluetooth/btqcomipc.c
> --- /dev/null
> +++ b/drivers/bluetooth/btqcomipc.c
[ ... ]
> +static void *btss_alloc_lmsg(struct qcom_btss *desc, u32 len,
> + struct ipc_aux_ptr *aux_ptr, bool *is_lbuf_full)
> +{
> + struct device *dev = desc->dev;
> + u8 idx, blks, blks_consumed;
> + void *ret_ptr;
> + u32 lsz;
> +
> + if (desc->tx_ctxt->lring_buf == 0) {
> + dev_err(dev, "no long message buffer initialized\n");
> + return ERR_PTR(-ENODEV);
> + }
> +
> + lsz = IPC_LBUF_SZ(desc->tx_ctxt, total_size, lring_buf, lmsg_buf_cnt);
[Severity: High]
Can this calculation result in data corruption on big-endian systems?
The IPC_LBUF_SZ macro operates directly on fields in desc->tx_ctxt which are
defined as __le16 and __le32. It looks like they are being used in arithmetic
without conversions like le16_to_cpu() or le32_to_cpu().
[ ... ]
> +static struct ring_buffer_info *btss_get_tx_rbuf(struct qcom_btss *desc,
> + bool *is_sbuf_full)
> +{
> + u8 idx;
> + struct ring_buffer_info *rinfo;
> +
> + for (rinfo = &(desc->tx_ctxt->sring_buf_info); rinfo != NULL;
> + rinfo = (struct ring_buffer_info *)(uintptr_t)(rinfo->next)) {
[Severity: High]
Is it safe to directly cast rinfo->next to a kernel pointer?
The rinfo->next value is an untrusted 32-bit little-endian physical offset
provided by the firmware. On a 64-bit kernel, casting this directly into a
pointer might result in an unmapped address, potentially causing a kernel
panic when dereferenced in the next loop iteration.
[Severity: High]
Could an adversary trigger a denial of service here?
Since the list traversal reads the next pointer from untrusted shared memory,
a malicious firmware could form a circular linked list. Without cycle
detection, the worker thread might spin indefinitely.
> + idx = (rinfo->widx + 1) % (desc->tx_ctxt->smsg_buf_cnt);
[Severity: High]
Could this lead to a divide-by-zero crash?
The driver trusts smsg_buf_cnt which is located in the shared context rings
and writable by the Bluetooth processor. A compromised firmware could set this
count to zero.
[ ... ]
> +static int btss_send(struct qcom_btss *desc, u16 msg_hdr,
> + struct sk_buff *skb)
> +{
[ ... ]
> +complete_tx:
> + rbuf->msg_hdr = cpu_to_le16(hdr);
> + rbuf->len = cpu_to_le16(len);
[Severity: High]
Can these assignments to I/O memory cause data corruption?
The desc->mem_region is mapped via devm_ioremap(), but this code accesses
the shared memory using normal pointer assignments instead of proper
accessors. Furthermore, there are no memory barriers (like dma_wmb()) between
copying the payload and updating the header, so the compiler or CPU might
reorder the writes and expose incomplete payloads.
[ ... ]
> +static inline int btss_recv_hci_frame(struct qcom_btss *desc, const u8 *data,
> + size_t len)
> +{
[ ... ]
> + case HCI_COMMAND_PKT: {
> + if (len < 1 + HCI_COMMAND_HDR_SIZE)
> + return -EILSEQ;
> + struct hci_command_hdr *hdr = (struct hci_command_hdr *)(data + 1);
> +
> + pkt_len = HCI_COMMAND_HDR_SIZE + le16_to_cpu(hdr->plen);
[Severity: High]
Will this corrupt packet lengths on big-endian platforms?
The hdr->plen field is defined as __u8. Passing a __u8 to le16_to_cpu()
implicitly casts it to __u16 before byte-swapping, so a length of 0x05 might
become 0x0500.
[ ... ]
> + skb = bt_skb_alloc(pkt_len, GFP_ATOMIC);
> + if (!skb) {
> + desc->hdev->stat.err_rx++;
[Severity: High]
Can this cause a NULL pointer dereference during early IRQ handling?
The interrupt is enabled in btqcomipc_probe() before desc->hdev is allocated.
If the firmware was left running and a pending interrupt fires immediately,
the worker will eventually call btss_recv_hci_frame() and try to increment
stat.err_rx on a NULL desc->hdev.
[ ... ]
> +static inline int btss_process_rx(struct qcom_btss *desc,
> + struct ring_buffer_info *rinfo,
> + bool *ack, u8 *rx_count)
> +{
[ ... ]
> + while (ridx != rinfo->widx) {
> + memset(&aux_ptr, 0, sizeof(struct ipc_aux_ptr));
> +
> + rbuf = &((struct ring_buffer *)(TO_APPS_ADDR(rinfo->rbuf)))[ridx];
> +
> + if (rbuf->msg_hdr & IPC_HDR_LONG_MSG) {
[Severity: High]
Is this an endianness conversion issue?
The msg_hdr field is explicitly __le16, but is being evaluated natively
against a host constant without using le16_to_cpu().
> + rxbuf = TO_APPS_ADDR(rbuf->payload.lmsg_data);
> + lsz = IPC_LBUF_SZ(desc->rx_ctxt, total_size, lring_buf,
> + lmsg_buf_cnt);
> +
> + if (IS_RX_MEM_NON_CONTIGIOUS(rbuf->payload.lmsg_data,
> + rbuf->len, lsz)) {
> + lbuf_idx = GET_RX_INDEX_FROM_BUF(
> + rbuf->payload.lmsg_data, lsz);
> +
> + blks_consumed = desc->rx_ctxt->lmsg_buf_cnt -
> + lbuf_idx;
> + aux_ptr.len = rbuf->len - (blks_consumed * lsz);
[Severity: High]
Could this subtraction result in an integer underflow?
Both rbuf->len and aux_ptr.len are controlled by the untrusted firmware.
An attacker could manipulate them so that aux_ptr.len becomes larger than
rbuf->len, underflowing into a massive value.
[ ... ]
> + switch (pkt_type) {
> + case IPC_HDR_PKT_TYPE_HCI:
> + buf = kmalloc(rbuf->len, GFP_ATOMIC);
> + if (!buf) {
> + rinfo->ridx = ridx;
> + return -ENOMEM;
> + }
> +
> + memcpy_fromio(buf, rxbuf, rbuf->len - aux_ptr.len);
[Severity: High]
Does this allow out-of-bounds reads on short messages?
For short messages, rxbuf points to a fixed 40-byte array (smsg_data). If
the firmware maliciously provides an rbuf->len greater than 40, this could
read past the end of the array.
Additionally, if the aux_ptr.len subtraction underflowed as noted above,
this memcpy_fromio() could overwrite the allocated buf bounds with a
massive copy size.
[ ... ]
> + ridx = (ridx + 1) % rinfo->ring_buf_cnt;
> +
> + if (rx_count)
> + (*rx_count)++;
[Severity: High]
Is this incrementing the maximum capacity configuration field?
When btss_worker() passes &desc->rx_ctxt->smsg_buf_cnt as the rx_count
parameter, this will increment the shared hardware configuration field that
defines the ring's maximum capacity, corrupting the hardware contract.
[ ... ]
> +static void btss_process_ack(struct qcom_btss *desc)
> +{
[ ... ]
> + while (tidx != rinfo->ridx) {
> + if (rbuf[tidx].msg_hdr & IPC_HDR_LONG_MSG) {
> + btss_free_lmsg(desc,
> + rbuf[tidx].payload.lmsg_data,
> + rbuf[tidx].len);
> + }
> +
> + tidx = (tidx + 1) % desc->tx_ctxt->smsg_buf_cnt;
[Severity: High]
Could this also lead to a divide-by-zero crash?
Like earlier, if the firmware sets the shared smsg_buf_cnt to zero, this
modulo operation will trigger a divide-by-zero exception.
[ ... ]
> +static void btss_worker(struct work_struct *work)
> +{
[ ... ]
> + for (rinfo = &(desc->rx_ctxt->sring_buf_info);
> + rinfo != NULL;
> + rinfo = (struct ring_buffer_info *)(uintptr_t)(rinfo->next)) {
> + ret = btss_process_rx(desc, rinfo, &ack,
> + &desc->rx_ctxt->smsg_buf_cnt);
[Severity: High]
Is it safe to directly cast rinfo->next to a kernel virtual pointer here?
This suffers from the same issue as in btss_get_tx_rbuf() and could lead to
an invalid pointer dereference or infinite loop without cycle detection.
[ ... ]
> +static int btcomqipc_firmware_load(struct qcom_btss *desc)
> +{
> + const struct elf32_phdr *phdrs;
> + const struct firmware *seg_fw;
> + const struct elf32_phdr *phdr;
> + const struct elf32_hdr *ehdr;
> + const struct firmware *fw;
> + int i, ret;
> +
> + ret = request_firmware(&fw, desc->firmware, desc->dev);
> + if (ret) {
> + dev_err(desc->dev, "Failed to request firmware: %d\n",
> + ret);
> + return ret;
> + }
> +
> + ehdr = (const struct elf32_hdr *)fw->data;
> + phdrs = (const struct elf32_phdr *)(ehdr + 1);
> +
> + ret = qcom_mdt_pas_init(desc->dev, fw, desc->firmware,
> + BTSS_PAS_ID, desc->mem_phys, NULL);
[Severity: Low]
Is this function call correct?
It seems that qcom_mdt_pas_init() is an internal function not exported in
include/linux/soc/qcom/mdt_loader.h. Should this be qcom_mdt_pas_load()
instead?
> + if (ret) {
> + dev_err(desc->dev, "PAS init failed: %d\n", ret);
> + goto release_fw;
> + }
> +
> + for (i = 0; i < ehdr->e_phnum; i++) {
> + char *seg_name __free(kfree) = kstrdup(desc->firmware,
> + GFP_KERNEL);
> + if (!seg_name) {
> + ret = -ENOMEM;
> + goto release_fw;
> + }
[Severity: Low]
Does this mix goto-based error handling with scope-based cleanup?
The kernel guidelines indicate that functions should not mix goto-based
cleanup labels (like goto release_fw) with __free() variable declarations.
> +
> + phdr = &phdrs[i];
> +
> + /* Only process valid loadable data segments */
> + if (phdr->p_type != PT_LOAD || !phdr->p_memsz)
> + continue;
> +
> + if (phdr->p_vaddr + phdr->p_filesz > desc->mem_size) {
[Severity: High]
Could this be vulnerable to a 32-bit integer overflow?
The fields p_vaddr and p_filesz are read from the ELF header. A maliciously
crafted firmware could supply extremely large values to trigger a wraparound,
bypassing this boundary check before the memcpy_toio().
> + dev_err(desc->dev,
> + "Segment data exceeds the reserved memory area!\n");
> + goto release_fw;
> + }
> +
> + /* Check if firmware is split across multiple segment files */
> + if (phdr->p_offset > fw->size ||
> + phdr->p_offset + phdr->p_filesz > fw->size) {
> + sprintf(seg_name + strlen(seg_name) - 3, "b%02d", i);
[Severity: High]
Can this result in a heap buffer underflow or overflow?
The seg_name buffer is allocated exactly to the length of desc->firmware.
If the firmware name length is less than 3, the pointer arithmetic wraps
around causing a wild out-of-bounds write. Furthermore, if i >= 100,
the format specifier %02d writes 3 or more characters plus a null terminator,
which will exceed the allocated string boundary.
> + ret = request_firmware(&seg_fw, seg_name,
> + desc->dev);
> + if (ret) {
> + dev_err(desc->dev,
> + "Could not find split segment binary: %s\n",
> + seg_name);
> + goto release_fw;
> + }
> +
> + /*
> + * Use the virtual instead of the physical address as
> + * the offset
> + */
> + memcpy_toio(desc->mem_region + phdr->p_vaddr,
> + seg_fw->data, phdr->p_filesz);
[Severity: High]
Does this copy implicitly trust phdr->p_filesz?
The driver does not appear to verify that the loaded file size (seg_fw->size)
is at least phdr->p_filesz. A truncated segment file could cause memcpy_toio
to read past the end of the seg_fw->data buffer.
[ ... ]
> +static int btqcomipc_open(struct hci_dev *hdev)
> +{
[ ... ]
> + /* Boot firmware */
> + ret = qcom_scm_pas_auth_and_reset(BTSS_PAS_ID);
> + if (ret) {
> + bt_dev_err(hdev, "Failed to boot firmware: %d", ret);
> + return ret;
> + }
> +
> + msleep(BTSS_PWR_CTRL_DELAY_MS);
> + ret = wait_event_timeout(desc->wait_q, READ_ONCE(desc->running),
> + msecs_to_jiffies(1000));
> +
> + if (!ret) {
> + bt_dev_err(hdev, "Timeout waiting for BTSS start");
> + return -ETIMEDOUT;
> + }
[Severity: Medium]
Is the TrustZone PAS allocation leaked if this timeout triggers?
If wait_event_timeout() times out, the function returns -ETIMEDOUT without
cleaning up the PAS allocation. The Bluetooth core subsystem does not invoke
close() when open() fails, leaving the peripheral core running.
[ ... ]
> +static int btqcomipc_close(struct hci_dev *hdev)
> +{
> + int ret;
> +
> + ret = qcom_scm_pas_shutdown(BTSS_PAS_ID);
> + if (ret) {
> + bt_dev_err(hdev, "Failed to stop firmware: %d", ret);
> + return ret;
> + }
> +
> + msleep(BTSS_PWR_CTRL_DELAY_MS);
> +
> + return 0;
> +}
[Severity: High]
Should desc->running be reset to false here?
When the device is brought down, desc->running remains true. If the device
is opened again, the wait_event_timeout() check in btqcomipc_open() will see
it as true from the previous session and return immediately without actually
waiting for the firmware to initialize.
[ ... ]
> +static int btqcomipc_send(struct hci_dev *hdev, struct sk_buff *skb)
> +{
> + u16 hdr = FIELD_PREP(IPC_HDR_PKT_TYPE_MASK, IPC_HDR_PKT_TYPE_HCI);
> + struct qcom_btss *desc = hci_get_drvdata(hdev);
> + int ret;
> +
> + if (unlikely(!READ_ONCE(desc->running))) {
> + bt_dev_err(hdev,
> + "BTSS not initialized, failed to send message");
> + ret = -ENODEV;
> + goto free_skb;
> + }
> +
> + ret = btss_send(desc, hdr, skb);
[Severity: High]
Can this cause a data race in the TX ring buffer?
The btss_send() function is invoked without acquiring desc->lock, modifying
shared TX ring state like widx and free counters. Concurrently, btss_worker()
runs in process context with the lock held and modifies the exact same state
via btss_process_ack().
> + if (ret) {
> + if (ret == -EAGAIN) {
> + if (skb_queue_len(&desc->tx_q) >= IPC_TX_QSIZE) {
> + bt_dev_err(hdev,
> + "TX queue full, dropping message");
> + hdev->stat.err_tx++;
> + ret = -ENOBUFS;
> + } else {
> + skb_queue_tail(&desc->tx_q, skb);
> + return 0;
> + }
> + } else {
> + bt_dev_err(hdev, "Failed to send message: %d", ret);
> + hdev->stat.err_tx++;
> + }
> + }
> +
> + btqcomipc_update_stats(desc->hdev, skb);
[Severity: Low]
Is it intentional to update statistics on failed transmissions?
If btss_send() fails and falls through to this point, byte_tx and cmd_tx will
be incremented for packets that were actually dropped.
> +
> +free_skb:
> + kfree_skb(skb);
[Severity: Low]
Should this use consume_skb() for successful transmissions?
If the packet was successfully consumed by the hardware, using kfree_skb()
can cause network monitoring tools to falsely report these packets as dropped.
[ ... ]
> +static int btqcomipc_init(struct qcom_btss *desc)
> +{
> + struct device *dev = desc->dev;
> + int ret;
> +
> + init_waitqueue_head(&desc->wait_q);
> + spin_lock_init(&desc->lock);
> + skb_queue_head_init(&desc->tx_q);
> +
> + desc->wq = create_singlethread_workqueue("btss_wq");
> + if (!desc->wq) {
> + dev_err(dev, "Failed to initialize workqueue\n");
> + return -EAGAIN;
> + }
> +
> + INIT_WORK(&desc->work, btss_worker);
> +
> + ret = devm_request_threaded_irq(dev, desc->irq, NULL, btss_irq_handler,
> + IRQF_TRIGGER_RISING | IRQF_ONESHOT,
> + "btss_irq", desc);
[Severity: Medium]
Is the workqueue permanently leaked if the IRQ request fails?
If devm_request_threaded_irq() returns an error, the function exits without
calling destroy_workqueue(), leaking the non-devres managed workqueue.
[ ... ]
> +static void btqcomipc_remove(struct platform_device *pdev)
> +{
> + struct qcom_btss *desc = platform_get_drvdata(pdev);
> +
> + if (!desc)
> + return;
> +
> + btqcomipc_deinit(desc);
> +
> + if (desc->hdev) {
> + hci_unregister_dev(desc->hdev);
[Severity: High]
Could this teardown ordering cause a hang during unbind?
By calling btqcomipc_deinit() first, the driver disables the IRQ. Then,
hci_unregister_dev() tries to gracefully shut down the controller by sending
an HCI_OP_RESET command. Because the IRQ is disabled, the response is never
received, leading to a multi-second timeout.
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260629-ipq5018-bluetooth-v2-0-02770f03b6bb@outlook.com?part=4
^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: [PATCH v2 3/6] firmware: qcom: scm: Add support for setting Bluetooth power modes
2026-06-29 13:01 ` [PATCH v2 3/6] firmware: qcom: scm: Add support for setting Bluetooth power modes George Moussalem via B4 Relay
@ 2026-06-30 13:02 ` sashiko-bot
2026-07-01 9:58 ` Bartosz Golaszewski
2026-07-01 10:40 ` Konrad Dybcio
2 siblings, 0 replies; 27+ messages in thread
From: sashiko-bot @ 2026-06-30 13:02 UTC (permalink / raw)
To: George Moussalem via B4 Relay; +Cc: robh, conor+dt, devicetree
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [High] Command ID collision causing false positive availability check and potential TrustZone memory corruption.
--
commit ad188a38cad8a7f123b53d24cb2303340d519071
Author: George Moussalem <george.moussalem@outlook.com>
firmware: qcom: scm: Add support for setting Bluetooth power modes
This commit adds support for configuring the Bluetooth subsystem power
optimization mode on the IPQ5018 SoC. It introduces a new SCM call to
TrustZone and checks for the call's availability before invoking it.
> diff --git a/drivers/firmware/qcom/qcom_scm.c b/drivers/firmware/qcom/qcom_scm.c
> --- a/drivers/firmware/qcom/qcom_scm.c
> +++ b/drivers/firmware/qcom/qcom_scm.c
[ ... ]
> +static int __qcom_scm_pas_set_bluetooth_power_mode(u32 pas_id, u32 val)
> +{
> + struct qcom_scm_desc desc = {
> + .svc = QCOM_SCM_SVC_PIL,
> + .cmd = QCOM_SCM_PIL_PAS_BT_PWR_MODE,
> + .arginfo = QCOM_SCM_ARGS(2),
[ ... ]
> +int qcom_scm_pas_set_bluetooth_power_mode(u32 pas_id, u32 val)
> +{
> + if (!__qcom_scm_is_call_available(__scm->dev, QCOM_SCM_SVC_PIL,
> + QCOM_SCM_PIL_PAS_BT_PWR_MODE))
> + return -EOPNOTSUPP;
[ ... ]
> diff --git a/drivers/firmware/qcom/qcom_scm.h b/drivers/firmware/qcom/qcom_scm.h
> --- a/drivers/firmware/qcom/qcom_scm.h
> +++ b/drivers/firmware/qcom/qcom_scm.h
> @@ -105,6 +105,7 @@ int qcom_scm_shm_bridge_enable(struct device *scm_dev);
> #define QCOM_SCM_PIL_PAS_SHUTDOWN 0x06
> #define QCOM_SCM_PIL_PAS_IS_SUPPORTED 0x07
> #define QCOM_SCM_PIL_PAS_MSS_RESET 0x0a
> +#define QCOM_SCM_PIL_PAS_BT_PWR_MODE 0x21
> #define QCOM_SCM_PIL_PAS_GET_RSCTABLE 0x21
[Severity: High]
Could this command ID overlap cause a false positive in the availability check
and trigger unintended behavior in TrustZone?
Because QCOM_SCM_PIL_PAS_BT_PWR_MODE and QCOM_SCM_PIL_PAS_GET_RSCTABLE are
both defined as 0x21 under the same service (QCOM_SCM_SVC_PIL), the call
to __qcom_scm_is_call_available() in qcom_scm_pas_set_bluetooth_power_mode()
will return true on any platform that supports getting the resource table,
even if it does not actually support the Bluetooth power mode command.
If the function proceeds, it will invoke command 0x21 with only 2 arguments
instead of the 5 expected by the GET_RSCTABLE handler. Since the unprovided
arguments default to 0, might this cause TrustZone to read or write at
physical address 0x0, potentially resulting in a Secure World crash or
memory corruption?
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260629-ipq5018-bluetooth-v2-0-02770f03b6bb@outlook.com?part=3
^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: [PATCH v2 5/6] arm64: dts: qcom: ipq5018: add nodes required for Bluetooth support
2026-06-29 13:01 ` [PATCH v2 5/6] arm64: dts: qcom: ipq5018: add nodes required for Bluetooth support George Moussalem via B4 Relay
2026-06-30 11:40 ` Konrad Dybcio
@ 2026-06-30 13:02 ` sashiko-bot
1 sibling, 0 replies; 27+ messages in thread
From: sashiko-bot @ 2026-06-30 13:02 UTC (permalink / raw)
To: George Moussalem via B4 Relay; +Cc: conor+dt, devicetree, robh
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [Low] Adding "syscon" to the apcs_glb compatible string violates the current DT binding schema and will cause a dtbs_check failure.
--
commit 8d5a37566d441600f3735791890dcc06ffb70e79
Author: George Moussalem <george.moussalem@outlook.com>
arm64: dts: qcom: ipq5018: add nodes required for Bluetooth support
This commit adds device tree nodes for the reserved memory carveout and
Bluetooth on the IPQ5018 platform. It also modifies the apcs_glb mailbox
node to include the syscon compatible string.
> diff --git a/arch/arm64/boot/dts/qcom/ipq5018.dtsi b/arch/arm64/boot/dts/qcom/ipq5018.dtsi
> index 6f8004a22a1ff..65a47ba7d3a34 100644
> --- a/arch/arm64/boot/dts/qcom/ipq5018.dtsi
> +++ b/arch/arm64/boot/dts/qcom/ipq5018.dtsi
[ ... ]
> @@ -647,7 +669,8 @@ watchdog: watchdog@b017000 {
>
> apcs_glb: mailbox@b111000 {
> compatible = "qcom,ipq5018-apcs-apps-global",
> - "qcom,ipq6018-apcs-apps-global";
> + "qcom,ipq6018-apcs-apps-global",
> + "syscon";
[Severity: Low]
Does adding "syscon" here without updating the device tree bindings schema
cause dtbs_check to fail?
The schema in Documentation/devicetree/bindings/mailbox/qcom,apcs-kpss-global.yaml
strictly limits the compatible array for qcom,ipq5018-apcs-apps-global to
exactly two items. Will the validation fail when parsing this new item?
Should the DT binding schema be updated in a companion patch to permit the
"syscon" compatible string for this node?
> reg = <0x0b111000 0x1000>;
> #clock-cells = <1>;
> clocks = <&a53pll>, <&xo_board_clk>, <&gcc GPLL0>;
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260629-ipq5018-bluetooth-v2-0-02770f03b6bb@outlook.com?part=5
^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: [PATCH v2 3/6] firmware: qcom: scm: Add support for setting Bluetooth power modes
2026-06-29 13:01 ` [PATCH v2 3/6] firmware: qcom: scm: Add support for setting Bluetooth power modes George Moussalem via B4 Relay
2026-06-30 13:02 ` sashiko-bot
@ 2026-07-01 9:58 ` Bartosz Golaszewski
2026-07-01 10:40 ` Konrad Dybcio
2 siblings, 0 replies; 27+ messages in thread
From: Bartosz Golaszewski @ 2026-07-01 9:58 UTC (permalink / raw)
To: george.moussalem
Cc: George Moussalem via B4 Relay, linux-block, linux-kernel,
linux-mmc, devicetree, linux-wireless, ath10k, linux-arm-msm,
linux-bluetooth, netdev, linux-remoteproc, Jens Axboe,
Ulf Hansson, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Johannes Berg, Jeff Johnson, Bartosz Golaszewski, Marcel Holtmann,
Luiz Augusto von Dentz, Balakrishna Godavarthi, Rocky Liao,
Saravana Kannan, Andrew Lunn, Heiner Kallweit, Russell King,
David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
Simon Horman, Bjorn Andersson, Konrad Dybcio, Mathieu Poirier,
Philipp Zabel
On Mon, 29 Jun 2026 15:01:46 +0200, George Moussalem via B4 Relay
<devnull+george.moussalem.outlook.com@kernel.org> said:
> From: George Moussalem <george.moussalem@outlook.com>
>
> The Bluetooth subsystem (BTSS) on the IPQ5018 SoC supports setting power
> modes which are required to be configured through a Secure Channel
> Manager (SCM) call to TrustZone. However, not all Trusted Execution
> Environment (QSEE) images support this call, so first check if the call
> is available.
>
> Signed-off-by: George Moussalem <george.moussalem@outlook.com>
> ---
Reviewed-by: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>
^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: [PATCH v2 2/6] Bluetooth: btqca: Add IPQ5018 support
2026-06-29 13:01 ` [PATCH v2 2/6] Bluetooth: btqca: Add IPQ5018 support George Moussalem via B4 Relay
@ 2026-07-01 9:59 ` Bartosz Golaszewski
0 siblings, 0 replies; 27+ messages in thread
From: Bartosz Golaszewski @ 2026-07-01 9:59 UTC (permalink / raw)
To: george.moussalem
Cc: Jens Axboe, Ulf Hansson, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Johannes Berg, Jeff Johnson, Bartosz Golaszewski,
Marcel Holtmann, Luiz Augusto von Dentz, Balakrishna Godavarthi,
Rocky Liao, Saravana Kannan, Andrew Lunn, Heiner Kallweit,
Russell King, David S. Miller, Eric Dumazet, Jakub Kicinski,
Paolo Abeni, Simon Horman, Bjorn Andersson, Konrad Dybcio,
Mathieu Poirier, Philipp Zabel, George Moussalem via B4 Relay,
linux-block, linux-kernel, linux-mmc, devicetree, linux-wireless,
ath10k, linux-arm-msm, linux-bluetooth, netdev, linux-remoteproc
On Mon, 29 Jun 2026 15:01:45 +0200, George Moussalem via B4 Relay
<devnull+george.moussalem.outlook.com@kernel.org> said:
> From: George Moussalem <george.moussalem@outlook.com>
>
> Add the IPQ5018 SoC type and support for loading its firmware.
>
> The firmware tested has been taken from GPL sources of various router
> boards. Firmware files needed are:
> - qca/bt_fw_patch.mbn
> - qca/mpnv10.bin
>
> Signed-off-by: George Moussalem <george.moussalem@outlook.com>
> ---
Acked-by: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>
^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: [PATCH v2 3/6] firmware: qcom: scm: Add support for setting Bluetooth power modes
2026-06-29 13:01 ` [PATCH v2 3/6] firmware: qcom: scm: Add support for setting Bluetooth power modes George Moussalem via B4 Relay
2026-06-30 13:02 ` sashiko-bot
2026-07-01 9:58 ` Bartosz Golaszewski
@ 2026-07-01 10:40 ` Konrad Dybcio
2026-07-01 13:15 ` George Moussalem
2 siblings, 1 reply; 27+ messages in thread
From: Konrad Dybcio @ 2026-07-01 10:40 UTC (permalink / raw)
To: george.moussalem, Jens Axboe, Ulf Hansson, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Johannes Berg, Jeff Johnson,
Bartosz Golaszewski, Marcel Holtmann, Luiz Augusto von Dentz,
Balakrishna Godavarthi, Rocky Liao, Saravana Kannan, Andrew Lunn,
Heiner Kallweit, Russell King, David S. Miller, Eric Dumazet,
Jakub Kicinski, Paolo Abeni, Simon Horman, Bjorn Andersson,
Konrad Dybcio, Mathieu Poirier, Philipp Zabel
Cc: linux-block, linux-kernel, linux-mmc, devicetree, linux-wireless,
ath10k, linux-arm-msm, linux-bluetooth, netdev, linux-remoteproc
On 6/29/26 3:01 PM, George Moussalem via B4 Relay wrote:
> From: George Moussalem <george.moussalem@outlook.com>
>
> The Bluetooth subsystem (BTSS) on the IPQ5018 SoC supports setting power
> modes which are required to be configured through a Secure Channel
> Manager (SCM) call to TrustZone. However, not all Trusted Execution
> Environment (QSEE) images support this call, so first check if the call
> is available.
>
> Signed-off-by: George Moussalem <george.moussalem@outlook.com>
> ---
I'm amazed changing this setting is a secure operation
[...]
> +/**
> + * qcom_scm_pas_set_bluetooth_power_mode() - Configure power optimization mode
> + * for the Bluetooth subsystem (BTSS)
> + * @pas_id: peripheral authentication service id
> + * @val: 0x0 for normal operation, 0x4 for ECO mode
If there's just two values, maybe we should make this take a `bool eco_mode`?
> + *
> + * Return: 0 on success, negative errno on failure.
> + * Returns -EOPNOTSUPP if the firmware configuration call is unavailable.
> + */
> +int qcom_scm_pas_set_bluetooth_power_mode(u32 pas_id, u32 val)
> +{
> + if (!__qcom_scm_is_call_available(__scm->dev, QCOM_SCM_SVC_PIL,
> + QCOM_SCM_PIL_PAS_BT_PWR_MODE))
> + return -EOPNOTSUPP;
> +
> + return __qcom_scm_pas_set_bluetooth_power_mode(pas_id, val);
Let's just inline the whole definition here - it's single-use anyway
Konrad
^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: [PATCH v2 4/6] Bluetooth: Introduce Qualcomm IPQ5018 IPC based HCI driver
2026-06-29 13:01 ` [PATCH v2 4/6] Bluetooth: Introduce Qualcomm IPQ5018 IPC based HCI driver George Moussalem via B4 Relay
2026-06-30 13:02 ` sashiko-bot
@ 2026-07-01 11:19 ` Konrad Dybcio
1 sibling, 0 replies; 27+ messages in thread
From: Konrad Dybcio @ 2026-07-01 11:19 UTC (permalink / raw)
To: george.moussalem, Jens Axboe, Ulf Hansson, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Johannes Berg, Jeff Johnson,
Bartosz Golaszewski, Marcel Holtmann, Luiz Augusto von Dentz,
Balakrishna Godavarthi, Rocky Liao, Saravana Kannan, Andrew Lunn,
Heiner Kallweit, Russell King, David S. Miller, Eric Dumazet,
Jakub Kicinski, Paolo Abeni, Simon Horman, Bjorn Andersson,
Konrad Dybcio, Mathieu Poirier, Philipp Zabel
Cc: linux-block, linux-kernel, linux-mmc, devicetree, linux-wireless,
ath10k, linux-arm-msm, linux-bluetooth, netdev, linux-remoteproc
On 6/29/26 3:01 PM, George Moussalem via B4 Relay wrote:
> From: George Moussalem <george.moussalem@outlook.com>
>
> Add support for the Bluetooth controller found in the IPQ5018 SoC.
> This driver implements firmware loading and the transport layer between
> the HCI core and the Bluetooth controller.
>
> The firmware is loaded by the host into the dedicated reserved memory
> carveout and authenticated by TrustZone. A Secure Channel Manager (SCM)
> call safely brings the peripheral core out of reset.
>
> A shared memory ring buffer topology handles runtime data frame
> transport between the host APSS and the controller.
>
> An outgoing APCS IPC bit and an incoming GIC interrupt handle host/guest
> signaling.
>
> Signed-off-by: George Moussalem <george.moussalem@outlook.com>
> ---
[...]
> +#include <linux/bits.h>
> +#include <linux/clk.h>
> +#include <linux/delay.h>
> +#include <linux/device.h>
> +#include <linux/elf.h>
> +#include <linux/firmware.h>
> +#include <linux/firmware/qcom/qcom_scm.h>
> +#include <linux/init.h>
> +#include <linux/interrupt.h>
> +#include <linux/io.h>
> +#include <linux/kernel.h>
> +#include <linux/mfd/syscon.h>
> +#include <linux/module.h>
> +#include <linux/of.h>
> +#include <linux/of_irq.h>
> +#include <linux/of_reserved_mem.h>
> +#include <linux/platform_device.h>
> +#include <linux/regmap.h>
> +#include <linux/reset.h>
> +#include <linux/skbuff.h>
> +#include <linux/slab.h>
> +#include <linux/soc/qcom/mdt_loader.h>
> +#include <linux/types.h>
> +#include <linux/workqueue.h>
I don't know for sure, but the amount of the includes suggests some may
be unnecessary
[...]
> +static void btqcomipc_update_stats(struct hci_dev *hdev, struct sk_buff *skb);
I don't think the forward-declaration is necessary
> +static struct ring_buffer_info *btss_get_tx_rbuf(struct qcom_btss *desc,
> + bool *is_sbuf_full)
> +{
> + u8 idx;
> + struct ring_buffer_info *rinfo;
> +
> + for (rinfo = &(desc->tx_ctxt->sring_buf_info); rinfo != NULL;
> + rinfo = (struct ring_buffer_info *)(uintptr_t)(rinfo->next)) {
> + idx = (rinfo->widx + 1) % (desc->tx_ctxt->smsg_buf_cnt);
That's one complex for-loop! Maybe move the assignments into the loop body
[...]
> + /* Account for HCI packet type as it's not included in the skb payload */
> + len = (skb) ? skb->len + 1 : 0;
Unnecessary parentheses, also in some other places
> + memset(&aux_ptr, 0, sizeof(struct ipc_aux_ptr));
You can do aux_ptr = { } at declaration
Konrad
^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: [PATCH v2 3/6] firmware: qcom: scm: Add support for setting Bluetooth power modes
2026-07-01 10:40 ` Konrad Dybcio
@ 2026-07-01 13:15 ` George Moussalem
2026-07-01 13:31 ` Konrad Dybcio
0 siblings, 1 reply; 27+ messages in thread
From: George Moussalem @ 2026-07-01 13:15 UTC (permalink / raw)
To: Konrad Dybcio, Jens Axboe, Ulf Hansson, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Johannes Berg, Jeff Johnson,
Bartosz Golaszewski, Marcel Holtmann, Luiz Augusto von Dentz,
Balakrishna Godavarthi, Rocky Liao, Saravana Kannan, Andrew Lunn,
Heiner Kallweit, Russell King, David S. Miller, Eric Dumazet,
Jakub Kicinski, Paolo Abeni, Simon Horman, Bjorn Andersson,
Konrad Dybcio, Mathieu Poirier, Philipp Zabel
Cc: linux-block, linux-kernel, linux-mmc, devicetree, linux-wireless,
ath10k, linux-arm-msm, linux-bluetooth, netdev, linux-remoteproc
On 7/1/26 14:40, Konrad Dybcio wrote:
> On 6/29/26 3:01 PM, George Moussalem via B4 Relay wrote:
>> From: George Moussalem <george.moussalem@outlook.com>
>>
>> The Bluetooth subsystem (BTSS) on the IPQ5018 SoC supports setting power
>> modes which are required to be configured through a Secure Channel
>> Manager (SCM) call to TrustZone. However, not all Trusted Execution
>> Environment (QSEE) images support this call, so first check if the call
>> is available.
>>
>> Signed-off-by: George Moussalem <george.moussalem@outlook.com>
>> ---
>
> I'm amazed changing this setting is a secure operation
>
> [...]
>
>> +/**
>> + * qcom_scm_pas_set_bluetooth_power_mode() - Configure power optimization mode
>> + * for the Bluetooth subsystem (BTSS)
>> + * @pas_id: peripheral authentication service id
>> + * @val: 0x0 for normal operation, 0x4 for ECO mode
>
> If there's just two values, maybe we should make this take a `bool eco_mode`?
that was the direction I was going in initially but then thought that
there may be more (undocumented) power modes I'm unaware off so changed
it to u32. I'll change it back to bool.
>
>> + *
>> + * Return: 0 on success, negative errno on failure.
>> + * Returns -EOPNOTSUPP if the firmware configuration call is unavailable.
>> + */
>> +int qcom_scm_pas_set_bluetooth_power_mode(u32 pas_id, u32 val)
>> +{
>> + if (!__qcom_scm_is_call_available(__scm->dev, QCOM_SCM_SVC_PIL,
>> + QCOM_SCM_PIL_PAS_BT_PWR_MODE))
>> + return -EOPNOTSUPP;
>> +
>> + return __qcom_scm_pas_set_bluetooth_power_mode(pas_id, val);
>
> Let's just inline the whole definition here - it's single-use anyway
will update, thanks.
>
> Konrad
Cheers,
George
^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: [PATCH v2 3/6] firmware: qcom: scm: Add support for setting Bluetooth power modes
2026-07-01 13:15 ` George Moussalem
@ 2026-07-01 13:31 ` Konrad Dybcio
0 siblings, 0 replies; 27+ messages in thread
From: Konrad Dybcio @ 2026-07-01 13:31 UTC (permalink / raw)
To: George Moussalem, Jens Axboe, Ulf Hansson, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Johannes Berg, Jeff Johnson,
Bartosz Golaszewski, Marcel Holtmann, Luiz Augusto von Dentz,
Balakrishna Godavarthi, Rocky Liao, Saravana Kannan, Andrew Lunn,
Heiner Kallweit, Russell King, David S. Miller, Eric Dumazet,
Jakub Kicinski, Paolo Abeni, Simon Horman, Bjorn Andersson,
Konrad Dybcio, Mathieu Poirier, Philipp Zabel
Cc: linux-block, linux-kernel, linux-mmc, devicetree, linux-wireless,
ath10k, linux-arm-msm, linux-bluetooth, netdev, linux-remoteproc
On 7/1/26 3:15 PM, George Moussalem wrote:
> On 7/1/26 14:40, Konrad Dybcio wrote:
>> On 6/29/26 3:01 PM, George Moussalem via B4 Relay wrote:
>>> From: George Moussalem <george.moussalem@outlook.com>
>>>
>>> The Bluetooth subsystem (BTSS) on the IPQ5018 SoC supports setting power
>>> modes which are required to be configured through a Secure Channel
>>> Manager (SCM) call to TrustZone. However, not all Trusted Execution
>>> Environment (QSEE) images support this call, so first check if the call
>>> is available.
>>>
>>> Signed-off-by: George Moussalem <george.moussalem@outlook.com>
>>> ---
>>
>> I'm amazed changing this setting is a secure operation
>>
>> [...]
>>
>>> +/**
>>> + * qcom_scm_pas_set_bluetooth_power_mode() - Configure power optimization mode
>>> + * for the Bluetooth subsystem (BTSS)
>>> + * @pas_id: peripheral authentication service id
>>> + * @val: 0x0 for normal operation, 0x4 for ECO mode
>>
>> If there's just two values, maybe we should make this take a `bool eco_mode`?
>
> that was the direction I was going in initially but then thought that
> there may be more (undocumented) power modes I'm unaware off so changed
> it to u32. I'll change it back to bool.
We can always change back if needed
Konrad
^ permalink raw reply [flat|nested] 27+ messages in thread
end of thread, other threads:[~2026-07-01 13:31 UTC | newest]
Thread overview: 27+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-06-29 13:01 [PATCH v2 0/6] Add support for IPQ5018 Bluetooth George Moussalem via B4 Relay
2026-06-29 13:01 ` [PATCH v2 1/6] dt-bindings: net: bluetooth: Document Qualcomm IPQ5018 Bluetooth controller George Moussalem via B4 Relay
2026-06-30 7:15 ` Krzysztof Kozlowski
2026-06-30 7:31 ` George Moussalem
2026-06-30 7:40 ` Krzysztof Kozlowski
2026-06-30 7:55 ` George Moussalem
2026-06-30 8:20 ` Krzysztof Kozlowski
2026-06-30 9:06 ` Konrad Dybcio
2026-06-30 9:09 ` Krzysztof Kozlowski
2026-06-30 8:20 ` Krzysztof Kozlowski
2026-06-29 13:01 ` [PATCH v2 2/6] Bluetooth: btqca: Add IPQ5018 support George Moussalem via B4 Relay
2026-07-01 9:59 ` Bartosz Golaszewski
2026-06-29 13:01 ` [PATCH v2 3/6] firmware: qcom: scm: Add support for setting Bluetooth power modes George Moussalem via B4 Relay
2026-06-30 13:02 ` sashiko-bot
2026-07-01 9:58 ` Bartosz Golaszewski
2026-07-01 10:40 ` Konrad Dybcio
2026-07-01 13:15 ` George Moussalem
2026-07-01 13:31 ` Konrad Dybcio
2026-06-29 13:01 ` [PATCH v2 4/6] Bluetooth: Introduce Qualcomm IPQ5018 IPC based HCI driver George Moussalem via B4 Relay
2026-06-30 13:02 ` sashiko-bot
2026-07-01 11:19 ` Konrad Dybcio
2026-06-29 13:01 ` [PATCH v2 5/6] arm64: dts: qcom: ipq5018: add nodes required for Bluetooth support George Moussalem via B4 Relay
2026-06-30 11:40 ` Konrad Dybcio
2026-06-30 12:09 ` George Moussalem
2026-06-30 12:12 ` Konrad Dybcio
2026-06-30 13:02 ` sashiko-bot
2026-06-29 13:01 ` [PATCH v2 6/6] MAINTAINERS: Add entry for Qualcomm IPQ5018 Bluetooth driver George Moussalem via B4 Relay
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox