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

Commit 9c656e9b authored by Yue Ma's avatar Yue Ma Committed by Gerrit - the friendly Code Review server
Browse files

cnss2: Fix synchronization issues related to idle shutdown



If system suspend/resume is going on, reject idle shutdown request
so that WLAN driver can restart the timer. Also there is a chance
that while idle shutdown is in progress, user requests interface up
for WLAN driver. Handle this case by checking return code from
idle shutdown callback.

Change-Id: If41bf43ed974d1759ed336a012c1af1182f00268
Signed-off-by: default avatarYue Ma <yuem@codeaurora.org>
parent 9c34f5b7
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -106,6 +106,9 @@ static int cnss_stats_show_state(struct seq_file *s,
		case CNSS_DRIVER_DEBUG:
			seq_puts(s, "DRIVER_DEBUG");
			continue;
		case CNSS_IN_SUSPEND_RESUME:
			seq_puts(s, "IN_SUSPEND_RESUME");
			continue;
		}

		seq_printf(s, "UNKNOWN-%d", i);
+5 −0
Original line number Diff line number Diff line
@@ -699,6 +699,11 @@ int cnss_idle_shutdown(struct device *dev)
		return -ENODEV;
	}

	if (test_bit(CNSS_IN_SUSPEND_RESUME, &plat_priv->driver_state)) {
		cnss_pr_dbg("System suspend or resume in progress, ignore idle shutdown\n");
		return -EAGAIN;
	}

	cnss_pr_dbg("Doing idle shutdown\n");

	if (!test_bit(CNSS_DRIVER_RECOVERY, &plat_priv->driver_state) &&
+1 −0
Original line number Diff line number Diff line
@@ -196,6 +196,7 @@ enum cnss_driver_state {
	CNSS_FW_BOOT_RECOVERY,
	CNSS_DEV_ERR_NOTIFY,
	CNSS_DRIVER_DEBUG,
	CNSS_IN_SUSPEND_RESUME,
};

struct cnss_recovery_data {
+31 −5
Original line number Diff line number Diff line
@@ -567,6 +567,7 @@ int cnss_pci_call_driver_probe(struct cnss_pci_data *pci_priv)
int cnss_pci_call_driver_remove(struct cnss_pci_data *pci_priv)
{
	struct cnss_plat_data *plat_priv;
	int ret;

	if (!pci_priv)
		return -ENODEV;
@@ -595,7 +596,12 @@ int cnss_pci_call_driver_remove(struct cnss_pci_data *pci_priv)
		clear_bit(CNSS_DEV_ERR_NOTIFY, &plat_priv->driver_state);
	} else if (test_bit(CNSS_DRIVER_IDLE_SHUTDOWN,
			    &plat_priv->driver_state)) {
		pci_priv->driver_ops->idle_shutdown(pci_priv->pci_dev);
		ret = pci_priv->driver_ops->idle_shutdown(pci_priv->pci_dev);
		if (ret == -EAGAIN) {
			clear_bit(CNSS_DRIVER_IDLE_SHUTDOWN,
				  &plat_priv->driver_state);
			return ret;
		}
		clear_bit(CNSS_DEV_ERR_NOTIFY, &plat_priv->driver_state);
	}

@@ -726,7 +732,9 @@ static int cnss_qca6174_shutdown(struct cnss_pci_data *pci_priv)

	cnss_pm_request_resume(pci_priv);

	cnss_pci_call_driver_remove(pci_priv);
	ret = cnss_pci_call_driver_remove(pci_priv);
	if (ret == -EAGAIN)
		goto out;

	cnss_request_bus_bandwidth(&plat_priv->plat_dev->dev,
				   CNSS_BUS_WIDTH_NONE);
@@ -742,6 +750,7 @@ static int cnss_qca6174_shutdown(struct cnss_pci_data *pci_priv)
	clear_bit(CNSS_DRIVER_UNLOADING, &plat_priv->driver_state);
	clear_bit(CNSS_DRIVER_IDLE_SHUTDOWN, &plat_priv->driver_state);

out:
	return ret;
}

@@ -842,7 +851,9 @@ static int cnss_qca6290_shutdown(struct cnss_pci_data *pci_priv)

	cnss_pm_request_resume(pci_priv);

	cnss_pci_call_driver_remove(pci_priv);
	ret = cnss_pci_call_driver_remove(pci_priv);
	if (ret == -EAGAIN)
		goto out;

	cnss_request_bus_bandwidth(&plat_priv->plat_dev->dev,
				   CNSS_BUS_WIDTH_NONE);
@@ -873,6 +884,7 @@ static int cnss_qca6290_shutdown(struct cnss_pci_data *pci_priv)
	clear_bit(CNSS_DRIVER_UNLOADING, &plat_priv->driver_state);
	clear_bit(CNSS_DRIVER_IDLE_SHUTDOWN, &plat_priv->driver_state);

out:
	return ret;
}

@@ -1355,12 +1367,19 @@ static int cnss_pci_suspend(struct device *dev)
	struct pci_dev *pci_dev = to_pci_dev(dev);
	struct cnss_pci_data *pci_priv = cnss_get_pci_priv(pci_dev);
	struct cnss_wlan_driver *driver_ops;
	struct cnss_plat_data *plat_priv;

	pm_message_t state = { .event = PM_EVENT_SUSPEND };

	if (!pci_priv)
		goto out;

	plat_priv = pci_priv->plat_priv;
	if (!plat_priv)
		goto out;

	set_bit(CNSS_IN_SUSPEND_RESUME, &plat_priv->driver_state);

	driver_ops = pci_priv->driver_ops;
	if (driver_ops && driver_ops->suspend) {
		ret = driver_ops->suspend(pci_dev, state);
@@ -1368,7 +1387,7 @@ static int cnss_pci_suspend(struct device *dev)
			cnss_pr_err("Failed to suspend host driver, err = %d\n",
				    ret);
			ret = -EAGAIN;
			goto out;
			goto clear_flag;
		}
	}

@@ -1396,6 +1415,8 @@ static int cnss_pci_suspend(struct device *dev)

	return 0;

clear_flag:
	clear_bit(CNSS_IN_SUSPEND_RESUME, &plat_priv->driver_state);
out:
	return ret;
}
@@ -1405,11 +1426,16 @@ static int cnss_pci_resume(struct device *dev)
	int ret = 0;
	struct pci_dev *pci_dev = to_pci_dev(dev);
	struct cnss_pci_data *pci_priv = cnss_get_pci_priv(pci_dev);
	struct cnss_plat_data *plat_priv;
	struct cnss_wlan_driver *driver_ops;

	if (!pci_priv)
		goto out;

	plat_priv = pci_priv->plat_priv;
	if (!plat_priv)
		goto out;

	if (pci_priv->pci_link_down_ind)
		goto out;

@@ -1435,7 +1461,7 @@ static int cnss_pci_resume(struct device *dev)
				    ret);
	}

	return 0;
	clear_bit(CNSS_IN_SUSPEND_RESUME, &plat_priv->driver_state);

out:
	return ret;