diff --git a/drivers/net/wireless/cnss_utils/wlan_firmware_service_v01.c b/drivers/net/wireless/cnss_utils/wlan_firmware_service_v01.c index e9c327789ddf..bfd9e41222fc 100644 --- a/drivers/net/wireless/cnss_utils/wlan_firmware_service_v01.c +++ b/drivers/net/wireless/cnss_utils/wlan_firmware_service_v01.c @@ -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"); diff --git a/drivers/net/wireless/cnss_utils/wlan_firmware_service_v01.h b/drivers/net/wireless/cnss_utils/wlan_firmware_service_v01.h index 41bc96173c62..ae6738b984ec 100644 --- a/drivers/net/wireless/cnss_utils/wlan_firmware_service_v01.h +++ b/drivers/net/wireless/cnss_utils/wlan_firmware_service_v01.h @@ -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 diff --git a/drivers/soc/qcom/icnss2/main.c b/drivers/soc/qcom/icnss2/main.c index ccad11be310d..1c9f1a663a0c 100644 --- a/drivers/soc/qcom/icnss2/main.c +++ b/drivers/soc/qcom/icnss2/main.c @@ -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); diff --git a/drivers/soc/qcom/icnss2/main.h b/drivers/soc/qcom/icnss2/main.h index 23d9f09ad7ed..c77fe8aebdcc 100644 --- a/drivers/soc/qcom/icnss2/main.h +++ b/drivers/soc/qcom/icnss2/main.h @@ -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; diff --git a/drivers/soc/qcom/icnss2/qmi.c b/drivers/soc/qcom/icnss2/qmi.c index efe5d5d6677c..d26188b28ac3 100644 --- a/drivers/soc/qcom/icnss2/qmi.c +++ b/drivers/soc/qcom/icnss2/qmi.c @@ -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 + }, {} }; diff --git a/drivers/soc/qcom/icnss2/qmi.h b/drivers/soc/qcom/icnss2/qmi.h index 5df52e753302..ffca6eacf168 100644 --- a/drivers/soc/qcom/icnss2/qmi.h +++ b/drivers/soc/qcom/icnss2/qmi.h @@ -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__*/