mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-08 12:58:12 -04:00
Merge "cnss2: Overload QDSS trace save indication for generic mem dump"
This commit is contained in:
commit
92bbd73111
4 changed files with 110 additions and 102 deletions
|
|
@ -533,8 +533,8 @@ static char *cnss_driver_event_to_str(enum cnss_driver_event_type type)
|
|||
return "WLFW_TWC_CFG_IND";
|
||||
case CNSS_DRIVER_EVENT_QDSS_TRACE_REQ_MEM:
|
||||
return "QDSS_TRACE_REQ_MEM";
|
||||
case CNSS_DRIVER_EVENT_QDSS_TRACE_SAVE:
|
||||
return "QDSS_TRACE_SAVE";
|
||||
case CNSS_DRIVER_EVENT_FW_MEM_FILE_SAVE:
|
||||
return "FW_MEM_FILE_SAVE";
|
||||
case CNSS_DRIVER_EVENT_QDSS_TRACE_FREE:
|
||||
return "QDSS_TRACE_FREE";
|
||||
case CNSS_DRIVER_EVENT_MAX:
|
||||
|
|
@ -1504,89 +1504,89 @@ static int cnss_qdss_trace_req_mem_hdlr(struct cnss_plat_data *plat_priv)
|
|||
return cnss_wlfw_qdss_trace_mem_info_send_sync(plat_priv);
|
||||
}
|
||||
|
||||
static void *cnss_qdss_trace_pa_to_va(struct cnss_plat_data *plat_priv,
|
||||
u64 pa, u32 size, int *seg_id)
|
||||
static void *cnss_get_fw_mem_pa_to_va(struct cnss_fw_mem *fw_mem,
|
||||
u32 mem_seg_len, u64 pa, u32 size)
|
||||
{
|
||||
int i = 0;
|
||||
struct cnss_fw_mem *qdss_mem = plat_priv->qdss_mem;
|
||||
u64 offset = 0;
|
||||
void *va = NULL;
|
||||
u64 local_pa;
|
||||
u32 local_size;
|
||||
|
||||
for (i = 0; i < plat_priv->qdss_mem_seg_len; i++) {
|
||||
local_pa = (u64)qdss_mem[i].pa;
|
||||
local_size = (u32)qdss_mem[i].size;
|
||||
for (i = 0; i < mem_seg_len; i++) {
|
||||
local_pa = (u64)fw_mem[i].pa;
|
||||
local_size = (u32)fw_mem[i].size;
|
||||
if (pa == local_pa && size <= local_size) {
|
||||
va = qdss_mem[i].va;
|
||||
va = fw_mem[i].va;
|
||||
break;
|
||||
}
|
||||
if (pa > local_pa &&
|
||||
pa < local_pa + local_size &&
|
||||
pa + size <= local_pa + local_size) {
|
||||
offset = pa - local_pa;
|
||||
va = qdss_mem[i].va + offset;
|
||||
va = fw_mem[i].va + offset;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
*seg_id = i;
|
||||
return va;
|
||||
}
|
||||
|
||||
static int cnss_qdss_trace_save_hdlr(struct cnss_plat_data *plat_priv,
|
||||
void *data)
|
||||
static int cnss_fw_mem_file_save_hdlr(struct cnss_plat_data *plat_priv,
|
||||
void *data)
|
||||
{
|
||||
struct cnss_qmi_event_qdss_trace_save_data *event_data = data;
|
||||
struct cnss_fw_mem *qdss_mem = plat_priv->qdss_mem;
|
||||
int ret = 0;
|
||||
int i;
|
||||
struct cnss_qmi_event_fw_mem_file_save_data *event_data = data;
|
||||
struct cnss_fw_mem *fw_mem_seg;
|
||||
int ret = 0L;
|
||||
void *va = NULL;
|
||||
u64 pa;
|
||||
u32 size;
|
||||
int seg_id = 0;
|
||||
u32 i, fw_mem_seg_len;
|
||||
|
||||
if (!plat_priv->qdss_mem_seg_len) {
|
||||
cnss_pr_err("Memory for QDSS trace is not available\n");
|
||||
return -ENOMEM;
|
||||
switch (event_data->mem_type) {
|
||||
case QMI_WLFW_MEM_TYPE_DDR_V01:
|
||||
if (!plat_priv->fw_mem_seg_len)
|
||||
goto invalid_mem_save;
|
||||
|
||||
fw_mem_seg = plat_priv->fw_mem;
|
||||
fw_mem_seg_len = plat_priv->fw_mem_seg_len;
|
||||
break;
|
||||
case QMI_WLFW_MEM_QDSS_V01:
|
||||
if (!plat_priv->qdss_mem_seg_len)
|
||||
goto invalid_mem_save;
|
||||
|
||||
fw_mem_seg = plat_priv->qdss_mem;
|
||||
fw_mem_seg_len = plat_priv->qdss_mem_seg_len;
|
||||
break;
|
||||
default:
|
||||
goto invalid_mem_save;
|
||||
}
|
||||
|
||||
if (event_data->mem_seg_len == 0) {
|
||||
for (i = 0; i < plat_priv->qdss_mem_seg_len; i++) {
|
||||
ret = cnss_genl_send_msg(qdss_mem[i].va,
|
||||
CNSS_GENL_MSG_TYPE_QDSS,
|
||||
event_data->file_name,
|
||||
qdss_mem[i].size);
|
||||
if (ret < 0) {
|
||||
cnss_pr_err("Fail to save QDSS data: %d\n",
|
||||
ret);
|
||||
break;
|
||||
}
|
||||
for (i = 0; i < event_data->mem_seg_len; i++) {
|
||||
va = cnss_get_fw_mem_pa_to_va(fw_mem_seg, fw_mem_seg_len,
|
||||
event_data->mem_seg[i].addr,
|
||||
event_data->mem_seg[i].size);
|
||||
if (!va) {
|
||||
cnss_pr_err("Fail to find matching va of pa %pa for mem type: %d\n",
|
||||
&event_data->mem_seg[i].addr,
|
||||
event_data->mem_type);
|
||||
ret = -EINVAL;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
for (i = 0; i < event_data->mem_seg_len; i++) {
|
||||
pa = event_data->mem_seg[i].addr;
|
||||
size = event_data->mem_seg[i].size;
|
||||
va = cnss_qdss_trace_pa_to_va(plat_priv, pa,
|
||||
size, &seg_id);
|
||||
if (!va) {
|
||||
cnss_pr_err("Fail to find matching va for pa %pa\n",
|
||||
&pa);
|
||||
ret = -EINVAL;
|
||||
break;
|
||||
}
|
||||
ret = cnss_genl_send_msg(va, CNSS_GENL_MSG_TYPE_QDSS,
|
||||
event_data->file_name, size);
|
||||
if (ret < 0) {
|
||||
cnss_pr_err("Fail to save QDSS data: %d\n",
|
||||
ret);
|
||||
break;
|
||||
}
|
||||
ret = cnss_genl_send_msg(va, CNSS_GENL_MSG_TYPE_QDSS,
|
||||
event_data->file_name,
|
||||
event_data->mem_seg[i].size);
|
||||
if (ret < 0) {
|
||||
cnss_pr_err("Fail to save fw mem data: %d\n",
|
||||
ret);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
kfree(data);
|
||||
return ret;
|
||||
|
||||
invalid_mem_save:
|
||||
cnss_pr_err("FW Mem type %d not allocated. Invalid save request\n",
|
||||
event_data->mem_type);
|
||||
kfree(data);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static int cnss_qdss_trace_free_hdlr(struct cnss_plat_data *plat_priv)
|
||||
|
|
@ -1689,9 +1689,9 @@ static void cnss_driver_event_work(struct work_struct *work)
|
|||
case CNSS_DRIVER_EVENT_QDSS_TRACE_REQ_MEM:
|
||||
ret = cnss_qdss_trace_req_mem_hdlr(plat_priv);
|
||||
break;
|
||||
case CNSS_DRIVER_EVENT_QDSS_TRACE_SAVE:
|
||||
ret = cnss_qdss_trace_save_hdlr(plat_priv,
|
||||
event->data);
|
||||
case CNSS_DRIVER_EVENT_FW_MEM_FILE_SAVE:
|
||||
ret = cnss_fw_mem_file_save_hdlr(plat_priv,
|
||||
event->data);
|
||||
break;
|
||||
case CNSS_DRIVER_EVENT_QDSS_TRACE_FREE:
|
||||
ret = cnss_qdss_trace_free_hdlr(plat_priv);
|
||||
|
|
|
|||
|
|
@ -259,7 +259,7 @@ enum cnss_driver_event_type {
|
|||
CNSS_DRIVER_EVENT_IMS_WFC_CALL_IND,
|
||||
CNSS_DRIVER_EVENT_WLFW_TWT_CFG_IND,
|
||||
CNSS_DRIVER_EVENT_QDSS_TRACE_REQ_MEM,
|
||||
CNSS_DRIVER_EVENT_QDSS_TRACE_SAVE,
|
||||
CNSS_DRIVER_EVENT_FW_MEM_FILE_SAVE,
|
||||
CNSS_DRIVER_EVENT_QDSS_TRACE_FREE,
|
||||
CNSS_DRIVER_EVENT_MAX,
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1919,63 +1919,73 @@ static void cnss_wlfw_qdss_trace_req_mem_ind_cb(struct qmi_handle *qmi_wlfw,
|
|||
0, NULL);
|
||||
}
|
||||
|
||||
static void cnss_wlfw_qdss_trace_save_ind_cb(struct qmi_handle *qmi_wlfw,
|
||||
struct sockaddr_qrtr *sq,
|
||||
struct qmi_txn *txn,
|
||||
const void *data)
|
||||
/**
|
||||
* cnss_wlfw_fw_mem_file_save_ind_cb: Save given FW mem to filesystem
|
||||
*
|
||||
* QDSS_TRACE_SAVE_IND feature is overloaded to provide any host allocated
|
||||
* fw memory segment for dumping to file system. Only one type of mem can be
|
||||
* saved per indication and is provided in mem seg index 0.
|
||||
*
|
||||
* Return: None
|
||||
*/
|
||||
static void cnss_wlfw_fw_mem_file_save_ind_cb(struct qmi_handle *qmi_wlfw,
|
||||
struct sockaddr_qrtr *sq,
|
||||
struct qmi_txn *txn,
|
||||
const void *data)
|
||||
{
|
||||
struct cnss_plat_data *plat_priv =
|
||||
container_of(qmi_wlfw, struct cnss_plat_data, qmi_wlfw);
|
||||
const struct wlfw_qdss_trace_save_ind_msg_v01 *ind_msg = data;
|
||||
struct cnss_qmi_event_qdss_trace_save_data *event_data;
|
||||
struct cnss_qmi_event_fw_mem_file_save_data *event_data;
|
||||
int i = 0;
|
||||
|
||||
cnss_pr_dbg("Received QMI WLFW QDSS trace save indication\n");
|
||||
|
||||
if (!txn) {
|
||||
if (!txn || !data) {
|
||||
cnss_pr_err("Spurious indication\n");
|
||||
return;
|
||||
}
|
||||
|
||||
cnss_pr_dbg("QDSS_trace_save info: source %u, total_size %u, file_name_valid %u, file_name %s\n",
|
||||
ind_msg->source, ind_msg->total_size,
|
||||
ind_msg->file_name_valid, ind_msg->file_name);
|
||||
|
||||
if (ind_msg->source == 1)
|
||||
cnss_pr_dbg("QMI fw_mem_file_save: source: %d mem_seg: %d type: %u len: %u\n",
|
||||
ind_msg->source, ind_msg->mem_seg_valid,
|
||||
ind_msg->mem_seg[0].type, ind_msg->mem_seg_len);
|
||||
if (ind_msg->source == 1 || !ind_msg->mem_seg_valid ||
|
||||
!ind_msg->mem_seg_len ||
|
||||
ind_msg->mem_seg_len > QMI_WLFW_MAX_STR_LEN_V01) {
|
||||
cnss_pr_err("Invalid FW mem file save indication\n");
|
||||
return;
|
||||
}
|
||||
|
||||
event_data = kzalloc(sizeof(*event_data), GFP_KERNEL);
|
||||
if (!event_data)
|
||||
return;
|
||||
|
||||
if (ind_msg->mem_seg_valid) {
|
||||
if (ind_msg->mem_seg_len > QDSS_TRACE_SEG_LEN_MAX) {
|
||||
cnss_pr_err("Invalid seg len %u\n",
|
||||
ind_msg->mem_seg_len);
|
||||
goto free_event_data;
|
||||
}
|
||||
cnss_pr_dbg("QDSS_trace_save seg len %u\n",
|
||||
ind_msg->mem_seg_len);
|
||||
event_data->mem_seg_len = ind_msg->mem_seg_len;
|
||||
for (i = 0; i < ind_msg->mem_seg_len; i++) {
|
||||
event_data->mem_seg[i].addr = ind_msg->mem_seg[i].addr;
|
||||
event_data->mem_seg[i].size = ind_msg->mem_seg[i].size;
|
||||
cnss_pr_dbg("seg-%d: addr 0x%llx size 0x%x\n",
|
||||
i, ind_msg->mem_seg[i].addr,
|
||||
ind_msg->mem_seg[i].size);
|
||||
}
|
||||
}
|
||||
|
||||
event_data->mem_type = ind_msg->mem_seg[0].type;
|
||||
event_data->mem_seg_len = ind_msg->mem_seg_len;
|
||||
event_data->total_size = ind_msg->total_size;
|
||||
|
||||
if (ind_msg->file_name_valid)
|
||||
strlcpy(event_data->file_name, ind_msg->file_name,
|
||||
QDSS_TRACE_FILE_NAME_MAX + 1);
|
||||
else
|
||||
strlcpy(event_data->file_name, "qdss_trace",
|
||||
QDSS_TRACE_FILE_NAME_MAX + 1);
|
||||
for (i = 0; i < ind_msg->mem_seg_len; i++) {
|
||||
event_data->mem_seg[i].addr = ind_msg->mem_seg[i].addr;
|
||||
event_data->mem_seg[i].size = ind_msg->mem_seg[i].size;
|
||||
if (event_data->mem_type != ind_msg->mem_seg[i].type) {
|
||||
cnss_pr_err("FW Mem file save ind cannot have multiple mem types\n");
|
||||
goto free_event_data;
|
||||
}
|
||||
cnss_pr_dbg("seg-%d: addr 0x%llx size 0x%x\n",
|
||||
i, ind_msg->mem_seg[i].addr,
|
||||
ind_msg->mem_seg[i].size);
|
||||
}
|
||||
|
||||
cnss_driver_event_post(plat_priv, CNSS_DRIVER_EVENT_QDSS_TRACE_SAVE,
|
||||
if (ind_msg->file_name_valid) {
|
||||
strlcpy(event_data->file_name, ind_msg->file_name,
|
||||
QMI_WLFW_MAX_STR_LEN_V01 + 1);
|
||||
} else {
|
||||
if (event_data->mem_type == QMI_WLFW_MEM_QDSS_V01)
|
||||
strlcpy(event_data->file_name, "qdss_trace",
|
||||
QMI_WLFW_MAX_STR_LEN_V01 + 1);
|
||||
else
|
||||
strlcpy(event_data->file_name, "fw_mem_dump",
|
||||
QMI_WLFW_MAX_STR_LEN_V01 + 1);
|
||||
}
|
||||
|
||||
cnss_driver_event_post(plat_priv, CNSS_DRIVER_EVENT_FW_MEM_FILE_SAVE,
|
||||
0, event_data);
|
||||
|
||||
return;
|
||||
|
|
@ -2207,7 +2217,7 @@ static struct qmi_msg_handler qmi_wlfw_msg_handlers[] = {
|
|||
.ei = wlfw_qdss_trace_save_ind_msg_v01_ei,
|
||||
.decoded_size =
|
||||
sizeof(struct wlfw_qdss_trace_save_ind_msg_v01),
|
||||
.fn = cnss_wlfw_qdss_trace_save_ind_cb
|
||||
.fn = cnss_wlfw_fw_mem_file_save_ind_cb
|
||||
},
|
||||
{
|
||||
.type = QMI_INDICATION,
|
||||
|
|
|
|||
|
|
@ -13,19 +13,17 @@ struct cnss_qmi_event_server_arrive_data {
|
|||
unsigned int port;
|
||||
};
|
||||
|
||||
#define QDSS_TRACE_SEG_LEN_MAX 32
|
||||
#define QDSS_TRACE_FILE_NAME_MAX 16
|
||||
|
||||
struct cnss_mem_seg {
|
||||
u64 addr;
|
||||
u32 size;
|
||||
};
|
||||
|
||||
struct cnss_qmi_event_qdss_trace_save_data {
|
||||
struct cnss_qmi_event_fw_mem_file_save_data {
|
||||
u32 total_size;
|
||||
u32 mem_seg_len;
|
||||
struct cnss_mem_seg mem_seg[QDSS_TRACE_SEG_LEN_MAX];
|
||||
char file_name[QDSS_TRACE_FILE_NAME_MAX + 1];
|
||||
enum wlfw_mem_type_enum_v01 mem_type;
|
||||
struct cnss_mem_seg mem_seg[QMI_WLFW_MAX_NUM_MEM_SEG_V01];
|
||||
char file_name[QMI_WLFW_MAX_STR_LEN_V01 + 1];
|
||||
};
|
||||
|
||||
#ifdef CONFIG_CNSS2_QMI
|
||||
|
|
|
|||
Loading…
Reference in a new issue