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

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

Merge "icnss: Remove the driver while device is going to shutdown"

parents cfa6662b 097d0812
Loading
Loading
Loading
Loading
+77 −0
Original line number Diff line number Diff line
@@ -34,6 +34,7 @@
#include <linux/of.h>
#include <linux/of_irq.h>
#include <linux/soc/qcom/qmi.h>
#include <linux/sysfs.h>
#include <soc/qcom/memory_dump.h>
#include <soc/qcom/icnss.h>
#include <soc/qcom/secure_buffer.h>
@@ -141,6 +142,18 @@ static const char * const icnss_pdr_cause[] = {
	[ICNSS_HOST_ERROR] = "Host error",
};

static ssize_t icnss_sysfs_store(struct kobject *kobj,
				 struct kobj_attribute *attr,
				 const char *buf, size_t count)
{
	atomic_set(&penv->is_shutdown, true);
	icnss_pr_dbg("Received shutdown indication");
	return count;
}

static struct kobj_attribute icnss_sysfs_attribute =
__ATTR(shutdown, 0660, NULL, icnss_sysfs_store);

static int icnss_assign_msa_perm(struct icnss_mem_region_info
				 *mem_region, enum icnss_msa_perm new_perm)
{
@@ -1250,6 +1263,32 @@ static int icnss_driver_event_unregister_driver(void *data)
	return 0;
}

static int icnss_call_driver_remove(struct icnss_priv *priv)
{
	icnss_pr_dbg("Calling driver remove state: 0x%lx\n", priv->state);

	clear_bit(ICNSS_FW_READY, &priv->state);

	if (test_bit(ICNSS_DRIVER_UNLOADING, &priv->state))
		return 0;

	if (!test_bit(ICNSS_DRIVER_PROBED, &priv->state))
		return 0;

	if (!priv->ops || !priv->ops->remove)
		return 0;

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

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

	icnss_hw_power_off(priv);

	return 0;
}

static int icnss_fw_crashed(struct icnss_priv *priv,
			    struct icnss_event_pd_service_down_data *event_data)
{
@@ -1442,6 +1481,12 @@ static int icnss_modem_notifier_nb(struct notifier_block *nb,

	priv->is_ssr = true;

	if (code == SUBSYS_BEFORE_SHUTDOWN && !notif->crashed &&
	    atomic_read(&priv->is_shutdown)) {
		atomic_set(&priv->is_shutdown, false);
		icnss_call_driver_remove(priv);
	}

	if (code == SUBSYS_BEFORE_SHUTDOWN && !notif->crashed &&
	    test_bit(ICNSS_BLOCK_SHUTDOWN, &priv->state)) {
		if (!wait_for_completion_timeout(&priv->unblock_shutdown,
@@ -3103,6 +3148,34 @@ static void icnss_debugfs_destroy(struct icnss_priv *priv)
	debugfs_remove_recursive(priv->root_dentry);
}

static void icnss_sysfs_create(struct icnss_priv *priv)
{
	struct kobject *icnss_kobject;
	int error = 0;

	atomic_set(&priv->is_shutdown, false);

	icnss_kobject = kobject_create_and_add("shutdown_wlan", kernel_kobj);
	if (!icnss_kobject) {
		icnss_pr_err("Unable to create kernel object");
		return;
	}

	priv->icnss_kobject = icnss_kobject;

	error = sysfs_create_file(icnss_kobject, &icnss_sysfs_attribute.attr);
	if (error)
		icnss_pr_err("Unable to create icnss sysfs file");
}

static void icnss_sysfs_destroy(struct icnss_priv *priv)
{
	struct kobject *icnss_kobject;

	icnss_kobject = priv->icnss_kobject;
	if (icnss_kobject)
		kobject_put(icnss_kobject);
}

static int icnss_get_vbatt_info(struct icnss_priv *priv)
{
@@ -3325,6 +3398,8 @@ static int icnss_probe(struct platform_device *pdev)

	icnss_debugfs_create(priv);

	icnss_sysfs_create(priv);

	ret = device_init_wakeup(&priv->pdev->dev, true);
	if (ret)
		icnss_pr_err("Failed to init platform device wakeup source, err = %d\n",
@@ -3356,6 +3431,8 @@ static int icnss_remove(struct platform_device *pdev)

	icnss_debugfs_destroy(penv);

	icnss_sysfs_destroy(penv);

	complete_all(&penv->unblock_shutdown);

	icnss_modem_ssr_unregister_notifier(penv);
+4 −0
Original line number Diff line number Diff line
@@ -9,6 +9,7 @@
#include <linux/adc-tm-clients.h>
#include <linux/iio/consumer.h>
#include <asm/dma-iommu.h>
#include <linux/kobject.h>

#define icnss_ipc_log_string(_x...) do {				\
	if (icnss_ipc_log_context)					\
@@ -361,6 +362,9 @@ struct icnss_priv {
	bool vbatt_supported;
	char function_name[WLFW_FUNCTION_NAME_LEN + 1];
	bool is_ssr;
	struct kobject *icnss_kobject;
	atomic_t is_shutdown;

};

int icnss_call_driver_uevent(struct icnss_priv *priv,