Merge "icnss: Defer modem graceful shutdown until probe complete"

tirimbino
qctecmdr Service 6 years ago committed by Gerrit - the friendly Code Review server
commit d8ccfa1eec
  1. 30
      drivers/soc/qcom/icnss.c
  2. 4
      drivers/soc/qcom/icnss_private.h

@ -1,4 +1,4 @@
/* 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
@ -66,6 +66,8 @@
#define ICNSS_QUIRKS_DEFAULT BIT(FW_REJUVENATE_ENABLE)
#define ICNSS_MAX_PROBE_CNT 2
#define PROBE_TIMEOUT 5000
static struct icnss_priv *penv;
unsigned long quirks = ICNSS_QUIRKS_DEFAULT;
@ -883,6 +885,8 @@ 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);
while (probe_cnt < ICNSS_MAX_PROBE_CNT) {
ret = priv->ops->probe(&priv->pdev->dev);
probe_cnt++;
@ -892,9 +896,13 @@ 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);
goto out;
}
complete(&penv->driver_probed);
clear_bit(ICNSS_DRIVER_LOADING, &priv->state);
set_bit(ICNSS_DRIVER_PROBED, &priv->state);
return 0;
@ -1033,6 +1041,8 @@ 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);
while (probe_cnt < ICNSS_MAX_PROBE_CNT) {
ret = penv->ops->probe(&penv->pdev->dev);
probe_cnt++;
@ -1042,9 +1052,13 @@ 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);
goto power_off;
}
complete(&penv->driver_probed);
clear_bit(ICNSS_DRIVER_LOADING, &penv->state);
set_bit(ICNSS_DRIVER_PROBED, &penv->state);
return 0;
@ -1269,6 +1283,13 @@ static int icnss_modem_notifier_nb(struct notifier_block *nb,
if (code != SUBSYS_BEFORE_SHUTDOWN)
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,
PROBE_TIMEOUT))
icnss_pr_err("wlan driver probe timeout\n");
}
if (code == SUBSYS_BEFORE_SHUTDOWN && !notif->crashed) {
ret = wlfw_send_modem_shutdown_msg(priv);
if (ret < 0)
@ -2579,6 +2600,9 @@ static int icnss_stats_show_state(struct seq_file *s, struct icnss_priv *priv)
continue;
case ICNSS_MODE_ON:
seq_puts(s, "MODE ON DONE");
continue;
case ICNSS_DRIVER_LOADING:
seq_puts(s, "WLAN DRIVER LOADING");
}
seq_printf(s, "UNKNOWN-%d", i);
@ -3202,6 +3226,8 @@ static int icnss_probe(struct platform_device *pdev)
penv = priv;
init_completion(&priv->driver_probed);
icnss_pr_info("Platform driver probed successfully\n");
return 0;
@ -3224,6 +3250,8 @@ static int icnss_remove(struct platform_device *pdev)
icnss_debugfs_destroy(penv);
complete_all(&penv->driver_probed);
icnss_modem_ssr_unregister_notifier(penv);
destroy_ramdump_device(penv->msa0_dump_dev);

@ -1,4 +1,4 @@
/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
/* Copyright (c) 2017-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
@ -156,6 +156,7 @@ enum icnss_driver_state {
ICNSS_DRIVER_UNLOADING,
ICNSS_REJUVENATE,
ICNSS_MODE_ON,
ICNSS_DRIVER_LOADING,
};
struct ce_irq_list {
@ -354,6 +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;
char function_name[WLFW_FUNCTION_NAME_LEN + 1];
};

Loading…
Cancel
Save