From: Kishore Batta <kishore.batta@oss.qualcomm.com>
To: Jonathan Corbet <corbet@lwn.net>,
Shuah Khan <skhan@linuxfoundation.org>,
Jeff Hugo <jeff.hugo@oss.qualcomm.com>,
Carl Vanderlip <carl.vanderlip@oss.qualcomm.com>,
Oded Gabbay <ogabbay@kernel.org>,
Manivannan Sadhasivam <mani@kernel.org>,
Randy Dunlap <rdunlap@infradead.org>
Cc: linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org,
linux-arm-msm@vger.kernel.org, dri-devel@lists.freedesktop.org,
mhi@lists.linux.dev,
Kishore Batta <kishore.batta@oss.qualcomm.com>
Subject: [PATCH v8 3/7] bus: mhi: Centralize Sahara firmware image table selection at probe time
Date: Mon, 12 Oct 2026 23:48:01 +0530 [thread overview]
Message-ID: <20261012-sahara_protocol_new_v2-v8-3-e12939d229a1@oss.qualcomm.com> (raw)
In-Reply-To: <20261012-sahara_protocol_new_v2-v8-0-e12939d229a1@oss.qualcomm.com>
The Sahara driver currently selects firmware image tables using scattered,
device specific conditionals in the probe path. This makes the logic harder
to follow, harder to extend for new devices, and spreads device knowledge
across multiple code paths.
Refactor firmware image table selection into a single, explicit probe time
mechanism by introducing a controller provided firmware mapping table that
captures device matching, Sahara image tables, firmware folder names, and
streaming behaviour in one place.
This centralizes device specific decisions in the controller driver,
simplifies the Sahara probe logic, and removes ad-hoc conditionals while
preserving existing behavior for all supported AIC devices. This is in
preparation for adding QDU100 support.
Signed-off-by: Kishore Batta <kishore.batta@oss.qualcomm.com>
---
drivers/accel/qaic/mhi_controller.c | 61 ++++++++++++++++++++++++++++
drivers/bus/mhi/host/clients/sahara/sahara.c | 60 +++++----------------------
include/linux/mhi.h | 17 ++++++++
3 files changed, 88 insertions(+), 50 deletions(-)
diff --git a/drivers/accel/qaic/mhi_controller.c b/drivers/accel/qaic/mhi_controller.c
index 40e6d262ef217aad8ddff6f69a38388ef683e3ed..dd320739c07ad4a35b74446e32f0e8e64e847d16 100644
--- a/drivers/accel/qaic/mhi_controller.c
+++ b/drivers/accel/qaic/mhi_controller.c
@@ -20,6 +20,62 @@ static unsigned int mhi_timeout_ms = 2000; /* 2 sec default */
module_param(mhi_timeout_ms, uint, 0600);
MODULE_PARM_DESC(mhi_timeout_ms, "MHI controller timeout value");
+static const char * const aic100_image_table[] = {
+ [1] = "qcom/aic100/fw1.bin",
+ [2] = "qcom/aic100/fw2.bin",
+ [4] = "qcom/aic100/fw4.bin",
+ [5] = "qcom/aic100/fw5.bin",
+ [6] = "qcom/aic100/fw6.bin",
+ [8] = "qcom/aic100/fw8.bin",
+ [9] = "qcom/aic100/fw9.bin",
+ [10] = "qcom/aic100/fw10.bin",
+};
+
+static const char * const aic200_image_table[] = {
+ [5] = "qcom/aic200/uefi.elf",
+ [12] = "qcom/aic200/aic200-nsp.bin",
+ [23] = "qcom/aic200/aop.mbn",
+ [32] = "qcom/aic200/tz.mbn",
+ [33] = "qcom/aic200/hypvm.mbn",
+ [38] = "qcom/aic200/xbl_config.elf",
+ [39] = "qcom/aic200/aic200_abl.elf",
+ [40] = "qcom/aic200/apdp.mbn",
+ [41] = "qcom/aic200/devcfg.mbn",
+ [42] = "qcom/aic200/sec.elf",
+ [43] = "qcom/aic200/aic200-hlos.elf",
+ [49] = "qcom/aic200/shrm.elf",
+ [50] = "qcom/aic200/cpucp.elf",
+ [51] = "qcom/aic200/aop_devcfg.mbn",
+ [54] = "qcom/aic200/qupv3fw.elf",
+ [57] = "qcom/aic200/cpucp_dtbs.elf",
+ [62] = "qcom/aic200/uefi_dtbs.elf",
+ [63] = "qcom/aic200/xbl_ac_config.mbn",
+ [64] = "qcom/aic200/tz_ac_config.mbn",
+ [65] = "qcom/aic200/hyp_ac_config.mbn",
+ [66] = "qcom/aic200/pdp.elf",
+ [67] = "qcom/aic200/pdp_cdb.elf",
+ [68] = "qcom/aic200/sdi.mbn",
+ [69] = "qcom/aic200/dcd.mbn",
+ [73] = "qcom/aic200/gearvm.mbn",
+ [74] = "qcom/aic200/sti.bin",
+ [76] = "qcom/aic200/tz_qti_config.mbn",
+ [78] = "qcom/aic200/pvs.bin",
+};
+
+static const struct mhi_sahara_fw_table aic100_sahara_fw = {
+ .image_table = aic100_image_table,
+ .table_size = ARRAY_SIZE(aic100_image_table),
+ .fw_folder = "aic100",
+ .non_streaming = true,
+};
+
+static const struct mhi_sahara_fw_table aic200_sahara_fw = {
+ .image_table = aic200_image_table,
+ .table_size = ARRAY_SIZE(aic200_image_table),
+ .fw_folder = "aic200",
+ .non_streaming = false,
+};
+
static const char *fw_image_paths[FAMILY_MAX] = {
[FAMILY_AIC100] = "qcom/aic100/sbl.bin",
[FAMILY_AIC200] = "qcom/aic200/sbl.bin",
@@ -871,6 +927,11 @@ struct mhi_controller *qaic_mhi_register_controller(struct pci_dev *pci_dev, voi
mhi_cntrl->name = "AIC100";
}
+ if (mhi_cntrl->name && !strcmp(mhi_cntrl->name, "AIC100"))
+ mhi_cntrl->sahara_fw = &aic100_sahara_fw;
+ else if (mhi_cntrl->name && !strcmp(mhi_cntrl->name, "AIC200"))
+ mhi_cntrl->sahara_fw = &aic200_sahara_fw;
+
/* use latest configured timeout */
mhi_config.timeout_ms = mhi_timeout_ms;
ret = mhi_register_controller(mhi_cntrl, &mhi_config);
diff --git a/drivers/bus/mhi/host/clients/sahara/sahara.c b/drivers/bus/mhi/host/clients/sahara/sahara.c
index dc64beae06ada6915a506ed8f4ae4d71c03158bb..74bf57f02873e463d0c2cfdd2673237840169df2 100644
--- a/drivers/bus/mhi/host/clients/sahara/sahara.c
+++ b/drivers/bus/mhi/host/clients/sahara/sahara.c
@@ -179,48 +179,7 @@ struct sahara_context {
u32 read_data_length;
bool is_mem_dump_mode;
bool non_streaming;
-};
-
-static const char * const aic100_image_table[] = {
- [1] = "qcom/aic100/fw1.bin",
- [2] = "qcom/aic100/fw2.bin",
- [4] = "qcom/aic100/fw4.bin",
- [5] = "qcom/aic100/fw5.bin",
- [6] = "qcom/aic100/fw6.bin",
- [8] = "qcom/aic100/fw8.bin",
- [9] = "qcom/aic100/fw9.bin",
- [10] = "qcom/aic100/fw10.bin",
-};
-
-static const char * const aic200_image_table[] = {
- [5] = "qcom/aic200/uefi.elf",
- [12] = "qcom/aic200/aic200-nsp.bin",
- [23] = "qcom/aic200/aop.mbn",
- [32] = "qcom/aic200/tz.mbn",
- [33] = "qcom/aic200/hypvm.mbn",
- [38] = "qcom/aic200/xbl_config.elf",
- [39] = "qcom/aic200/aic200_abl.elf",
- [40] = "qcom/aic200/apdp.mbn",
- [41] = "qcom/aic200/devcfg.mbn",
- [42] = "qcom/aic200/sec.elf",
- [43] = "qcom/aic200/aic200-hlos.elf",
- [49] = "qcom/aic200/shrm.elf",
- [50] = "qcom/aic200/cpucp.elf",
- [51] = "qcom/aic200/aop_devcfg.mbn",
- [54] = "qcom/aic200/qupv3fw.elf",
- [57] = "qcom/aic200/cpucp_dtbs.elf",
- [62] = "qcom/aic200/uefi_dtbs.elf",
- [63] = "qcom/aic200/xbl_ac_config.mbn",
- [64] = "qcom/aic200/tz_ac_config.mbn",
- [65] = "qcom/aic200/hyp_ac_config.mbn",
- [66] = "qcom/aic200/pdp.elf",
- [67] = "qcom/aic200/pdp_cdb.elf",
- [68] = "qcom/aic200/sdi.mbn",
- [69] = "qcom/aic200/dcd.mbn",
- [73] = "qcom/aic200/gearvm.mbn",
- [74] = "qcom/aic200/sti.bin",
- [76] = "qcom/aic200/tz_qti_config.mbn",
- [78] = "qcom/aic200/pvs.bin",
+ const char *fw_folder;
};
static bool is_streaming(struct sahara_context *context)
@@ -796,6 +755,7 @@ static void sahara_read_data_processing(struct work_struct *work)
static int sahara_mhi_probe(struct mhi_device *mhi_dev, const struct mhi_device_id *id)
{
+ const struct mhi_sahara_fw_table *sahara_fw;
struct sahara_context *context;
int ret;
int i;
@@ -808,14 +768,14 @@ static int sahara_mhi_probe(struct mhi_device *mhi_dev, const struct mhi_device_
if (!context->rx)
return -ENOMEM;
- if (!strcmp(mhi_dev->mhi_cntrl->name, "AIC200")) {
- context->image_table = aic200_image_table;
- context->table_size = ARRAY_SIZE(aic200_image_table);
- } else {
- context->image_table = aic100_image_table;
- context->table_size = ARRAY_SIZE(aic100_image_table);
- context->non_streaming = true;
- }
+ sahara_fw = mhi_dev->mhi_cntrl->sahara_fw;
+ if (!sahara_fw || !sahara_fw->image_table || !sahara_fw->table_size)
+ return -ENODEV;
+
+ context->image_table = sahara_fw->image_table;
+ context->table_size = sahara_fw->table_size;
+ context->non_streaming = sahara_fw->non_streaming;
+ context->fw_folder = sahara_fw->fw_folder;
/*
* There are two firmware implementations for READ_DATA handling.
diff --git a/include/linux/mhi.h b/include/linux/mhi.h
index 65e8a397cc50b89d045a242aa1164ea7fb8c9696..e1d12e8c1eb80945be6a6d0a5896d92ac221ab81 100644
--- a/include/linux/mhi.h
+++ b/include/linux/mhi.h
@@ -252,6 +252,21 @@ struct mhi_channel_config {
bool wake_capable;
};
+/**
+ * struct mhi_sahara_fw_table - Controller provided sahara firmware mapping
+ * @image_table: Sparse array indexed by Sahara image ID
+ * @table_size: Size of @image_table
+ * @fw_folder: Firmware folder name.
+ * @non_streaming: Streaming feature support (optional)
+ *
+ */
+struct mhi_sahara_fw_table {
+ const char *const *image_table;
+ u32 table_size;
+ const char *fw_folder;
+ bool non_streaming;
+};
+
/**
* struct mhi_event_config - Event ring configuration structure for controller
* @num_elements: The number of elements that can be queued to this ring
@@ -381,6 +396,7 @@ struct mhi_controller_config {
* @no_m3: Device doesn't support M3 state
* @irq_flags: irq flags passed to request_irq (optional)
* @mru: the default MRU for the MHI device
+ * @sahara_fw: Sahara firmware mapping
*
* Fields marked as (required) need to be populated by the controller driver
* before calling mhi_register_controller(). For the fields marked as (optional)
@@ -467,6 +483,7 @@ struct mhi_controller {
bool no_m3;
unsigned long irq_flags;
u32 mru;
+ const struct mhi_sahara_fw_table *sahara_fw;
};
/**
--
2.34.1
next prev parent reply other threads:[~2026-10-12 18:18 UTC|newest]
Thread overview: 10+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-10-12 18:17 [PATCH v8 0/7] Qualcomm Sahara protocol enhancements Kishore Batta
2026-10-12 18:17 ` [PATCH v8 1/7] Add documentation for Sahara protocol Kishore Batta
2026-10-12 18:18 ` [PATCH v8 2/7] bus: mhi: Move Sahara protocol driver under MHI host client drivers Kishore Batta
2026-10-12 20:43 ` Uwe Kleine-König
2026-10-12 21:35 ` Trilok Soni
2026-10-12 18:18 ` Kishore Batta [this message]
2026-10-12 18:18 ` [PATCH v8 4/7] bus: mhi: Add QDU100 Sahara variant and firmware fallback Kishore Batta
2026-10-12 18:18 ` [PATCH v8 5/7] bus: mhi: Load DDR training data using device serial number Kishore Batta
2026-10-12 18:18 ` [PATCH v8 6/7] bus: mhi: Capture DDR training data via command mode Kishore Batta
2026-10-12 18:18 ` [PATCH v8 7/7] bus: mhi: Expose DDR training data via controller sysfs Kishore Batta
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20261012-sahara_protocol_new_v2-v8-3-e12939d229a1@oss.qualcomm.com \
--to=kishore.batta@oss.qualcomm.com \
--cc=carl.vanderlip@oss.qualcomm.com \
--cc=corbet@lwn.net \
--cc=dri-devel@lists.freedesktop.org \
--cc=jeff.hugo@oss.qualcomm.com \
--cc=linux-arm-msm@vger.kernel.org \
--cc=linux-doc@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=mani@kernel.org \
--cc=mhi@lists.linux.dev \
--cc=ogabbay@kernel.org \
--cc=rdunlap@infradead.org \
--cc=skhan@linuxfoundation.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®