Skip to content

Commit

Permalink
drm/nv50-/disp: handle supervisor tasks from workqueue
Browse files Browse the repository at this point in the history
i2c_algo_bit sleeps...

Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
  • Loading branch information
Ben Skeggs committed Feb 20, 2013
1 parent 7dcd060 commit 5cc027f
Show file tree
Hide file tree
Showing 9 changed files with 53 additions and 32 deletions.
22 changes: 12 additions & 10 deletions drivers/gpu/drm/nouveau/core/engine/disp/nv50.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}

Expand Down Expand Up @@ -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);
}

Expand Down Expand Up @@ -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);
}

Expand Down Expand Up @@ -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;
}
}
Expand All @@ -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;
Expand Down
6 changes: 6 additions & 0 deletions drivers/gpu/drm/nouveau/core/engine/disp/nv50.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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[];
Expand All @@ -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
1 change: 1 addition & 0 deletions drivers/gpu/drm/nouveau/core/engine/disp/nv84.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
1 change: 1 addition & 0 deletions drivers/gpu/drm/nouveau/core/engine/disp/nv94.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
1 change: 1 addition & 0 deletions drivers/gpu/drm/nouveau/core/engine/disp/nva0.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
1 change: 1 addition & 0 deletions drivers/gpu/drm/nouveau/core/engine/disp/nva3.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
47 changes: 26 additions & 21 deletions drivers/gpu/drm/nouveau/core/engine/disp/nvd0.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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;
Expand Down
1 change: 1 addition & 0 deletions drivers/gpu/drm/nouveau/core/engine/disp/nve0.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
5 changes: 4 additions & 1 deletion drivers/gpu/drm/nouveau/nv50_display.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down

0 comments on commit 5cc027f

Please sign in to comment.