mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-25 14:13:01 -04:00
icnss2: Add code for SSR dump collection feature for moselle
Add code for SSR dump collection feature for moselle. Change-Id: Iccc42bdc4d9c0074963164a6b95724853009c43f Signed-off-by: Mohammed Siddiq <msiddiq@codeaurora.org>
This commit is contained in:
parent
aa860b5b17
commit
a2f4049dd7
6 changed files with 441 additions and 5 deletions
|
|
@ -495,6 +495,50 @@ static struct qmi_elem_info wlfw_host_ddr_range_s_v01_ei[] = {
|
|||
},
|
||||
};
|
||||
|
||||
static struct qmi_elem_info wlfw_m3_segment_info_s_v01_ei[] = {
|
||||
{
|
||||
.data_type = QMI_SIGNED_4_BYTE_ENUM,
|
||||
.elem_len = 1,
|
||||
.elem_size = sizeof(enum wlfw_m3_segment_type_v01),
|
||||
.array_type = NO_ARRAY,
|
||||
.tlv_type = 0,
|
||||
.offset = offsetof(struct wlfw_m3_segment_info_s_v01,
|
||||
type),
|
||||
},
|
||||
{
|
||||
.data_type = QMI_UNSIGNED_8_BYTE,
|
||||
.elem_len = 1,
|
||||
.elem_size = sizeof(u64),
|
||||
.array_type = NO_ARRAY,
|
||||
.tlv_type = 0,
|
||||
.offset = offsetof(struct wlfw_m3_segment_info_s_v01,
|
||||
addr),
|
||||
},
|
||||
{
|
||||
.data_type = QMI_UNSIGNED_8_BYTE,
|
||||
.elem_len = 1,
|
||||
.elem_size = sizeof(u64),
|
||||
.array_type = NO_ARRAY,
|
||||
.tlv_type = 0,
|
||||
.offset = offsetof(struct wlfw_m3_segment_info_s_v01,
|
||||
size),
|
||||
},
|
||||
{
|
||||
.data_type = QMI_STRING,
|
||||
.elem_len = QMI_WLFW_MAX_STR_LEN_V01 + 1,
|
||||
.elem_size = sizeof(char),
|
||||
.array_type = NO_ARRAY,
|
||||
.tlv_type = 0,
|
||||
.offset = offsetof(struct wlfw_m3_segment_info_s_v01,
|
||||
name),
|
||||
},
|
||||
{
|
||||
.data_type = QMI_EOTI,
|
||||
.array_type = NO_ARRAY,
|
||||
.tlv_type = QMI_COMMON_TLV_TYPE,
|
||||
},
|
||||
};
|
||||
|
||||
struct qmi_elem_info wlfw_ind_register_req_msg_v01_ei[] = {
|
||||
{
|
||||
.data_type = QMI_OPT_FLAG,
|
||||
|
|
@ -876,6 +920,25 @@ struct qmi_elem_info wlfw_ind_register_req_msg_v01_ei[] = {
|
|||
wlfw_ind_register_req_msg_v01,
|
||||
qdss_mem_ready_enable),
|
||||
},
|
||||
{
|
||||
.data_type = QMI_OPT_FLAG,
|
||||
.elem_len = 1,
|
||||
.elem_size = sizeof(u8),
|
||||
.array_type = NO_ARRAY,
|
||||
.tlv_type = 0x23,
|
||||
.offset =
|
||||
offsetof(struct wlfw_ind_register_req_msg_v01,
|
||||
m3_dump_upload_segments_req_enable_valid),
|
||||
},
|
||||
{
|
||||
.data_type = QMI_UNSIGNED_1_BYTE,
|
||||
.elem_len = 1,
|
||||
.elem_size = sizeof(u8),
|
||||
.array_type = NO_ARRAY,
|
||||
.tlv_type = 0x23,
|
||||
.offset = offsetof(struct wlfw_ind_register_req_msg_v01,
|
||||
m3_dump_upload_segments_req_enable),
|
||||
},
|
||||
{
|
||||
.data_type = QMI_EOTI,
|
||||
.array_type = NO_ARRAY,
|
||||
|
|
@ -4967,5 +5030,45 @@ struct qmi_elem_info wlfw_pcie_gen_switch_resp_msg_v01_ei[] = {
|
|||
};
|
||||
EXPORT_SYMBOL(wlfw_pcie_gen_switch_resp_msg_v01_ei);
|
||||
|
||||
struct qmi_elem_info wlfw_m3_dump_upload_segments_req_ind_msg_v01_ei[] = {
|
||||
{
|
||||
.data_type = QMI_UNSIGNED_4_BYTE,
|
||||
.elem_len = 1,
|
||||
.elem_size = sizeof(u32),
|
||||
.array_type = NO_ARRAY,
|
||||
.tlv_type = 0x01,
|
||||
.offset =
|
||||
offsetof(struct wlfw_m3_dump_upload_segments_req_ind_msg_v01,
|
||||
pdev_id),
|
||||
},
|
||||
{
|
||||
.data_type = QMI_UNSIGNED_4_BYTE,
|
||||
.elem_len = 1,
|
||||
.elem_size = sizeof(u32),
|
||||
.array_type = NO_ARRAY,
|
||||
.tlv_type = 0x02,
|
||||
.offset =
|
||||
offsetof(struct wlfw_m3_dump_upload_segments_req_ind_msg_v01,
|
||||
no_of_valid_segments),
|
||||
},
|
||||
{
|
||||
.data_type = QMI_STRUCT,
|
||||
.elem_len = QMI_WLFW_MAX_M3_SEGMENTS_SIZE_V01,
|
||||
.elem_size = sizeof(struct wlfw_m3_segment_info_s_v01),
|
||||
.array_type = STATIC_ARRAY,
|
||||
.tlv_type = 0x03,
|
||||
.offset =
|
||||
offsetof(struct wlfw_m3_dump_upload_segments_req_ind_msg_v01,
|
||||
m3_segment),
|
||||
.ei_array = wlfw_m3_segment_info_s_v01_ei,
|
||||
},
|
||||
{
|
||||
.data_type = QMI_EOTI,
|
||||
.array_type = NO_ARRAY,
|
||||
.tlv_type = QMI_COMMON_TLV_TYPE,
|
||||
},
|
||||
};
|
||||
EXPORT_SYMBOL(wlfw_m3_dump_upload_segments_req_ind_msg_v01_ei);
|
||||
|
||||
MODULE_LICENSE("GPL v2");
|
||||
MODULE_DESCRIPTION("WLAN qmi service driver");
|
||||
|
|
|
|||
|
|
@ -69,6 +69,7 @@
|
|||
#define QMI_WLFW_GET_INFO_RESP_V01 0x004A
|
||||
#define QMI_WLFW_PCIE_GEN_SWITCH_RESP_V01 0x0053
|
||||
#define QMI_WLFW_INI_REQ_V01 0x002F
|
||||
#define QMI_WLFW_M3_DUMP_UPLOAD_SEGMENTS_REQ_IND_V01 0x0054
|
||||
#define QMI_WLFW_MSA_READY_REQ_V01 0x002E
|
||||
#define QMI_WLFW_M3_DUMP_UPLOAD_DONE_REQ_V01 0x004E
|
||||
#define QMI_WLFW_CAP_RESP_V01 0x0024
|
||||
|
|
@ -96,6 +97,7 @@
|
|||
#define QMI_WLFW_QDSS_TRACE_FREE_IND_V01 0x0046
|
||||
#define QMI_WLFW_QDSS_MEM_READY_IND_V01 0x0052
|
||||
|
||||
#define QMI_WLFW_MAX_M3_SEGMENTS_SIZE_V01 10
|
||||
#define QMI_WLFW_MAX_NUM_MEMORY_REGIONS_V01 2
|
||||
#define QMI_WLFW_MAX_NUM_MEM_SEG_V01 32
|
||||
#define QMI_WLFW_MAX_NUM_CAL_V01 5
|
||||
|
|
@ -225,6 +227,18 @@ enum wlfw_power_save_mode_v01 {
|
|||
WLFW_POWER_SAVE_MODE_MAX_VAL_V01 = INT_MAX,
|
||||
};
|
||||
|
||||
enum wlfw_m3_segment_type_v01 {
|
||||
WLFW_M3_SEGMENT_TYPE_MIN_VAL_V01 = INT_MIN,
|
||||
QMI_M3_SEGMENT_INVALID_V01 = 0,
|
||||
QMI_M3_SEGMENT_PHYAREG_V01 = 1,
|
||||
QMI_M3_SEGMENT_PHYDBG_V01 = 2,
|
||||
QMI_M3_SEGMENT_WMAC0_REG_V01 = 3,
|
||||
QMI_M3_SEGMENT_WCSSDBG_V01 = 4,
|
||||
QMI_M3_SEGMENT_PHYAPDMEM_V01 = 5,
|
||||
QMI_M3_SEGMENT_MAX_V01 = 6,
|
||||
WLFW_M3_SEGMENT_TYPE_MAX_VAL_V01 = INT_MAX,
|
||||
};
|
||||
|
||||
#define QMI_WLFW_CE_ATTR_FLAGS_V01 ((u32)0x00)
|
||||
#define QMI_WLFW_CE_ATTR_NO_SNOOP_V01 ((u32)0x01)
|
||||
#define QMI_WLFW_CE_ATTR_BYTE_SWAP_DATA_V01 ((u32)0x02)
|
||||
|
|
@ -327,6 +341,13 @@ struct wlfw_host_ddr_range_s_v01 {
|
|||
u64 size;
|
||||
};
|
||||
|
||||
struct wlfw_m3_segment_info_s_v01 {
|
||||
enum wlfw_m3_segment_type_v01 type;
|
||||
u64 addr;
|
||||
u64 size;
|
||||
char name[QMI_WLFW_MAX_STR_LEN_V01 + 1];
|
||||
};
|
||||
|
||||
struct wlfw_ind_register_req_msg_v01 {
|
||||
u8 fw_ready_enable_valid;
|
||||
u8 fw_ready_enable;
|
||||
|
|
@ -366,8 +387,11 @@ struct wlfw_ind_register_req_msg_v01 {
|
|||
u8 wfc_call_twt_config_enable;
|
||||
u8 qdss_mem_ready_enable_valid;
|
||||
u8 qdss_mem_ready_enable;
|
||||
u8 m3_dump_upload_segments_req_enable_valid;
|
||||
u8 m3_dump_upload_segments_req_enable;
|
||||
};
|
||||
#define WLFW_IND_REGISTER_REQ_MSG_V01_MAX_MSG_LEN 82
|
||||
|
||||
#define WLFW_IND_REGISTER_REQ_MSG_V01_MAX_MSG_LEN 86
|
||||
extern struct qmi_elem_info wlfw_ind_register_req_msg_v01_ei[];
|
||||
|
||||
struct wlfw_ind_register_resp_msg_v01 {
|
||||
|
|
@ -1132,4 +1156,14 @@ struct wlfw_pcie_gen_switch_resp_msg_v01 {
|
|||
#define WLFW_PCIE_GEN_SWITCH_RESP_MSG_V01_MAX_MSG_LEN 7
|
||||
extern struct qmi_elem_info wlfw_pcie_gen_switch_resp_msg_v01_ei[];
|
||||
|
||||
struct wlfw_m3_dump_upload_segments_req_ind_msg_v01 {
|
||||
u32 pdev_id;
|
||||
u32 no_of_valid_segments;
|
||||
struct wlfw_m3_segment_info_s_v01
|
||||
m3_segment[QMI_WLFW_MAX_M3_SEGMENTS_SIZE_V01];
|
||||
};
|
||||
|
||||
#define WLFW_M3_DUMP_UPLOAD_SEGMENTS_REQ_IND_MSG_V01_MAX_MSG_LEN 387
|
||||
extern struct qmi_elem_info wlfw_m3_dump_upload_segments_req_ind_msg_v01_ei[];
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -58,6 +58,13 @@
|
|||
#define ICNSS_WLAN_SERVICE_NAME "wlan/fw"
|
||||
#define ICNSS_DEFAULT_FEATURE_MASK 0x01
|
||||
|
||||
#define ICNSS_M3_SEGMENT(segment) "wcnss_"segment
|
||||
#define ICNSS_M3_SEGMENT_PHYAREG "phyareg"
|
||||
#define ICNSS_M3_SEGMENT_PHYA "phydbg"
|
||||
#define ICNSS_M3_SEGMENT_WMACREG "wmac0reg"
|
||||
#define ICNSS_M3_SEGMENT_WCSSDBG "WCSSDBG"
|
||||
#define ICNSS_M3_SEGMENT_PHYAM3 "PHYAPDMEM"
|
||||
|
||||
#define ICNSS_QUIRKS_DEFAULT BIT(FW_REJUVENATE_ENABLE)
|
||||
#define ICNSS_MAX_PROBE_CNT 2
|
||||
|
||||
|
|
@ -174,6 +181,8 @@ char *icnss_driver_event_to_str(enum icnss_driver_event_type type)
|
|||
return "QDSS_TRACE_SAVE";
|
||||
case ICNSS_DRIVER_EVENT_QDSS_TRACE_FREE:
|
||||
return "QDSS_TRACE_FREE";
|
||||
case ICNSS_DRIVER_EVENT_M3_DUMP_UPLOAD_REQ:
|
||||
return "M3_DUMP_UPLOAD";
|
||||
case ICNSS_DRIVER_EVENT_MAX:
|
||||
return "EVENT_MAX";
|
||||
}
|
||||
|
|
@ -1284,6 +1293,61 @@ static int icnss_qdss_trace_free_hdlr(struct icnss_priv *priv)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int icnss_m3_dump_upload_req_hdlr(struct icnss_priv *priv,
|
||||
void *data)
|
||||
{
|
||||
struct icnss_m3_upload_segments_req_data *event_data = data;
|
||||
struct ramdump_segment segment;
|
||||
int i, status = 0, ret = 0;
|
||||
|
||||
for (i = 0; i < event_data->no_of_valid_segments; i++) {
|
||||
memset(&segment, 0, sizeof(segment));
|
||||
segment.v_address = devm_ioremap(&priv->pdev->dev,
|
||||
event_data->m3_segment[i].addr,
|
||||
event_data->m3_segment[i].size);
|
||||
if (!segment.v_address) {
|
||||
icnss_pr_err("Failed to ioremap M3 Dump region");
|
||||
ret = -ENOMEM;
|
||||
goto send_resp;
|
||||
}
|
||||
|
||||
segment.size = event_data->m3_segment[i].size;
|
||||
segment.name = event_data->m3_segment[i].name;
|
||||
|
||||
switch (event_data->m3_segment[i].type) {
|
||||
case QMI_M3_SEGMENT_PHYAREG_V01:
|
||||
ret = do_ramdump(priv->m3_dump_dev_seg1, &segment, 1);
|
||||
break;
|
||||
case QMI_M3_SEGMENT_PHYDBG_V01:
|
||||
ret = do_ramdump(priv->m3_dump_dev_seg2, &segment, 1);
|
||||
break;
|
||||
case QMI_M3_SEGMENT_WMAC0_REG_V01:
|
||||
ret = do_ramdump(priv->m3_dump_dev_seg3, &segment, 1);
|
||||
break;
|
||||
case QMI_M3_SEGMENT_WCSSDBG_V01:
|
||||
ret = do_ramdump(priv->m3_dump_dev_seg4, &segment, 1);
|
||||
break;
|
||||
case QMI_M3_SEGMENT_PHYAPDMEM_V01:
|
||||
ret = do_ramdump(priv->m3_dump_dev_seg5, &segment, 1);
|
||||
break;
|
||||
default:
|
||||
icnss_pr_err("Invalid Segment type: %d",
|
||||
event_data->m3_segment[i].type);
|
||||
}
|
||||
|
||||
if (ret) {
|
||||
status = ret;
|
||||
icnss_pr_err("Failed to dump m3 %s segment, err = %d\n",
|
||||
event_data->m3_segment[i].name, ret);
|
||||
}
|
||||
}
|
||||
send_resp:
|
||||
icnss_wlfw_m3_dump_upload_done_send_sync(priv, event_data->pdev_id,
|
||||
status);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void icnss_driver_event_work(struct work_struct *work)
|
||||
{
|
||||
struct icnss_priv *priv =
|
||||
|
|
@ -1357,6 +1421,9 @@ static void icnss_driver_event_work(struct work_struct *work)
|
|||
case ICNSS_DRIVER_EVENT_QDSS_TRACE_FREE:
|
||||
ret = icnss_qdss_trace_free_hdlr(priv);
|
||||
break;
|
||||
case ICNSS_DRIVER_EVENT_M3_DUMP_UPLOAD_REQ:
|
||||
ret = icnss_m3_dump_upload_req_hdlr(priv, event->data);
|
||||
break;
|
||||
default:
|
||||
icnss_pr_err("Invalid Event type: %d", event->type);
|
||||
kfree(event);
|
||||
|
|
@ -1819,6 +1886,58 @@ out:
|
|||
|
||||
}
|
||||
|
||||
static int icnss_create_ramdump_devices(struct icnss_priv *priv)
|
||||
{
|
||||
|
||||
if (!priv || !priv->pdev) {
|
||||
icnss_pr_err("Platform priv or pdev is NULL\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
priv->msa0_dump_dev = create_ramdump_device("wcss_msa0",
|
||||
&priv->pdev->dev);
|
||||
if (!priv->msa0_dump_dev)
|
||||
return -ENOMEM;
|
||||
|
||||
if (priv->device_id == WCN6750_DEVICE_ID) {
|
||||
priv->m3_dump_dev_seg1 = create_ramdump_device(
|
||||
ICNSS_M3_SEGMENT(
|
||||
ICNSS_M3_SEGMENT_PHYAREG),
|
||||
&priv->pdev->dev);
|
||||
if (!priv->m3_dump_dev_seg1)
|
||||
return -ENOMEM;
|
||||
|
||||
priv->m3_dump_dev_seg2 = create_ramdump_device(
|
||||
ICNSS_M3_SEGMENT(
|
||||
ICNSS_M3_SEGMENT_PHYA),
|
||||
&priv->pdev->dev);
|
||||
if (!priv->m3_dump_dev_seg2)
|
||||
return -ENOMEM;
|
||||
|
||||
priv->m3_dump_dev_seg3 = create_ramdump_device(
|
||||
ICNSS_M3_SEGMENT(
|
||||
ICNSS_M3_SEGMENT_WMACREG),
|
||||
&priv->pdev->dev);
|
||||
if (!priv->m3_dump_dev_seg3)
|
||||
return -ENOMEM;
|
||||
|
||||
priv->m3_dump_dev_seg4 = create_ramdump_device(
|
||||
ICNSS_M3_SEGMENT(
|
||||
ICNSS_M3_SEGMENT_WCSSDBG),
|
||||
&priv->pdev->dev);
|
||||
if (!priv->m3_dump_dev_seg4)
|
||||
return -ENOMEM;
|
||||
|
||||
priv->m3_dump_dev_seg5 = create_ramdump_device(
|
||||
ICNSS_M3_SEGMENT(
|
||||
ICNSS_M3_SEGMENT_PHYAM3),
|
||||
&priv->pdev->dev);
|
||||
if (!priv->m3_dump_dev_seg5)
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int icnss_enable_recovery(struct icnss_priv *priv)
|
||||
{
|
||||
|
|
@ -1834,10 +1953,9 @@ static int icnss_enable_recovery(struct icnss_priv *priv)
|
|||
goto enable_pdr;
|
||||
}
|
||||
|
||||
priv->msa0_dump_dev = create_ramdump_device("wcss_msa0",
|
||||
&priv->pdev->dev);
|
||||
if (!priv->msa0_dump_dev)
|
||||
return -ENOMEM;
|
||||
ret = icnss_create_ramdump_devices(priv);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
icnss_modem_ssr_register_notifier(priv);
|
||||
if (test_bit(SSR_ONLY, &priv->ctrl_params.quirks)) {
|
||||
|
|
@ -3386,6 +3504,14 @@ static int icnss_remove(struct platform_device *pdev)
|
|||
|
||||
destroy_ramdump_device(priv->msa0_dump_dev);
|
||||
|
||||
if (priv->device_id == WCN6750_DEVICE_ID) {
|
||||
destroy_ramdump_device(priv->m3_dump_dev_seg1);
|
||||
destroy_ramdump_device(priv->m3_dump_dev_seg2);
|
||||
destroy_ramdump_device(priv->m3_dump_dev_seg3);
|
||||
destroy_ramdump_device(priv->m3_dump_dev_seg4);
|
||||
destroy_ramdump_device(priv->m3_dump_dev_seg5);
|
||||
}
|
||||
|
||||
icnss_pdr_unregister_notifier(priv);
|
||||
|
||||
icnss_unregister_fw_service(priv);
|
||||
|
|
|
|||
|
|
@ -54,6 +54,7 @@ enum icnss_driver_event_type {
|
|||
ICNSS_DRIVER_EVENT_QDSS_TRACE_REQ_MEM,
|
||||
ICNSS_DRIVER_EVENT_QDSS_TRACE_SAVE,
|
||||
ICNSS_DRIVER_EVENT_QDSS_TRACE_FREE,
|
||||
ICNSS_DRIVER_EVENT_M3_DUMP_UPLOAD_REQ,
|
||||
ICNSS_DRIVER_EVENT_MAX,
|
||||
};
|
||||
|
||||
|
|
@ -389,6 +390,11 @@ struct icnss_priv {
|
|||
uint8_t *diag_reg_read_buf;
|
||||
atomic_t pm_count;
|
||||
struct ramdump_device *msa0_dump_dev;
|
||||
struct ramdump_device *m3_dump_dev_seg1;
|
||||
struct ramdump_device *m3_dump_dev_seg2;
|
||||
struct ramdump_device *m3_dump_dev_seg3;
|
||||
struct ramdump_device *m3_dump_dev_seg4;
|
||||
struct ramdump_device *m3_dump_dev_seg5;
|
||||
bool force_err_fatal;
|
||||
bool allow_recursive_recovery;
|
||||
bool early_crash_ind;
|
||||
|
|
|
|||
|
|
@ -44,6 +44,7 @@
|
|||
#define DUMMY_BDF_FILE_NAME "bdwlan.dmy"
|
||||
|
||||
#define DEVICE_BAR_SIZE 0x200000
|
||||
#define M3_SEGMENT_ADDR_MASK 0xFFFFFFFF
|
||||
|
||||
#ifdef CONFIG_ICNSS2_DEBUG
|
||||
bool ignore_fw_timeout;
|
||||
|
|
@ -539,6 +540,8 @@ int wlfw_ind_register_send_sync_msg(struct icnss_priv *priv)
|
|||
req->qdss_trace_free_enable = 1;
|
||||
req->respond_get_info_enable_valid = 1;
|
||||
req->respond_get_info_enable = 1;
|
||||
req->m3_dump_upload_segments_req_enable_valid = 1;
|
||||
req->m3_dump_upload_segments_req_enable = 1;
|
||||
}
|
||||
|
||||
priv->stats.ind_register_req++;
|
||||
|
|
@ -1570,6 +1573,67 @@ out:
|
|||
return ret;
|
||||
}
|
||||
|
||||
int icnss_wlfw_m3_dump_upload_done_send_sync(struct icnss_priv *priv,
|
||||
u32 pdev_id, int status)
|
||||
{
|
||||
struct wlfw_m3_dump_upload_done_req_msg_v01 *req;
|
||||
struct wlfw_m3_dump_upload_done_resp_msg_v01 *resp;
|
||||
struct qmi_txn txn;
|
||||
int ret = 0;
|
||||
|
||||
req = kzalloc(sizeof(*req), GFP_KERNEL);
|
||||
if (!req)
|
||||
return -ENOMEM;
|
||||
|
||||
resp = kzalloc(sizeof(*resp), GFP_KERNEL);
|
||||
if (!resp) {
|
||||
kfree(req);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
icnss_pr_dbg("Sending M3 Upload done req, pdev %d, status %d\n",
|
||||
pdev_id, status);
|
||||
|
||||
req->pdev_id = pdev_id;
|
||||
req->status = status;
|
||||
|
||||
ret = qmi_txn_init(&priv->qmi, &txn,
|
||||
wlfw_m3_dump_upload_done_resp_msg_v01_ei, resp);
|
||||
if (ret < 0) {
|
||||
icnss_pr_err("Fail to initialize txn for M3 dump upload done req: err %d\n",
|
||||
ret);
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = qmi_send_request(&priv->qmi, NULL, &txn,
|
||||
QMI_WLFW_M3_DUMP_UPLOAD_DONE_REQ_V01,
|
||||
WLFW_M3_DUMP_UPLOAD_DONE_REQ_MSG_V01_MAX_MSG_LEN,
|
||||
wlfw_m3_dump_upload_done_req_msg_v01_ei, req);
|
||||
if (ret < 0) {
|
||||
qmi_txn_cancel(&txn);
|
||||
icnss_pr_err("Fail to send M3 dump upload done request: err %d\n",
|
||||
ret);
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = qmi_txn_wait(&txn, priv->ctrl_params.qmi_timeout);
|
||||
if (ret < 0) {
|
||||
icnss_pr_err("Fail to wait for response of M3 dump upload done request, err %d\n",
|
||||
ret);
|
||||
goto out;
|
||||
} else if (resp->resp.result != QMI_RESULT_SUCCESS_V01) {
|
||||
icnss_pr_err("M3 Dump Upload Done Req failed, result: %d, err: 0x%X\n",
|
||||
resp->resp.result, resp->resp.error);
|
||||
ret = -resp->resp.result;
|
||||
goto out;
|
||||
}
|
||||
|
||||
out:
|
||||
kfree(req);
|
||||
kfree(resp);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void fw_ready_ind_cb(struct qmi_handle *qmi, struct sockaddr_qrtr *sq,
|
||||
struct qmi_txn *txn, const void *data)
|
||||
{
|
||||
|
|
@ -1961,6 +2025,78 @@ static void icnss_wlfw_respond_get_info_ind_cb(struct qmi_handle *qmi,
|
|||
ind_msg->data_len);
|
||||
}
|
||||
|
||||
static void icnss_wlfw_m3_dump_upload_segs_req_ind_cb(struct qmi_handle *qmi,
|
||||
struct sockaddr_qrtr *sq,
|
||||
struct qmi_txn *txn,
|
||||
const void *d)
|
||||
{
|
||||
struct icnss_priv *priv = container_of(qmi, struct icnss_priv, qmi);
|
||||
const struct wlfw_m3_dump_upload_segments_req_ind_msg_v01 *ind_msg = d;
|
||||
struct icnss_m3_upload_segments_req_data *event_data = NULL;
|
||||
u64 max_mapped_addr = 0;
|
||||
u64 segment_addr = 0;
|
||||
int i = 0;
|
||||
|
||||
icnss_pr_dbg("Received QMI WLFW M3 dump upload sigments indication\n");
|
||||
|
||||
if (!txn) {
|
||||
icnss_pr_err("Spurious indication\n");
|
||||
return;
|
||||
}
|
||||
|
||||
icnss_pr_dbg("M3 Dump upload info: pdev_id: %d no_of_segments: %d\n",
|
||||
ind_msg->pdev_id, ind_msg->no_of_valid_segments);
|
||||
|
||||
if (ind_msg->no_of_valid_segments > QMI_WLFW_MAX_M3_SEGMENTS_SIZE_V01)
|
||||
return;
|
||||
|
||||
event_data = kzalloc(sizeof(*event_data), GFP_KERNEL);
|
||||
if (!event_data)
|
||||
return;
|
||||
|
||||
event_data->pdev_id = ind_msg->pdev_id;
|
||||
event_data->no_of_valid_segments = ind_msg->no_of_valid_segments;
|
||||
max_mapped_addr = priv->msa_pa + priv->msa_mem_size;
|
||||
|
||||
for (i = 0; i < ind_msg->no_of_valid_segments; i++) {
|
||||
segment_addr = ind_msg->m3_segment[i].addr &
|
||||
M3_SEGMENT_ADDR_MASK;
|
||||
|
||||
if (ind_msg->m3_segment[i].size > priv->msa_mem_size ||
|
||||
segment_addr >= max_mapped_addr ||
|
||||
segment_addr < priv->msa_pa ||
|
||||
ind_msg->m3_segment[i].size +
|
||||
segment_addr > max_mapped_addr) {
|
||||
icnss_pr_dbg("Received out of range Segment %d Addr: 0x%llx Size: 0x%x, Name: %s, type: %d\n",
|
||||
(i + 1), segment_addr,
|
||||
ind_msg->m3_segment[i].size,
|
||||
ind_msg->m3_segment[i].name,
|
||||
ind_msg->m3_segment[i].type);
|
||||
goto out;
|
||||
}
|
||||
|
||||
event_data->m3_segment[i].addr = segment_addr;
|
||||
event_data->m3_segment[i].size = ind_msg->m3_segment[i].size;
|
||||
event_data->m3_segment[i].type = ind_msg->m3_segment[i].type;
|
||||
strlcpy(event_data->m3_segment[i].name,
|
||||
ind_msg->m3_segment[i].name,
|
||||
WLFW_MAX_STR_LEN + 1);
|
||||
|
||||
icnss_pr_dbg("Received Segment %d Addr: 0x%llx Size: 0x%x, Name: %s, type: %d\n",
|
||||
(i + 1), segment_addr,
|
||||
ind_msg->m3_segment[i].size,
|
||||
ind_msg->m3_segment[i].name,
|
||||
ind_msg->m3_segment[i].type);
|
||||
}
|
||||
|
||||
icnss_driver_event_post(priv, ICNSS_DRIVER_EVENT_M3_DUMP_UPLOAD_REQ,
|
||||
0, event_data);
|
||||
|
||||
return;
|
||||
out:
|
||||
kfree(event_data);
|
||||
}
|
||||
|
||||
static struct qmi_msg_handler wlfw_msg_handlers[] = {
|
||||
{
|
||||
.type = QMI_INDICATION,
|
||||
|
|
@ -2037,6 +2173,14 @@ static struct qmi_msg_handler wlfw_msg_handlers[] = {
|
|||
sizeof(struct wlfw_respond_get_info_ind_msg_v01),
|
||||
.fn = icnss_wlfw_respond_get_info_ind_cb
|
||||
},
|
||||
{
|
||||
.type = QMI_INDICATION,
|
||||
.msg_id = QMI_WLFW_M3_DUMP_UPLOAD_SEGMENTS_REQ_IND_V01,
|
||||
.ei = wlfw_m3_dump_upload_segments_req_ind_msg_v01_ei,
|
||||
.decoded_size =
|
||||
sizeof(struct wlfw_m3_dump_upload_segments_req_ind_msg_v01),
|
||||
.fn = icnss_wlfw_m3_dump_upload_segs_req_ind_cb
|
||||
},
|
||||
{}
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -8,6 +8,8 @@
|
|||
|
||||
#define QDSS_TRACE_SEG_LEN_MAX 32
|
||||
#define QDSS_TRACE_FILE_NAME_MAX 16
|
||||
#define M3_SEGMENTS_SIZE_MAX 10
|
||||
#define M3_SEGMENT_NAME_LEN_MAX 16
|
||||
|
||||
struct icnss_mem_seg {
|
||||
u64 addr;
|
||||
|
|
@ -21,6 +23,19 @@ struct icnss_qmi_event_qdss_trace_save_data {
|
|||
char file_name[QDSS_TRACE_FILE_NAME_MAX + 1];
|
||||
};
|
||||
|
||||
struct icnss_m3_segment {
|
||||
u32 type;
|
||||
u64 addr;
|
||||
u64 size;
|
||||
char name[M3_SEGMENT_NAME_LEN_MAX + 1];
|
||||
};
|
||||
|
||||
struct icnss_m3_upload_segments_req_data {
|
||||
u32 pdev_id;
|
||||
u32 no_of_valid_segments;
|
||||
struct icnss_m3_segment m3_segment[M3_SEGMENTS_SIZE_MAX];
|
||||
};
|
||||
|
||||
#ifndef CONFIG_ICNSS2_QMI
|
||||
|
||||
static inline int wlfw_ind_register_send_sync_msg(struct icnss_priv *priv)
|
||||
|
|
@ -146,6 +161,12 @@ int wlfw_send_soc_wake_msg(struct icnss_priv *priv,
|
|||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int icnss_wlfw_m3_dump_upload_done_send_sync(struct icnss_priv *priv,
|
||||
u32 pdev_id, int status)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
int wlfw_ind_register_send_sync_msg(struct icnss_priv *priv);
|
||||
int icnss_connect_to_fw_server(struct icnss_priv *priv, void *data);
|
||||
|
|
@ -187,6 +208,8 @@ int icnss_wlfw_get_info_send_sync(struct icnss_priv *priv, int type,
|
|||
void *cmd, int cmd_len);
|
||||
int wlfw_send_soc_wake_msg(struct icnss_priv *priv,
|
||||
enum wlfw_soc_wake_enum_v01 type);
|
||||
int icnss_wlfw_m3_dump_upload_done_send_sync(struct icnss_priv *priv,
|
||||
u32 pdev_id, int status);
|
||||
#endif
|
||||
|
||||
#endif /* __ICNSS_QMI_H__*/
|
||||
|
|
|
|||
Loading…
Reference in a new issue