Commit d5d7a0fa authored by Ben Skeggs's avatar Ben Skeggs

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

Signed-off-by: default avatarBen Skeggs <bskeggs@redhat.com>
parent ed76a870
...@@ -71,6 +71,10 @@ struct nouveau_clock { ...@@ -71,6 +71,10 @@ struct nouveau_clock {
struct list_head states; struct list_head states;
int state_nr; int state_nr;
struct work_struct work;
wait_queue_head_t wait;
atomic_t waiting;
int pstate; /* current */ int pstate; /* current */
int ustate; /* user-requested (-1 disabled, -2 perfmon) */ int ustate; /* user-requested (-1 disabled, -2 perfmon) */
int astate; /* perfmon adjustment (base) */ int astate; /* perfmon adjustment (base) */
......
...@@ -194,10 +194,14 @@ nouveau_pstate_prog(struct nouveau_clock *clk, int pstatei) ...@@ -194,10 +194,14 @@ nouveau_pstate_prog(struct nouveau_clock *clk, int pstatei)
return nouveau_cstate_prog(clk, pstate, 0); return nouveau_cstate_prog(clk, pstate, 0);
} }
static int static void
nouveau_pstate_calc(struct nouveau_clock *clk) 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, nv_trace(clk, "P %d U %d A %d T %d D %d\n", clk->pstate,
clk->ustate, clk->astate, clk->tstate, clk->dstate); clk->ustate, clk->astate, clk->tstate, clk->dstate);
...@@ -211,9 +215,25 @@ nouveau_pstate_calc(struct nouveau_clock *clk) ...@@ -211,9 +215,25 @@ nouveau_pstate_calc(struct nouveau_clock *clk)
} }
nv_trace(clk, "-> %d\n", pstate); nv_trace(clk, "-> %d\n", pstate);
if (pstate != clk->pstate) if (pstate != clk->pstate) {
ret = nouveau_pstate_prog(clk, pstate); int ret = nouveau_pstate_prog(clk, pstate);
return ret; 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 static void
...@@ -371,7 +391,7 @@ nouveau_clock_ustate(struct nouveau_clock *clk, int req) ...@@ -371,7 +391,7 @@ nouveau_clock_ustate(struct nouveau_clock *clk, int req)
int ret = nouveau_clock_ustate_update(clk, req); int ret = nouveau_clock_ustate_update(clk, req);
if (ret) if (ret)
return ret; return ret;
return nouveau_pstate_calc(clk); return nouveau_pstate_calc(clk, true);
} }
int int
...@@ -381,7 +401,7 @@ nouveau_clock_astate(struct nouveau_clock *clk, int req, int rel) ...@@ -381,7 +401,7 @@ nouveau_clock_astate(struct nouveau_clock *clk, int req, int rel)
if ( rel) clk->astate += rel; if ( rel) clk->astate += rel;
clk->astate = min(clk->astate, clk->state_nr - 1); clk->astate = min(clk->astate, clk->state_nr - 1);
clk->astate = max(clk->astate, 0); clk->astate = max(clk->astate, 0);
return nouveau_pstate_calc(clk); return nouveau_pstate_calc(clk, true);
} }
int int
...@@ -391,7 +411,7 @@ nouveau_clock_tstate(struct nouveau_clock *clk, int req, int rel) ...@@ -391,7 +411,7 @@ nouveau_clock_tstate(struct nouveau_clock *clk, int req, int rel)
if ( rel) clk->tstate += rel; if ( rel) clk->tstate += rel;
clk->tstate = min(clk->tstate, 0); clk->tstate = min(clk->tstate, 0);
clk->tstate = max(clk->tstate, -(clk->state_nr - 1)); clk->tstate = max(clk->tstate, -(clk->state_nr - 1));
return nouveau_pstate_calc(clk); return nouveau_pstate_calc(clk, true);
} }
int int
...@@ -401,7 +421,7 @@ nouveau_clock_dstate(struct nouveau_clock *clk, int req, int rel) ...@@ -401,7 +421,7 @@ nouveau_clock_dstate(struct nouveau_clock *clk, int req, int rel)
if ( rel) clk->dstate += rel; if ( rel) clk->dstate += rel;
clk->dstate = min(clk->dstate, clk->state_nr - 1); clk->dstate = min(clk->dstate, clk->state_nr - 1);
clk->dstate = max(clk->dstate, 0); 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) ...@@ -434,7 +454,7 @@ _nouveau_clock_init(struct nouveau_object *object)
clk->tstate = 0; clk->tstate = 0;
clk->dstate = 0; clk->dstate = 0;
clk->pstate = -1; clk->pstate = -1;
nouveau_pstate_calc(clk); nouveau_pstate_calc(clk, true);
return 0; return 0;
} }
...@@ -474,6 +494,10 @@ nouveau_clock_create_(struct nouveau_object *parent, ...@@ -474,6 +494,10 @@ nouveau_clock_create_(struct nouveau_object *parent,
clk->domains = clocks; clk->domains = clocks;
clk->ustate = -1; clk->ustate = -1;
INIT_WORK(&clk->work, nouveau_pstate_work);
init_waitqueue_head(&clk->wait);
atomic_set(&clk->waiting, 0);
idx = 0; idx = 0;
do { do {
ret = nouveau_pstate_new(clk, idx++); ret = nouveau_pstate_new(clk, idx++);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment