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

Commit 6ce5178b authored by Sameer Thalappil's avatar Sameer Thalappil Committed by Yuanyuan Liu
Browse files

icnss: Add support for force error fatal from WLAN FW



For certain FW failures, SSR dump alone is not sufficient for root
causing the failure reason. For those cases, add support to force
download mode when FW indicates these failures thru a smp2p triggered
error indication.

CRs-Fixed: 2159316
Change-Id: I0a4b040a30f9a5fb5ad3d87273f3dea66f26e98e
Signed-off-by: default avatarSameer Thalappil <sameert@codeaurora.org>
parent e60c815c
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -29,6 +29,7 @@ Optional properties:
  - qcom,icnss-adc_tm: VADC handle for vph_pwr notification APIs.
  - qcom,smmu-s1-bypass: Boolean context flag to set SMMU to S1 bypass
  - qcom,wlan-msa-fixed-region: phandle, specifier pairs to children of /reserved-memory
  - qcom,gpio-force-fatal-error: SMP2P bit triggered by WLAN FW to force error fatal.

Example:

@@ -59,4 +60,5 @@ Example:
	qcom,smmu-s1-bypass;
	vdd-0.8-cx-mx-supply = <&pm8998_l5>;
	qcom,vdd-0.8-cx-mx-config = <800000 800000 2400 1000>;
	qcom,gpio-forced-fatal-error = <&smp2pgpio_wlan_1_in 0 0>;
    };
+47 −0
Original line number Diff line number Diff line
@@ -36,6 +36,7 @@
#include <linux/thread_info.h>
#include <linux/uaccess.h>
#include <linux/etherdevice.h>
#include <linux/of_gpio.h>
#include <soc/qcom/memory_dump.h>
#include <soc/qcom/icnss.h>
#include <soc/qcom/secure_buffer.h>
@@ -607,6 +608,47 @@ int icnss_power_off(struct device *dev)
}
EXPORT_SYMBOL(icnss_power_off);

static irqreturn_t fw_error_fatal_handler(int irq, void *ctx)
{
	struct icnss_priv *priv = ctx;

	if (priv)
		priv->force_err_fatal = true;

	icnss_pr_err("Received force error fatal request from FW\n");

	return IRQ_HANDLED;
}

static void icnss_register_force_error_fatal(struct icnss_priv *priv)
{
	int gpio, irq, ret;

	if (!of_find_property(priv->pdev->dev.of_node,
				"qcom,gpio-force-fatal-error", NULL)) {
		icnss_pr_dbg("Error fatal smp2p handler not registered\n");
		return;
	}
	gpio = of_get_named_gpio(priv->pdev->dev.of_node,
				"qcom,gpio-force-fatal-error", 0);
	if (!gpio_is_valid(gpio)) {
		icnss_pr_err("Invalid GPIO for error fatal smp2p %d\n", gpio);
		return;
	}
	irq = gpio_to_irq(gpio);
	if (irq < 0) {
		icnss_pr_err("Invalid IRQ for error fatal smp2p %u\n", irq);
		return;
	}
	ret = request_irq(irq, fw_error_fatal_handler,
			IRQF_TRIGGER_RISING, "wlanfw-err", priv);
	if (ret < 0) {
		icnss_pr_err("Unable to regiser for error fatal IRQ handler %d",
				irq);
		return;
	}
	icnss_pr_dbg("FW force error fatal handler registered\n");
}

int icnss_call_driver_uevent(struct icnss_priv *priv,
				    enum icnss_uevent uevent, void *data)
@@ -678,6 +720,8 @@ static int icnss_driver_event_server_arrive(void *data)
	wlfw_dynamic_feature_mask_send_sync_msg(penv,
						dynamic_feature_mask);

	icnss_register_force_error_fatal(penv);

	return ret;

err_setup_msa:
@@ -964,6 +1008,9 @@ static int icnss_driver_event_pd_service_down(struct icnss_priv *priv,
		goto out;
	}

	if (priv->force_err_fatal)
		ICNSS_ASSERT(0);

	if (event_data->crashed)
		icnss_fw_crashed(priv, event_data);
	else
+1 −0
Original line number Diff line number Diff line
@@ -332,6 +332,7 @@ struct icnss_priv {
	atomic_t pm_count;
	struct ramdump_device *msa0_dump_dev;
	bool bypass_s1_smmu;
	bool force_err_fatal;
	u8 cause_for_rejuvenation;
	u8 requesting_sub_system;
	u16 line_number;