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

Commit d5d7a0fa authored by Ben Skeggs's avatar Ben Skeggs
Browse files

drm/nouveau/clk: schedule pstate changes through a workqueue



Signed-off-by: default avatarBen Skeggs <bskeggs@redhat.com>
parent ed76a870
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -71,6 +71,10 @@ struct nouveau_clock {
	struct list_head states;
	int state_nr;

	struct work_struct work;
	wait_queue_head_t wait;
	atomic_t waiting;

	int pstate; /* current */
	int ustate; /* user-requested (-1 disabled, -2 perfmon) */
	int astate; /* perfmon adjustment (base) */
+35 −11
Original line number Diff line number Diff line
@@ -194,10 +194,14 @@ nouveau_pstate_prog(struct nouveau_clock *clk, int pstatei)
	return nouveau_cstate_prog(clk, pstate, 0);
}

static int
nouveau_pstate_calc(struct nouveau_clock *clk)
static void
nouveau_pstate_work(struct work_struct *work)
{
	int pstate, ret = 0;
	struct nouveau_clock *clk = container_of(work, typeof(*clk), work);
	int pstate;

	if (!atomic_xchg(&clk->waiting, 0))
		return;

	nv_trace(clk, "P %d U %d A %d T %d D %d\n", clk->pstate,
		 clk->ustate, clk->astate, clk->tstate, clk->dstate);
@@ -211,9 +215,25 @@ nouveau_pstate_calc(struct nouveau_clock *clk)
	}

	nv_trace(clk, "-> %d\n", pstate);
	if (pstate != clk->pstate)
		ret = nouveau_pstate_prog(clk, pstate);
	return ret;
	if (pstate != clk->pstate) {
		int ret = nouveau_pstate_prog(clk, pstate);
		if (ret) {
			nv_error(clk, "error setting pstate %d: %d\n",
				 pstate, ret);
		}
	}

	wake_up_all(&clk->wait);
}

static int
nouveau_pstate_calc(struct nouveau_clock *clk, bool wait)
{
	atomic_set(&clk->waiting, 1);
	schedule_work(&clk->work);
	if (wait)
		wait_event(clk->wait, !atomic_read(&clk->waiting));
	return 0;
}

static void
@@ -371,7 +391,7 @@ nouveau_clock_ustate(struct nouveau_clock *clk, int req)
	int ret = nouveau_clock_ustate_update(clk, req);
	if (ret)
		return ret;
	return nouveau_pstate_calc(clk);
	return nouveau_pstate_calc(clk, true);
}

int
@@ -381,7 +401,7 @@ nouveau_clock_astate(struct nouveau_clock *clk, int req, int rel)
	if ( rel) clk->astate += rel;
	clk->astate = min(clk->astate, clk->state_nr - 1);
	clk->astate = max(clk->astate, 0);
	return nouveau_pstate_calc(clk);
	return nouveau_pstate_calc(clk, true);
}

int
@@ -391,7 +411,7 @@ nouveau_clock_tstate(struct nouveau_clock *clk, int req, int rel)
	if ( rel) clk->tstate += rel;
	clk->tstate = min(clk->tstate, 0);
	clk->tstate = max(clk->tstate, -(clk->state_nr - 1));
	return nouveau_pstate_calc(clk);
	return nouveau_pstate_calc(clk, true);
}

int
@@ -401,7 +421,7 @@ nouveau_clock_dstate(struct nouveau_clock *clk, int req, int rel)
	if ( rel) clk->dstate += rel;
	clk->dstate = min(clk->dstate, clk->state_nr - 1);
	clk->dstate = max(clk->dstate, 0);
	return nouveau_pstate_calc(clk);
	return nouveau_pstate_calc(clk, true);
}

/******************************************************************************
@@ -434,7 +454,7 @@ _nouveau_clock_init(struct nouveau_object *object)
	clk->tstate = 0;
	clk->dstate = 0;
	clk->pstate = -1;
	nouveau_pstate_calc(clk);
	nouveau_pstate_calc(clk, true);
	return 0;
}

@@ -474,6 +494,10 @@ nouveau_clock_create_(struct nouveau_object *parent,
	clk->domains = clocks;
	clk->ustate = -1;

	INIT_WORK(&clk->work, nouveau_pstate_work);
	init_waitqueue_head(&clk->wait);
	atomic_set(&clk->waiting, 0);

	idx = 0;
	do {
		ret = nouveau_pstate_new(clk, idx++);