[DONOTMERGE] [NOTEVENRFC] [PATCH 11/11] wifi: ath12k: bind to QRTR endpoint ID in ath12k_qmi_ops_new_server

Mihai Moldovan ionic at ionic.de
Mon Nov 4 23:06:25 PST 2024


If possible, fetch the QRTR endpoint ID in ath12k_qmi_ops_new_server,
which should be late enough for all initializations to already have
happened, and bind to this endpoint ID if fetching it worked.

This finally allows using multiple ath12k-based cards with the same QRTR
node/port combination to work simultanenous (and, for that matter, at
all), including combinations of ath11k-based and ath12k-based cards.

Caveat: it would be better to actually bind to the correct QRTR endpoint
ID right at socket creation time (i.e., when qmi_handle_init is called).
However, we cannot do this, because the socket creation is the part that
actually kicks off qrtr-mhi probing and initialization.
ath12k_qmi_ops_new_server is "early enough" in that it should work
mostly fine, but obviously, there is a time in which messages for other
endpoints can be coming in as well before we actually bound to the
endpoint ID we are interested in.

Unfortunately, I have no idea how to avoid this and properly get the
QRTR endpoint ID before actually creating the socket.

Signed-off-by: Mihai Moldovan <ionic at ionic.de>
Tested-on: WCN7850 hw2.0 PCI WLAN.HMT.1.0.c5-00481-QCAHMTSWPL_V1.0_V2.0_SILICONZ-3
---
 drivers/net/wireless/ath/ath12k/qmi.c | 49 +++++++++++++++++++++++++++
 drivers/net/wireless/ath/ath12k/qmi.h |  1 +
 2 files changed, 50 insertions(+)

diff --git a/drivers/net/wireless/ath/ath12k/qmi.c b/drivers/net/wireless/ath/ath12k/qmi.c
index d2d9d03c7a28..96bc0a3cb86f 100644
--- a/drivers/net/wireless/ath/ath12k/qmi.c
+++ b/drivers/net/wireless/ath/ath12k/qmi.c
@@ -9,8 +9,10 @@
 #include "qmi.h"
 #include "core.h"
 #include "debug.h"
+#include "hif.h"
 #include <linux/of.h>
 #include <linux/firmware.h>
+#include <net/sock.h>
 
 #define SLEEP_CLOCK_SELECT_INTERNAL_BIT	0x02
 #define HOST_CSTATE_BIT			0x04
@@ -3264,6 +3266,21 @@ static int ath12k_qmi_ops_new_server(struct qmi_handle *qmi_hdl,
 	struct sockaddr_qrtr *sq = &qmi->sq;
 	int ret;
 
+	ret = ath12k_hif_set_qrtr_endpoint_id(ab);
+	if (ret)
+		ath12k_warn(ab, "failed to set QRTR endpoint ID: %d\n", ret);
+	else {
+		ret = ath12k_qmi_bind_endpoint_id(ab);
+
+		if (ret)
+			ath12k_warn(ab, "failed to bind to QRTR endpoint ID: "
+					"%d\n", ret);
+	}
+
+	if (ret)
+		ath12k_warn(ab, "continuing without, but only one device per "
+				"system will be supported\n");
+
 	sq->sq_family = AF_QIPCRTR;
 	sq->sq_node = service->node;
 	sq->sq_port = service->port;
@@ -3414,3 +3431,35 @@ void ath12k_qmi_free_resource(struct ath12k_base *ab)
 	ath12k_qmi_free_target_mem_chunk(ab);
 	ath12k_qmi_m3_free(ab);
 }
+
+int ath12k_qmi_bind_endpoint_id(struct ath12k_base *ab)
+{
+	struct ath12k_qmi *qmi = NULL;
+	struct qmi_handle *handle = NULL;
+	const struct proto_ops *ops = NULL;
+	int ret;
+
+	if (!ab)
+		return -EINVAL;
+
+	qmi = &ab->qmi;
+	handle = &qmi->handle;
+
+	if (!handle->sock)
+		return -ENODEV;
+
+	ops = READ_ONCE(handle->sock->ops);
+
+	if (!ops)
+		return -ENODEV;
+
+	if (!ops->setsockopt)
+		return -ENXIO;
+
+	ath12k_dbg(ab, ATH12K_DBG_QMI, "calling ops->setsockopt...\n");
+	ret = ops->setsockopt(handle->sock, SOL_QRTR, QRTR_BIND_ENDPOINT,
+			      KERNEL_SOCKPTR(&handle->endpoint_id),
+			      sizeof(handle->endpoint_id));
+
+	return ret;
+}
diff --git a/drivers/net/wireless/ath/ath12k/qmi.h b/drivers/net/wireless/ath/ath12k/qmi.h
index 0dfcbd8cb59b..6358f75475cf 100644
--- a/drivers/net/wireless/ath/ath12k/qmi.h
+++ b/drivers/net/wireless/ath/ath12k/qmi.h
@@ -600,5 +600,6 @@ void ath12k_qmi_firmware_stop(struct ath12k_base *ab);
 void ath12k_qmi_deinit_service(struct ath12k_base *ab);
 int ath12k_qmi_init_service(struct ath12k_base *ab);
 void ath12k_qmi_free_resource(struct ath12k_base *ab);
+int ath12k_qmi_bind_endpoint_id(struct ath12k_base *ab);
 
 #endif
-- 
2.45.2




More information about the ath11k mailing list