[PATCH v3 02/12] bus: mhi: allow mhi to know about its qrtr endpoint id and free it
Juha-Matti Tilli
juha-matti.tilli at iki.fi
Tue Sep 8 02:31:35 PDT 2026
It is slightly less than ideal to have MHI know about its QRTR endpoint
id, since MHI can be compiled in without QRTR. However, since many users
of MHI use QRTR, I was bold enough to edit the MHI controller data
structure. The only alternative to this editing is to have a hash table
or worse, an O(N) lookup list inside QRTR to turn MHI controller data
pointer to QRTR endpoint id. However, even in that case the QRTR
endpoint id needs to be freed when the MHI controller is freed, so it is
impossible to do this in a non-leaky way without editing MHI controller.
It's a good question whether the QRTR endpoint it should be stored to
mhi_controller or mhi_device. In most cases, it shouldn't matter, as two
PCIe ath11k/ath12k cards have two mhi_controllers. So, I followed the
original idea by Mihai Moldovan that mhi_controller has 1:1 relationship
to QRTR endpoint.
MHI controller needs a function pointer to actually free the QRTR
endpoint id, since MHI can be compiled in without QRTR, so the freeing
has to happen externally.
Signed-off-by: Juha-Matti Tilli <juha-matti.tilli at iki.fi>
---
drivers/bus/mhi/host/init.c | 8 ++++++++
include/linux/mhi.h | 5 +++++
2 files changed, 13 insertions(+)
diff --git a/drivers/bus/mhi/host/init.c b/drivers/bus/mhi/host/init.c
index fd3050889412d..d96b099432640 100644
--- a/drivers/bus/mhi/host/init.c
+++ b/drivers/bus/mhi/host/init.c
@@ -947,6 +947,9 @@ int mhi_register_controller(struct mhi_controller *mhi_cntrl,
rwlock_init(&mhi_cntrl->pm_lock);
spin_lock_init(&mhi_cntrl->transition_lock);
spin_lock_init(&mhi_cntrl->wlock);
+ spin_lock_init(&mhi_cntrl->qrtr_endpoint_lock);
+ mhi_cntrl->qrtr_endpoint_id = 0;
+ mhi_cntrl->free_qrtr_endpoint_id = NULL;
INIT_WORK(&mhi_cntrl->st_worker, mhi_pm_st_worker);
init_waitqueue_head(&mhi_cntrl->state_event);
@@ -1087,6 +1090,11 @@ void mhi_unregister_controller(struct mhi_controller *mhi_cntrl)
put_device(&mhi_dev->dev);
ida_free(&mhi_controller_ida, mhi_cntrl->index);
+
+ spin_lock(&mhi_cntrl->qrtr_endpoint_lock);
+ if (mhi_cntrl->free_qrtr_endpoint_id)
+ mhi_cntrl->free_qrtr_endpoint_id(mhi_cntrl);
+ spin_unlock(&mhi_cntrl->qrtr_endpoint_lock);
}
EXPORT_SYMBOL_GPL(mhi_unregister_controller);
diff --git a/include/linux/mhi.h b/include/linux/mhi.h
index 8616bacd8675d..d6d5c93e41cb0 100644
--- a/include/linux/mhi.h
+++ b/include/linux/mhi.h
@@ -361,6 +361,7 @@ struct mhi_controller_config {
* @st_worker: State transition worker
* @hiprio_wq: High priority workqueue for MHI work such as state transitions
* @state_event: State change event
+ * @qrtr_endpoint_id: The QRTR endpoint id associated with this MHI controller
* @status_cb: CB function to notify power states of the device (required)
* @wake_get: CB function to assert device wake (optional)
* @wake_put: CB function to de-assert device wake (optional)
@@ -373,6 +374,7 @@ struct mhi_controller_config {
* @write_reg: Write a MHI register via the physical link (required)
* @reset: Controller specific reset function (optional)
* @edl_trigger: CB function to trigger EDL mode (optional)
+ * @free_qrtr_endpoint_id: Function to free the QRTR endpoint id
* @buffer_len: Bounce buffer length
* @index: Index of the MHI controller instance
* @bounce_buf: Use of bounce buffer
@@ -440,6 +442,8 @@ struct mhi_controller {
struct work_struct st_worker;
struct workqueue_struct *hiprio_wq;
wait_queue_head_t state_event;
+ u32 qrtr_endpoint_id;
+ spinlock_t qrtr_endpoint_lock;
void (*status_cb)(struct mhi_controller *mhi_cntrl,
enum mhi_callback cb);
@@ -458,6 +462,7 @@ struct mhi_controller {
u32 val);
void (*reset)(struct mhi_controller *mhi_cntrl);
int (*edl_trigger)(struct mhi_controller *mhi_cntrl);
+ void (*free_qrtr_endpoint_id)(void *mhi_cntrl_void);
size_t buffer_len;
int index;
--
2.34.1
More information about the ath12k
mailing list