drm/nouveau/gr/gf100: wait for GR idle after GO_IDLE bundle
After submitting a GO_IDLE bundle, one must wait for GR to effectively be idle before submitting the next bundle. Failure to do so may result in undefined behavior in some rare cases. Signed-off-by: Alexandre Courbot <acourbot@nvidia.com> Reported-by: Kary Jin <karyj@nvidia.com> Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
This commit is contained in:
Родитель
19bf09cecf
Коммит
4a8cf4513d
|
@ -663,6 +663,37 @@ gf100_gr_zbc_init(struct gf100_gr_priv *priv)
|
|||
gf100_gr_zbc_clear_depth(priv, index);
|
||||
}
|
||||
|
||||
/**
|
||||
* Wait until GR goes idle. GR is considered idle if it is disabled by the
|
||||
* MC (0x200) register, or GR is not busy and a context switch is not in
|
||||
* progress.
|
||||
*/
|
||||
int
|
||||
gf100_gr_wait_idle(struct gf100_gr_priv *priv)
|
||||
{
|
||||
unsigned long end_jiffies = jiffies + msecs_to_jiffies(2000);
|
||||
bool gr_enabled, ctxsw_active, gr_busy;
|
||||
|
||||
do {
|
||||
/*
|
||||
* required to make sure FIFO_ENGINE_STATUS (0x2640) is
|
||||
* up-to-date
|
||||
*/
|
||||
nv_rd32(priv, 0x400700);
|
||||
|
||||
gr_enabled = nv_rd32(priv, 0x200) & 0x1000;
|
||||
ctxsw_active = nv_rd32(priv, 0x2640) & 0x8000;
|
||||
gr_busy = nv_rd32(priv, 0x40060c) & 0x1;
|
||||
|
||||
if (!gr_enabled || (!gr_busy && !ctxsw_active))
|
||||
return 0;
|
||||
} while (time_before(jiffies, end_jiffies));
|
||||
|
||||
nv_error(priv, "wait for idle timeout (en: %d, ctxsw: %d, busy: %d)\n",
|
||||
gr_enabled, ctxsw_active, gr_busy);
|
||||
return -EAGAIN;
|
||||
}
|
||||
|
||||
void
|
||||
gf100_gr_mmio(struct gf100_gr_priv *priv, const struct gf100_gr_pack *p)
|
||||
{
|
||||
|
@ -699,6 +730,12 @@ gf100_gr_icmd(struct gf100_gr_priv *priv, const struct gf100_gr_pack *p)
|
|||
|
||||
while (addr < next) {
|
||||
nv_wr32(priv, 0x400200, addr);
|
||||
/**
|
||||
* Wait for GR to go idle after submitting a
|
||||
* GO_IDLE bundle
|
||||
*/
|
||||
if ((addr & 0xffff) == 0xe100)
|
||||
gf100_gr_wait_idle(priv);
|
||||
nv_wait(priv, 0x400700, 0x00000004, 0x00000000);
|
||||
addr += init->pitch;
|
||||
}
|
||||
|
|
|
@ -181,6 +181,7 @@ struct gf100_gr_oclass {
|
|||
int ppc_nr;
|
||||
};
|
||||
|
||||
int gf100_gr_wait_idle(struct gf100_gr_priv *);
|
||||
void gf100_gr_mmio(struct gf100_gr_priv *, const struct gf100_gr_pack *);
|
||||
void gf100_gr_icmd(struct gf100_gr_priv *, const struct gf100_gr_pack *);
|
||||
void gf100_gr_mthd(struct gf100_gr_priv *, const struct gf100_gr_pack *);
|
||||
|
|
Загрузка…
Ссылка в новой задаче