Merge "icnss2: Add support for MHI state info"
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 ca3f998..5419b1b 100644
--- a/drivers/net/wireless/cnss_utils/wlan_firmware_service_v01.c
+++ b/drivers/net/wireless/cnss_utils/wlan_firmware_service_v01.c
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: GPL-2.0-only
-/* Copyright (c) 2015-2021, The Linux Foundation. All rights reserved. */
+/* Copyright (c) 2021, The Linux Foundation. All rights reserved. */
#include "wlan_firmware_service_v01.h"
@@ -464,7 +464,8 @@
.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,
+ .offset = offsetof(struct
+ wlfw_m3_segment_info_s_v01,
type),
},
{
@@ -473,7 +474,8 @@
.elem_size = sizeof(u64),
.array_type = NO_ARRAY,
.tlv_type = 0,
- .offset = offsetof(struct wlfw_m3_segment_info_s_v01,
+ .offset = offsetof(struct
+ wlfw_m3_segment_info_s_v01,
addr),
},
{
@@ -482,7 +484,8 @@
.elem_size = sizeof(u64),
.array_type = NO_ARRAY,
.tlv_type = 0,
- .offset = offsetof(struct wlfw_m3_segment_info_s_v01,
+ .offset = offsetof(struct
+ wlfw_m3_segment_info_s_v01,
size),
},
{
@@ -491,7 +494,8 @@
.elem_size = sizeof(char),
.array_type = NO_ARRAY,
.tlv_type = 0,
- .offset = offsetof(struct wlfw_m3_segment_info_s_v01,
+ .offset = offsetof(struct
+ wlfw_m3_segment_info_s_v01,
name),
},
{
@@ -508,7 +512,8 @@
.elem_size = sizeof(u64),
.array_type = NO_ARRAY,
.tlv_type = 0,
- .offset = offsetof(struct wlfw_dev_mem_info_s_v01,
+ .offset = offsetof(struct
+ wlfw_dev_mem_info_s_v01,
start),
},
{
@@ -517,7 +522,8 @@
.elem_size = sizeof(u64),
.array_type = NO_ARRAY,
.tlv_type = 0,
- .offset = offsetof(struct wlfw_dev_mem_info_s_v01,
+ .offset = offsetof(struct
+ wlfw_dev_mem_info_s_v01,
size),
},
{
@@ -877,7 +883,8 @@
.array_type = NO_ARRAY,
.tlv_type = 0x23,
.offset =
- offsetof(struct wlfw_ind_register_req_msg_v01,
+ offsetof(struct
+ wlfw_ind_register_req_msg_v01,
m3_dump_upload_segments_req_enable_valid),
},
{
@@ -886,7 +893,8 @@
.elem_size = sizeof(u8),
.array_type = NO_ARRAY,
.tlv_type = 0x23,
- .offset = offsetof(struct wlfw_ind_register_req_msg_v01,
+ .offset = offsetof(struct
+ wlfw_ind_register_req_msg_v01,
m3_dump_upload_segments_req_enable),
},
{
@@ -1556,7 +1564,8 @@
.elem_size = sizeof(u8),
.array_type = NO_ARRAY,
.tlv_type = 0x1C,
- .offset = offsetof(struct wlfw_cap_resp_msg_v01,
+ .offset = offsetof(struct
+ wlfw_cap_resp_msg_v01,
dev_mem_info_valid),
},
{
@@ -1565,7 +1574,8 @@
.elem_size = sizeof(struct wlfw_dev_mem_info_s_v01),
.array_type = STATIC_ARRAY,
.tlv_type = 0x1C,
- .offset = offsetof(struct wlfw_cap_resp_msg_v01,
+ .offset = offsetof(struct
+ wlfw_cap_resp_msg_v01,
dev_mem_info),
.ei_array = wlfw_dev_mem_info_s_v01_ei,
},
@@ -1805,6 +1815,26 @@
cal_remove_supported),
},
{
+ .data_type = QMI_OPT_FLAG,
+ .elem_len = 1,
+ .elem_size = sizeof(u8),
+ .array_type = NO_ARRAY,
+ .tlv_type = 0x12,
+ .offset = offsetof(struct
+ wlfw_cal_report_req_msg_v01,
+ cal_file_download_size_valid),
+ },
+ {
+ .data_type = QMI_UNSIGNED_8_BYTE,
+ .elem_len = 1,
+ .elem_size = sizeof(u64),
+ .array_type = NO_ARRAY,
+ .tlv_type = 0x12,
+ .offset = offsetof(struct
+ wlfw_cal_report_req_msg_v01,
+ cal_file_download_size),
+ },
+ {
.data_type = QMI_EOTI,
.array_type = NO_ARRAY,
.tlv_type = QMI_COMMON_TLV_TYPE,
@@ -3041,7 +3071,8 @@
.elem_size = sizeof(u8),
.array_type = NO_ARRAY,
.tlv_type = 0x10,
- .offset = offsetof(struct wlfw_fw_init_done_ind_msg_v01,
+ .offset = offsetof(struct
+ wlfw_fw_init_done_ind_msg_v01,
hang_data_addr_offset_valid),
},
{
@@ -3050,7 +3081,8 @@
.elem_size = sizeof(u32),
.array_type = NO_ARRAY,
.tlv_type = 0x10,
- .offset = offsetof(struct wlfw_fw_init_done_ind_msg_v01,
+ .offset = offsetof(struct
+ wlfw_fw_init_done_ind_msg_v01,
hang_data_addr_offset),
},
{
@@ -3059,7 +3091,8 @@
.elem_size = sizeof(u8),
.array_type = NO_ARRAY,
.tlv_type = 0x11,
- .offset = offsetof(struct wlfw_fw_init_done_ind_msg_v01,
+ .offset = offsetof(struct
+ wlfw_fw_init_done_ind_msg_v01,
hang_data_length_valid),
},
{
@@ -3068,7 +3101,8 @@
.elem_size = sizeof(u16),
.array_type = NO_ARRAY,
.tlv_type = 0x11,
- .offset = offsetof(struct wlfw_fw_init_done_ind_msg_v01,
+ .offset = offsetof(struct
+ wlfw_fw_init_done_ind_msg_v01,
hang_data_length),
},
{
@@ -3335,6 +3369,26 @@
struct qmi_elem_info wlfw_cal_done_ind_msg_v01_ei[] = {
{
+ .data_type = QMI_OPT_FLAG,
+ .elem_len = 1,
+ .elem_size = sizeof(u8),
+ .array_type = NO_ARRAY,
+ .tlv_type = 0x10,
+ .offset = offsetof(struct
+ wlfw_cal_done_ind_msg_v01,
+ cal_file_upload_size_valid),
+ },
+ {
+ .data_type = QMI_UNSIGNED_8_BYTE,
+ .elem_len = 1,
+ .elem_size = sizeof(u64),
+ .array_type = NO_ARRAY,
+ .tlv_type = 0x10,
+ .offset = offsetof(struct
+ wlfw_cal_done_ind_msg_v01,
+ cal_file_upload_size),
+ },
+ {
.data_type = QMI_EOTI,
.array_type = NO_ARRAY,
.tlv_type = QMI_COMMON_TLV_TYPE,
@@ -4369,6 +4423,46 @@
bar_size),
},
{
+ .data_type = QMI_OPT_FLAG,
+ .elem_len = 1,
+ .elem_size = sizeof(u8),
+ .array_type = NO_ARRAY,
+ .tlv_type = 0x12,
+ .offset = offsetof(struct
+ wlfw_device_info_resp_msg_v01,
+ mhi_state_info_addr_valid),
+ },
+ {
+ .data_type = QMI_UNSIGNED_8_BYTE,
+ .elem_len = 1,
+ .elem_size = sizeof(u64),
+ .array_type = NO_ARRAY,
+ .tlv_type = 0x12,
+ .offset = offsetof(struct
+ wlfw_device_info_resp_msg_v01,
+ mhi_state_info_addr),
+ },
+ {
+ .data_type = QMI_OPT_FLAG,
+ .elem_len = 1,
+ .elem_size = sizeof(u8),
+ .array_type = NO_ARRAY,
+ .tlv_type = 0x13,
+ .offset = offsetof(struct
+ wlfw_device_info_resp_msg_v01,
+ mhi_state_info_size_valid),
+ },
+ {
+ .data_type = QMI_UNSIGNED_4_BYTE,
+ .elem_len = 1,
+ .elem_size = sizeof(u32),
+ .array_type = NO_ARRAY,
+ .tlv_type = 0x13,
+ .offset = offsetof(struct
+ wlfw_device_info_resp_msg_v01,
+ mhi_state_info_size),
+ },
+ {
.data_type = QMI_EOTI,
.array_type = NO_ARRAY,
.tlv_type = QMI_COMMON_TLV_TYPE,
@@ -4730,7 +4824,8 @@
.array_type = NO_ARRAY,
.tlv_type = 0x01,
.offset =
- offsetof(struct wlfw_m3_dump_upload_segments_req_ind_msg_v01,
+ offsetof(struct
+ wlfw_m3_dump_upload_segments_req_ind_msg_v01,
pdev_id),
},
{
@@ -4740,7 +4835,8 @@
.array_type = NO_ARRAY,
.tlv_type = 0x02,
.offset =
- offsetof(struct wlfw_m3_dump_upload_segments_req_ind_msg_v01,
+ offsetof(struct
+ wlfw_m3_dump_upload_segments_req_ind_msg_v01,
no_of_valid_segments),
},
{
@@ -4750,7 +4846,8 @@
.array_type = STATIC_ARRAY,
.tlv_type = 0x03,
.offset =
- offsetof(struct wlfw_m3_dump_upload_segments_req_ind_msg_v01,
+ offsetof(struct
+ wlfw_m3_dump_upload_segments_req_ind_msg_v01,
m3_segment),
.ei_array = wlfw_m3_segment_info_s_v01_ei,
},
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 d3a2dd6..b5ed622 100644
--- a/drivers/net/wireless/cnss_utils/wlan_firmware_service_v01.h
+++ b/drivers/net/wireless/cnss_utils/wlan_firmware_service_v01.h
@@ -1,5 +1,5 @@
/* SPDX-License-Identifier: GPL-2.0-only */
-/* Copyright (c) 2015-2021, The Linux Foundation. All rights reserved. */
+/* Copyright (c) 2021, The Linux Foundation. All rights reserved. */
#ifndef WLAN_FIRMWARE_SERVICE_V01_H
#define WLAN_FIRMWARE_SERVICE_V01_H
@@ -99,7 +99,7 @@
#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_MEM_SEG_V01 52
#define QMI_WLFW_MAX_NUM_CAL_V01 5
#define QMI_WLFW_MAX_DATA_SIZE_V01 6144
#define QMI_WLFW_FUNCTION_NAME_LEN_V01 128
@@ -396,7 +396,6 @@
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 86
extern struct qmi_elem_info wlfw_ind_register_req_msg_v01_ei[];
@@ -516,7 +515,6 @@
struct wlfw_dev_mem_info_s_v01
dev_mem_info[QMI_WLFW_MAX_DEV_MEM_NUM_V01];
};
-
#define WLFW_CAP_RESP_MSG_V01_MAX_MSG_LEN 320
extern struct qmi_elem_info wlfw_cap_resp_msg_v01_ei[];
@@ -555,8 +553,11 @@
u8 xo_cal_data;
u8 cal_remove_supported_valid;
u8 cal_remove_supported;
+ u8 cal_file_download_size_valid;
+ u64 cal_file_download_size;
};
-#define WLFW_CAL_REPORT_REQ_MSG_V01_MAX_MSG_LEN 32
+
+#define WLFW_CAL_REPORT_REQ_MSG_V01_MAX_MSG_LEN 43
extern struct qmi_elem_info wlfw_cal_report_req_msg_v01_ei[];
struct wlfw_cal_report_resp_msg_v01 {
@@ -784,14 +785,16 @@
u32 mem_seg_len;
struct wlfw_mem_seg_s_v01 mem_seg[QMI_WLFW_MAX_NUM_MEM_SEG_V01];
};
-#define WLFW_REQUEST_MEM_IND_MSG_V01_MAX_MSG_LEN 1124
+
+#define WLFW_REQUEST_MEM_IND_MSG_V01_MAX_MSG_LEN 1824
extern struct qmi_elem_info wlfw_request_mem_ind_msg_v01_ei[];
struct wlfw_respond_mem_req_msg_v01 {
u32 mem_seg_len;
struct wlfw_mem_seg_resp_s_v01 mem_seg[QMI_WLFW_MAX_NUM_MEM_SEG_V01];
};
-#define WLFW_RESPOND_MEM_REQ_MSG_V01_MAX_MSG_LEN 548
+
+#define WLFW_RESPOND_MEM_REQ_MSG_V01_MAX_MSG_LEN 888
extern struct qmi_elem_info wlfw_respond_mem_req_msg_v01_ei[];
struct wlfw_respond_mem_resp_msg_v01 {
@@ -812,7 +815,6 @@
u8 hang_data_length_valid;
u16 hang_data_length;
};
-
#define WLFW_FW_INIT_DONE_IND_MSG_V01_MAX_MSG_LEN 12
extern struct qmi_elem_info wlfw_fw_init_done_ind_msg_v01_ei[];
@@ -878,28 +880,33 @@
extern struct qmi_elem_info wlfw_xo_cal_ind_msg_v01_ei[];
struct wlfw_cal_done_ind_msg_v01 {
- char placeholder;
+ u8 cal_file_upload_size_valid;
+ u64 cal_file_upload_size;
};
-#define WLFW_CAL_DONE_IND_MSG_V01_MAX_MSG_LEN 0
+
+#define WLFW_CAL_DONE_IND_MSG_V01_MAX_MSG_LEN 11
extern struct qmi_elem_info wlfw_cal_done_ind_msg_v01_ei[];
struct wlfw_qdss_trace_req_mem_ind_msg_v01 {
u32 mem_seg_len;
struct wlfw_mem_seg_s_v01 mem_seg[QMI_WLFW_MAX_NUM_MEM_SEG_V01];
};
-#define WLFW_QDSS_TRACE_REQ_MEM_IND_MSG_V01_MAX_MSG_LEN 1124
+
+#define WLFW_QDSS_TRACE_REQ_MEM_IND_MSG_V01_MAX_MSG_LEN 1824
extern struct qmi_elem_info wlfw_qdss_trace_req_mem_ind_msg_v01_ei[];
struct wlfw_qdss_trace_mem_info_req_msg_v01 {
u32 mem_seg_len;
struct wlfw_mem_seg_resp_s_v01 mem_seg[QMI_WLFW_MAX_NUM_MEM_SEG_V01];
};
-#define WLFW_QDSS_TRACE_MEM_INFO_REQ_MSG_V01_MAX_MSG_LEN 548
+
+#define WLFW_QDSS_TRACE_MEM_INFO_REQ_MSG_V01_MAX_MSG_LEN 888
extern struct qmi_elem_info wlfw_qdss_trace_mem_info_req_msg_v01_ei[];
struct wlfw_qdss_trace_mem_info_resp_msg_v01 {
struct qmi_response_type_v01 resp;
};
+
#define WLFW_QDSS_TRACE_MEM_INFO_RESP_MSG_V01_MAX_MSG_LEN 7
extern struct qmi_elem_info wlfw_qdss_trace_mem_info_resp_msg_v01_ei[];
@@ -912,7 +919,8 @@
u8 file_name_valid;
char file_name[QMI_WLFW_MAX_STR_LEN_V01 + 1];
};
-#define WLFW_QDSS_TRACE_SAVE_IND_MSG_V01_MAX_MSG_LEN 581
+
+#define WLFW_QDSS_TRACE_SAVE_IND_MSG_V01_MAX_MSG_LEN 921
extern struct qmi_elem_info wlfw_qdss_trace_save_ind_msg_v01_ei[];
struct wlfw_qdss_trace_data_req_msg_v01 {
@@ -978,7 +986,8 @@
u32 mem_seg_len;
struct wlfw_mem_seg_resp_s_v01 mem_seg[QMI_WLFW_MAX_NUM_MEM_SEG_V01];
};
-#define WLFW_QDSS_TRACE_FREE_IND_MSG_V01_MAX_MSG_LEN 548
+
+#define WLFW_QDSS_TRACE_FREE_IND_MSG_V01_MAX_MSG_LEN 888
extern struct qmi_elem_info wlfw_qdss_trace_free_ind_msg_v01_ei[];
struct wlfw_shutdown_req_msg_v01 {
@@ -1057,6 +1066,7 @@
struct wlfw_get_info_resp_msg_v01 {
struct qmi_response_type_v01 resp;
};
+
#define WLFW_GET_INFO_RESP_MSG_V01_MAX_MSG_LEN 7
extern struct qmi_elem_info wlfw_get_info_resp_msg_v01_ei[];
@@ -1085,8 +1095,13 @@
u64 bar_addr;
u8 bar_size_valid;
u32 bar_size;
+ u8 mhi_state_info_addr_valid;
+ u64 mhi_state_info_addr;
+ u8 mhi_state_info_size_valid;
+ u32 mhi_state_info_size;
};
-#define WLFW_DEVICE_INFO_RESP_MSG_V01_MAX_MSG_LEN 25
+
+#define WLFW_DEVICE_INFO_RESP_MSG_V01_MAX_MSG_LEN 43
extern struct qmi_elem_info wlfw_device_info_resp_msg_v01_ei[];
struct wlfw_m3_dump_upload_req_ind_msg_v01 {
@@ -1183,7 +1198,6 @@
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[];
diff --git a/drivers/soc/qcom/icnss2/main.c b/drivers/soc/qcom/icnss2/main.c
index 7fbe376..e82beac 100644
--- a/drivers/soc/qcom/icnss2/main.c
+++ b/drivers/soc/qcom/icnss2/main.c
@@ -618,8 +618,8 @@
}
priv->mem_base_va = devm_ioremap(&priv->pdev->dev,
- priv->mem_base_pa,
- priv->mem_base_size);
+ priv->mem_base_pa,
+ priv->mem_base_size);
if (!priv->mem_base_va) {
icnss_pr_err("Ioremap failed for bar address\n");
goto err_power_on;
@@ -629,6 +629,17 @@
&priv->mem_base_pa,
priv->mem_base_va);
+ if (priv->mhi_state_info_pa)
+ priv->mhi_state_info_va = devm_ioremap(&priv->pdev->dev,
+ priv->mhi_state_info_pa,
+ PAGE_SIZE);
+ if (!priv->mhi_state_info_va)
+ icnss_pr_err("Ioremap failed for MHI info address\n");
+
+ icnss_pr_dbg("MHI state info Address pa: %pa, va: 0x%pK\n",
+ &priv->mhi_state_info_pa,
+ priv->mhi_state_info_va);
+
icnss_wlfw_bdf_dnld_send_sync(priv, ICNSS_BDF_REGDB);
ret = icnss_wlfw_bdf_dnld_send_sync(priv,
@@ -1453,6 +1464,7 @@
break;
case ICNSS_DRIVER_EVENT_M3_DUMP_UPLOAD_REQ:
ret = icnss_m3_dump_upload_req_hdlr(priv, event->data);
+ break;
case ICNSS_DRIVER_EVENT_QDSS_TRACE_REQ_DATA:
ret = icnss_qdss_trace_req_data_hdlr(priv,
event->data);
@@ -1977,7 +1989,8 @@
return 0;
}
-static int icnss_trigger_ssr_smp2p(struct icnss_priv *priv)
+static int icnss_send_smp2p(struct icnss_priv *priv,
+ enum icnss_smp2p_msg_id msg_id)
{
unsigned int value = 0;
int ret;
@@ -1985,19 +1998,22 @@
if (IS_ERR(priv->smp2p_info.smem_state))
return -EINVAL;
+ if (test_bit(ICNSS_FW_DOWN, &priv->state))
+ return -ENODEV;
+
value |= priv->smp2p_info.seq++;
value <<= ICNSS_SMEM_SEQ_NO_POS;
- value |= ICNSS_TRIGGER_SSR;
+ value |= msg_id;
+
+ icnss_pr_vdbg1("Sending SMP2P value: 0x%X\n", value);
+
ret = qcom_smem_state_update_bits(
priv->smp2p_info.smem_state,
ICNSS_SMEM_VALUE_MASK,
value);
if (ret)
- icnss_pr_vdbg1("Error in SMP2P sent ret: %d\n", ret);
+ icnss_pr_vdbg1("Error in SMP2P send ret: %d\n", ret);
- icnss_pr_vdbg1("Initiate Root PD restart. SMP2P sent value: 0x%X\n",
- value);
- set_bit(ICNSS_HOST_TRIGGERED_PDR, &priv->state);
return ret;
}
@@ -2470,6 +2486,22 @@
}
EXPORT_SYMBOL(icnss_get_soc_info);
+int icnss_get_mhi_state(struct device *dev)
+{
+ struct icnss_priv *priv = dev_get_drvdata(dev);
+
+ if (!priv) {
+ icnss_pr_err("Platform driver not initialized\n");
+ return -EINVAL;
+ }
+
+ if (!priv->mhi_state_info_va)
+ return -ENOMEM;
+
+ return ioread32(priv->mhi_state_info_va);
+}
+EXPORT_SYMBOL(icnss_get_mhi_state);
+
int icnss_set_fw_log_mode(struct device *dev, uint8_t fw_log_mode)
{
int ret;
@@ -2553,9 +2585,6 @@
{
struct icnss_priv *priv = dev_get_drvdata(dev);
- if (!dev)
- return -ENODEV;
-
if (!priv) {
icnss_pr_err("Platform driver not initialized\n");
return -EINVAL;
@@ -2565,6 +2594,22 @@
}
EXPORT_SYMBOL(icnss_is_device_awake);
+int icnss_is_pci_ep_awake(struct device *dev)
+{
+ struct icnss_priv *priv = dev_get_drvdata(dev);
+
+ if (!priv) {
+ icnss_pr_err("Platform driver not initialized\n");
+ return -EINVAL;
+ }
+
+ if (!priv->mhi_state_info_va)
+ return -ENOMEM;
+
+ return ioread32(priv->mhi_state_info_va + ICNSS_PCI_EP_WAKE_OFFSET);
+}
+EXPORT_SYMBOL(icnss_is_pci_ep_awake);
+
int icnss_athdiag_read(struct device *dev, uint32_t offset,
uint32_t mem_type, uint32_t data_len,
uint8_t *output)
@@ -2846,8 +2891,13 @@
goto out;
}
- if (priv->device_id == WCN6750_DEVICE_ID)
- return icnss_trigger_ssr_smp2p(priv);
+ if (priv->device_id == WCN6750_DEVICE_ID) {
+ icnss_pr_vdbg1("Initiate Root PD restart");
+ ret = icnss_send_smp2p(priv, ICNSS_TRIGGER_SSR);
+ if (!ret)
+ set_bit(ICNSS_HOST_TRIGGERED_PDR, &priv->state);
+ return ret;
+ }
if (!test_bit(ICNSS_PDR_REGISTERED, &priv->state)) {
icnss_pr_err("PD restart not enabled to trigger recovery: state: 0x%lx\n",
@@ -2926,8 +2976,6 @@
int icnss_exit_power_save(struct device *dev)
{
struct icnss_priv *priv = dev_get_drvdata(dev);
- unsigned int value = 0;
- int ret;
icnss_pr_vdbg1("Calling Exit Power Save\n");
@@ -2935,21 +2983,34 @@
!test_bit(ICNSS_MODE_ON, &priv->state))
return 0;
- value |= priv->smp2p_info.seq++;
- value <<= ICNSS_SMEM_SEQ_NO_POS;
- value |= ICNSS_POWER_SAVE_EXIT;
- ret = qcom_smem_state_update_bits(
- priv->smp2p_info.smem_state,
- ICNSS_SMEM_VALUE_MASK,
- value);
- if (ret)
- icnss_pr_vdbg1("Error in SMP2P sent ret: %d\n", ret);
-
- icnss_pr_vdbg1("SMP2P sent value: 0x%X\n", value);
- return ret;
+ return icnss_send_smp2p(priv, ICNSS_POWER_SAVE_EXIT);
}
EXPORT_SYMBOL(icnss_exit_power_save);
+int icnss_prevent_l1(struct device *dev)
+{
+ struct icnss_priv *priv = dev_get_drvdata(dev);
+
+ if (test_bit(ICNSS_PD_RESTART, &priv->state) ||
+ !test_bit(ICNSS_MODE_ON, &priv->state))
+ return 0;
+
+ return icnss_send_smp2p(priv, ICNSS_PCI_EP_POWER_SAVE_EXIT);
+}
+EXPORT_SYMBOL(icnss_prevent_l1);
+
+void icnss_allow_l1(struct device *dev)
+{
+ struct icnss_priv *priv = dev_get_drvdata(dev);
+
+ if (test_bit(ICNSS_PD_RESTART, &priv->state) ||
+ !test_bit(ICNSS_MODE_ON, &priv->state))
+ return;
+
+ icnss_send_smp2p(priv, ICNSS_PCI_EP_POWER_SAVE_ENTER);
+}
+EXPORT_SYMBOL(icnss_allow_l1);
+
void icnss_allow_recursive_recovery(struct device *dev)
{
struct icnss_priv *priv = dev_get_drvdata(dev);
@@ -3699,7 +3760,6 @@
static int icnss_pm_suspend(struct device *dev)
{
struct icnss_priv *priv = dev_get_drvdata(dev);
- unsigned int value = 0;
int ret = 0;
if (priv->magic != ICNSS_MAGIC) {
@@ -3723,19 +3783,7 @@
!test_bit(ICNSS_MODE_ON, &priv->state))
return 0;
- value |= priv->smp2p_info.seq++;
- value <<= ICNSS_SMEM_SEQ_NO_POS;
- value |= ICNSS_POWER_SAVE_ENTER;
-
- ret = qcom_smem_state_update_bits(
- priv->smp2p_info.smem_state,
- ICNSS_SMEM_VALUE_MASK,
- value);
- if (ret)
- icnss_pr_vdbg1("Error in SMP2P sent ret: %d\n",
- ret);
-
- icnss_pr_vdbg1("SMP2P sent value: 0x%X\n", value);
+ ret = icnss_send_smp2p(priv, ICNSS_POWER_SAVE_ENTER);
}
priv->stats.pm_suspend++;
set_bit(ICNSS_PM_SUSPEND, &priv->state);
@@ -3836,7 +3884,6 @@
static int icnss_pm_runtime_suspend(struct device *dev)
{
struct icnss_priv *priv = dev_get_drvdata(dev);
- unsigned int value = 0;
int ret = 0;
if (priv->magic != ICNSS_MAGIC) {
@@ -3856,18 +3903,7 @@
!test_bit(ICNSS_MODE_ON, &priv->state))
return 0;
- value |= priv->smp2p_info.seq++;
- value <<= ICNSS_SMEM_SEQ_NO_POS;
- value |= ICNSS_POWER_SAVE_ENTER;
-
- ret = qcom_smem_state_update_bits(
- priv->smp2p_info.smem_state,
- ICNSS_SMEM_VALUE_MASK,
- value);
- if (ret)
- icnss_pr_vdbg1("Error in SMP2P sent ret: %d\n", ret);
-
- icnss_pr_vdbg1("SMP2P sent value: 0x%X\n", value);
+ ret = icnss_send_smp2p(priv, ICNSS_POWER_SAVE_ENTER);
}
out:
return ret;
diff --git a/drivers/soc/qcom/icnss2/main.h b/drivers/soc/qcom/icnss2/main.h
index c4901a6..1354ca8 100644
--- a/drivers/soc/qcom/icnss2/main.h
+++ b/drivers/soc/qcom/icnss2/main.h
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
- * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved.
*/
#ifndef __MAIN_H__
@@ -25,6 +25,7 @@
#define THERMAL_NAME_LENGTH 20
#define ICNSS_SMEM_VALUE_MASK 0xFFFFFFFF
#define ICNSS_SMEM_SEQ_NO_POS 16
+#define ICNSS_PCI_EP_WAKE_OFFSET 4
extern uint64_t dynamic_feature_mask;
@@ -178,6 +179,8 @@
ICNSS_POWER_SAVE_ENTER = 1,
ICNSS_POWER_SAVE_EXIT,
ICNSS_TRIGGER_SSR,
+ ICNSS_PCI_EP_POWER_SAVE_ENTER = 6,
+ ICNSS_PCI_EP_POWER_SAVE_EXIT,
};
struct icnss_stats {
@@ -342,6 +345,9 @@
phys_addr_t mem_base_pa;
void __iomem *mem_base_va;
u32 mem_base_size;
+ phys_addr_t mhi_state_info_pa;
+ void __iomem *mhi_state_info_va;
+ u32 mhi_state_info_size;
struct iommu_domain *iommu_domain;
dma_addr_t smmu_iova_start;
size_t smmu_iova_len;
diff --git a/drivers/soc/qcom/icnss2/qmi.c b/drivers/soc/qcom/icnss2/qmi.c
index 8a8b576..fad86c7 100644
--- a/drivers/soc/qcom/icnss2/qmi.c
+++ b/drivers/soc/qcom/icnss2/qmi.c
@@ -334,6 +334,15 @@
goto out;
}
+ if (resp->mhi_state_info_addr_valid)
+ priv->mhi_state_info_pa = resp->mhi_state_info_addr;
+
+ if (resp->mhi_state_info_size_valid)
+ priv->mhi_state_info_size = resp->mhi_state_info_size;
+
+ if (!priv->mhi_state_info_pa)
+ icnss_pr_err("Fail to get MHI info address\n");
+
kfree(resp);
kfree(req);
return 0;
diff --git a/include/soc/qcom/icnss2.h b/include/soc/qcom/icnss2.h
index 940241e..0a1406c 100644
--- a/include/soc/qcom/icnss2.h
+++ b/include/soc/qcom/icnss2.h
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
- * Copyright (c) 2015-2020, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2015-2021, The Linux Foundation. All rights reserved.
*/
#ifndef _ICNSS_WLAN_H_
#define _ICNSS_WLAN_H_
@@ -191,4 +191,8 @@
unsigned long *thermal_state,
int tcdev_id);
extern int icnss_exit_power_save(struct device *dev);
+extern int icnss_prevent_l1(struct device *dev);
+extern void icnss_allow_l1(struct device *dev);
+extern int icnss_get_mhi_state(struct device *dev);
+extern int icnss_is_pci_ep_awake(struct device *dev);
#endif /* _ICNSS_WLAN_H_ */