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

Commit bc5baf5c authored by Jingxiang Ge's avatar Jingxiang Ge Committed by snandini
Browse files

qcacmn: Add lock protection for prevent_suspend_list

Need to protect prevent_suspend_list by runtime_lock.
Issue happens when
1 printing lock0 of prevent_suspend_list in thread0
2 thread0 scheduled out and lock0 is released.
3 return back to thread0, it will using lock0 pointer
  to check next lock, then issue happens.

Fix is adding runtime_lock to protect.

Change-Id: I7182651e445cf5008dba73e15b2c261cc125577f
CRs-Fixed: 2883052
parent 1eb33580
Loading
Loading
Loading
Loading
+27 −15
Original line number Diff line number Diff line
@@ -42,6 +42,8 @@
#include "hif_exec.h"

#ifdef FEATURE_RUNTIME_PM
#define PREVENT_LIST_STRING_LEN 200

/**
 * hif_pci_pm_runtime_enabled() - To check if Runtime PM is enabled
 * @scn: hif context
@@ -733,29 +735,40 @@ void hif_process_runtime_suspend_failure(struct hif_opaque_softc *hif_ctx)
	hif_runtime_pm_set_state_on(scn);
}

static void hif_pm_runtime_print_prevent_list(struct hif_softc *scn)
{
	struct hif_runtime_pm_ctx *rpm_ctx = hif_bus_get_rpm_ctx(scn);
	struct hif_pm_runtime_lock *ctx;

	hif_info("prevent_suspend_cnt %u", rpm_ctx->prevent_suspend_cnt);
	list_for_each_entry(ctx, &rpm_ctx->prevent_suspend_list, list)
		hif_info("%s", ctx->name);
}

static bool hif_pm_runtime_is_suspend_allowed(struct hif_softc *scn)
{
	struct hif_runtime_pm_ctx *rpm_ctx = hif_bus_get_rpm_ctx(scn);
	bool ret;
	struct hif_pm_runtime_lock *ctx;
	uint32_t prevent_suspend_cnt;
	char *str_buf;
	bool is_suspend_allowed;
	int len = 0;

	if (!scn->hif_config.enable_runtime_pm)
		return 0;
		return false;

	str_buf = qdf_mem_malloc(PREVENT_LIST_STRING_LEN);
	if (!str_buf)
		return false;

	spin_lock_bh(&rpm_ctx->runtime_lock);
	ret = (rpm_ctx->prevent_suspend_cnt == 0);
	prevent_suspend_cnt = rpm_ctx->prevent_suspend_cnt;
	is_suspend_allowed = (prevent_suspend_cnt == 0);
	if (!is_suspend_allowed) {
		list_for_each_entry(ctx, &rpm_ctx->prevent_suspend_list, list)
			len += qdf_scnprintf(str_buf + len,
				PREVENT_LIST_STRING_LEN - len,
				"%s ", ctx->name);
	}
	spin_unlock_bh(&rpm_ctx->runtime_lock);

	return ret;
	if (!is_suspend_allowed)
		hif_info("prevent_suspend_cnt %u, prevent_list: %s",
			 rpm_ctx->prevent_suspend_cnt, str_buf);

	qdf_mem_free(str_buf);

	return is_suspend_allowed;
}

/**
@@ -783,7 +796,6 @@ int hif_pre_runtime_suspend(struct hif_opaque_softc *hif_ctx)
	/* keep this after set suspending */
	if (!hif_pm_runtime_is_suspend_allowed(scn)) {
		hif_info("Runtime PM not allowed now");
		hif_pm_runtime_print_prevent_list(scn);
		return -EINVAL;
	}