Commit 5cc027f6 authored by Ben Skeggs's avatar Ben Skeggs

drm/nv50-/disp: handle supervisor tasks from workqueue

i2c_algo_bit sleeps...
Signed-off-by: default avatarBen Skeggs <bskeggs@redhat.com>
parent 7dcd060c
......@@ -940,7 +940,6 @@ nv50_disp_intr_unk10(struct nv50_disp_priv *priv, u32 super)
exec_script(priv, head, 1);
}
nv_wr32(priv, 0x610024, 0x00000010);
nv_wr32(priv, 0x610030, 0x80000000);
}
......@@ -1097,7 +1096,6 @@ nv50_disp_intr_unk20(struct nv50_disp_priv *priv, u32 super)
}
}
nv_wr32(priv, 0x610024, 0x00000020);
nv_wr32(priv, 0x610030, 0x80000000);
}
......@@ -1136,22 +1134,23 @@ nv50_disp_intr_unk40(struct nv50_disp_priv *priv, u32 super)
}
}
nv_wr32(priv, 0x610024, 0x00000040);
nv_wr32(priv, 0x610030, 0x80000000);
}
static void
nv50_disp_intr_super(struct nv50_disp_priv *priv, u32 intr1)
void
nv50_disp_intr_supervisor(struct work_struct *work)
{
struct nv50_disp_priv *priv =
container_of(work, struct nv50_disp_priv, supervisor);
u32 super = nv_rd32(priv, 0x610030);
nv_debug(priv, "supervisor 0x%08x 0x%08x\n", intr1, super);
nv_debug(priv, "supervisor 0x%08x 0x%08x\n", priv->super, super);
if (intr1 & 0x00000010)
if (priv->super & 0x00000010)
nv50_disp_intr_unk10(priv, super);
if (intr1 & 0x00000020)
if (priv->super & 0x00000020)
nv50_disp_intr_unk20(priv, super);
if (intr1 & 0x00000040)
if (priv->super & 0x00000040)
nv50_disp_intr_unk40(priv, super);
}
......@@ -1180,7 +1179,9 @@ nv50_disp_intr(struct nouveau_subdev *subdev)
}
if (intr1 & 0x00000070) {
nv50_disp_intr_super(priv, intr1);
priv->super = (intr1 & 0x00000070);
schedule_work(&priv->supervisor);
nv_wr32(priv, 0x610024, priv->super);
intr1 &= ~0x00000070;
}
}
......@@ -1202,6 +1203,7 @@ nv50_disp_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
nv_engine(priv)->sclass = nv50_disp_base_oclass;
nv_engine(priv)->cclass = &nv50_disp_cclass;
nv_subdev(priv)->intr = nv50_disp_intr;
INIT_WORK(&priv->supervisor, nv50_disp_intr_supervisor);
priv->sclass = nv50_disp_sclass;
priv->head.nr = 2;
priv->dac.nr = 3;
......
......@@ -15,6 +15,10 @@ struct dcb_output;
struct nv50_disp_priv {
struct nouveau_disp base;
struct nouveau_oclass *sclass;
struct work_struct supervisor;
u32 super;
struct {
int nr;
} head;
......@@ -126,6 +130,7 @@ extern struct nouveau_ofuncs nv50_disp_oimm_ofuncs;
extern struct nouveau_ofuncs nv50_disp_curs_ofuncs;
extern struct nouveau_ofuncs nv50_disp_base_ofuncs;
extern struct nouveau_oclass nv50_disp_cclass;
void nv50_disp_intr_supervisor(struct work_struct *);
void nv50_disp_intr(struct nouveau_subdev *);
extern struct nouveau_omthds nv84_disp_base_omthds[];
......@@ -139,6 +144,7 @@ extern struct nouveau_ofuncs nvd0_disp_oimm_ofuncs;
extern struct nouveau_ofuncs nvd0_disp_curs_ofuncs;
extern struct nouveau_ofuncs nvd0_disp_base_ofuncs;
extern struct nouveau_oclass nvd0_disp_cclass;
void nvd0_disp_intr_supervisor(struct work_struct *);
void nvd0_disp_intr(struct nouveau_subdev *);
#endif
......@@ -72,6 +72,7 @@ nv84_disp_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
nv_engine(priv)->sclass = nv84_disp_base_oclass;
nv_engine(priv)->cclass = &nv50_disp_cclass;
nv_subdev(priv)->intr = nv50_disp_intr;
INIT_WORK(&priv->supervisor, nv50_disp_intr_supervisor);
priv->sclass = nv84_disp_sclass;
priv->head.nr = 2;
priv->dac.nr = 3;
......
......@@ -78,6 +78,7 @@ nv94_disp_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
nv_engine(priv)->sclass = nv94_disp_base_oclass;
nv_engine(priv)->cclass = &nv50_disp_cclass;
nv_subdev(priv)->intr = nv50_disp_intr;
INIT_WORK(&priv->supervisor, nv50_disp_intr_supervisor);
priv->sclass = nv94_disp_sclass;
priv->head.nr = 2;
priv->dac.nr = 3;
......
......@@ -62,6 +62,7 @@ nva0_disp_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
nv_engine(priv)->sclass = nva0_disp_base_oclass;
nv_engine(priv)->cclass = &nv50_disp_cclass;
nv_subdev(priv)->intr = nv50_disp_intr;
INIT_WORK(&priv->supervisor, nv50_disp_intr_supervisor);
priv->sclass = nva0_disp_sclass;
priv->head.nr = 2;
priv->dac.nr = 3;
......
......@@ -79,6 +79,7 @@ nva3_disp_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
nv_engine(priv)->sclass = nva3_disp_base_oclass;
nv_engine(priv)->cclass = &nv50_disp_cclass;
nv_subdev(priv)->intr = nv50_disp_intr;
INIT_WORK(&priv->supervisor, nv50_disp_intr_supervisor);
priv->sclass = nva3_disp_sclass;
priv->head.nr = 2;
priv->dac.nr = 3;
......
......@@ -835,6 +835,26 @@ nvd0_display_unk4_handler(struct nv50_disp_priv *priv, u32 head, u32 mask)
nv_wr32(priv, 0x6101d0, 0x80000000);
}
void
nvd0_disp_intr_supervisor(struct work_struct *work)
{
struct nv50_disp_priv *priv =
container_of(work, struct nv50_disp_priv, supervisor);
u32 mask = 0, head = ~0;
while (!mask && ++head < priv->head.nr)
mask = nv_rd32(priv, 0x6101d4 + (head * 0x800));
nv_debug(priv, "supervisor %08x %08x %d\n", priv->super, mask, head);
if (priv->super & 0x00000001)
nvd0_display_unk1_handler(priv, head, mask);
if (priv->super & 0x00000002)
nvd0_display_unk2_handler(priv, head, mask);
if (priv->super & 0x00000004)
nvd0_display_unk4_handler(priv, head, mask);
}
void
nvd0_disp_intr(struct nouveau_subdev *subdev)
{
......@@ -868,27 +888,11 @@ nvd0_disp_intr(struct nouveau_subdev *subdev)
if (intr & 0x00100000) {
u32 stat = nv_rd32(priv, 0x6100ac);
u32 mask = 0, crtc = ~0;
while (!mask && ++crtc < priv->head.nr)
mask = nv_rd32(priv, 0x6101d4 + (crtc * 0x800));
if (stat & 0x00000001) {
nv_wr32(priv, 0x6100ac, 0x00000001);
nvd0_display_unk1_handler(priv, crtc, mask);
stat &= ~0x00000001;
}
if (stat & 0x00000002) {
nv_wr32(priv, 0x6100ac, 0x00000002);
nvd0_display_unk2_handler(priv, crtc, mask);
stat &= ~0x00000002;
}
if (stat & 0x00000004) {
nv_wr32(priv, 0x6100ac, 0x00000004);
nvd0_display_unk4_handler(priv, crtc, mask);
stat &= ~0x00000004;
if (stat & 0x00000007) {
priv->super = (stat & 0x00000007);
schedule_work(&priv->supervisor);
nv_wr32(priv, 0x6100ac, priv->super);
stat &= ~0x00000007;
}
if (stat) {
......@@ -929,6 +933,7 @@ nvd0_disp_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
nv_engine(priv)->sclass = nvd0_disp_base_oclass;
nv_engine(priv)->cclass = &nv50_disp_cclass;
nv_subdev(priv)->intr = nvd0_disp_intr;
INIT_WORK(&priv->supervisor, nvd0_disp_intr_supervisor);
priv->sclass = nvd0_disp_sclass;
priv->head.nr = heads;
priv->dac.nr = 3;
......
......@@ -63,6 +63,7 @@ nve0_disp_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
nv_engine(priv)->sclass = nve0_disp_base_oclass;
nv_engine(priv)->cclass = &nv50_disp_cclass;
nv_subdev(priv)->intr = nvd0_disp_intr;
INIT_WORK(&priv->supervisor, nvd0_disp_intr_supervisor);
priv->sclass = nve0_disp_sclass;
priv->head.nr = heads;
priv->dac.nr = 3;
......
......@@ -424,7 +424,10 @@ evo_kick(u32 *push, void *evoc)
static bool
evo_sync_wait(void *data)
{
return nouveau_bo_rd32(data, EVO_MAST_NTFY) != 0x00000000;
if (nouveau_bo_rd32(data, EVO_MAST_NTFY) != 0x00000000)
return true;
usleep_range(1, 2);
return false;
}
static int
......
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