[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