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

Commit faf83ec6 authored by Yue Ma's avatar Yue Ma
Browse files

cnss2: Add support to monitor PM QOS votes



CPU PM QOS votes can be used as a precondition to decide whether
WLAN device is worth to enter runtime PM suspend. Add support to
monitor PM QOS votes while WLAN device is powered on.

Change-Id: Ida5128ae0ed9335be17ea220d6d26a386d35ac02
Signed-off-by: default avatarYue Ma <yuem@codeaurora.org>
parent aa7030af
Loading
Loading
Loading
Loading
+72 −2
Original line number Diff line number Diff line
@@ -58,6 +58,7 @@
static DEFINE_SPINLOCK(pci_link_down_lock);
static DEFINE_SPINLOCK(pci_reg_window_lock);
static DEFINE_SPINLOCK(time_sync_lock);
static DEFINE_SPINLOCK(pm_qos_lock);

#define MHI_TIMEOUT_OVERWRITE_MS	(plat_priv->ctrl_params.mhi_timeout)
#define MHI_M2_TIMEOUT_MS		(plat_priv->ctrl_params.mhi_m2_timeout)
@@ -1202,6 +1203,73 @@ static void cnss_pci_stop_time_sync_update(struct cnss_pci_data *pci_priv)
	cancel_delayed_work_sync(&pci_priv->time_sync_work);
}

static int cnss_pci_pm_qos_notify(struct notifier_block *nb,
				  unsigned long curr_val, void *cpus)
{
	struct cnss_pci_data *pci_priv =
		container_of(nb, struct cnss_pci_data, pm_qos_nb);
	unsigned long flags;

	spin_lock_irqsave(&pm_qos_lock, flags);

	if (!pci_priv->runtime_pm_prevented &&
	    curr_val != PM_QOS_CPU_DMA_LAT_DEFAULT_VALUE) {
		cnss_pci_pm_runtime_get_noresume(pci_priv);
		pci_priv->runtime_pm_prevented = true;
	} else if (pci_priv->runtime_pm_prevented &&
		   curr_val == PM_QOS_CPU_DMA_LAT_DEFAULT_VALUE) {
		cnss_pci_pm_runtime_put_noidle(pci_priv);
		pci_priv->runtime_pm_prevented = false;
	}

	spin_unlock_irqrestore(&pm_qos_lock, flags);

	return NOTIFY_DONE;
}

static int cnss_pci_pm_qos_add_notifier(struct cnss_pci_data *pci_priv)
{
	int ret;

	if (pci_priv->device_id == QCA6174_DEVICE_ID)
		return 0;

	pci_priv->pm_qos_nb.notifier_call = cnss_pci_pm_qos_notify;
	ret = pm_qos_add_notifier(PM_QOS_CPU_DMA_LATENCY,
				  &pci_priv->pm_qos_nb);
	if (ret)
		cnss_pr_err("Failed to add qos notifier, err = %d\n",
			    ret);

	return ret;
}

static int cnss_pci_pm_qos_remove_notifier(struct cnss_pci_data *pci_priv)
{
	int ret;
	unsigned long flags;

	if (pci_priv->device_id == QCA6174_DEVICE_ID)
		return 0;

	ret = pm_qos_remove_notifier(PM_QOS_CPU_DMA_LATENCY,
				     &pci_priv->pm_qos_nb);
	if (ret)
		cnss_pr_dbg("Failed to remove qos notifier, err = %d\n",
			    ret);

	spin_lock_irqsave(&pm_qos_lock, flags);

	if (pci_priv->runtime_pm_prevented) {
		cnss_pci_pm_runtime_put_noidle(pci_priv);
		pci_priv->runtime_pm_prevented = false;
	}

	spin_unlock_irqrestore(&pm_qos_lock, flags);

	return ret;
}

int cnss_pci_call_driver_probe(struct cnss_pci_data *pci_priv)
{
	int ret = 0;
@@ -1263,6 +1331,7 @@ int cnss_pci_call_driver_probe(struct cnss_pci_data *pci_priv)
	}

	cnss_pci_start_time_sync_update(pci_priv);
	cnss_pci_pm_qos_add_notifier(pci_priv);

	return 0;

@@ -1280,8 +1349,6 @@ int cnss_pci_call_driver_remove(struct cnss_pci_data *pci_priv)

	plat_priv = pci_priv->plat_priv;

	cnss_pci_stop_time_sync_update(pci_priv);

	if (test_bit(CNSS_COLD_BOOT_CAL, &plat_priv->driver_state) ||
	    test_bit(CNSS_FW_BOOT_RECOVERY, &plat_priv->driver_state) ||
	    test_bit(CNSS_DRIVER_DEBUG, &plat_priv->driver_state)) {
@@ -1294,6 +1361,9 @@ int cnss_pci_call_driver_remove(struct cnss_pci_data *pci_priv)
		return -EINVAL;
	}

	cnss_pci_pm_qos_remove_notifier(pci_priv);
	cnss_pci_stop_time_sync_update(pci_priv);

	if (test_bit(CNSS_DRIVER_RECOVERY, &plat_priv->driver_state) &&
	    test_bit(CNSS_DRIVER_PROBED, &plat_priv->driver_state)) {
		pci_priv->driver_ops->shutdown(pci_priv->pci_dev);
+2 −0
Original line number Diff line number Diff line
@@ -72,6 +72,8 @@ struct cnss_pci_data {
	struct pci_saved_state *saved_state;
	struct pci_saved_state *default_state;
	struct msm_pcie_register_event msm_pci_event;
	struct notifier_block pm_qos_nb;
	u8 runtime_pm_prevented;
	atomic_t auto_suspended;
	atomic_t drv_connected;
	u8 drv_connected_last;