[DONOTMERGE] [NOTEVENRFC] [PATCH 01/11] bus: mhi: host: add QRTR endpoint ID to mhi_device
Mihai Moldovan
ionic at ionic.de
Mon Nov 4 23:06:15 PST 2024
We need a way to communicate between QMI clients (e.g., ath11k and
ath12k) and QRTR internals.
Unfortunately, clients are on the "wrong" side of a socket and cannot
really extract QRTR data easily, and, to make matters worse, not at all
until the socket is properly connected. Further complicating the matter
is that multiple clients can be connected to the same server socket, so
even if we would add additional control message support for fetching the
data we are interested in, there is no way for the QRTR system to know
what endpoint ID the client is actually interested in.
However, MHI and its data is a central place that essentially connects
both sides. Both the QRTR subsystem and QMI clients have access to MHI
devices, so we will employ a really ugly IPC scheme in which QRTR will
write the endpoint ID associated with an MHI (controller) device to
mhi_dev->mhi_cntrl->mhi_dev->qrtr_endpoint_id once the endpoint ID
initialization has happened for a specific MHI device, and clients can
then fetch this data at a later time by also going through
mhi_dev->mhi_cntrl->mhi_dev->qrtr_endpoint_id.
This is incredibly ugly. It also certainly is not the correct way to do
this. It is also racy, because clients need to fetch the QRTR endpoint
ID after QRTR has actually initialized it, or they will just see a value
of zero (which is an illegal endpoint ID, so at least we have some sort
of guard for this uglyness).
I just was not able to come up with any other idea that would actually
work.
Signed-off-by: Mihai Moldovan <ionic at ionic.de>
Depends-on: 25a7151cdc98 ("net: qrtr: ns: support multiple endpoints")
Link: https://patch.msgid.link/20241018181842.1368394-1-denkenz@gmail.com
---
drivers/bus/mhi/host/init.c | 1 +
drivers/bus/mhi/host/main.c | 64 +++++++++++++++++++++++++++++++++++++
include/linux/mhi.h | 20 ++++++++++++
3 files changed, 85 insertions(+)
diff --git a/drivers/bus/mhi/host/init.c b/drivers/bus/mhi/host/init.c
index a9b1f8beee7b..b35e722b0802 100644
--- a/drivers/bus/mhi/host/init.c
+++ b/drivers/bus/mhi/host/init.c
@@ -1262,6 +1262,7 @@ struct mhi_device *mhi_alloc_device(struct mhi_controller *mhi_cntrl)
mhi_dev->mhi_cntrl = mhi_cntrl;
mhi_dev->dev_wake = 0;
+ mhi_dev->qrtr_endpoint_id = 0;
return mhi_dev;
}
diff --git a/drivers/bus/mhi/host/main.c b/drivers/bus/mhi/host/main.c
index 4de75674f193..c774e941fbb7 100644
--- a/drivers/bus/mhi/host/main.c
+++ b/drivers/bus/mhi/host/main.c
@@ -1707,3 +1707,67 @@ int mhi_get_channel_doorbell_offset(struct mhi_controller *mhi_cntrl, u32 *chdb_
return 0;
}
EXPORT_SYMBOL_GPL(mhi_get_channel_doorbell_offset);
+
+
+int mhi_set_qrtr_endpoint_id(struct mhi_device *mhi_dev, u32 qrtr_endpoint_id)
+{
+ struct mhi_controller *mhi_cntrl = NULL;
+ struct mhi_device *mhi_cntrl_dev = NULL;
+ struct device *dev = NULL;
+
+ if (!mhi_dev)
+ return -ENODEV;
+
+ mhi_cntrl = mhi_dev->mhi_cntrl;
+
+ if (!mhi_cntrl)
+ return -ENODEV;
+
+ mhi_cntrl_dev = mhi_cntrl->mhi_dev;
+
+ if (!mhi_cntrl_dev)
+ return -ENODEV;
+
+ dev = &mhi_cntrl_dev->dev;
+
+ if (dev)
+ dev_dbg(dev, "setting qrtr_endpoint_id = %u for mhi_dev->mhi_cntrl->mhi_dev = %p", qrtr_endpoint_id, mhi_cntrl_dev);
+
+ mhi_cntrl_dev->qrtr_endpoint_id = qrtr_endpoint_id;
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(mhi_set_qrtr_endpoint_id);
+
+int mhi_get_qrtr_endpoint_id(struct mhi_device *mhi_dev, u32 *qrtr_endpoint_id)
+{
+ struct mhi_controller *mhi_cntrl = NULL;
+ struct mhi_device *mhi_cntrl_dev = NULL;
+ struct device *dev = NULL;
+
+ if (!qrtr_endpoint_id)
+ return -EINVAL;
+
+ if (!mhi_dev)
+ return -ENODEV;
+
+ mhi_cntrl = mhi_dev->mhi_cntrl;
+
+ if (!mhi_cntrl)
+ return -ENODEV;
+
+ mhi_cntrl_dev = mhi_cntrl->mhi_dev;
+
+ if (!mhi_cntrl_dev)
+ return -ENODEV;
+
+ WRITE_ONCE(*qrtr_endpoint_id, mhi_cntrl_dev->qrtr_endpoint_id);
+
+ dev = &mhi_cntrl_dev->dev;
+
+ if (dev)
+ dev_dbg(dev, "queried qrtr_endpoint_id = %u for mhi_dev->mhi_ctrl->mhi_dev = %p", *qrtr_endpoint_id, mhi_cntrl_dev);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(mhi_get_qrtr_endpoint_id);
diff --git a/include/linux/mhi.h b/include/linux/mhi.h
index 059dc94d20bb..2262be3ee5b1 100644
--- a/include/linux/mhi.h
+++ b/include/linux/mhi.h
@@ -462,6 +462,7 @@ struct mhi_controller {
* @ul_chan_id: MHI channel id for UL transfer
* @dl_chan_id: MHI channel id for DL transfer
* @dev_wake: Device wakeup counter
+ * @qrtr_endpoint_id: endpoint ID associated with QRTR
*/
struct mhi_device {
const struct mhi_device_id *id;
@@ -474,6 +475,7 @@ struct mhi_device {
int ul_chan_id;
int dl_chan_id;
u32 dev_wake;
+ u32 qrtr_endpoint_id;
};
/**
@@ -827,4 +829,22 @@ bool mhi_queue_is_full(struct mhi_device *mhi_dev, enum dma_data_direction dir);
*/
int mhi_get_channel_doorbell_offset(struct mhi_controller *mhi_cntrl, u32 *chdb_offset);
+/**
+ * mhi_set_qrtr_endpoint_id - Sets supplied QRTR endpoint ID
+ * @mhi_dev: Device to set the QRTR endpoint ID for
+ * @qrtr_endpoint_id: ID to set
+ *
+ * Return: 0 if setting data succeeded, a negative error code otherwise
+ */
+int mhi_set_qrtr_endpoint_id(struct mhi_device *mhi_dev, u32 qrtr_endpoint_id);
+
+/**
+ * mhi_get_qrtr_endpoint_id - Gets QRTR endpoint ID for specified MHI device
+ * @mhi_dev: Device to get the QRTR endpoint ID for
+ * @qrtr_endpoint_id: pointer to save the QRTR endpoint ID to
+ *
+ * Return: 0 if fetching data succeeded, a negative error code otherwise
+ */
+int mhi_get_qrtr_endpoint_id(struct mhi_device *mhi_dev, u32 *qrtr_endpoint_id);
+
#endif /* _MHI_H_ */
--
2.45.2
More information about the ath11k
mailing list