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

Commit a1c93228 authored by Yue Ma's avatar Yue Ma
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 the return code from
idle shutdown callback.

Change-Id: If41bf43ed974d1759ed336a012c1af1182f00268
Signed-off-by: default avatarYue Ma <yuem@codeaurora.org>
parent d8ffb2cd
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -104,6 +104,9 @@ static int cnss_stats_show_state(struct seq_file *s,
		case CNSS_IMS_CONNECTED:
			seq_puts(s, "IMS_CONNECTED");
			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
@@ -696,6 +696,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
@@ -202,6 +202,7 @@ enum cnss_driver_state {
	CNSS_DRIVER_DEBUG,
	CNSS_COEX_CONNECTED,
	CNSS_IMS_CONNECTED,
	CNSS_IN_SUSPEND_RESUME,
};

struct cnss_recovery_data {
+26 −6
Original line number Diff line number Diff line
@@ -1008,6 +1008,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;
@@ -1037,7 +1038,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);
	}

@@ -1173,7 +1179,9 @@ static int cnss_qca6174_shutdown(struct cnss_pci_data *pci_priv)

	cnss_pci_pm_runtime_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);
@@ -1189,6 +1197,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;
}

@@ -1289,7 +1298,9 @@ static int cnss_qca6290_shutdown(struct cnss_pci_data *pci_priv)

	cnss_pci_pm_runtime_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);
@@ -1322,6 +1333,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;
}

@@ -1731,6 +1743,8 @@ static int cnss_pci_suspend(struct device *dev)
	if (!cnss_is_device_powered_on(plat_priv))
		goto out;

	set_bit(CNSS_IN_SUSPEND_RESUME, &plat_priv->driver_state);

	if (!test_bit(DISABLE_DRV, &plat_priv->ctrl_params.quirks))
		pci_priv->drv_connected_last =
			cnss_pci_get_drv_connected(pci_priv);
@@ -1742,7 +1756,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;
		}
	}

@@ -1785,7 +1799,9 @@ static int cnss_pci_suspend(struct device *dev)
resume_driver:
	if (driver_ops && driver_ops->resume)
		driver_ops->resume(pci_dev);
clear_flag:
	pci_priv->drv_connected_last = 0;
	clear_bit(CNSS_IN_SUSPEND_RESUME, &plat_priv->driver_state);
out:
	return ret;
}
@@ -1795,11 +1811,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;

@@ -1842,8 +1863,7 @@ static int cnss_pci_resume(struct device *dev)
	}

	pci_priv->drv_connected_last = 0;

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

out:
	return ret;