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

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

Merge "icnss: block modem shutdown during driver reinit"

parents 93dece08 5513c092
Loading
Loading
Loading
Loading
+31 −18
Original line number Diff line number Diff line
@@ -606,6 +606,21 @@ bool icnss_is_fw_ready(void)
}
EXPORT_SYMBOL(icnss_is_fw_ready);

void icnss_block_shutdown(bool status)
{
	if (!penv)
		return;

	if (status) {
		set_bit(ICNSS_BLOCK_SHUTDOWN, &penv->state);
		reinit_completion(&penv->unblock_shutdown);
	} else {
		clear_bit(ICNSS_BLOCK_SHUTDOWN, &penv->state);
		complete(&penv->unblock_shutdown);
	}
}
EXPORT_SYMBOL(icnss_block_shutdown);

bool icnss_is_fw_down(void)
{
	if (!penv)
@@ -885,8 +900,7 @@ static int icnss_call_driver_probe(struct icnss_priv *priv)

	icnss_hw_power_on(priv);

	set_bit(ICNSS_DRIVER_LOADING, &priv->state);
	reinit_completion(&penv->driver_probed);
	icnss_block_shutdown(true);
	while (probe_cnt < ICNSS_MAX_PROBE_CNT) {
		ret = priv->ops->probe(&priv->pdev->dev);
		probe_cnt++;
@@ -896,13 +910,11 @@ static int icnss_call_driver_probe(struct icnss_priv *priv)
	if (ret < 0) {
		icnss_pr_err("Driver probe failed: %d, state: 0x%lx, probe_cnt: %d\n",
			     ret, priv->state, probe_cnt);
		complete(&penv->driver_probed);
		clear_bit(ICNSS_DRIVER_LOADING, &penv->state);
		icnss_block_shutdown(false);
		goto out;
	}

	complete(&penv->driver_probed);
	clear_bit(ICNSS_DRIVER_LOADING, &priv->state);
	icnss_block_shutdown(false);
	set_bit(ICNSS_DRIVER_PROBED, &priv->state);

	return 0;
@@ -960,16 +972,20 @@ static int icnss_pd_restart_complete(struct icnss_priv *priv)

	icnss_hw_power_on(priv);

	icnss_block_shutdown(true);

	ret = priv->ops->reinit(&priv->pdev->dev);
	if (ret < 0) {
		icnss_fatal_err("Driver reinit failed: %d, state: 0x%lx\n",
				ret, priv->state);
		if (!priv->allow_recursive_recovery)
			ICNSS_ASSERT(false);
		icnss_block_shutdown(false);
		goto out_power_off;
	}

out:
	icnss_block_shutdown(false);
	clear_bit(ICNSS_SHUTDOWN_DONE, &penv->state);
	return 0;

@@ -1041,8 +1057,7 @@ static int icnss_driver_event_register_driver(void *data)
	if (ret)
		goto out;

	set_bit(ICNSS_DRIVER_LOADING, &penv->state);
	reinit_completion(&penv->driver_probed);
	icnss_block_shutdown(true);
	while (probe_cnt < ICNSS_MAX_PROBE_CNT) {
		ret = penv->ops->probe(&penv->pdev->dev);
		probe_cnt++;
@@ -1052,13 +1067,11 @@ static int icnss_driver_event_register_driver(void *data)
	if (ret) {
		icnss_pr_err("Driver probe failed: %d, state: 0x%lx, probe_cnt: %d\n",
			     ret, penv->state, probe_cnt);
		clear_bit(ICNSS_DRIVER_LOADING, &penv->state);
		complete(&penv->driver_probed);
		icnss_block_shutdown(false);
		goto power_off;
	}

	complete(&penv->driver_probed);
	clear_bit(ICNSS_DRIVER_LOADING, &penv->state);
	icnss_block_shutdown(false);
	set_bit(ICNSS_DRIVER_PROBED, &penv->state);

	return 0;
@@ -1284,8 +1297,8 @@ static int icnss_modem_notifier_nb(struct notifier_block *nb,
		return NOTIFY_OK;

	if (code == SUBSYS_BEFORE_SHUTDOWN && !notif->crashed &&
	    test_bit(ICNSS_DRIVER_LOADING, &priv->state)) {
		if (!wait_for_completion_timeout(&priv->driver_probed,
	    test_bit(ICNSS_BLOCK_SHUTDOWN, &priv->state)) {
		if (!wait_for_completion_timeout(&priv->unblock_shutdown,
						 PROBE_TIMEOUT))
			icnss_pr_err("wlan driver probe timeout\n");
	}
@@ -2601,8 +2614,8 @@ static int icnss_stats_show_state(struct seq_file *s, struct icnss_priv *priv)
		case ICNSS_MODE_ON:
			seq_puts(s, "MODE ON DONE");
			continue;
		case ICNSS_DRIVER_LOADING:
			seq_puts(s, "WLAN DRIVER LOADING");
		case ICNSS_BLOCK_SHUTDOWN:
			seq_puts(s, "BLOCK SHUTDOWN");
		}

		seq_printf(s, "UNKNOWN-%d", i);
@@ -3226,7 +3239,7 @@ static int icnss_probe(struct platform_device *pdev)

	penv = priv;

	init_completion(&priv->driver_probed);
	init_completion(&priv->unblock_shutdown);

	icnss_pr_info("Platform driver probed successfully\n");

@@ -3250,7 +3263,7 @@ static int icnss_remove(struct platform_device *pdev)

	icnss_debugfs_destroy(penv);

	complete_all(&penv->driver_probed);
	complete_all(&penv->unblock_shutdown);

	icnss_modem_ssr_unregister_notifier(penv);

+2 −2
Original line number Diff line number Diff line
@@ -156,7 +156,7 @@ enum icnss_driver_state {
	ICNSS_DRIVER_UNLOADING,
	ICNSS_REJUVENATE,
	ICNSS_MODE_ON,
	ICNSS_DRIVER_LOADING,
	ICNSS_BLOCK_SHUTDOWN,
};

struct ce_irq_list {
@@ -355,7 +355,7 @@ struct icnss_priv {
	bool is_hyp_disabled;
	uint32_t fw_error_fatal_irq;
	uint32_t fw_early_crash_irq;
	struct completion driver_probed;
	struct completion unblock_shutdown;
	char function_name[WLFW_FUNCTION_NAME_LEN + 1];
};

+2 −1
Original line number Diff line number Diff line
/* Copyright (c) 2015-2018, The Linux Foundation. All rights reserved.
/* Copyright (c) 2015-2019, The Linux Foundation. All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 and
@@ -144,4 +144,5 @@ extern bool icnss_is_fw_ready(void);
extern bool icnss_is_fw_down(void);
extern bool icnss_is_rejuvenate(void);
extern int icnss_trigger_recovery(struct device *dev);
extern void icnss_block_shutdown(bool status);
#endif /* _ICNSS_WLAN_H_ */