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

Commit 5718dfc6 authored by Yuanyuan Liu's avatar Yuanyuan Liu
Browse files

icnss: Do not send uevent when driver is unloading



If modem crashed during wlan driver unloading, icnss driver
will call driver uevent callback to send FW down uevent when
it receives BEFORE_SHUTDOWN notification. If wlan driver is
de-initialized just before the callback is called, kernel will
panic as driver's context is freed. This can be avoid by not
sending uevent when wlan host driver is unloading. Instead,
icnss driver will provide an API to host driver to check if
WLAN FW is down or not.

CRs-Fixed: 2161425
Change-Id: I569fd85366522606ececeda74df85c51b9b2fc28
Signed-off-by: default avatarYuanyuan Liu <yuanliu@codeaurora.org>
parent 373476f5
Loading
Loading
Loading
Loading
+21 −2
Original line number Diff line number Diff line
@@ -281,6 +281,7 @@ enum icnss_driver_state {
	ICNSS_SHUTDOWN_DONE,
	ICNSS_HOST_TRIGGERED_PDR,
	ICNSS_FW_DOWN,
	ICNSS_DRIVER_UNLOADING,
};

struct ce_irq_list {
@@ -1149,6 +1150,16 @@ bool icnss_is_fw_ready(void)
}
EXPORT_SYMBOL(icnss_is_fw_ready);

bool icnss_is_fw_down(void)
{
	if (!penv)
		return false;
	else
		return test_bit(ICNSS_FW_DOWN, &penv->state);
}
EXPORT_SYMBOL(icnss_is_fw_down);


int icnss_power_off(struct device *dev)
{
	struct icnss_priv *priv = dev_get_drvdata(dev);
@@ -2279,9 +2290,11 @@ static int icnss_driver_event_unregister_driver(void *data)
		goto out;
	}

	set_bit(ICNSS_DRIVER_UNLOADING, &penv->state);
	if (penv->ops)
		penv->ops->remove(&penv->pdev->dev);

	clear_bit(ICNSS_DRIVER_UNLOADING, &penv->state);
	clear_bit(ICNSS_DRIVER_PROBED, &penv->state);

	penv->ops = NULL;
@@ -2304,8 +2317,10 @@ static int icnss_call_driver_remove(struct icnss_priv *priv)
	if (!priv->ops || !priv->ops->remove)
		return 0;

	set_bit(ICNSS_DRIVER_UNLOADING, &penv->state);
	penv->ops->remove(&priv->pdev->dev);

	clear_bit(ICNSS_DRIVER_UNLOADING, &penv->state);
	clear_bit(ICNSS_DRIVER_PROBED, &priv->state);

	icnss_hw_power_off(penv);
@@ -2511,7 +2526,8 @@ static int icnss_modem_notifier_nb(struct notifier_block *nb,
		icnss_ignore_qmi_timeout(true);

		fw_down_data.crashed = !!notif->crashed;
		if (test_bit(ICNSS_FW_READY, &priv->state))
		if (test_bit(ICNSS_FW_READY, &priv->state) &&
		    !test_bit(ICNSS_DRIVER_UNLOADING, &priv->state))
			icnss_call_driver_uevent(priv,
						 ICNSS_UEVENT_FW_DOWN,
						 &fw_down_data);
@@ -2655,7 +2671,8 @@ static int icnss_service_notifier_notify(struct notifier_block *nb,
		icnss_ignore_qmi_timeout(true);

		fw_down_data.crashed = event_data->crashed;
		if (test_bit(ICNSS_FW_READY, &priv->state))
		if (test_bit(ICNSS_FW_READY, &priv->state) &&
		    !test_bit(ICNSS_DRIVER_UNLOADING, &priv->state))
			icnss_call_driver_uevent(priv,
						 ICNSS_UEVENT_FW_DOWN,
						 &fw_down_data);
@@ -3815,6 +3832,8 @@ static int icnss_stats_show_state(struct seq_file *s, struct icnss_priv *priv)
		case ICNSS_FW_DOWN:
			seq_puts(s, "FW DOWN");
			continue;
		case ICNSS_DRIVER_UNLOADING:
			seq_puts(s, "DRIVER UNLOADING");
		}

		seq_printf(s, "UNKNOWN-%d", i);
+1 −0
Original line number Diff line number Diff line
@@ -142,5 +142,6 @@ extern int icnss_smmu_map(struct device *dev, phys_addr_t paddr,
extern unsigned int icnss_socinfo_get_serial_number(struct device *dev);
extern bool icnss_is_qmi_disable(struct device *dev);
extern bool icnss_is_fw_ready(void);
extern bool icnss_is_fw_down(void);
extern int icnss_trigger_recovery(struct device *dev);
#endif /* _ICNSS_WLAN_H_ */