drm/nv50-/disp: handle supervisor tasks from workqueue
i2c_algo_bit sleeps... Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
This commit is contained in:
parent
7dcd060c0e
commit
5cc027f6b1
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue