diff mbox series

[v5,3/6] drm/mediatek: Detect CMDQ execution timeout

Message ID 20211027021857.20816-4-jason-jh.lin@mediatek.com (mailing list archive)
State New, archived
Headers show
Series CMDQ refinement of Mediatek DRM driver | expand

Commit Message

Jason-JH Lin (林睿祥) Oct. 27, 2021, 2:18 a.m. UTC
From: Chun-Kuang Hu <chunkuang.hu@kernel.org>

CMDQ is used to update display register in vblank period, so
it should be execute in next 2 vblank. One vblank interrupt
before send message (occasionally) and one vblank interrupt
after cmdq done. If it fail to execute in next 3 vblank,
tiemout happen.

Signed-off-by: Chun-Kuang Hu <chunkuang.hu@kernel.org>
Signed-off-by: jason-jh.lin <jason-jh.lin@mediatek.com>
Reviewed-by: Chun-Kuang Hu <chunkuang.hu@kernel.org>
---
 drivers/gpu/drm/mediatek/mtk_drm_crtc.c | 20 ++++++++++++++++++--
 1 file changed, 18 insertions(+), 2 deletions(-)

Comments

Fei Shao Oct. 27, 2021, 9:31 a.m. UTC | #1
Hi Jason,

On Wed, Oct 27, 2021 at 10:19 AM jason-jh.lin <jason-jh.lin@mediatek.com> wrote:
>
> From: Chun-Kuang Hu <chunkuang.hu@kernel.org>
>
> CMDQ is used to update display register in vblank period, so
> it should be execute in next 2 vblank. One vblank interrupt
> before send message (occasionally) and one vblank interrupt
> after cmdq done. If it fail to execute in next 3 vblank,
> tiemout happen.
>
> Signed-off-by: Chun-Kuang Hu <chunkuang.hu@kernel.org>
> Signed-off-by: jason-jh.lin <jason-jh.lin@mediatek.com>
> Reviewed-by: Chun-Kuang Hu <chunkuang.hu@kernel.org>
> ---
>  drivers/gpu/drm/mediatek/mtk_drm_crtc.c | 20 ++++++++++++++++++--
>  1 file changed, 18 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/gpu/drm/mediatek/mtk_drm_crtc.c b/drivers/gpu/drm/mediatek/mtk_drm_crtc.c
> index e23e3224ac67..dad1f85ee315 100644
> --- a/drivers/gpu/drm/mediatek/mtk_drm_crtc.c
> +++ b/drivers/gpu/drm/mediatek/mtk_drm_crtc.c
> @@ -54,6 +54,7 @@ struct mtk_drm_crtc {
>  #if IS_REACHABLE(CONFIG_MTK_CMDQ)
>         struct cmdq_client              cmdq_client;
>         u32                             cmdq_event;
> +       u32                             cmdq_vblank_cnt;
>  #endif
>
>         struct device                   *mmsys_dev;
> @@ -227,7 +228,10 @@ struct mtk_ddp_comp *mtk_drm_ddp_comp_for_plane(struct drm_crtc *crtc,
>  static void ddp_cmdq_cb(struct mbox_client *cl, void *mssg)
>  {
>         struct cmdq_cb_data *data = mssg;
> +       struct cmdq_client *cmdq_cl = container_of(cl, struct cmdq_client, client);
> +       struct mtk_drm_crtc *mtk_crtc = container_of(cmdq_cl, struct mtk_drm_crtc, cmdq_client);
>
> +       mtk_crtc->cmdq_vblank_cnt = 0;
>         cmdq_pkt_destroy(data->pkt);
>  }
>  #endif
> @@ -483,6 +487,15 @@ static void mtk_drm_crtc_update_config(struct mtk_drm_crtc *mtk_crtc,
>                                            cmdq_handle->pa_base,
>                                            cmdq_handle->cmd_buf_size,
>                                            DMA_TO_DEVICE);
> +               /*
> +                * CMDQ command should execute in next 3 vblank.
> +                * One vblank interrupt before send message (occasionally)
> +                * and one vblank interrupt after cmdq done,
> +                * so it's timeout after 3 vblank interrupt.
> +                * If it fail to execute in next 3 vblank, timeout happen.
> +                */
> +               mtk_crtc->cmdq_vblank_cnt = 3;
> +
>                 mbox_send_message(mtk_crtc->cmdq_client.chan, cmdq_handle);
>                 mbox_client_txdone(mtk_crtc->cmdq_client.chan, 0);
>         }
> @@ -499,11 +512,14 @@ static void mtk_crtc_ddp_irq(void *data)
>
>  #if IS_REACHABLE(CONFIG_MTK_CMDQ)
>         if (!priv->data->shadow_register && !mtk_crtc->cmdq_client.chan)
> +               mtk_crtc_ddp_config(crtc, NULL);
> +       else if (mtk_crtc->cmdq_vblank_cnt > 0 && --mtk_crtc->cmdq_vblank_cnt == 0)
I think atomic_dec_and_test() does what you want to do here.




> +               DRM_ERROR("mtk_crtc %d CMDQ execute command timeout!\n",
> +                         drm_crtc_index(&mtk_crtc->base));
>  #else
>         if (!priv->data->shadow_register)
> -#endif
>                 mtk_crtc_ddp_config(crtc, NULL);
> -
> +#endif
>         mtk_drm_finish_page_flip(mtk_crtc);
>  }
>
> --
> 2.18.0
>
Chun-Kuang Hu Oct. 27, 2021, 11:47 p.m. UTC | #2
Hi, Fei:

Fei Shao <fshao@chromium.org> 於 2021年10月27日 週三 下午5:32寫道:
>
> Hi Jason,
>
> On Wed, Oct 27, 2021 at 10:19 AM jason-jh.lin <jason-jh.lin@mediatek.com> wrote:
> >
> > From: Chun-Kuang Hu <chunkuang.hu@kernel.org>
> >
> > CMDQ is used to update display register in vblank period, so
> > it should be execute in next 2 vblank. One vblank interrupt
> > before send message (occasionally) and one vblank interrupt
> > after cmdq done. If it fail to execute in next 3 vblank,
> > tiemout happen.
> >
> > Signed-off-by: Chun-Kuang Hu <chunkuang.hu@kernel.org>
> > Signed-off-by: jason-jh.lin <jason-jh.lin@mediatek.com>
> > Reviewed-by: Chun-Kuang Hu <chunkuang.hu@kernel.org>
> > ---
> >  drivers/gpu/drm/mediatek/mtk_drm_crtc.c | 20 ++++++++++++++++++--
> >  1 file changed, 18 insertions(+), 2 deletions(-)
> >
> > diff --git a/drivers/gpu/drm/mediatek/mtk_drm_crtc.c b/drivers/gpu/drm/mediatek/mtk_drm_crtc.c
> > index e23e3224ac67..dad1f85ee315 100644
> > --- a/drivers/gpu/drm/mediatek/mtk_drm_crtc.c
> > +++ b/drivers/gpu/drm/mediatek/mtk_drm_crtc.c
> > @@ -54,6 +54,7 @@ struct mtk_drm_crtc {
> >  #if IS_REACHABLE(CONFIG_MTK_CMDQ)
> >         struct cmdq_client              cmdq_client;
> >         u32                             cmdq_event;
> > +       u32                             cmdq_vblank_cnt;
> >  #endif
> >
> >         struct device                   *mmsys_dev;
> > @@ -227,7 +228,10 @@ struct mtk_ddp_comp *mtk_drm_ddp_comp_for_plane(struct drm_crtc *crtc,
> >  static void ddp_cmdq_cb(struct mbox_client *cl, void *mssg)
> >  {
> >         struct cmdq_cb_data *data = mssg;
> > +       struct cmdq_client *cmdq_cl = container_of(cl, struct cmdq_client, client);
> > +       struct mtk_drm_crtc *mtk_crtc = container_of(cmdq_cl, struct mtk_drm_crtc, cmdq_client);
> >
> > +       mtk_crtc->cmdq_vblank_cnt = 0;
> >         cmdq_pkt_destroy(data->pkt);
> >  }
> >  #endif
> > @@ -483,6 +487,15 @@ static void mtk_drm_crtc_update_config(struct mtk_drm_crtc *mtk_crtc,
> >                                            cmdq_handle->pa_base,
> >                                            cmdq_handle->cmd_buf_size,
> >                                            DMA_TO_DEVICE);
> > +               /*
> > +                * CMDQ command should execute in next 3 vblank.
> > +                * One vblank interrupt before send message (occasionally)
> > +                * and one vblank interrupt after cmdq done,
> > +                * so it's timeout after 3 vblank interrupt.
> > +                * If it fail to execute in next 3 vblank, timeout happen.
> > +                */
> > +               mtk_crtc->cmdq_vblank_cnt = 3;
> > +
> >                 mbox_send_message(mtk_crtc->cmdq_client.chan, cmdq_handle);
> >                 mbox_client_txdone(mtk_crtc->cmdq_client.chan, 0);
> >         }
> > @@ -499,11 +512,14 @@ static void mtk_crtc_ddp_irq(void *data)
> >
> >  #if IS_REACHABLE(CONFIG_MTK_CMDQ)
> >         if (!priv->data->shadow_register && !mtk_crtc->cmdq_client.chan)
> > +               mtk_crtc_ddp_config(crtc, NULL);
> > +       else if (mtk_crtc->cmdq_vblank_cnt > 0 && --mtk_crtc->cmdq_vblank_cnt == 0)
> I think atomic_dec_and_test() does what you want to do here.

I think this operation is not necessary to be atomic operation, and
this statement could be reduced to

else if (--mtk_crtc->cmdq_vblank_cnt == 0)

>
>
>
>
> > +               DRM_ERROR("mtk_crtc %d CMDQ execute command timeout!\n",
> > +                         drm_crtc_index(&mtk_crtc->base));
> >  #else
> >         if (!priv->data->shadow_register)
> > -#endif
> >                 mtk_crtc_ddp_config(crtc, NULL);
> > -
> > +#endif
> >         mtk_drm_finish_page_flip(mtk_crtc);
> >  }
> >
> > --
> > 2.18.0
> >
Fei Shao Oct. 28, 2021, 3:19 a.m. UTC | #3
Hi Chun-Kuang,

On Thu, Oct 28, 2021 at 7:47 AM Chun-Kuang Hu <chunkuang.hu@kernel.org> wrote:
>
> Hi, Fei:
>
> Fei Shao <fshao@chromium.org> 於 2021年10月27日 週三 下午5:32寫道:
> >
> > Hi Jason,
> >
> > On Wed, Oct 27, 2021 at 10:19 AM jason-jh.lin <jason-jh.lin@mediatek.com> wrote:
> > >
> > > From: Chun-Kuang Hu <chunkuang.hu@kernel.org>
> > >
> > > CMDQ is used to update display register in vblank period, so
> > > it should be execute in next 2 vblank. One vblank interrupt
> > > before send message (occasionally) and one vblank interrupt
> > > after cmdq done. If it fail to execute in next 3 vblank,
> > > tiemout happen.
> > >
> > > Signed-off-by: Chun-Kuang Hu <chunkuang.hu@kernel.org>
> > > Signed-off-by: jason-jh.lin <jason-jh.lin@mediatek.com>
> > > Reviewed-by: Chun-Kuang Hu <chunkuang.hu@kernel.org>
> > > ---
> > >  drivers/gpu/drm/mediatek/mtk_drm_crtc.c | 20 ++++++++++++++++++--
> > >  1 file changed, 18 insertions(+), 2 deletions(-)
> > >
> > > diff --git a/drivers/gpu/drm/mediatek/mtk_drm_crtc.c b/drivers/gpu/drm/mediatek/mtk_drm_crtc.c
> > > index e23e3224ac67..dad1f85ee315 100644
> > > --- a/drivers/gpu/drm/mediatek/mtk_drm_crtc.c
> > > +++ b/drivers/gpu/drm/mediatek/mtk_drm_crtc.c
> > > @@ -54,6 +54,7 @@ struct mtk_drm_crtc {
> > >  #if IS_REACHABLE(CONFIG_MTK_CMDQ)
> > >         struct cmdq_client              cmdq_client;
> > >         u32                             cmdq_event;
> > > +       u32                             cmdq_vblank_cnt;
> > >  #endif
> > >
> > >         struct device                   *mmsys_dev;
> > > @@ -227,7 +228,10 @@ struct mtk_ddp_comp *mtk_drm_ddp_comp_for_plane(struct drm_crtc *crtc,
> > >  static void ddp_cmdq_cb(struct mbox_client *cl, void *mssg)
> > >  {
> > >         struct cmdq_cb_data *data = mssg;
> > > +       struct cmdq_client *cmdq_cl = container_of(cl, struct cmdq_client, client);
> > > +       struct mtk_drm_crtc *mtk_crtc = container_of(cmdq_cl, struct mtk_drm_crtc, cmdq_client);
> > >
> > > +       mtk_crtc->cmdq_vblank_cnt = 0;
> > >         cmdq_pkt_destroy(data->pkt);
> > >  }
> > >  #endif
> > > @@ -483,6 +487,15 @@ static void mtk_drm_crtc_update_config(struct mtk_drm_crtc *mtk_crtc,
> > >                                            cmdq_handle->pa_base,
> > >                                            cmdq_handle->cmd_buf_size,
> > >                                            DMA_TO_DEVICE);
> > > +               /*
> > > +                * CMDQ command should execute in next 3 vblank.
> > > +                * One vblank interrupt before send message (occasionally)
> > > +                * and one vblank interrupt after cmdq done,
> > > +                * so it's timeout after 3 vblank interrupt.
> > > +                * If it fail to execute in next 3 vblank, timeout happen.
> > > +                */
> > > +               mtk_crtc->cmdq_vblank_cnt = 3;
> > > +
> > >                 mbox_send_message(mtk_crtc->cmdq_client.chan, cmdq_handle);
> > >                 mbox_client_txdone(mtk_crtc->cmdq_client.chan, 0);
> > >         }
> > > @@ -499,11 +512,14 @@ static void mtk_crtc_ddp_irq(void *data)
> > >
> > >  #if IS_REACHABLE(CONFIG_MTK_CMDQ)
> > >         if (!priv->data->shadow_register && !mtk_crtc->cmdq_client.chan)
> > > +               mtk_crtc_ddp_config(crtc, NULL);
> > > +       else if (mtk_crtc->cmdq_vblank_cnt > 0 && --mtk_crtc->cmdq_vblank_cnt == 0)
> > I think atomic_dec_and_test() does what you want to do here.
>
> I think this operation is not necessary to be atomic operation, and
> this statement could be reduced to
>
> else if (--mtk_crtc->cmdq_vblank_cnt == 0)

I was thinking about using existing helpers to wrap up the counter
operations, but I agree that it's not necessary.
Just dropping the redundant check would be good enough.


>
> >
> > > +               DRM_ERROR("mtk_crtc %d CMDQ execute command timeout!\n",
> > > +                         drm_crtc_index(&mtk_crtc->base));
> > >  #else
> > >         if (!priv->data->shadow_register)
> > > -#endif
> > >                 mtk_crtc_ddp_config(crtc, NULL);
> > > -
> > > +#endif
> > >         mtk_drm_finish_page_flip(mtk_crtc);
> > >  }
> > >
> > > --
> > > 2.18.0
> > >
Chun-Kuang Hu Nov. 17, 2021, 11:51 p.m. UTC | #4
Hi, Fei:

Fei Shao <fshao@chromium.org> 於 2021年10月28日 週四 上午11:19寫道:
>
> Hi Chun-Kuang,
>
> On Thu, Oct 28, 2021 at 7:47 AM Chun-Kuang Hu <chunkuang.hu@kernel.org> wrote:
> >
> > Hi, Fei:
> >
> > Fei Shao <fshao@chromium.org> 於 2021年10月27日 週三 下午5:32寫道:
> > >
> > > Hi Jason,
> > >
> > > On Wed, Oct 27, 2021 at 10:19 AM jason-jh.lin <jason-jh.lin@mediatek.com> wrote:
> > > >
> > > > From: Chun-Kuang Hu <chunkuang.hu@kernel.org>
> > > >
> > > > CMDQ is used to update display register in vblank period, so
> > > > it should be execute in next 2 vblank. One vblank interrupt
> > > > before send message (occasionally) and one vblank interrupt
> > > > after cmdq done. If it fail to execute in next 3 vblank,
> > > > tiemout happen.
> > > >
> > > > Signed-off-by: Chun-Kuang Hu <chunkuang.hu@kernel.org>
> > > > Signed-off-by: jason-jh.lin <jason-jh.lin@mediatek.com>
> > > > Reviewed-by: Chun-Kuang Hu <chunkuang.hu@kernel.org>
> > > > ---
> > > >  drivers/gpu/drm/mediatek/mtk_drm_crtc.c | 20 ++++++++++++++++++--
> > > >  1 file changed, 18 insertions(+), 2 deletions(-)
> > > >
> > > > diff --git a/drivers/gpu/drm/mediatek/mtk_drm_crtc.c b/drivers/gpu/drm/mediatek/mtk_drm_crtc.c
> > > > index e23e3224ac67..dad1f85ee315 100644
> > > > --- a/drivers/gpu/drm/mediatek/mtk_drm_crtc.c
> > > > +++ b/drivers/gpu/drm/mediatek/mtk_drm_crtc.c
> > > > @@ -54,6 +54,7 @@ struct mtk_drm_crtc {
> > > >  #if IS_REACHABLE(CONFIG_MTK_CMDQ)
> > > >         struct cmdq_client              cmdq_client;
> > > >         u32                             cmdq_event;
> > > > +       u32                             cmdq_vblank_cnt;
> > > >  #endif
> > > >
> > > >         struct device                   *mmsys_dev;
> > > > @@ -227,7 +228,10 @@ struct mtk_ddp_comp *mtk_drm_ddp_comp_for_plane(struct drm_crtc *crtc,
> > > >  static void ddp_cmdq_cb(struct mbox_client *cl, void *mssg)
> > > >  {
> > > >         struct cmdq_cb_data *data = mssg;
> > > > +       struct cmdq_client *cmdq_cl = container_of(cl, struct cmdq_client, client);
> > > > +       struct mtk_drm_crtc *mtk_crtc = container_of(cmdq_cl, struct mtk_drm_crtc, cmdq_client);
> > > >
> > > > +       mtk_crtc->cmdq_vblank_cnt = 0;
> > > >         cmdq_pkt_destroy(data->pkt);
> > > >  }
> > > >  #endif
> > > > @@ -483,6 +487,15 @@ static void mtk_drm_crtc_update_config(struct mtk_drm_crtc *mtk_crtc,
> > > >                                            cmdq_handle->pa_base,
> > > >                                            cmdq_handle->cmd_buf_size,
> > > >                                            DMA_TO_DEVICE);
> > > > +               /*
> > > > +                * CMDQ command should execute in next 3 vblank.
> > > > +                * One vblank interrupt before send message (occasionally)
> > > > +                * and one vblank interrupt after cmdq done,
> > > > +                * so it's timeout after 3 vblank interrupt.
> > > > +                * If it fail to execute in next 3 vblank, timeout happen.
> > > > +                */
> > > > +               mtk_crtc->cmdq_vblank_cnt = 3;
> > > > +
> > > >                 mbox_send_message(mtk_crtc->cmdq_client.chan, cmdq_handle);
> > > >                 mbox_client_txdone(mtk_crtc->cmdq_client.chan, 0);
> > > >         }
> > > > @@ -499,11 +512,14 @@ static void mtk_crtc_ddp_irq(void *data)
> > > >
> > > >  #if IS_REACHABLE(CONFIG_MTK_CMDQ)
> > > >         if (!priv->data->shadow_register && !mtk_crtc->cmdq_client.chan)
> > > > +               mtk_crtc_ddp_config(crtc, NULL);
> > > > +       else if (mtk_crtc->cmdq_vblank_cnt > 0 && --mtk_crtc->cmdq_vblank_cnt == 0)
> > > I think atomic_dec_and_test() does what you want to do here.
> >
> > I think this operation is not necessary to be atomic operation, and
> > this statement could be reduced to
> >
> > else if (--mtk_crtc->cmdq_vblank_cnt == 0)
>
> I was thinking about using existing helpers to wrap up the counter
> operations, but I agree that it's not necessary.
> Just dropping the redundant check would be good enough.

I find one thing so that I would like this version. If we do not check
mtk_crtc->cmdq_vblank_cnt > 0, mtk_crtc->cmdq_vblank_cnt would
decrease to minus. And one day it would round to positive. So I would
pick this version instead of v6.

Regards,
Chun-Kuang.

>
>
> >
> > >
> > > > +               DRM_ERROR("mtk_crtc %d CMDQ execute command timeout!\n",
> > > > +                         drm_crtc_index(&mtk_crtc->base));
> > > >  #else
> > > >         if (!priv->data->shadow_register)
> > > > -#endif
> > > >                 mtk_crtc_ddp_config(crtc, NULL);
> > > > -
> > > > +#endif
> > > >         mtk_drm_finish_page_flip(mtk_crtc);
> > > >  }
> > > >
> > > > --
> > > > 2.18.0
> > > >
diff mbox series

Patch

diff --git a/drivers/gpu/drm/mediatek/mtk_drm_crtc.c b/drivers/gpu/drm/mediatek/mtk_drm_crtc.c
index e23e3224ac67..dad1f85ee315 100644
--- a/drivers/gpu/drm/mediatek/mtk_drm_crtc.c
+++ b/drivers/gpu/drm/mediatek/mtk_drm_crtc.c
@@ -54,6 +54,7 @@  struct mtk_drm_crtc {
 #if IS_REACHABLE(CONFIG_MTK_CMDQ)
 	struct cmdq_client		cmdq_client;
 	u32				cmdq_event;
+	u32				cmdq_vblank_cnt;
 #endif
 
 	struct device			*mmsys_dev;
@@ -227,7 +228,10 @@  struct mtk_ddp_comp *mtk_drm_ddp_comp_for_plane(struct drm_crtc *crtc,
 static void ddp_cmdq_cb(struct mbox_client *cl, void *mssg)
 {
 	struct cmdq_cb_data *data = mssg;
+	struct cmdq_client *cmdq_cl = container_of(cl, struct cmdq_client, client);
+	struct mtk_drm_crtc *mtk_crtc = container_of(cmdq_cl, struct mtk_drm_crtc, cmdq_client);
 
+	mtk_crtc->cmdq_vblank_cnt = 0;
 	cmdq_pkt_destroy(data->pkt);
 }
 #endif
@@ -483,6 +487,15 @@  static void mtk_drm_crtc_update_config(struct mtk_drm_crtc *mtk_crtc,
 					   cmdq_handle->pa_base,
 					   cmdq_handle->cmd_buf_size,
 					   DMA_TO_DEVICE);
+		/*
+		 * CMDQ command should execute in next 3 vblank.
+		 * One vblank interrupt before send message (occasionally)
+		 * and one vblank interrupt after cmdq done,
+		 * so it's timeout after 3 vblank interrupt.
+		 * If it fail to execute in next 3 vblank, timeout happen.
+		 */
+		mtk_crtc->cmdq_vblank_cnt = 3;
+
 		mbox_send_message(mtk_crtc->cmdq_client.chan, cmdq_handle);
 		mbox_client_txdone(mtk_crtc->cmdq_client.chan, 0);
 	}
@@ -499,11 +512,14 @@  static void mtk_crtc_ddp_irq(void *data)
 
 #if IS_REACHABLE(CONFIG_MTK_CMDQ)
 	if (!priv->data->shadow_register && !mtk_crtc->cmdq_client.chan)
+		mtk_crtc_ddp_config(crtc, NULL);
+	else if (mtk_crtc->cmdq_vblank_cnt > 0 && --mtk_crtc->cmdq_vblank_cnt == 0)
+		DRM_ERROR("mtk_crtc %d CMDQ execute command timeout!\n",
+			  drm_crtc_index(&mtk_crtc->base));
 #else
 	if (!priv->data->shadow_register)
-#endif
 		mtk_crtc_ddp_config(crtc, NULL);
-
+#endif
 	mtk_drm_finish_page_flip(mtk_crtc);
 }