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

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

Merge "icnss: Update the smp2p node parsing"

parents 30072165 8fc75829
Loading
Loading
Loading
Loading
+11 −4
Original line number Diff line number Diff line
@@ -29,10 +29,13 @@ 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.
  - qcom,gpio-early-crash-ind: SMP2P bit triggered by WLAN FW to indicate FW is in assert.
  - qcom,hyp_disabled: Boolean context flag to disable hyperviser

WLAN SMP2P sub nodes

  - qcom,smp2p_map_wlan_1_in - represents the in smp2p to
				  wlan driver from modem.

Example:

    qcom,icnss@0a000000 {
@@ -62,7 +65,11 @@ 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>;
	qcom,gpio-early-crash-ind = <&smp2pgpio_wlan_1_in 1 0>;
	qcom,hyp_disabled;
	qcom,smp2p_map_wlan_1_in {
		interrupts-extended = <&smp2p_wlan_1_in 0 0>,
			<&smp2p_wlan_1_in 1 0>;
		interrupt-names = "qcom,smp2p-force-fatal-error",
			"qcom,smp2p-early-crash-ind";
	};
    };
+75 −40
Original line number Diff line number Diff line
@@ -36,7 +36,8 @@
#include <linux/thread_info.h>
#include <linux/uaccess.h>
#include <linux/etherdevice.h>
#include <linux/of_gpio.h>
#include <linux/of.h>
#include <linux/of_irq.h>
#include <linux/soc/qcom/qmi.h>
#include <soc/qcom/memory_dump.h>
#include <soc/qcom/icnss.h>
@@ -653,10 +654,17 @@ static irqreturn_t fw_error_fatal_handler(int irq, void *ctx)
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};

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

	if (priv) {
		if (test_bit(ICNSS_FW_READY, &priv->state) &&
		    !test_bit(ICNSS_DRIVER_UNLOADING, &priv->state)) {
			fw_down_data.crashed = true;
			icnss_call_driver_uevent(priv, ICNSS_UEVENT_FW_DOWN,
						 &fw_down_data);
		}
		set_bit(ICNSS_FW_DOWN, &priv->state);
		icnss_ignore_fw_timeout(true);
	}
@@ -667,61 +675,84 @@ static irqreturn_t fw_crash_indication_handler(int irq, void *ctx)
	return IRQ_HANDLED;
}

static void register_fw_error_notifications(struct icnss_priv *priv)
static void register_fw_error_notifications(struct device *dev)
{
	int gpio, irq, ret;
	struct icnss_priv *priv = dev_get_drvdata(dev);
	struct device_node *dev_node;
	int irq = 0, ret = 0;

	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);
	if (!priv)
		return;
	}
	irq = gpio_to_irq(gpio);
	if (irq < 0) {
		icnss_pr_err("Invalid IRQ for error fatal smp2p %u\n", irq);

	dev_node = of_find_node_by_name(NULL, "qcom,smp2p_map_wlan_1_in");
	if (!dev_node) {
		icnss_pr_err("Failed to get smp2p node for force-fatal-error\n");
		return;
	}
	ret = request_irq(irq, fw_error_fatal_handler,
			IRQF_TRIGGER_RISING, "wlanfw-err", priv);

	icnss_pr_dbg("smp2p node->name=%s\n", dev_node->name);

	if (strcmp("qcom,smp2p_map_wlan_1_in", dev_node->name) == 0) {
		ret = irq = of_irq_get_byname(dev_node,
					      "qcom,smp2p-force-fatal-error");
		if (ret < 0) {
		icnss_pr_err("Unable to register for error fatal IRQ handler %d",
			icnss_pr_err("Unable to get force-fatal-error irq %d\n",
				     irq);
			return;
		}
	icnss_pr_dbg("FW force error fatal handler registered\n");
	}

	if (!of_find_property(priv->pdev->dev.of_node,
				"qcom,gpio-early-crash-ind", NULL)) {
		icnss_pr_dbg("FW early crash indication handler not registered\n");
	ret = devm_request_threaded_irq(dev, irq, NULL, fw_error_fatal_handler,
					IRQF_TRIGGER_RISING, "wlanfw-err",
					priv);
	if (ret < 0) {
		icnss_pr_err("Unable to register for error fatal IRQ handler %d ret = %d",
			     irq, ret);
		return;
	}
	gpio = of_get_named_gpio(priv->pdev->dev.of_node,
				"qcom,gpio-early-crash-ind", 0);
	if (!gpio_is_valid(gpio)) {
		icnss_pr_err("Invalid GPIO for early crash indication %d\n",
				gpio);
	icnss_pr_dbg("FW force error fatal handler registered irq = %d\n", irq);
	priv->fw_error_fatal_irq = irq;
}

static void register_early_crash_notifications(struct device *dev)
{
	struct icnss_priv *priv = dev_get_drvdata(dev);
	struct device_node *dev_node;
	int irq = 0, ret = 0;

	if (!priv)
		return;

	dev_node = of_find_node_by_name(NULL, "qcom,smp2p_map_wlan_1_in");
	if (!dev_node) {
		icnss_pr_err("Failed to get smp2p node for early-crash-ind\n");
		return;
	}
	irq = gpio_to_irq(gpio);
	if (irq < 0) {
		icnss_pr_err("Invalid IRQ for early crash indication %u\n",

	icnss_pr_dbg("smp2p node->name=%s\n", dev_node->name);

	if (strcmp("qcom,smp2p_map_wlan_1_in", dev_node->name) == 0) {
		ret = irq = of_irq_get_byname(dev_node,
					      "qcom,smp2p-early-crash-ind");
		if (ret < 0) {
			icnss_pr_err("Unable to get early-crash-ind irq %d\n",
				     irq);
			return;
		}
	ret = request_irq(irq, fw_crash_indication_handler,
			IRQF_TRIGGER_RISING, "wlanfw-early-crash-ind", priv);
	}

	ret = devm_request_threaded_irq(dev, irq, NULL,
					fw_crash_indication_handler,
					IRQF_TRIGGER_RISING,
					"wlanfw-early-crash-ind",
					priv);
	if (ret < 0) {
		icnss_pr_err("Unable to register for early crash indication IRQ handler %d",
				irq);
		icnss_pr_err("Unable to register for early crash indication IRQ handler %d ret = %d",
			     irq, ret);
		return;
	}
	icnss_pr_dbg("FW crash indication handler registered\n");
	icnss_pr_dbg("FW crash indication handler registered irq = %d\n", irq);
	priv->fw_early_crash_irq = irq;
}

int icnss_call_driver_uevent(struct icnss_priv *priv,
@@ -794,7 +825,11 @@ static int icnss_driver_event_server_arrive(void *data)
	wlfw_dynamic_feature_mask_send_sync_msg(penv,
						dynamic_feature_mask);

	register_fw_error_notifications(penv);
	if (!penv->fw_error_fatal_irq)
		register_fw_error_notifications(&penv->pdev->dev);

	if (!penv->fw_early_crash_irq)
		register_early_crash_notifications(&penv->pdev->dev);

	return ret;

+2 −0
Original line number Diff line number Diff line
@@ -348,6 +348,8 @@ struct icnss_priv {
	u16 line_number;
	struct mutex dev_lock;
	bool is_hyp_disabled;
	uint32_t fw_error_fatal_irq;
	uint32_t fw_early_crash_irq;
	char function_name[WLFW_FUNCTION_NAME_LEN + 1];
};