mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-12 07:37:31 -04:00
Merge "cnss2: Setup DMS QMI client for WLAN MAC address"
This commit is contained in:
commit
8f4bf966d4
8 changed files with 406 additions and 91 deletions
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -122,6 +122,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);
|
||||
|
|
|
|||
73
drivers/net/wireless/cnss2/device_management_service_v01.c
Normal file
73
drivers/net/wireless/cnss2/device_management_service_v01.c
Normal file
|
|
@ -0,0 +1,73 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/* Copyright (c) 2020, The Linux Foundation. All rights reserved. */
|
||||
|
||||
#include <linux/soc/qcom/qmi.h>
|
||||
|
||||
#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,
|
||||
},
|
||||
};
|
||||
39
drivers/net/wireless/cnss2/device_management_service_v01.h
Normal file
39
drivers/net/wireless/cnss2/device_management_service_v01.h
Normal file
|
|
@ -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
|
||||
|
|
@ -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";
|
||||
}
|
||||
|
|
@ -1638,6 +1677,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);
|
||||
|
|
@ -2773,10 +2818,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;
|
||||
|
|
@ -2794,6 +2843,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:
|
||||
|
|
@ -2829,6 +2880,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);
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
|
|
|||
Loading…
Reference in a new issue