From 4813317b908a0774092a968d5236d0321a82a0cc Mon Sep 17 00:00:00 2001 From: Sandeep Singh Date: Thu, 3 Sep 2020 10:44:14 -0700 Subject: [PATCH] cnss2: Setup DMS QMI client for WLAN MAC address WLAN MAC address can be provisioned using NV memory based setup. DMS QMI server connection is required to retrieve this MAC address. Thus setup DMS QMI client in cnss platform driver and send this MAC address for WLAN FW before mission mode enable. Change-Id: I4dac4c589910a34952b0f63fd4394f5dd02315b8 Signed-off-by: Sandeep Singh Signed-off-by: Manikandan Mohan --- drivers/net/wireless/cnss2/Makefile | 2 +- drivers/net/wireless/cnss2/debug.c | 3 + .../cnss2/device_management_service_v01.c | 73 +++++ .../cnss2/device_management_service_v01.h | 39 +++ drivers/net/wireless/cnss2/main.c | 54 +++- drivers/net/wireless/cnss2/main.h | 10 + drivers/net/wireless/cnss2/qmi.c | 280 ++++++++++++------ drivers/net/wireless/cnss2/qmi.h | 36 +++ 8 files changed, 406 insertions(+), 91 deletions(-) create mode 100644 drivers/net/wireless/cnss2/device_management_service_v01.c create mode 100644 drivers/net/wireless/cnss2/device_management_service_v01.h diff --git a/drivers/net/wireless/cnss2/Makefile b/drivers/net/wireless/cnss2/Makefile index c6d55eed00c6..023dd437adec 100644 --- a/drivers/net/wireless/cnss2/Makefile +++ b/drivers/net/wireless/cnss2/Makefile @@ -8,4 +8,4 @@ cnss2-y += debug.o cnss2-y += pci.o cnss2-y += power.o cnss2-y += genl.o -cnss2-$(CONFIG_CNSS2_QMI) += qmi.o wlan_firmware_service_v01.o coexistence_service_v01.o ip_multimedia_subsystem_private_service_v01.o +cnss2-$(CONFIG_CNSS2_QMI) += qmi.o wlan_firmware_service_v01.o coexistence_service_v01.o ip_multimedia_subsystem_private_service_v01.o device_management_service_v01.o diff --git a/drivers/net/wireless/cnss2/debug.c b/drivers/net/wireless/cnss2/debug.c index 5556b95d8e82..92311383c04c 100644 --- a/drivers/net/wireless/cnss2/debug.c +++ b/drivers/net/wireless/cnss2/debug.c @@ -121,6 +121,9 @@ static int cnss_stats_show_state(struct seq_file *s, case CNSS_QMI_DEL_SERVER: seq_puts(s, "DEL_SERVER_IN_PROGRESS"); continue; + case CNSS_QMI_DMS_CONNECTED: + seq_puts(s, "DMS_CONNECTED"); + continue; } seq_printf(s, "UNKNOWN-%d", i); diff --git a/drivers/net/wireless/cnss2/device_management_service_v01.c b/drivers/net/wireless/cnss2/device_management_service_v01.c new file mode 100644 index 000000000000..a714d64239a5 --- /dev/null +++ b/drivers/net/wireless/cnss2/device_management_service_v01.c @@ -0,0 +1,73 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* Copyright (c) 2020, The Linux Foundation. All rights reserved. */ + +#include + +#include "device_management_service_v01.h" + +struct qmi_elem_info dms_get_mac_address_req_msg_v01_ei[] = { + { + .data_type = QMI_SIGNED_4_BYTE_ENUM, + .elem_len = 1, + .elem_size = sizeof(enum dms_device_mac_enum_v01), + .array_type = NO_ARRAY, + .tlv_type = 0x01, + .offset = offsetof(struct + dms_get_mac_address_req_msg_v01, + device), + }, + { + .data_type = QMI_EOTI, + .array_type = NO_ARRAY, + .tlv_type = QMI_COMMON_TLV_TYPE, + }, +}; + +struct qmi_elem_info dms_get_mac_address_resp_msg_v01_ei[] = { + { + .data_type = QMI_STRUCT, + .elem_len = 1, + .elem_size = sizeof(struct qmi_response_type_v01), + .array_type = NO_ARRAY, + .tlv_type = 0x02, + .offset = offsetof(struct + dms_get_mac_address_resp_msg_v01, + resp), + .ei_array = qmi_response_type_v01_ei, + }, + { + .data_type = QMI_OPT_FLAG, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x10, + .offset = offsetof(struct + dms_get_mac_address_resp_msg_v01, + mac_address_valid), + }, + { + .data_type = QMI_DATA_LEN, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x10, + .offset = offsetof(struct + dms_get_mac_address_resp_msg_v01, + mac_address_len), + }, + { + .data_type = QMI_UNSIGNED_1_BYTE, + .elem_len = QMI_DMS_MAC_ADDR_MAX_V01, + .elem_size = sizeof(u8), + .array_type = VAR_LEN_ARRAY, + .tlv_type = 0x10, + .offset = offsetof(struct + dms_get_mac_address_resp_msg_v01, + mac_address), + }, + { + .data_type = QMI_EOTI, + .array_type = NO_ARRAY, + .tlv_type = QMI_COMMON_TLV_TYPE, + }, +}; diff --git a/drivers/net/wireless/cnss2/device_management_service_v01.h b/drivers/net/wireless/cnss2/device_management_service_v01.h new file mode 100644 index 000000000000..ba0a40402f8c --- /dev/null +++ b/drivers/net/wireless/cnss2/device_management_service_v01.h @@ -0,0 +1,39 @@ +/* SPDX-License-Identifier: GPL-2.0-only + * Copyright (c) 2020, The Linux Foundation. All rights reserved. + */ + +#ifndef DEVICE_MANAGEMENT_SERVICE_V01_H +#define DEVICE_MANAGEMENT_SERVICE_V01_H + +#define DMS_SERVICE_ID_V01 0x02 +#define DMS_SERVICE_VERS_V01 0x01 + +#define QMI_DMS_GET_MAC_ADDRESS_RESP_V01 0x005C +#define QMI_DMS_GET_MAC_ADDRESS_REQ_V01 0x005C +#define QMI_DMS_MAC_ADDR_MAX_V01 8 + +enum dms_device_mac_enum_v01 { + DMS_DEVICE_MAC_ENUM_MIN_VAL_V01 = INT_MIN, + DMS_DEVICE_MAC_WLAN_V01 = 0, + DMS_DEVICE_MAC_BT_V01 = 1, + DMS_DEVICE_MAC_ENUM_MAX_VAL_V01 = INT_MAX, +}; + +struct dms_get_mac_address_req_msg_v01 { + enum dms_device_mac_enum_v01 device; +}; + +#define DMS_GET_MAC_ADDRESS_REQ_MSG_V01_MAX_MSG_LEN 7 +extern struct qmi_elem_info dms_get_mac_address_req_msg_v01_ei[]; + +struct dms_get_mac_address_resp_msg_v01 { + struct qmi_response_type_v01 resp; + u8 mac_address_valid; + u32 mac_address_len; + u8 mac_address[QMI_DMS_MAC_ADDR_MAX_V01]; +}; + +#define DMS_GET_MAC_ADDRESS_RESP_MSG_V01_MAX_MSG_LEN 19 +extern struct qmi_elem_info dms_get_mac_address_resp_msg_v01_ei[]; + +#endif diff --git a/drivers/net/wireless/cnss2/main.c b/drivers/net/wireless/cnss2/main.c index 029a6cd09dfe..b66c47313718 100644 --- a/drivers/net/wireless/cnss2/main.c +++ b/drivers/net/wireless/cnss2/main.c @@ -405,6 +405,40 @@ static void cnss_release_antenna_sharing(struct cnss_plat_data *plat_priv) coex_antenna_switch_to_mdm_send_sync_msg(plat_priv); } +#define CNSS_DMS_QMI_CONNECTION_WAIT_MS 50 +#define CNSS_DMS_QMI_CONNECTION_WAIT_RETRY 200 +static int cnss_setup_dms_mac(struct cnss_plat_data *plat_priv) +{ + u32 i; + int ret = 0; + + /* DTSI property use-nv-mac is used to force DMS MAC address for WLAN. + * Thus assert on failure to get MAC from DMS even after retries + */ + if (plat_priv->use_nv_mac) { + for (i = 0; i < CNSS_DMS_QMI_CONNECTION_WAIT_RETRY; i++) { + if (plat_priv->dms.mac_valid) + break; + + ret = cnss_qmi_get_dms_mac(plat_priv); + if (ret == 0) + break; + msleep(CNSS_DMS_QMI_CONNECTION_WAIT_MS); + } + if (!plat_priv->dms.mac_valid) { + cnss_pr_err("Unable to get MAC from DMS\n"); + CNSS_ASSERT(0); + return -EINVAL; + } + } + if (plat_priv->dms.mac_valid) + ret = + cnss_wlfw_wlan_mac_req_send_sync(plat_priv, plat_priv->dms.mac, + ARRAY_SIZE(plat_priv->dms.mac)); + + return ret; +} + static int cnss_fw_ready_hdlr(struct cnss_plat_data *plat_priv) { int ret = 0; @@ -432,6 +466,7 @@ static int cnss_fw_ready_hdlr(struct cnss_plat_data *plat_priv) ret = cnss_wlfw_wlan_mode_send_sync(plat_priv, CNSS_CALIBRATION); } else { + ret = cnss_setup_dms_mac(plat_priv); ret = cnss_bus_call_driver_probe(plat_priv); } @@ -493,6 +528,10 @@ static char *cnss_driver_event_to_str(enum cnss_driver_event_type type) return "QDSS_TRACE_SAVE"; case CNSS_DRIVER_EVENT_QDSS_TRACE_FREE: return "QDSS_TRACE_FREE"; + case CNSS_DRIVER_EVENT_DMS_SERVER_ARRIVE: + return "DMS_SERVER_ARRIVE"; + case CNSS_DRIVER_EVENT_DMS_SERVER_EXIT: + return "DMS_SERVER_EXIT"; case CNSS_DRIVER_EVENT_MAX: return "EVENT_MAX"; } @@ -1637,6 +1676,12 @@ static void cnss_driver_event_work(struct work_struct *work) case CNSS_DRIVER_EVENT_QDSS_TRACE_FREE: ret = cnss_qdss_trace_free_hdlr(plat_priv); break; + case CNSS_DRIVER_EVENT_DMS_SERVER_ARRIVE: + ret = cnss_dms_server_arrive(plat_priv, event->data); + break; + case CNSS_DRIVER_EVENT_DMS_SERVER_EXIT: + ret = cnss_dms_server_exit(plat_priv); + break; default: cnss_pr_err("Invalid driver event type: %d", event->type); @@ -2767,10 +2812,14 @@ static int cnss_probe(struct platform_device *plat_dev) if (ret) goto deinit_event_work; - ret = cnss_debugfs_create(plat_priv); + ret = cnss_dms_init(plat_priv); if (ret) goto deinit_qmi; + ret = cnss_debugfs_create(plat_priv); + if (ret) + goto deinit_dms; + ret = cnss_misc_init(plat_priv); if (ret) goto destroy_debugfs; @@ -2788,6 +2837,8 @@ static int cnss_probe(struct platform_device *plat_dev) destroy_debugfs: cnss_debugfs_destroy(plat_priv); +deinit_dms: + cnss_dms_deinit(plat_priv); deinit_qmi: cnss_qmi_deinit(plat_priv); deinit_event_work: @@ -2823,6 +2874,7 @@ static int cnss_remove(struct platform_device *plat_dev) cnss_misc_deinit(plat_priv); cnss_debugfs_destroy(plat_priv); cnss_qmi_deinit(plat_priv); + cnss_dms_deinit(plat_priv); cnss_event_work_deinit(plat_priv); cnss_remove_sysfs(plat_priv); cnss_unregister_bus_scale(plat_priv); diff --git a/drivers/net/wireless/cnss2/main.h b/drivers/net/wireless/cnss2/main.h index c58161caae33..224aaac73699 100644 --- a/drivers/net/wireless/cnss2/main.h +++ b/drivers/net/wireless/cnss2/main.h @@ -258,6 +258,8 @@ enum cnss_driver_event_type { CNSS_DRIVER_EVENT_QDSS_TRACE_REQ_MEM, CNSS_DRIVER_EVENT_QDSS_TRACE_SAVE, CNSS_DRIVER_EVENT_QDSS_TRACE_FREE, + CNSS_DRIVER_EVENT_DMS_SERVER_ARRIVE, + CNSS_DRIVER_EVENT_DMS_SERVER_EXIT, CNSS_DRIVER_EVENT_MAX, }; @@ -282,6 +284,7 @@ enum cnss_driver_state { CNSS_COLD_BOOT_CAL_DONE, CNSS_IN_PANIC, CNSS_QMI_DEL_SERVER, + CNSS_QMI_DMS_CONNECTED = 20, }; struct cnss_recovery_data { @@ -376,6 +379,11 @@ enum cnss_ce_index { CNSS_CE_COMMON, }; +struct cnss_dms_data { + u32 mac_valid; + u8 mac[QMI_WLFW_MAC_ADDR_SIZE_V01]; +}; + struct cnss_plat_data { struct platform_device *plat_dev; void *bus_priv; @@ -409,6 +417,7 @@ struct cnss_plat_data { struct workqueue_struct *event_wq; struct work_struct recovery_work; struct qmi_handle qmi_wlfw; + struct qmi_handle qmi_dms; struct wlfw_rf_chip_info chip_info; struct wlfw_rf_board_info board_info; struct wlfw_soc_info soc_info; @@ -458,6 +467,7 @@ struct cnss_plat_data { struct cnss_tcs_info tcs_info; bool fw_pcie_gen_switch; u8 pcie_gen_speed; + struct cnss_dms_data dms; }; #ifdef CONFIG_ARCH_QCOM diff --git a/drivers/net/wireless/cnss2/qmi.c b/drivers/net/wireless/cnss2/qmi.c index 13e10f3b8f73..323a9bdf65bc 100644 --- a/drivers/net/wireless/cnss2/qmi.c +++ b/drivers/net/wireless/cnss2/qmi.c @@ -27,6 +27,7 @@ #define QMI_WLFW_MAX_RECV_BUF_SIZE SZ_8K #define IMSPRIVATE_SERVICE_MAX_MSG_LEN SZ_8K +#define DMS_QMI_MAX_MSG_LEN SZ_256 #define QMI_WLFW_MAC_READY_TIMEOUT_MS 50 #define QMI_WLFW_MAC_READY_MAX_RETRY 200 @@ -752,35 +753,19 @@ out: return ret; } -static int cnss_wlfw_wlan_mac_req_send_sync(struct cnss_plat_data *plat_priv, - u8 *mac, u32 mac_len) +int cnss_wlfw_wlan_mac_req_send_sync(struct cnss_plat_data *plat_priv, + u8 *mac, u32 mac_len) { - struct wlfw_mac_addr_req_msg_v01 *req; - struct wlfw_mac_addr_resp_msg_v01 *resp; + struct wlfw_mac_addr_req_msg_v01 req; + struct wlfw_mac_addr_resp_msg_v01 resp = {0}; struct qmi_txn txn; int ret; - u8 is_query; - if (!plat_priv) - return -ENODEV; - - /* NULL mac && zero mac_len means querying the status of MAC in FW */ - if ((mac && mac_len != QMI_WLFW_MAC_ADDR_SIZE_V01) || - (!mac && mac_len != 0)) + if (!plat_priv || !mac || mac_len != QMI_WLFW_MAC_ADDR_SIZE_V01) return -EINVAL; - req = kzalloc(sizeof(*req), GFP_KERNEL); - if (!req) - return -ENOMEM; - - resp = kzalloc(sizeof(*resp), GFP_KERNEL); - if (!resp) { - kfree(req); - return -ENOMEM; - } - ret = qmi_txn_init(&plat_priv->qmi_wlfw, &txn, - wlfw_mac_addr_resp_msg_v01_ei, resp); + wlfw_mac_addr_resp_msg_v01_ei, &resp); if (ret < 0) { cnss_pr_err("Failed to initialize txn for mac req, err: %d\n", ret); @@ -788,25 +773,18 @@ static int cnss_wlfw_wlan_mac_req_send_sync(struct cnss_plat_data *plat_priv, goto out; } - is_query = !mac; - if (!is_query) { - /* DO NOT print this for mac query, that might be too many */ cnss_pr_dbg("Sending WLAN mac req [%pM], state: 0x%lx\n", mac, plat_priv->driver_state); - memcpy(req->mac_addr, mac, mac_len); - - /* 0 - query status of wlfw MAC; 1 - set wlfw MAC */ - req->mac_addr_valid = 1; - } + memcpy(req.mac_addr, mac, mac_len); + req.mac_addr_valid = 1; ret = qmi_send_request(&plat_priv->qmi_wlfw, NULL, &txn, QMI_WLFW_MAC_ADDR_REQ_V01, WLFW_MAC_ADDR_REQ_MSG_V01_MAX_MSG_LEN, - wlfw_mac_addr_req_msg_v01_ei, req); + wlfw_mac_addr_req_msg_v01_ei, &req); if (ret < 0) { qmi_txn_cancel(&txn); cnss_pr_err("Failed to send mac req, err: %d\n", ret); - ret = -EIO; goto out; } @@ -815,68 +793,19 @@ static int cnss_wlfw_wlan_mac_req_send_sync(struct cnss_plat_data *plat_priv, if (ret < 0) { cnss_pr_err("Failed to wait for resp of mac req, err: %d\n", ret); - ret = -EIO; goto out; } - if (resp->resp.result != QMI_RESULT_SUCCESS_V01) { + if (resp.resp.result != QMI_RESULT_SUCCESS_V01) { cnss_pr_err("WLAN mac req failed, result: %d, err: %d\n", - resp->resp.result); - - ret = -EIO; - goto out; + resp.resp.result); + ret = -resp.resp.result; } - - if (resp->resp.error != QMI_ERR_NONE_V01) { - ret = ((resp->resp.error == QMI_ERR_NETWORK_NOT_READY_V01 && - is_query) ? -EAGAIN : -EIO); - if (ret != -EAGAIN) - cnss_pr_err("Got error resp for mac req, err: %d\n", - resp->resp.error); - goto out; - } - - cnss_pr_dbg("WLAN mac req completed\n"); - out: - kfree(req); - kfree(resp); return ret; } -static void cnss_wait_for_wlfw_mac_ready(struct cnss_plat_data *plat_priv) -{ - int ret, retry = 0; - - if (!plat_priv) - return; - - cnss_pr_dbg("Checking wlfw mac, state: 0x%lx\n", - plat_priv->driver_state); - do { - /* query the current status of WLAN MAC */ - ret = cnss_wlfw_wlan_mac_req_send_sync(plat_priv, NULL, 0); - if (!ret) { - cnss_pr_dbg("wlfw mac is ready\n"); - break; - } - - if (ret != -EAGAIN) { - cnss_pr_err("failed to query wlfw mac, error: %d\n", - ret); - break; - } - - if (++retry >= QMI_WLFW_MAC_READY_MAX_RETRY) { - cnss_pr_err("Timeout to wait for wlfw mac ready\n"); - break; - } - - msleep(QMI_WLFW_MAC_READY_TIMEOUT_MS); - } while (true); -} - int cnss_wlfw_wlan_mode_send_sync(struct cnss_plat_data *plat_priv, enum cnss_driver_mode mode) { @@ -888,9 +817,6 @@ int cnss_wlfw_wlan_mode_send_sync(struct cnss_plat_data *plat_priv, if (!plat_priv) return -ENODEV; - if (mode == CNSS_MISSION && plat_priv->use_nv_mac) - cnss_wait_for_wlfw_mac_ready(plat_priv); - cnss_pr_dbg("Sending mode message, mode: %s(%d), state: 0x%lx\n", cnss_qmi_mode_to_str(mode), mode, plat_priv->driver_state); @@ -2467,14 +2393,15 @@ int cnss_qmi_init(struct cnss_plat_data *plat_priv) QMI_WLFW_MAX_RECV_BUF_SIZE, &qmi_wlfw_ops, qmi_wlfw_msg_handlers); if (ret < 0) { - cnss_pr_err("Failed to initialize QMI handle, err: %d\n", ret); + cnss_pr_err("Failed to initialize WLFW QMI handle, err: %d\n", + ret); goto out; } ret = qmi_add_lookup(&plat_priv->qmi_wlfw, WLFW_SERVICE_ID_V01, WLFW_SERVICE_VERS_V01, WLFW_SERVICE_INS_ID_V01); if (ret < 0) - cnss_pr_err("Failed to add QMI lookup, err: %d\n", ret); + cnss_pr_err("Failed to add WLFW QMI lookup, err: %d\n", ret); out: return ret; @@ -2485,6 +2412,181 @@ void cnss_qmi_deinit(struct cnss_plat_data *plat_priv) qmi_handle_release(&plat_priv->qmi_wlfw); } +int cnss_qmi_get_dms_mac(struct cnss_plat_data *plat_priv) +{ + struct dms_get_mac_address_req_msg_v01 req; + struct dms_get_mac_address_resp_msg_v01 resp; + struct qmi_txn txn; + int ret = 0; + + if (!test_bit(CNSS_QMI_DMS_CONNECTED, &plat_priv->driver_state)) { + cnss_pr_err("DMS QMI connection not established\n"); + return -EINVAL; + } + cnss_pr_dbg("Requesting DMS MAC address"); + + memset(&resp, 0, sizeof(resp)); + ret = qmi_txn_init(&plat_priv->qmi_dms, &txn, + dms_get_mac_address_resp_msg_v01_ei, &resp); + if (ret < 0) { + cnss_pr_err("Failed to initialize txn for dms, err: %d\n", + ret); + goto out; + } + req.device = DMS_DEVICE_MAC_WLAN_V01; + ret = qmi_send_request(&plat_priv->qmi_dms, NULL, &txn, + QMI_DMS_GET_MAC_ADDRESS_REQ_V01, + DMS_GET_MAC_ADDRESS_REQ_MSG_V01_MAX_MSG_LEN, + dms_get_mac_address_req_msg_v01_ei, &req); + if (ret < 0) { + qmi_txn_cancel(&txn); + cnss_pr_err("Failed to send QMI_DMS_GET_MAC_ADDRESS_REQ_V01, err: %d\n", + ret); + goto out; + } + ret = qmi_txn_wait(&txn, QMI_WLFW_TIMEOUT_JF); + if (ret < 0) { + cnss_pr_err("Failed to wait for QMI_DMS_GET_MAC_ADDRESS_RESP_V01, err: %d\n", + ret); + goto out; + } + + if (resp.resp.result != QMI_RESULT_SUCCESS_V01) { + cnss_pr_err("QMI_DMS_GET_MAC_ADDRESS_REQ_V01 failed, result: %d, err: %d\n", + resp.resp.result, resp.resp.error); + ret = -resp.resp.result; + goto out; + } + if (!resp.mac_address_valid || + resp.mac_address_len != QMI_WLFW_MAC_ADDR_SIZE_V01) { + cnss_pr_err("Invalid MAC address received from DMS\n"); + plat_priv->dms.mac_valid = false; + goto out; + } + plat_priv->dms.mac_valid = true; + memcpy(plat_priv->dms.mac, resp.mac_address, QMI_WLFW_MAC_ADDR_SIZE_V01); + cnss_pr_info("Received DMS MAC: [%pM]\n", plat_priv->dms.mac); +out: + return ret; +} + +static int cnss_dms_connect_to_server(struct cnss_plat_data *plat_priv, + void *data) +{ + struct cnss_qmi_event_server_arrive_data *event_data = data; + struct qmi_handle *qmi_dms = &plat_priv->qmi_dms; + struct sockaddr_qrtr sq = {0}; + int ret = 0; + + if (!event_data) + return -EINVAL; + + sq.sq_family = AF_QIPCRTR; + sq.sq_node = event_data->node; + sq.sq_port = event_data->port; + kfree(data); + + ret = kernel_connect(qmi_dms->sock, (struct sockaddr *)&sq, + sizeof(sq), 0); + if (ret < 0) { + cnss_pr_err("Failed to connect to QMI DMS remote service port\n"); + goto out; + } + + set_bit(CNSS_QMI_DMS_CONNECTED, &plat_priv->driver_state); + cnss_pr_info("QMI DMS service connected, state: 0x%lx\n", + plat_priv->driver_state); + cnss_qmi_get_dms_mac(plat_priv); +out: + return ret; +} + +int cnss_dms_server_arrive(struct cnss_plat_data *plat_priv, void *data) +{ + int ret = 0; + + if (!plat_priv) { + cnss_pr_err("Platform not initialized on DMS server arrive\n"); + return -ENODEV; + } + ret = cnss_dms_connect_to_server(plat_priv, data); + return ret; +} + +int cnss_dms_server_exit(struct cnss_plat_data *plat_priv) +{ + if (!plat_priv) + return -ENODEV; + + clear_bit(CNSS_QMI_DMS_CONNECTED, &plat_priv->driver_state); + cnss_pr_info("QMI DMS service disconnected, state: 0x%lx\n", + plat_priv->driver_state); + return 0; +} + +static int dms_new_server(struct qmi_handle *qmi_dms, + struct qmi_service *service) +{ + struct cnss_plat_data *plat_priv = + container_of(qmi_dms, struct cnss_plat_data, qmi_dms); + struct cnss_qmi_event_server_arrive_data *event_data; + + cnss_pr_err("DMS server arriving: node %u port %u\n", + service->node, service->port); + + event_data = kzalloc(sizeof(*event_data), GFP_KERNEL); + if (!event_data) + return -ENOMEM; + + event_data->node = service->node; + event_data->port = service->port; + + cnss_driver_event_post(plat_priv, CNSS_DRIVER_EVENT_DMS_SERVER_ARRIVE, + 0, event_data); + + return 0; +} + +static void dms_del_server(struct qmi_handle *qmi_dms, + struct qmi_service *service) +{ + struct cnss_plat_data *plat_priv = + container_of(qmi_dms, struct cnss_plat_data, qmi_dms); + + cnss_pr_dbg("DMS server exiting\n"); + cnss_driver_event_post(plat_priv, CNSS_DRIVER_EVENT_DMS_SERVER_EXIT, 0, + NULL); +} + +static struct qmi_ops qmi_dms_ops = { + .new_server = dms_new_server, + .del_server = dms_del_server, +}; + +int cnss_dms_init(struct cnss_plat_data *plat_priv) +{ + int ret = 0; + + ret = qmi_handle_init(&plat_priv->qmi_dms, DMS_QMI_MAX_MSG_LEN, + &qmi_dms_ops, NULL); + if (ret < 0) { + cnss_pr_err("Failed to initialize DMS handle, err: %d\n", ret); + goto out; + } + + ret = qmi_add_lookup(&plat_priv->qmi_dms, DMS_SERVICE_ID_V01, + DMS_SERVICE_VERS_V01, 0); + if (ret < 0) + cnss_pr_err("Failed to add DMS lookup, err: %d\n", ret); +out: + return ret; +} + +void cnss_dms_deinit(struct cnss_plat_data *plat_priv) +{ + qmi_handle_release(&plat_priv->qmi_dms); +} + int coex_antenna_switch_to_wlan_send_sync_msg(struct cnss_plat_data *plat_priv) { int ret; diff --git a/drivers/net/wireless/cnss2/qmi.h b/drivers/net/wireless/cnss2/qmi.h index 9413a93dac70..0b39ffd8d46f 100644 --- a/drivers/net/wireless/cnss2/qmi.h +++ b/drivers/net/wireless/cnss2/qmi.h @@ -31,6 +31,7 @@ struct cnss_qmi_event_qdss_trace_save_data { #ifdef CONFIG_CNSS2_QMI #include "coexistence_service_v01.h" #include "ip_multimedia_subsystem_private_service_v01.h" +#include "device_management_service_v01.h" int cnss_qmi_init(struct cnss_plat_data *plat_priv); void cnss_qmi_deinit(struct cnss_plat_data *plat_priv); @@ -69,6 +70,13 @@ int cnss_register_ims_service(struct cnss_plat_data *plat_priv); void cnss_unregister_ims_service(struct cnss_plat_data *plat_priv); int cnss_wlfw_send_pcie_gen_speed_sync(struct cnss_plat_data *plat_priv); void cnss_ignore_qmi_failure(bool ignore); +int cnss_qmi_get_dms_mac(struct cnss_plat_data *plat_priv); +int cnss_wlfw_wlan_mac_req_send_sync(struct cnss_plat_data *plat_priv, + u8 *mac, u32 mac_len); +int cnss_dms_server_arrive(struct cnss_plat_data *plat_priv, void *data); +int cnss_dms_server_exit(struct cnss_plat_data *plat_priv); +int cnss_dms_init(struct cnss_plat_data *plat_priv); +void cnss_dms_deinit(struct cnss_plat_data *plat_priv); #else #define QMI_WLFW_TIMEOUT_MS 10000 @@ -222,6 +230,34 @@ void cnss_unregister_ims_service(struct cnss_plat_data *plat_priv) {} static inline int cnss_wlfw_send_pcie_gen_speed_sync(struct cnss_plat_data *plat_priv) {} void cnss_ignore_qmi_failure(bool ignore) {}; +static inline int cnss_qmi_get_dms_mac(struct cnss_plat_data *plat_priv) +{ + return 0; +} + +int cnss_wlfw_wlan_mac_req_send_sync(struct cnss_plat_data *plat_priv, + u8 *mac, u32 mac_len) +{ + return 0; +} + +static inline +int cnss_dms_server_arrive(struct cnss_plat_data *plat_priv, void *data) +{ + return 0; +} + +static inline int cnss_dms_server_exit(struct cnss_plat_data *plat_priv) +{ + return 0; +} + +static inline int cnss_dms_init(struct cnss_plat_data *plat_priv) +{ + return 0; +} + +static inline void cnss_dms_deinit(struct cnss_plat_data *plat_priv) {} #endif /* CONFIG_CNSS2_QMI */ #endif /* _CNSS_QMI_H */