Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 2b63b9c9 authored by Naman Padhiar's avatar Naman Padhiar
Browse files

icnss2: Add support for MHI state info



Read MHI state from MSA and export API to get MHI state.
Add SMP2P handshakes according to below sequence to manage
PCI EP low power state.
1. Host driver calls prevent_l1.
2. ICNSS sends SMP2P to FW with PCI_EP_POWER_SAVE_EXIT.
3. FW bring EP out of power save and update in memory
   location.
4. Once Host reads updated value it access registers.
4. Host driver calls allow_l1.
5. ICNSS send SMP2P to FW with PCI_EP_POWER_SAVE_ENTER.

Change-Id: Ia93a270cbe86d1fb7c8402c69eb9b64b1400abb6
Signed-off-by: default avatarNaman Padhiar <npadhiar@codeaurora.org>
parent b78bfb96
Loading
Loading
Loading
Loading
+115 −18
Original line number Diff line number Diff line
// 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 @@ static struct qmi_elem_info wlfw_m3_segment_info_s_v01_ei[] = {
		.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 @@ static struct qmi_elem_info wlfw_m3_segment_info_s_v01_ei[] = {
		.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 @@ static struct qmi_elem_info wlfw_m3_segment_info_s_v01_ei[] = {
		.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 @@ static struct qmi_elem_info wlfw_m3_segment_info_s_v01_ei[] = {
		.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 @@ static struct qmi_elem_info wlfw_dev_mem_info_s_v01_ei[] = {
		.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 @@ static struct qmi_elem_info wlfw_dev_mem_info_s_v01_ei[] = {
		.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 @@ struct qmi_elem_info wlfw_ind_register_req_msg_v01_ei[] = {
		.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 @@ struct qmi_elem_info wlfw_ind_register_req_msg_v01_ei[] = {
		.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 @@ struct qmi_elem_info wlfw_cap_resp_msg_v01_ei[] = {
		.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 @@ struct qmi_elem_info wlfw_cap_resp_msg_v01_ei[] = {
		.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,
	},
@@ -1804,6 +1814,26 @@ struct qmi_elem_info wlfw_cal_report_req_msg_v01_ei[] = {
		.offset         = offsetof(struct wlfw_cal_report_req_msg_v01,
					   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,
@@ -3041,7 +3071,8 @@ struct qmi_elem_info wlfw_fw_init_done_ind_msg_v01_ei[] = {
		.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 @@ struct qmi_elem_info wlfw_fw_init_done_ind_msg_v01_ei[] = {
		.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 @@ struct qmi_elem_info wlfw_fw_init_done_ind_msg_v01_ei[] = {
		.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 @@ struct qmi_elem_info wlfw_fw_init_done_ind_msg_v01_ei[] = {
		.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),
	},
	{
@@ -3334,6 +3368,26 @@ struct qmi_elem_info wlfw_xo_cal_ind_msg_v01_ei[] = {
};

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,
@@ -4368,6 +4422,46 @@ struct qmi_elem_info wlfw_device_info_resp_msg_v01_ei[] = {
		.offset         = offsetof(struct wlfw_device_info_resp_msg_v01,
					   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,
@@ -4730,7 +4824,8 @@ struct qmi_elem_info wlfw_m3_dump_upload_segments_req_ind_msg_v01_ei[] = {
		.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 @@ struct qmi_elem_info wlfw_m3_dump_upload_segments_req_ind_msg_v01_ei[] = {
		.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 @@ struct qmi_elem_info wlfw_m3_dump_upload_segments_req_ind_msg_v01_ei[] = {
		.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,
	},
+30 −16
Original line number Diff line number Diff line
/* 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 @@ struct wlfw_ind_register_req_msg_v01 {
	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_cap_resp_msg_v01 {
	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 @@ struct wlfw_cal_report_req_msg_v01 {
	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 @@ struct wlfw_request_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_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 @@ struct wlfw_fw_init_done_ind_msg_v01 {
	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 @@ struct wlfw_xo_cal_ind_msg_v01 {
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 @@ struct wlfw_qdss_trace_save_ind_msg_v01 {
	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 @@ struct wlfw_qdss_trace_free_ind_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_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 @@ extern struct qmi_elem_info wlfw_get_info_req_msg_v01_ei[];
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 @@ struct wlfw_device_info_resp_msg_v01 {
	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_dump_upload_segments_req_ind_msg_v01 {
	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[];

+90 −54
Original line number Diff line number Diff line
@@ -629,6 +629,17 @@ static int icnss_driver_event_server_arrive(struct icnss_priv *priv,
			     &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 @@ static void icnss_driver_event_work(struct work_struct *work)
			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 @@ static int icnss_enable_recovery(struct icnss_priv *priv)
	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 @@ static int icnss_trigger_ssr_smp2p(struct icnss_priv *priv)
	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 @@ int icnss_get_soc_info(struct device *dev, struct icnss_soc_info *info)
}
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 @@ int icnss_is_device_awake(struct device *dev)
{
	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 @@ int icnss_is_device_awake(struct device *dev)
}
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 @@ int icnss_trigger_recovery(struct device *dev)
		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 @@ EXPORT_SYMBOL(icnss_idle_restart);
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 @@ int icnss_exit_power_save(struct device *dev)
	    !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_remove(struct platform_device *pdev)
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 @@ static int icnss_pm_suspend(struct device *dev)
			    !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_resume_noirq(struct device *dev)
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 @@ static int icnss_pm_runtime_suspend(struct device *dev)
		    !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;
+7 −1
Original line number Diff line number Diff line
/* 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 @@ enum icnss_smp2p_msg_id {
	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 @@ struct icnss_priv {
	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;
+9 −0
Original line number Diff line number Diff line
@@ -334,6 +334,15 @@ int wlfw_device_info_send_msg(struct icnss_priv *priv)
		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;
Loading