Loading drivers/gpu/drm/nouveau/core/engine/fifo/nve0.c +87 −2 Original line number Diff line number Diff line Loading @@ -65,6 +65,10 @@ struct nve0_fifo_engn { struct nve0_fifo_priv { struct nouveau_fifo base; struct work_struct fault; u64 mask; struct nve0_fifo_engn engine[FIFO_ENGINE_NR]; struct { struct nouveau_gpuobj *mem; Loading Loading @@ -393,6 +397,75 @@ nve0_fifo_cclass = { * PFIFO engine ******************************************************************************/ static inline int nve0_fifo_engidx(struct nve0_fifo_priv *priv, u32 engn) { switch (engn) { case NVDEV_ENGINE_GR : case NVDEV_ENGINE_COPY2: engn = 0; break; case NVDEV_ENGINE_BSP : engn = 1; break; case NVDEV_ENGINE_PPP : engn = 2; break; case NVDEV_ENGINE_VP : engn = 3; break; case NVDEV_ENGINE_COPY0: engn = 4; break; case NVDEV_ENGINE_COPY1: engn = 5; break; case NVDEV_ENGINE_VENC : engn = 6; break; default: return -1; } return engn; } static void nve0_fifo_recover_work(struct work_struct *work) { struct nve0_fifo_priv *priv = container_of(work, typeof(*priv), fault); struct nouveau_object *engine; unsigned long flags; u32 engn, engm = 0; u64 mask, todo; spin_lock_irqsave(&priv->base.lock, flags); mask = priv->mask; priv->mask = 0ULL; spin_unlock_irqrestore(&priv->base.lock, flags); for (todo = mask; engn = __ffs64(todo), todo; todo &= ~(1 << engn)) engm |= 1 << nve0_fifo_engidx(priv, engn); nv_mask(priv, 0x002630, engm, engm); for (todo = mask; engn = __ffs64(todo), todo; todo &= ~(1 << engn)) { if ((engine = (void *)nouveau_engine(priv, engn))) { nv_ofuncs(engine)->fini(engine, false); WARN_ON(nv_ofuncs(engine)->init(engine)); } nve0_fifo_runlist_update(priv, nve0_fifo_engidx(priv, engn)); } nv_wr32(priv, 0x00262c, engm); nv_mask(priv, 0x002630, engm, 0x00000000); } static void nve0_fifo_recover(struct nve0_fifo_priv *priv, struct nouveau_engine *engine, struct nve0_fifo_chan *chan) { struct nouveau_object *engobj = nv_object(engine); u32 chid = chan->base.chid; unsigned long flags; nv_error(priv, "%s engine fault on channel %d, recovering...\n", nv_subdev(engine)->name, chid); nv_mask(priv, 0x800004 + (chid * 0x08), 0x00000800, 0x00000800); chan->state = KILLED; spin_lock_irqsave(&priv->base.lock, flags); priv->mask |= 1ULL << nv_engidx(engobj); spin_unlock_irqrestore(&priv->base.lock, flags); schedule_work(&priv->fault); } static int nve0_fifo_swmthd(struct nve0_fifo_priv *priv, u32 chid, u32 mthd, u32 data) { Loading Loading @@ -572,8 +645,8 @@ nve0_fifo_intr_fault(struct nve0_fifo_priv *priv, int unit) u32 write = (stat & 0x00000080); u32 hub = (stat & 0x00000040); u32 reason = (stat & 0x0000000f); struct nouveau_object *engctx = NULL; struct nouveau_engine *engine; struct nouveau_object *engctx = NULL, *object; struct nouveau_engine *engine = NULL; const struct nouveau_enum *er, *eu, *ec; char erunk[6] = ""; char euunk[6] = ""; Loading Loading @@ -623,6 +696,16 @@ nve0_fifo_intr_fault(struct nve0_fifo_priv *priv, int unit) ec ? ec->name : ecunk, (u64)inst << 12, nouveau_client_name(engctx)); object = engctx; while (object) { switch (nv_mclass(object)) { case NVE0_CHANNEL_IND_CLASS: nve0_fifo_recover(priv, engine, (void *)object); break; } object = object->parent; } nouveau_engctx_put(engctx); } Loading Loading @@ -889,6 +972,8 @@ nve0_fifo_ctor(struct nouveau_object *parent, struct nouveau_object *engine, if (ret) return ret; INIT_WORK(&priv->fault, nve0_fifo_recover_work); for (i = 0; i < FIFO_ENGINE_NR; i++) { ret = nouveau_gpuobj_new(nv_object(priv), NULL, 0x8000, 0x1000, 0, &priv->engine[i].runlist[0]); Loading Loading
drivers/gpu/drm/nouveau/core/engine/fifo/nve0.c +87 −2 Original line number Diff line number Diff line Loading @@ -65,6 +65,10 @@ struct nve0_fifo_engn { struct nve0_fifo_priv { struct nouveau_fifo base; struct work_struct fault; u64 mask; struct nve0_fifo_engn engine[FIFO_ENGINE_NR]; struct { struct nouveau_gpuobj *mem; Loading Loading @@ -393,6 +397,75 @@ nve0_fifo_cclass = { * PFIFO engine ******************************************************************************/ static inline int nve0_fifo_engidx(struct nve0_fifo_priv *priv, u32 engn) { switch (engn) { case NVDEV_ENGINE_GR : case NVDEV_ENGINE_COPY2: engn = 0; break; case NVDEV_ENGINE_BSP : engn = 1; break; case NVDEV_ENGINE_PPP : engn = 2; break; case NVDEV_ENGINE_VP : engn = 3; break; case NVDEV_ENGINE_COPY0: engn = 4; break; case NVDEV_ENGINE_COPY1: engn = 5; break; case NVDEV_ENGINE_VENC : engn = 6; break; default: return -1; } return engn; } static void nve0_fifo_recover_work(struct work_struct *work) { struct nve0_fifo_priv *priv = container_of(work, typeof(*priv), fault); struct nouveau_object *engine; unsigned long flags; u32 engn, engm = 0; u64 mask, todo; spin_lock_irqsave(&priv->base.lock, flags); mask = priv->mask; priv->mask = 0ULL; spin_unlock_irqrestore(&priv->base.lock, flags); for (todo = mask; engn = __ffs64(todo), todo; todo &= ~(1 << engn)) engm |= 1 << nve0_fifo_engidx(priv, engn); nv_mask(priv, 0x002630, engm, engm); for (todo = mask; engn = __ffs64(todo), todo; todo &= ~(1 << engn)) { if ((engine = (void *)nouveau_engine(priv, engn))) { nv_ofuncs(engine)->fini(engine, false); WARN_ON(nv_ofuncs(engine)->init(engine)); } nve0_fifo_runlist_update(priv, nve0_fifo_engidx(priv, engn)); } nv_wr32(priv, 0x00262c, engm); nv_mask(priv, 0x002630, engm, 0x00000000); } static void nve0_fifo_recover(struct nve0_fifo_priv *priv, struct nouveau_engine *engine, struct nve0_fifo_chan *chan) { struct nouveau_object *engobj = nv_object(engine); u32 chid = chan->base.chid; unsigned long flags; nv_error(priv, "%s engine fault on channel %d, recovering...\n", nv_subdev(engine)->name, chid); nv_mask(priv, 0x800004 + (chid * 0x08), 0x00000800, 0x00000800); chan->state = KILLED; spin_lock_irqsave(&priv->base.lock, flags); priv->mask |= 1ULL << nv_engidx(engobj); spin_unlock_irqrestore(&priv->base.lock, flags); schedule_work(&priv->fault); } static int nve0_fifo_swmthd(struct nve0_fifo_priv *priv, u32 chid, u32 mthd, u32 data) { Loading Loading @@ -572,8 +645,8 @@ nve0_fifo_intr_fault(struct nve0_fifo_priv *priv, int unit) u32 write = (stat & 0x00000080); u32 hub = (stat & 0x00000040); u32 reason = (stat & 0x0000000f); struct nouveau_object *engctx = NULL; struct nouveau_engine *engine; struct nouveau_object *engctx = NULL, *object; struct nouveau_engine *engine = NULL; const struct nouveau_enum *er, *eu, *ec; char erunk[6] = ""; char euunk[6] = ""; Loading Loading @@ -623,6 +696,16 @@ nve0_fifo_intr_fault(struct nve0_fifo_priv *priv, int unit) ec ? ec->name : ecunk, (u64)inst << 12, nouveau_client_name(engctx)); object = engctx; while (object) { switch (nv_mclass(object)) { case NVE0_CHANNEL_IND_CLASS: nve0_fifo_recover(priv, engine, (void *)object); break; } object = object->parent; } nouveau_engctx_put(engctx); } Loading Loading @@ -889,6 +972,8 @@ nve0_fifo_ctor(struct nouveau_object *parent, struct nouveau_object *engine, if (ret) return ret; INIT_WORK(&priv->fault, nve0_fifo_recover_work); for (i = 0; i < FIFO_ENGINE_NR; i++) { ret = nouveau_gpuobj_new(nv_object(priv), NULL, 0x8000, 0x1000, 0, &priv->engine[i].runlist[0]); Loading