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

Commit d6b71839 authored by qctecmdr's avatar qctecmdr Committed by Gerrit - the friendly Code Review server
Browse files

Merge "icnss: Add icnss code to handle hang event data"

parents 24cb777b 5e6e9898
Loading
Loading
Loading
Loading
+43 −10
Original line number Diff line number Diff line
@@ -571,6 +571,27 @@ int icnss_power_off(struct device *dev)
}
EXPORT_SYMBOL(icnss_power_off);

int icnss_update_fw_down_params(struct icnss_priv *priv,
				struct icnss_uevent_fw_down_data *fw_down_data,
				bool crashed)
{
	fw_down_data->crashed = crashed;

	if (!priv->hang_event_data_va)
		return -EINVAL;

	priv->hang_event_data = kmemdup(priv->hang_event_data_va,
					priv->hang_event_data_len,
					GFP_ATOMIC);
	if (!priv->hang_event_data)
		return -ENOMEM;

	// Update the hang event params
	fw_down_data->hang_event_data = priv->hang_event_data;
	fw_down_data->hang_event_data_len = priv->hang_event_data_len;
	return 0;
}

static irqreturn_t fw_error_fatal_handler(int irq, void *ctx)
{
	struct icnss_priv *priv = ctx;
@@ -587,6 +608,7 @@ static irqreturn_t fw_crash_indication_handler(int irq, void *ctx)
{
	struct icnss_priv *priv = ctx;
	struct icnss_uevent_fw_down_data fw_down_data = {0};
	int ret = 0;

	icnss_pr_err("Received early crash indication from FW\n");

@@ -595,9 +617,18 @@ static irqreturn_t fw_crash_indication_handler(int irq, void *ctx)
		icnss_ignore_fw_timeout(true);

		if (test_bit(ICNSS_FW_READY, &priv->state)) {
			fw_down_data.crashed = true;
			ret = icnss_update_fw_down_params(priv, &fw_down_data,
							  true);
			if (ret)
				icnss_pr_err("Unable to allocate memory for Hang event data\n");

			icnss_call_driver_uevent(priv, ICNSS_UEVENT_FW_DOWN,
						 &fw_down_data);

			if (!ret) {
				kfree(priv->hang_event_data);
				priv->hang_event_data = NULL;
			}
		}
	}

@@ -1426,7 +1457,7 @@ static int icnss_modem_notifier_nb(struct notifier_block *nb,
	struct notif_data *notif = data;
	struct icnss_priv *priv = container_of(nb, struct icnss_priv,
					       modem_ssr_nb);
	struct icnss_uevent_fw_down_data fw_down_data;
	struct icnss_uevent_fw_down_data fw_down_data = {0};

	icnss_pr_vdbg("Modem-Notify: event %lu\n", code);

@@ -1449,11 +1480,12 @@ static int icnss_modem_notifier_nb(struct notifier_block *nb,
		set_bit(ICNSS_FW_DOWN, &priv->state);
		icnss_ignore_fw_timeout(true);

		if (test_bit(ICNSS_FW_READY, &priv->state)) {
			fw_down_data.crashed = !!notif->crashed;
		if (test_bit(ICNSS_FW_READY, &priv->state))
			icnss_call_driver_uevent(priv,
						 ICNSS_UEVENT_FW_DOWN,
						 &fw_down_data);
		}
		return NOTIFY_OK;
	}

@@ -1476,12 +1508,12 @@ static int icnss_modem_notifier_nb(struct notifier_block *nb,

	event_data->crashed = notif->crashed;

	if (test_bit(ICNSS_FW_READY, &priv->state)) {
		fw_down_data.crashed = !!notif->crashed;
	if (test_bit(ICNSS_FW_READY, &priv->state))
		icnss_call_driver_uevent(priv,
					 ICNSS_UEVENT_FW_DOWN,
					 &fw_down_data);

	}
	icnss_driver_event_post(ICNSS_DRIVER_EVENT_PD_SERVICE_DOWN,
				ICNSS_EVENT_SYNC, event_data);

@@ -1545,7 +1577,7 @@ static int icnss_service_notifier_notify(struct notifier_block *nb,
					       service_notifier_nb);
	enum pd_subsys_state *state = data;
	struct icnss_event_pd_service_down_data *event_data;
	struct icnss_uevent_fw_down_data fw_down_data;
	struct icnss_uevent_fw_down_data fw_down_data = {0};
	enum icnss_pdr_cause_index cause = ICNSS_ROOT_PD_CRASH;

	icnss_pr_dbg("PD service notification: 0x%lx state: 0x%lx\n",
@@ -1598,12 +1630,13 @@ static int icnss_service_notifier_notify(struct notifier_block *nb,
		set_bit(ICNSS_FW_DOWN, &priv->state);
		icnss_ignore_fw_timeout(true);

		if (test_bit(ICNSS_FW_READY, &priv->state)) {
			fw_down_data.crashed = event_data->crashed;
		if (test_bit(ICNSS_FW_READY, &priv->state))
			icnss_call_driver_uevent(priv,
						 ICNSS_UEVENT_FW_DOWN,
						 &fw_down_data);
		}
	}

	clear_bit(ICNSS_HOST_TRIGGERED_PDR, &priv->state);
	icnss_driver_event_post(ICNSS_DRIVER_EVENT_PD_SERVICE_DOWN,
+5 −1
Original line number Diff line number Diff line
@@ -253,6 +253,7 @@ struct icnss_stats {
#define WLFW_MAX_NUM_CE 12
#define WLFW_MAX_NUM_SVC 24
#define WLFW_MAX_NUM_SHADOW_REG 24
#define WLFW_MAX_HANG_EVENT_DATA_SIZE 400

struct service_notifier_context {
	void *handle;
@@ -350,7 +351,10 @@ struct icnss_priv {
	bool is_ssr;
	struct kobject *icnss_kobject;
	atomic_t is_shutdown;

	phys_addr_t hang_event_data_pa;
	void __iomem *hang_event_data_va;
	uint16_t hang_event_data_len;
	void *hang_event_data;
};

struct icnss_reg_info {
+59 −1
Original line number Diff line number Diff line
@@ -19,6 +19,7 @@
#include <linux/ipc_logging.h>
#include <linux/thread_info.h>
#include <linux/soc/qcom/qmi.h>
#include <linux/platform_device.h>
#include <soc/qcom/icnss.h>
#include <soc/qcom/service-locator.h>
#include <soc/qcom/service-notifier.h>
@@ -1012,7 +1013,7 @@ int wlfw_dynamic_feature_mask_send_sync_msg(struct icnss_priv *priv,
void icnss_handle_rejuvenate(struct icnss_priv *priv)
{
	struct icnss_event_pd_service_down_data *event_data;
	struct icnss_uevent_fw_down_data fw_down_data;
	struct icnss_uevent_fw_down_data fw_down_data = {0};

	event_data = kzalloc(sizeof(*event_data), GFP_KERNEL);
	if (event_data == NULL)
@@ -1047,6 +1048,10 @@ static void msa_ready_ind_cb(struct qmi_handle *qmi, struct sockaddr_qrtr *sq,
			     struct qmi_txn *txn, const void *data)
{
	struct icnss_priv *priv = container_of(qmi, struct icnss_priv, qmi);
	struct device *dev = &priv->pdev->dev;
	const struct wlfw_msa_ready_ind_msg_v01 *ind_msg = data;
	uint64_t msa_base_addr = priv->msa_pa;
	phys_addr_t hang_data_phy_addr;

	icnss_pr_dbg("Received MSA Ready Indication\n");

@@ -1056,6 +1061,59 @@ static void msa_ready_ind_cb(struct qmi_handle *qmi, struct sockaddr_qrtr *sq,
	}

	priv->stats.msa_ready_ind++;

	/* Check if the length is valid &
	 * the length should not be 0 and
	 * should be <=  WLFW_MAX_HANG_EVENT_DATA_SIZE(400)
	 */

	if (ind_msg->hang_data_length_valid &&
	    ind_msg->hang_data_length &&
	    ind_msg->hang_data_length <= WLFW_MAX_HANG_EVENT_DATA_SIZE)
		priv->hang_event_data_len = ind_msg->hang_data_length;
	else
		goto out;

	/* Check if the offset is valid &
	 * the offset should be in range of 0 to msa_mem_size-hang_data_length
	 */

	if (ind_msg->hang_data_addr_offset_valid &&
	    (ind_msg->hang_data_addr_offset <= (priv->msa_mem_size -
						 ind_msg->hang_data_length)))
		hang_data_phy_addr = msa_base_addr +
						ind_msg->hang_data_addr_offset;
	else
		goto out;

	if (priv->hang_event_data_pa == hang_data_phy_addr)
		goto exit;

	priv->hang_event_data_pa = hang_data_phy_addr;
	priv->hang_event_data_va = devm_ioremap(dev, priv->hang_event_data_pa,
						ind_msg->hang_data_length);

	if (!priv->hang_event_data_va) {
		icnss_pr_err("Hang Data ioremap failed: phy addr: %pa\n",
			     &priv->hang_event_data_pa);
		goto fail;
	}
exit:
	icnss_pr_dbg("Hang Event Data details,Offset:0x%x, Length:0x%x,va_addr: 0x%pK\n",
		     ind_msg->hang_data_addr_offset,
		     ind_msg->hang_data_length,
		     priv->hang_event_data_va);

	return;

out:
	icnss_pr_err("Invalid Hang Data details, Offset:0x%x, Length:0x%x",
		     ind_msg->hang_data_addr_offset,
		     ind_msg->hang_data_length);
fail:
	priv->hang_event_data_va = NULL;
	priv->hang_event_data_pa = 0;
	priv->hang_event_data_len = 0;
}

static void pin_connect_result_ind_cb(struct qmi_handle *qmi,
+37 −1
Original line number Diff line number Diff line
// SPDX-License-Identifier: GPL-2.0-only
/*
 * Copyright (c) 2018-2019, The Linux Foundation. All rights reserved.
 * Copyright (c) 2018-2020, The Linux Foundation. All rights reserved.
 */
#include <linux/soc/qcom/qmi.h>

@@ -512,6 +512,42 @@ struct qmi_elem_info wlfw_fw_ready_ind_msg_v01_ei[] = {
};

struct qmi_elem_info wlfw_msa_ready_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_msa_ready_ind_msg_v01,
					   hang_data_addr_offset_valid),
	},
	{
		.data_type      = QMI_UNSIGNED_4_BYTE,
		.elem_len       = 1,
		.elem_size      = sizeof(u32),
		.array_type       = NO_ARRAY,
		.tlv_type       = 0x10,
		.offset         = offsetof(struct wlfw_msa_ready_ind_msg_v01,
					   hang_data_addr_offset),
	},
	{
		.data_type      = QMI_OPT_FLAG,
		.elem_len       = 1,
		.elem_size      = sizeof(u8),
		.array_type       = NO_ARRAY,
		.tlv_type       = 0x11,
		.offset         = offsetof(struct wlfw_msa_ready_ind_msg_v01,
					   hang_data_length_valid),
	},
	{
		.data_type      = QMI_UNSIGNED_2_BYTE,
		.elem_len       = 1,
		.elem_size      = sizeof(u16),
		.array_type       = NO_ARRAY,
		.tlv_type       = 0x11,
		.offset         = offsetof(struct wlfw_msa_ready_ind_msg_v01,
					   hang_data_length),
	},
	{
		.data_type      = QMI_EOTI,
		.array_type       = NO_ARRAY,
+6 −3
Original line number Diff line number Diff line
/* SPDX-License-Identifier: GPL-2.0-only */
/*
 * Copyright (c) 2018-2019, The Linux Foundation. All rights reserved.
 * Copyright (c) 2018-2020, The Linux Foundation. All rights reserved.
 */
#ifndef WLAN_FIRMWARE_SERVICE_V01_H
#define WLAN_FIRMWARE_SERVICE_V01_H
@@ -211,9 +211,12 @@ struct wlfw_fw_ready_ind_msg_v01 {
extern struct qmi_elem_info wlfw_fw_ready_ind_msg_v01_ei[];

struct wlfw_msa_ready_ind_msg_v01 {
	char placeholder;
	u8 hang_data_addr_offset_valid;
	u32 hang_data_addr_offset;
	u8 hang_data_length_valid;
	u16 hang_data_length;
};
#define WLFW_MSA_READY_IND_MSG_V01_MAX_MSG_LEN 0
#define WLFW_MSA_READY_IND_MSG_V01_MAX_MSG_LEN 12
extern struct qmi_elem_info wlfw_msa_ready_ind_msg_v01_ei[];

struct wlfw_pin_connect_result_ind_msg_v01 {
Loading