[DONOTMERGE] [NOTEVENRFC] [PATCH 08/11] wifi: ath11k: bind to QRTR endpoint ID in ath11k_qmi_ops_new_server

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


If possible, fetch the QRTR endpoint ID in ath11k_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 ath11k-based cards with the same QRTR
node/port combination to work simultanenous (and, for that matter, at
all).

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.
ath11k_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: QCA6390 hw2.0 PCI WLAN.HST.1.0.1-05266-QCAHSTSWPLZ_V2_TO_X86-1
---
 drivers/net/wireless/ath/ath11k/qmi.c | 50 +++++++++++++++++++++++++++
 drivers/net/wireless/ath/ath11k/qmi.h |  1 +
 2 files changed, 51 insertions(+)

diff --git a/drivers/net/wireless/ath/ath11k/qmi.c b/drivers/net/wireless/ath/ath11k/qmi.c
index 7a22483b35cd..4c88e04362bc 100644
--- a/drivers/net/wireless/ath/ath11k/qmi.c
+++ b/drivers/net/wireless/ath/ath11k/qmi.c
@@ -15,6 +15,7 @@
 #include <linux/ioport.h>
 #include <linux/firmware.h>
 #include <linux/of_irq.h>
+#include <net/sock.h>
 
 #define SLEEP_CLOCK_SELECT_INTERNAL_BIT	0x02
 #define HOST_CSTATE_BIT			0x04
@@ -3164,6 +3165,23 @@ static int ath11k_qmi_ops_new_server(struct qmi_handle *qmi_hdl,
 	struct sockaddr_qrtr *sq = &qmi->sq;
 	int ret;
 
+	ret = ath11k_set_qrtr_endpoint_id(ab);
+	if (ret)
+		ath11k_warn(ab, "failed to set QRTR endpoint ID: %d\n", ret);
+	else {
+		ath11k_dbg(ab, ATH11K_DBG_QMI, "trying to bind qrtr endpoint...\n");
+		ret = ath11k_qmi_bind_endpoint_id(ab);
+		ath11k_dbg(ab, ATH11K_DBG_QMI, "bound bind qrtr endpoint...\n");
+
+		if (ret)
+			ath11k_warn(ab, "failed to bind to QRTR endpoint ID: "
+					"%d\n", ret);
+	}
+
+	if (ret)
+		ath11k_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;
@@ -3355,3 +3373,35 @@ void ath11k_qmi_free_resource(struct ath11k_base *ab)
 	ath11k_qmi_free_target_mem_chunk(ab);
 	ath11k_qmi_m3_free(ab);
 }
+
+int ath11k_qmi_bind_endpoint_id(struct ath11k_base *ab)
+{
+	struct ath11k_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;
+
+	ath11k_dbg(ab, ATH11K_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/ath11k/qmi.h b/drivers/net/wireless/ath/ath11k/qmi.h
index 7e06d100af57..35361f844874 100644
--- a/drivers/net/wireless/ath/ath11k/qmi.h
+++ b/drivers/net/wireless/ath/ath11k/qmi.h
@@ -518,5 +518,6 @@ void ath11k_qmi_deinit_service(struct ath11k_base *ab);
 int ath11k_qmi_init_service(struct ath11k_base *ab);
 void ath11k_qmi_free_resource(struct ath11k_base *ab);
 int ath11k_qmi_fwreset_from_cold_boot(struct ath11k_base *ab);
+int ath11k_qmi_bind_endpoint_id(struct ath11k_base *ab);
 
 #endif
-- 
2.45.2




More information about the ath11k mailing list