All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] drm/komeda: Adds error event print functionality
@ 2019-06-27  3:10 ` Lowry Li (Arm Technology China)
  0 siblings, 0 replies; 37+ messages in thread
From: Lowry Li (Arm Technology China) @ 2019-06-27  3:10 UTC (permalink / raw)
  To: Liviu Dudau, james qian wang (Arm Technology China),
	maarten.lankhorst, seanpaul, airlied, Brian Starkey
  Cc: Julien Yin (Arm Technology China),
	Jonathan Chai (Arm Technology China),
	Ayan Halder, dri-devel, linux-kernel, nd

Adds to print the event message when error happens and the same event
will not be printed until next vsync.

Signed-off-by: Lowry Li (Arm Technology China) <lowry.li@arm.com>
---
 drivers/gpu/drm/arm/display/komeda/Makefile       |   1 +
 drivers/gpu/drm/arm/display/komeda/komeda_dev.h   |  13 ++
 drivers/gpu/drm/arm/display/komeda/komeda_event.c | 144 ++++++++++++++++++++++
 drivers/gpu/drm/arm/display/komeda/komeda_kms.c   |   2 +
 4 files changed, 160 insertions(+)
 create mode 100644 drivers/gpu/drm/arm/display/komeda/komeda_event.c

diff --git a/drivers/gpu/drm/arm/display/komeda/Makefile b/drivers/gpu/drm/arm/display/komeda/Makefile
index 38aa584..3f53d2d 100644
--- a/drivers/gpu/drm/arm/display/komeda/Makefile
+++ b/drivers/gpu/drm/arm/display/komeda/Makefile
@@ -7,6 +7,7 @@ ccflags-y := \
 komeda-y := \
 	komeda_drv.o \
 	komeda_dev.o \
+	komeda_event.o \
 	komeda_format_caps.o \
 	komeda_coeffs.o \
 	komeda_color_mgmt.o \
diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_dev.h b/drivers/gpu/drm/arm/display/komeda/komeda_dev.h
index 096f9f7..e863ec3 100644
--- a/drivers/gpu/drm/arm/display/komeda/komeda_dev.h
+++ b/drivers/gpu/drm/arm/display/komeda/komeda_dev.h
@@ -40,6 +40,17 @@
 #define KOMEDA_ERR_TTNG			BIT_ULL(30)
 #define KOMEDA_ERR_TTF			BIT_ULL(31)
 
+#define KOMEDA_ERR_EVENTS	\
+	(KOMEDA_EVENT_URUN	| KOMEDA_EVENT_IBSY	| KOMEDA_EVENT_OVR |\
+	KOMEDA_ERR_TETO		| KOMEDA_ERR_TEMR	| KOMEDA_ERR_TITR |\
+	KOMEDA_ERR_CPE		| KOMEDA_ERR_CFGE	| KOMEDA_ERR_AXIE |\
+	KOMEDA_ERR_ACE0		| KOMEDA_ERR_ACE1	| KOMEDA_ERR_ACE2 |\
+	KOMEDA_ERR_ACE3		| KOMEDA_ERR_DRIFTTO	| KOMEDA_ERR_FRAMETO |\
+	KOMEDA_ERR_ZME		| KOMEDA_ERR_MERR	| KOMEDA_ERR_TCF |\
+	KOMEDA_ERR_TTNG		| KOMEDA_ERR_TTF)
+
+#define KOMEDA_WARN_EVENTS	KOMEDA_ERR_CSCE
+
 /* malidp device id */
 enum {
 	MALI_D71 = 0,
@@ -207,6 +218,8 @@ struct komeda_dev {
 
 struct komeda_dev *dev_to_mdev(struct device *dev);
 
+void komeda_print_events(struct komeda_events *evts);
+
 int komeda_dev_resume(struct komeda_dev *mdev);
 int komeda_dev_suspend(struct komeda_dev *mdev);
 #endif /*_KOMEDA_DEV_H_*/
diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_event.c b/drivers/gpu/drm/arm/display/komeda/komeda_event.c
new file mode 100644
index 0000000..309dbe2
--- /dev/null
+++ b/drivers/gpu/drm/arm/display/komeda/komeda_event.c
@@ -0,0 +1,144 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * (C) COPYRIGHT 2019 ARM Limited. All rights reserved.
+ * Author: James.Qian.Wang <james.qian.wang@arm.com>
+ *
+ */
+#include <drm/drm_print.h>
+
+#include "komeda_dev.h"
+
+struct komeda_str {
+	char *str;
+	u32 sz;
+	u32 len;
+};
+
+/* return 0 on success,  < 0 on no space.
+ */
+static int komeda_sprintf(struct komeda_str *str, const char *fmt, ...)
+{
+	va_list args;
+	int num, free_sz;
+	int err;
+
+	free_sz = str->sz - str->len;
+	if (free_sz <= 0)
+		return -ENOSPC;
+
+	va_start(args, fmt);
+
+	num = vsnprintf(str->str + str->len, free_sz, fmt, args);
+
+	va_end(args);
+
+	if (num <= free_sz) {
+		str->len += num;
+		err = 0;
+	} else {
+		str->len = str->sz;
+		err = -ENOSPC;
+	}
+
+	return err;
+}
+
+static void evt_sprintf(struct komeda_str *str, u64 evt, const char *msg)
+{
+	if (evt)
+		komeda_sprintf(str, msg);
+}
+
+static void evt_str(struct komeda_str *str, u64 events)
+{
+	if (events == 0ULL) {
+		evt_sprintf(str, 1, "None");
+		return;
+	}
+
+	evt_sprintf(str, events & KOMEDA_EVENT_VSYNC, "VSYNC|");
+	evt_sprintf(str, events & KOMEDA_EVENT_FLIP, "FLIP|");
+	evt_sprintf(str, events & KOMEDA_EVENT_EOW, "EOW|");
+	evt_sprintf(str, events & KOMEDA_EVENT_MODE, "OP-MODE|");
+
+	evt_sprintf(str, events & KOMEDA_EVENT_URUN, "UNDERRUN|");
+	evt_sprintf(str, events & KOMEDA_EVENT_OVR, "OVERRUN|");
+
+	/* GLB error */
+	evt_sprintf(str, events & KOMEDA_ERR_MERR, "MERR|");
+	evt_sprintf(str, events & KOMEDA_ERR_FRAMETO, "FRAMETO|");
+
+	/* DOU error */
+	evt_sprintf(str, events & KOMEDA_ERR_DRIFTTO, "DRIFTTO|");
+	evt_sprintf(str, events & KOMEDA_ERR_FRAMETO, "FRAMETO|");
+	evt_sprintf(str, events & KOMEDA_ERR_TETO, "TETO|");
+	evt_sprintf(str, events & KOMEDA_ERR_CSCE, "CSCE|");
+
+	/* LPU errors or events */
+	evt_sprintf(str, events & KOMEDA_EVENT_IBSY, "IBSY|");
+	evt_sprintf(str, events & KOMEDA_ERR_AXIE, "AXIE|");
+	evt_sprintf(str, events & KOMEDA_ERR_ACE0, "ACE0|");
+	evt_sprintf(str, events & KOMEDA_ERR_ACE1, "ACE1|");
+	evt_sprintf(str, events & KOMEDA_ERR_ACE2, "ACE2|");
+	evt_sprintf(str, events & KOMEDA_ERR_ACE3, "ACE3|");
+
+	/* LPU TBU errors*/
+	evt_sprintf(str, events & KOMEDA_ERR_TCF, "TCF|");
+	evt_sprintf(str, events & KOMEDA_ERR_TTNG, "TTNG|");
+	evt_sprintf(str, events & KOMEDA_ERR_TITR, "TITR|");
+	evt_sprintf(str, events & KOMEDA_ERR_TEMR, "TEMR|");
+	evt_sprintf(str, events & KOMEDA_ERR_TTF, "TTF|");
+
+	/* CU errors*/
+	evt_sprintf(str, events & KOMEDA_ERR_CPE, "COPROC|");
+	evt_sprintf(str, events & KOMEDA_ERR_ZME, "ZME|");
+	evt_sprintf(str, events & KOMEDA_ERR_CFGE, "CFGE|");
+	evt_sprintf(str, events & KOMEDA_ERR_TEMR, "TEMR|");
+
+	if (str->len > 0 && (str->str[str->len - 1] == '|')) {
+		str->str[str->len - 1] = 0;
+		str->len--;
+	}
+}
+
+static bool is_new_frame(struct komeda_events *a)
+{
+	return (a->pipes[0] | a->pipes[1]) & KOMEDA_EVENT_FLIP;
+}
+
+void komeda_print_events(struct komeda_events *evts)
+{
+	u64 print_evts = KOMEDA_ERR_EVENTS;
+	static bool en_print = true;
+
+	/* reduce the same msg print, only print the first evt for one frame */
+	if (evts->global || is_new_frame(evts))
+		en_print = true;
+	if (!en_print)
+		return;
+
+#ifdef DEBUG
+	print_evts |= KOMEDA_WARN_EVENTS;
+#endif
+
+	if ((evts->global | evts->pipes[0] | evts->pipes[1]) & print_evts) {
+		#define STR_SZ		128
+		char msg[STR_SZ];
+		struct komeda_str str;
+
+		str.str = msg;
+		str.sz  = STR_SZ;
+		str.len = 0;
+
+		komeda_sprintf(&str, "gcu: ");
+		evt_str(&str, evts->global);
+		komeda_sprintf(&str, ", pipes[0]: ");
+		evt_str(&str, evts->pipes[0]);
+		komeda_sprintf(&str, ", pipes[1]: ");
+		evt_str(&str, evts->pipes[1]);
+
+		DRM_ERROR("err detect: %s\n", msg);
+
+		en_print = false;
+	}
+}
diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_kms.c b/drivers/gpu/drm/arm/display/komeda/komeda_kms.c
index 647bce5..1462bac 100644
--- a/drivers/gpu/drm/arm/display/komeda/komeda_kms.c
+++ b/drivers/gpu/drm/arm/display/komeda/komeda_kms.c
@@ -47,6 +47,8 @@ static irqreturn_t komeda_kms_irq_handler(int irq, void *data)
 	memset(&evts, 0, sizeof(evts));
 	status = mdev->funcs->irq_handler(mdev, &evts);
 
+	komeda_print_events(&evts);
+
 	/* Notify the crtc to handle the events */
 	for (i = 0; i < kms->n_crtcs; i++)
 		komeda_crtc_handle_event(&kms->crtcs[i], &evts);
-- 
1.9.1


^ permalink raw reply related	[flat|nested] 37+ messages in thread

* [PATCH] drm/komeda: Adds error event print functionality
@ 2019-06-27  3:10 ` Lowry Li (Arm Technology China)
  0 siblings, 0 replies; 37+ messages in thread
From: Lowry Li (Arm Technology China) @ 2019-06-27  3:10 UTC (permalink / raw)
  To: Liviu Dudau, james qian wang (Arm Technology China),
	maarten.lankhorst, seanpaul, airlied, Brian Starkey
  Cc: Ayan Halder, Jonathan Chai (Arm Technology China),
	linux-kernel, dri-devel, Julien Yin (Arm Technology China),
	nd

Adds to print the event message when error happens and the same event
will not be printed until next vsync.

Signed-off-by: Lowry Li (Arm Technology China) <lowry.li@arm.com>
---
 drivers/gpu/drm/arm/display/komeda/Makefile       |   1 +
 drivers/gpu/drm/arm/display/komeda/komeda_dev.h   |  13 ++
 drivers/gpu/drm/arm/display/komeda/komeda_event.c | 144 ++++++++++++++++++++++
 drivers/gpu/drm/arm/display/komeda/komeda_kms.c   |   2 +
 4 files changed, 160 insertions(+)
 create mode 100644 drivers/gpu/drm/arm/display/komeda/komeda_event.c

diff --git a/drivers/gpu/drm/arm/display/komeda/Makefile b/drivers/gpu/drm/arm/display/komeda/Makefile
index 38aa584..3f53d2d 100644
--- a/drivers/gpu/drm/arm/display/komeda/Makefile
+++ b/drivers/gpu/drm/arm/display/komeda/Makefile
@@ -7,6 +7,7 @@ ccflags-y := \
 komeda-y := \
 	komeda_drv.o \
 	komeda_dev.o \
+	komeda_event.o \
 	komeda_format_caps.o \
 	komeda_coeffs.o \
 	komeda_color_mgmt.o \
diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_dev.h b/drivers/gpu/drm/arm/display/komeda/komeda_dev.h
index 096f9f7..e863ec3 100644
--- a/drivers/gpu/drm/arm/display/komeda/komeda_dev.h
+++ b/drivers/gpu/drm/arm/display/komeda/komeda_dev.h
@@ -40,6 +40,17 @@
 #define KOMEDA_ERR_TTNG			BIT_ULL(30)
 #define KOMEDA_ERR_TTF			BIT_ULL(31)
 
+#define KOMEDA_ERR_EVENTS	\
+	(KOMEDA_EVENT_URUN	| KOMEDA_EVENT_IBSY	| KOMEDA_EVENT_OVR |\
+	KOMEDA_ERR_TETO		| KOMEDA_ERR_TEMR	| KOMEDA_ERR_TITR |\
+	KOMEDA_ERR_CPE		| KOMEDA_ERR_CFGE	| KOMEDA_ERR_AXIE |\
+	KOMEDA_ERR_ACE0		| KOMEDA_ERR_ACE1	| KOMEDA_ERR_ACE2 |\
+	KOMEDA_ERR_ACE3		| KOMEDA_ERR_DRIFTTO	| KOMEDA_ERR_FRAMETO |\
+	KOMEDA_ERR_ZME		| KOMEDA_ERR_MERR	| KOMEDA_ERR_TCF |\
+	KOMEDA_ERR_TTNG		| KOMEDA_ERR_TTF)
+
+#define KOMEDA_WARN_EVENTS	KOMEDA_ERR_CSCE
+
 /* malidp device id */
 enum {
 	MALI_D71 = 0,
@@ -207,6 +218,8 @@ struct komeda_dev {
 
 struct komeda_dev *dev_to_mdev(struct device *dev);
 
+void komeda_print_events(struct komeda_events *evts);
+
 int komeda_dev_resume(struct komeda_dev *mdev);
 int komeda_dev_suspend(struct komeda_dev *mdev);
 #endif /*_KOMEDA_DEV_H_*/
diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_event.c b/drivers/gpu/drm/arm/display/komeda/komeda_event.c
new file mode 100644
index 0000000..309dbe2
--- /dev/null
+++ b/drivers/gpu/drm/arm/display/komeda/komeda_event.c
@@ -0,0 +1,144 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * (C) COPYRIGHT 2019 ARM Limited. All rights reserved.
+ * Author: James.Qian.Wang <james.qian.wang@arm.com>
+ *
+ */
+#include <drm/drm_print.h>
+
+#include "komeda_dev.h"
+
+struct komeda_str {
+	char *str;
+	u32 sz;
+	u32 len;
+};
+
+/* return 0 on success,  < 0 on no space.
+ */
+static int komeda_sprintf(struct komeda_str *str, const char *fmt, ...)
+{
+	va_list args;
+	int num, free_sz;
+	int err;
+
+	free_sz = str->sz - str->len;
+	if (free_sz <= 0)
+		return -ENOSPC;
+
+	va_start(args, fmt);
+
+	num = vsnprintf(str->str + str->len, free_sz, fmt, args);
+
+	va_end(args);
+
+	if (num <= free_sz) {
+		str->len += num;
+		err = 0;
+	} else {
+		str->len = str->sz;
+		err = -ENOSPC;
+	}
+
+	return err;
+}
+
+static void evt_sprintf(struct komeda_str *str, u64 evt, const char *msg)
+{
+	if (evt)
+		komeda_sprintf(str, msg);
+}
+
+static void evt_str(struct komeda_str *str, u64 events)
+{
+	if (events == 0ULL) {
+		evt_sprintf(str, 1, "None");
+		return;
+	}
+
+	evt_sprintf(str, events & KOMEDA_EVENT_VSYNC, "VSYNC|");
+	evt_sprintf(str, events & KOMEDA_EVENT_FLIP, "FLIP|");
+	evt_sprintf(str, events & KOMEDA_EVENT_EOW, "EOW|");
+	evt_sprintf(str, events & KOMEDA_EVENT_MODE, "OP-MODE|");
+
+	evt_sprintf(str, events & KOMEDA_EVENT_URUN, "UNDERRUN|");
+	evt_sprintf(str, events & KOMEDA_EVENT_OVR, "OVERRUN|");
+
+	/* GLB error */
+	evt_sprintf(str, events & KOMEDA_ERR_MERR, "MERR|");
+	evt_sprintf(str, events & KOMEDA_ERR_FRAMETO, "FRAMETO|");
+
+	/* DOU error */
+	evt_sprintf(str, events & KOMEDA_ERR_DRIFTTO, "DRIFTTO|");
+	evt_sprintf(str, events & KOMEDA_ERR_FRAMETO, "FRAMETO|");
+	evt_sprintf(str, events & KOMEDA_ERR_TETO, "TETO|");
+	evt_sprintf(str, events & KOMEDA_ERR_CSCE, "CSCE|");
+
+	/* LPU errors or events */
+	evt_sprintf(str, events & KOMEDA_EVENT_IBSY, "IBSY|");
+	evt_sprintf(str, events & KOMEDA_ERR_AXIE, "AXIE|");
+	evt_sprintf(str, events & KOMEDA_ERR_ACE0, "ACE0|");
+	evt_sprintf(str, events & KOMEDA_ERR_ACE1, "ACE1|");
+	evt_sprintf(str, events & KOMEDA_ERR_ACE2, "ACE2|");
+	evt_sprintf(str, events & KOMEDA_ERR_ACE3, "ACE3|");
+
+	/* LPU TBU errors*/
+	evt_sprintf(str, events & KOMEDA_ERR_TCF, "TCF|");
+	evt_sprintf(str, events & KOMEDA_ERR_TTNG, "TTNG|");
+	evt_sprintf(str, events & KOMEDA_ERR_TITR, "TITR|");
+	evt_sprintf(str, events & KOMEDA_ERR_TEMR, "TEMR|");
+	evt_sprintf(str, events & KOMEDA_ERR_TTF, "TTF|");
+
+	/* CU errors*/
+	evt_sprintf(str, events & KOMEDA_ERR_CPE, "COPROC|");
+	evt_sprintf(str, events & KOMEDA_ERR_ZME, "ZME|");
+	evt_sprintf(str, events & KOMEDA_ERR_CFGE, "CFGE|");
+	evt_sprintf(str, events & KOMEDA_ERR_TEMR, "TEMR|");
+
+	if (str->len > 0 && (str->str[str->len - 1] == '|')) {
+		str->str[str->len - 1] = 0;
+		str->len--;
+	}
+}
+
+static bool is_new_frame(struct komeda_events *a)
+{
+	return (a->pipes[0] | a->pipes[1]) & KOMEDA_EVENT_FLIP;
+}
+
+void komeda_print_events(struct komeda_events *evts)
+{
+	u64 print_evts = KOMEDA_ERR_EVENTS;
+	static bool en_print = true;
+
+	/* reduce the same msg print, only print the first evt for one frame */
+	if (evts->global || is_new_frame(evts))
+		en_print = true;
+	if (!en_print)
+		return;
+
+#ifdef DEBUG
+	print_evts |= KOMEDA_WARN_EVENTS;
+#endif
+
+	if ((evts->global | evts->pipes[0] | evts->pipes[1]) & print_evts) {
+		#define STR_SZ		128
+		char msg[STR_SZ];
+		struct komeda_str str;
+
+		str.str = msg;
+		str.sz  = STR_SZ;
+		str.len = 0;
+
+		komeda_sprintf(&str, "gcu: ");
+		evt_str(&str, evts->global);
+		komeda_sprintf(&str, ", pipes[0]: ");
+		evt_str(&str, evts->pipes[0]);
+		komeda_sprintf(&str, ", pipes[1]: ");
+		evt_str(&str, evts->pipes[1]);
+
+		DRM_ERROR("err detect: %s\n", msg);
+
+		en_print = false;
+	}
+}
diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_kms.c b/drivers/gpu/drm/arm/display/komeda/komeda_kms.c
index 647bce5..1462bac 100644
--- a/drivers/gpu/drm/arm/display/komeda/komeda_kms.c
+++ b/drivers/gpu/drm/arm/display/komeda/komeda_kms.c
@@ -47,6 +47,8 @@ static irqreturn_t komeda_kms_irq_handler(int irq, void *data)
 	memset(&evts, 0, sizeof(evts));
 	status = mdev->funcs->irq_handler(mdev, &evts);
 
+	komeda_print_events(&evts);
+
 	/* Notify the crtc to handle the events */
 	for (i = 0; i < kms->n_crtcs; i++)
 		komeda_crtc_handle_event(&kms->crtcs[i], &evts);
-- 
1.9.1

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 37+ messages in thread

* Re: [PATCH] drm/komeda: Adds error event print functionality
  2019-06-27  3:10 ` Lowry Li (Arm Technology China)
@ 2019-06-27  9:22   ` james qian wang (Arm Technology China)
  -1 siblings, 0 replies; 37+ messages in thread
From: james qian wang (Arm Technology China) @ 2019-06-27  9:22 UTC (permalink / raw)
  To: Lowry Li (Arm Technology China)
  Cc: Liviu Dudau, maarten.lankhorst, seanpaul, airlied, Brian Starkey,
	Julien Yin (Arm Technology China),
	Jonathan Chai (Arm Technology China),
	Ayan Halder, dri-devel, linux-kernel, nd

On Thu, Jun 27, 2019 at 11:10:36AM +0800, Lowry Li (Arm Technology China) wrote:
> Adds to print the event message when error happens and the same event
> will not be printed until next vsync.
> 
> Signed-off-by: Lowry Li (Arm Technology China) <lowry.li@arm.com>
> ---
>  drivers/gpu/drm/arm/display/komeda/Makefile       |   1 +
>  drivers/gpu/drm/arm/display/komeda/komeda_dev.h   |  13 ++
>  drivers/gpu/drm/arm/display/komeda/komeda_event.c | 144 ++++++++++++++++++++++
>  drivers/gpu/drm/arm/display/komeda/komeda_kms.c   |   2 +
>  4 files changed, 160 insertions(+)
>  create mode 100644 drivers/gpu/drm/arm/display/komeda/komeda_event.c
> 
> diff --git a/drivers/gpu/drm/arm/display/komeda/Makefile b/drivers/gpu/drm/arm/display/komeda/Makefile
> index 38aa584..3f53d2d 100644
> --- a/drivers/gpu/drm/arm/display/komeda/Makefile
> +++ b/drivers/gpu/drm/arm/display/komeda/Makefile
> @@ -7,6 +7,7 @@ ccflags-y := \
>  komeda-y := \
>  	komeda_drv.o \
>  	komeda_dev.o \
> +	komeda_event.o \
>  	komeda_format_caps.o \
>  	komeda_coeffs.o \
>  	komeda_color_mgmt.o \
> diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_dev.h b/drivers/gpu/drm/arm/display/komeda/komeda_dev.h
> index 096f9f7..e863ec3 100644
> --- a/drivers/gpu/drm/arm/display/komeda/komeda_dev.h
> +++ b/drivers/gpu/drm/arm/display/komeda/komeda_dev.h
> @@ -40,6 +40,17 @@
>  #define KOMEDA_ERR_TTNG			BIT_ULL(30)
>  #define KOMEDA_ERR_TTF			BIT_ULL(31)
>  
> +#define KOMEDA_ERR_EVENTS	\
> +	(KOMEDA_EVENT_URUN	| KOMEDA_EVENT_IBSY	| KOMEDA_EVENT_OVR |\
> +	KOMEDA_ERR_TETO		| KOMEDA_ERR_TEMR	| KOMEDA_ERR_TITR |\
> +	KOMEDA_ERR_CPE		| KOMEDA_ERR_CFGE	| KOMEDA_ERR_AXIE |\
> +	KOMEDA_ERR_ACE0		| KOMEDA_ERR_ACE1	| KOMEDA_ERR_ACE2 |\
> +	KOMEDA_ERR_ACE3		| KOMEDA_ERR_DRIFTTO	| KOMEDA_ERR_FRAMETO |\
> +	KOMEDA_ERR_ZME		| KOMEDA_ERR_MERR	| KOMEDA_ERR_TCF |\
> +	KOMEDA_ERR_TTNG		| KOMEDA_ERR_TTF)
> +
> +#define KOMEDA_WARN_EVENTS	KOMEDA_ERR_CSCE
> +
>  /* malidp device id */
>  enum {
>  	MALI_D71 = 0,
> @@ -207,6 +218,8 @@ struct komeda_dev {
>  
>  struct komeda_dev *dev_to_mdev(struct device *dev);
>  
> +void komeda_print_events(struct komeda_events *evts);
> +
>  int komeda_dev_resume(struct komeda_dev *mdev);
>  int komeda_dev_suspend(struct komeda_dev *mdev);
>  #endif /*_KOMEDA_DEV_H_*/
> diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_event.c b/drivers/gpu/drm/arm/display/komeda/komeda_event.c
> new file mode 100644
> index 0000000..309dbe2
> --- /dev/null
> +++ b/drivers/gpu/drm/arm/display/komeda/komeda_event.c
> @@ -0,0 +1,144 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * (C) COPYRIGHT 2019 ARM Limited. All rights reserved.
> + * Author: James.Qian.Wang <james.qian.wang@arm.com>
> + *
> + */
> +#include <drm/drm_print.h>
> +
> +#include "komeda_dev.h"
> +
> +struct komeda_str {
> +	char *str;
> +	u32 sz;
> +	u32 len;
> +};
> +
> +/* return 0 on success,  < 0 on no space.
> + */
> +static int komeda_sprintf(struct komeda_str *str, const char *fmt, ...)
> +{
> +	va_list args;
> +	int num, free_sz;
> +	int err;
> +
> +	free_sz = str->sz - str->len;
> +	if (free_sz <= 0)
> +		return -ENOSPC;
> +
> +	va_start(args, fmt);
> +
> +	num = vsnprintf(str->str + str->len, free_sz, fmt, args);
> +
> +	va_end(args);
> +
> +	if (num <= free_sz) {
> +		str->len += num;
> +		err = 0;
> +	} else {
> +		str->len = str->sz;
> +		err = -ENOSPC;
> +	}
> +
> +	return err;
> +}
> +
> +static void evt_sprintf(struct komeda_str *str, u64 evt, const char *msg)
> +{
> +	if (evt)
> +		komeda_sprintf(str, msg);
> +}
> +
> +static void evt_str(struct komeda_str *str, u64 events)
> +{
> +	if (events == 0ULL) {
> +		evt_sprintf(str, 1, "None");
> +		return;
> +	}
> +
> +	evt_sprintf(str, events & KOMEDA_EVENT_VSYNC, "VSYNC|");
> +	evt_sprintf(str, events & KOMEDA_EVENT_FLIP, "FLIP|");
> +	evt_sprintf(str, events & KOMEDA_EVENT_EOW, "EOW|");
> +	evt_sprintf(str, events & KOMEDA_EVENT_MODE, "OP-MODE|");
> +
> +	evt_sprintf(str, events & KOMEDA_EVENT_URUN, "UNDERRUN|");
> +	evt_sprintf(str, events & KOMEDA_EVENT_OVR, "OVERRUN|");
> +
> +	/* GLB error */
> +	evt_sprintf(str, events & KOMEDA_ERR_MERR, "MERR|");
> +	evt_sprintf(str, events & KOMEDA_ERR_FRAMETO, "FRAMETO|");
> +
> +	/* DOU error */
> +	evt_sprintf(str, events & KOMEDA_ERR_DRIFTTO, "DRIFTTO|");
> +	evt_sprintf(str, events & KOMEDA_ERR_FRAMETO, "FRAMETO|");
> +	evt_sprintf(str, events & KOMEDA_ERR_TETO, "TETO|");
> +	evt_sprintf(str, events & KOMEDA_ERR_CSCE, "CSCE|");
> +
> +	/* LPU errors or events */
> +	evt_sprintf(str, events & KOMEDA_EVENT_IBSY, "IBSY|");
> +	evt_sprintf(str, events & KOMEDA_ERR_AXIE, "AXIE|");
> +	evt_sprintf(str, events & KOMEDA_ERR_ACE0, "ACE0|");
> +	evt_sprintf(str, events & KOMEDA_ERR_ACE1, "ACE1|");
> +	evt_sprintf(str, events & KOMEDA_ERR_ACE2, "ACE2|");
> +	evt_sprintf(str, events & KOMEDA_ERR_ACE3, "ACE3|");
> +
> +	/* LPU TBU errors*/
> +	evt_sprintf(str, events & KOMEDA_ERR_TCF, "TCF|");
> +	evt_sprintf(str, events & KOMEDA_ERR_TTNG, "TTNG|");
> +	evt_sprintf(str, events & KOMEDA_ERR_TITR, "TITR|");
> +	evt_sprintf(str, events & KOMEDA_ERR_TEMR, "TEMR|");
> +	evt_sprintf(str, events & KOMEDA_ERR_TTF, "TTF|");
> +
> +	/* CU errors*/
> +	evt_sprintf(str, events & KOMEDA_ERR_CPE, "COPROC|");
> +	evt_sprintf(str, events & KOMEDA_ERR_ZME, "ZME|");
> +	evt_sprintf(str, events & KOMEDA_ERR_CFGE, "CFGE|");
> +	evt_sprintf(str, events & KOMEDA_ERR_TEMR, "TEMR|");
> +
> +	if (str->len > 0 && (str->str[str->len - 1] == '|')) {
> +		str->str[str->len - 1] = 0;
> +		str->len--;
> +	}
> +}
> +
> +static bool is_new_frame(struct komeda_events *a)
> +{
> +	return (a->pipes[0] | a->pipes[1]) & KOMEDA_EVENT_FLIP;
> +}
> +
> +void komeda_print_events(struct komeda_events *evts)
> +{
> +	u64 print_evts = KOMEDA_ERR_EVENTS;
> +	static bool en_print = true;
> +
> +	/* reduce the same msg print, only print the first evt for one frame */
> +	if (evts->global || is_new_frame(evts))
> +		en_print = true;
> +	if (!en_print)
> +		return;
> +
> +#ifdef DEBUG
> +	print_evts |= KOMEDA_WARN_EVENTS;
> +#endif
> +
> +	if ((evts->global | evts->pipes[0] | evts->pipes[1]) & print_evts) {
> +		#define STR_SZ		128
> +		char msg[STR_SZ];
> +		struct komeda_str str;
> +
> +		str.str = msg;
> +		str.sz  = STR_SZ;
> +		str.len = 0;
> +
> +		komeda_sprintf(&str, "gcu: ");
> +		evt_str(&str, evts->global);
> +		komeda_sprintf(&str, ", pipes[0]: ");
> +		evt_str(&str, evts->pipes[0]);
> +		komeda_sprintf(&str, ", pipes[1]: ");
> +		evt_str(&str, evts->pipes[1]);
> +
> +		DRM_ERROR("err detect: %s\n", msg);
> +
> +		en_print = false;
> +	}
> +}
> diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_kms.c b/drivers/gpu/drm/arm/display/komeda/komeda_kms.c
> index 647bce5..1462bac 100644
> --- a/drivers/gpu/drm/arm/display/komeda/komeda_kms.c
> +++ b/drivers/gpu/drm/arm/display/komeda/komeda_kms.c
> @@ -47,6 +47,8 @@ static irqreturn_t komeda_kms_irq_handler(int irq, void *data)
>  	memset(&evts, 0, sizeof(evts));
>  	status = mdev->funcs->irq_handler(mdev, &evts);
>  
> +	komeda_print_events(&evts);
> +
>  	/* Notify the crtc to handle the events */
>  	for (i = 0; i < kms->n_crtcs; i++)
>  		komeda_crtc_handle_event(&kms->crtcs[i], &evts);
> -- 
> 1.9.1
> 

Looks good to me.

Reviewed-by: James Qian Wang (Arm Technology China) <james.qian.wang@arm.com>

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [PATCH] drm/komeda: Adds error event print functionality
@ 2019-06-27  9:22   ` james qian wang (Arm Technology China)
  0 siblings, 0 replies; 37+ messages in thread
From: james qian wang (Arm Technology China) @ 2019-06-27  9:22 UTC (permalink / raw)
  To: Lowry Li (Arm Technology China)
  Cc: nd, airlied, Liviu Dudau, Jonathan Chai (Arm Technology China),
	linux-kernel, dri-devel, Julien Yin (Arm Technology China),
	seanpaul, Ayan Halder

On Thu, Jun 27, 2019 at 11:10:36AM +0800, Lowry Li (Arm Technology China) wrote:
> Adds to print the event message when error happens and the same event
> will not be printed until next vsync.
> 
> Signed-off-by: Lowry Li (Arm Technology China) <lowry.li@arm.com>
> ---
>  drivers/gpu/drm/arm/display/komeda/Makefile       |   1 +
>  drivers/gpu/drm/arm/display/komeda/komeda_dev.h   |  13 ++
>  drivers/gpu/drm/arm/display/komeda/komeda_event.c | 144 ++++++++++++++++++++++
>  drivers/gpu/drm/arm/display/komeda/komeda_kms.c   |   2 +
>  4 files changed, 160 insertions(+)
>  create mode 100644 drivers/gpu/drm/arm/display/komeda/komeda_event.c
> 
> diff --git a/drivers/gpu/drm/arm/display/komeda/Makefile b/drivers/gpu/drm/arm/display/komeda/Makefile
> index 38aa584..3f53d2d 100644
> --- a/drivers/gpu/drm/arm/display/komeda/Makefile
> +++ b/drivers/gpu/drm/arm/display/komeda/Makefile
> @@ -7,6 +7,7 @@ ccflags-y := \
>  komeda-y := \
>  	komeda_drv.o \
>  	komeda_dev.o \
> +	komeda_event.o \
>  	komeda_format_caps.o \
>  	komeda_coeffs.o \
>  	komeda_color_mgmt.o \
> diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_dev.h b/drivers/gpu/drm/arm/display/komeda/komeda_dev.h
> index 096f9f7..e863ec3 100644
> --- a/drivers/gpu/drm/arm/display/komeda/komeda_dev.h
> +++ b/drivers/gpu/drm/arm/display/komeda/komeda_dev.h
> @@ -40,6 +40,17 @@
>  #define KOMEDA_ERR_TTNG			BIT_ULL(30)
>  #define KOMEDA_ERR_TTF			BIT_ULL(31)
>  
> +#define KOMEDA_ERR_EVENTS	\
> +	(KOMEDA_EVENT_URUN	| KOMEDA_EVENT_IBSY	| KOMEDA_EVENT_OVR |\
> +	KOMEDA_ERR_TETO		| KOMEDA_ERR_TEMR	| KOMEDA_ERR_TITR |\
> +	KOMEDA_ERR_CPE		| KOMEDA_ERR_CFGE	| KOMEDA_ERR_AXIE |\
> +	KOMEDA_ERR_ACE0		| KOMEDA_ERR_ACE1	| KOMEDA_ERR_ACE2 |\
> +	KOMEDA_ERR_ACE3		| KOMEDA_ERR_DRIFTTO	| KOMEDA_ERR_FRAMETO |\
> +	KOMEDA_ERR_ZME		| KOMEDA_ERR_MERR	| KOMEDA_ERR_TCF |\
> +	KOMEDA_ERR_TTNG		| KOMEDA_ERR_TTF)
> +
> +#define KOMEDA_WARN_EVENTS	KOMEDA_ERR_CSCE
> +
>  /* malidp device id */
>  enum {
>  	MALI_D71 = 0,
> @@ -207,6 +218,8 @@ struct komeda_dev {
>  
>  struct komeda_dev *dev_to_mdev(struct device *dev);
>  
> +void komeda_print_events(struct komeda_events *evts);
> +
>  int komeda_dev_resume(struct komeda_dev *mdev);
>  int komeda_dev_suspend(struct komeda_dev *mdev);
>  #endif /*_KOMEDA_DEV_H_*/
> diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_event.c b/drivers/gpu/drm/arm/display/komeda/komeda_event.c
> new file mode 100644
> index 0000000..309dbe2
> --- /dev/null
> +++ b/drivers/gpu/drm/arm/display/komeda/komeda_event.c
> @@ -0,0 +1,144 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * (C) COPYRIGHT 2019 ARM Limited. All rights reserved.
> + * Author: James.Qian.Wang <james.qian.wang@arm.com>
> + *
> + */
> +#include <drm/drm_print.h>
> +
> +#include "komeda_dev.h"
> +
> +struct komeda_str {
> +	char *str;
> +	u32 sz;
> +	u32 len;
> +};
> +
> +/* return 0 on success,  < 0 on no space.
> + */
> +static int komeda_sprintf(struct komeda_str *str, const char *fmt, ...)
> +{
> +	va_list args;
> +	int num, free_sz;
> +	int err;
> +
> +	free_sz = str->sz - str->len;
> +	if (free_sz <= 0)
> +		return -ENOSPC;
> +
> +	va_start(args, fmt);
> +
> +	num = vsnprintf(str->str + str->len, free_sz, fmt, args);
> +
> +	va_end(args);
> +
> +	if (num <= free_sz) {
> +		str->len += num;
> +		err = 0;
> +	} else {
> +		str->len = str->sz;
> +		err = -ENOSPC;
> +	}
> +
> +	return err;
> +}
> +
> +static void evt_sprintf(struct komeda_str *str, u64 evt, const char *msg)
> +{
> +	if (evt)
> +		komeda_sprintf(str, msg);
> +}
> +
> +static void evt_str(struct komeda_str *str, u64 events)
> +{
> +	if (events == 0ULL) {
> +		evt_sprintf(str, 1, "None");
> +		return;
> +	}
> +
> +	evt_sprintf(str, events & KOMEDA_EVENT_VSYNC, "VSYNC|");
> +	evt_sprintf(str, events & KOMEDA_EVENT_FLIP, "FLIP|");
> +	evt_sprintf(str, events & KOMEDA_EVENT_EOW, "EOW|");
> +	evt_sprintf(str, events & KOMEDA_EVENT_MODE, "OP-MODE|");
> +
> +	evt_sprintf(str, events & KOMEDA_EVENT_URUN, "UNDERRUN|");
> +	evt_sprintf(str, events & KOMEDA_EVENT_OVR, "OVERRUN|");
> +
> +	/* GLB error */
> +	evt_sprintf(str, events & KOMEDA_ERR_MERR, "MERR|");
> +	evt_sprintf(str, events & KOMEDA_ERR_FRAMETO, "FRAMETO|");
> +
> +	/* DOU error */
> +	evt_sprintf(str, events & KOMEDA_ERR_DRIFTTO, "DRIFTTO|");
> +	evt_sprintf(str, events & KOMEDA_ERR_FRAMETO, "FRAMETO|");
> +	evt_sprintf(str, events & KOMEDA_ERR_TETO, "TETO|");
> +	evt_sprintf(str, events & KOMEDA_ERR_CSCE, "CSCE|");
> +
> +	/* LPU errors or events */
> +	evt_sprintf(str, events & KOMEDA_EVENT_IBSY, "IBSY|");
> +	evt_sprintf(str, events & KOMEDA_ERR_AXIE, "AXIE|");
> +	evt_sprintf(str, events & KOMEDA_ERR_ACE0, "ACE0|");
> +	evt_sprintf(str, events & KOMEDA_ERR_ACE1, "ACE1|");
> +	evt_sprintf(str, events & KOMEDA_ERR_ACE2, "ACE2|");
> +	evt_sprintf(str, events & KOMEDA_ERR_ACE3, "ACE3|");
> +
> +	/* LPU TBU errors*/
> +	evt_sprintf(str, events & KOMEDA_ERR_TCF, "TCF|");
> +	evt_sprintf(str, events & KOMEDA_ERR_TTNG, "TTNG|");
> +	evt_sprintf(str, events & KOMEDA_ERR_TITR, "TITR|");
> +	evt_sprintf(str, events & KOMEDA_ERR_TEMR, "TEMR|");
> +	evt_sprintf(str, events & KOMEDA_ERR_TTF, "TTF|");
> +
> +	/* CU errors*/
> +	evt_sprintf(str, events & KOMEDA_ERR_CPE, "COPROC|");
> +	evt_sprintf(str, events & KOMEDA_ERR_ZME, "ZME|");
> +	evt_sprintf(str, events & KOMEDA_ERR_CFGE, "CFGE|");
> +	evt_sprintf(str, events & KOMEDA_ERR_TEMR, "TEMR|");
> +
> +	if (str->len > 0 && (str->str[str->len - 1] == '|')) {
> +		str->str[str->len - 1] = 0;
> +		str->len--;
> +	}
> +}
> +
> +static bool is_new_frame(struct komeda_events *a)
> +{
> +	return (a->pipes[0] | a->pipes[1]) & KOMEDA_EVENT_FLIP;
> +}
> +
> +void komeda_print_events(struct komeda_events *evts)
> +{
> +	u64 print_evts = KOMEDA_ERR_EVENTS;
> +	static bool en_print = true;
> +
> +	/* reduce the same msg print, only print the first evt for one frame */
> +	if (evts->global || is_new_frame(evts))
> +		en_print = true;
> +	if (!en_print)
> +		return;
> +
> +#ifdef DEBUG
> +	print_evts |= KOMEDA_WARN_EVENTS;
> +#endif
> +
> +	if ((evts->global | evts->pipes[0] | evts->pipes[1]) & print_evts) {
> +		#define STR_SZ		128
> +		char msg[STR_SZ];
> +		struct komeda_str str;
> +
> +		str.str = msg;
> +		str.sz  = STR_SZ;
> +		str.len = 0;
> +
> +		komeda_sprintf(&str, "gcu: ");
> +		evt_str(&str, evts->global);
> +		komeda_sprintf(&str, ", pipes[0]: ");
> +		evt_str(&str, evts->pipes[0]);
> +		komeda_sprintf(&str, ", pipes[1]: ");
> +		evt_str(&str, evts->pipes[1]);
> +
> +		DRM_ERROR("err detect: %s\n", msg);
> +
> +		en_print = false;
> +	}
> +}
> diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_kms.c b/drivers/gpu/drm/arm/display/komeda/komeda_kms.c
> index 647bce5..1462bac 100644
> --- a/drivers/gpu/drm/arm/display/komeda/komeda_kms.c
> +++ b/drivers/gpu/drm/arm/display/komeda/komeda_kms.c
> @@ -47,6 +47,8 @@ static irqreturn_t komeda_kms_irq_handler(int irq, void *data)
>  	memset(&evts, 0, sizeof(evts));
>  	status = mdev->funcs->irq_handler(mdev, &evts);
>  
> +	komeda_print_events(&evts);
> +
>  	/* Notify the crtc to handle the events */
>  	for (i = 0; i < kms->n_crtcs; i++)
>  		komeda_crtc_handle_event(&kms->crtcs[i], &evts);
> -- 
> 1.9.1
> 

Looks good to me.

Reviewed-by: James Qian Wang (Arm Technology China) <james.qian.wang@arm.com>
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [PATCH] drm/komeda: Adds error event print functionality
  2019-06-27  3:10 ` Lowry Li (Arm Technology China)
@ 2019-07-18 13:17   ` Liviu Dudau
  -1 siblings, 0 replies; 37+ messages in thread
From: Liviu Dudau @ 2019-07-18 13:17 UTC (permalink / raw)
  To: Lowry Li (Arm Technology China)
  Cc: james qian wang (Arm Technology China),
	maarten.lankhorst, seanpaul, airlied, Brian Starkey,
	Julien Yin (Arm Technology China),
	Jonathan Chai (Arm Technology China),
	Ayan Halder, dri-devel, linux-kernel, nd

On Thu, Jun 27, 2019 at 04:10:36AM +0100, Lowry Li (Arm Technology China) wrote:
> Adds to print the event message when error happens and the same event
> will not be printed until next vsync.
> 
> Signed-off-by: Lowry Li (Arm Technology China) <lowry.li@arm.com>
> ---
>  drivers/gpu/drm/arm/display/komeda/Makefile       |   1 +
>  drivers/gpu/drm/arm/display/komeda/komeda_dev.h   |  13 ++
>  drivers/gpu/drm/arm/display/komeda/komeda_event.c | 144 ++++++++++++++++++++++
>  drivers/gpu/drm/arm/display/komeda/komeda_kms.c   |   2 +
>  4 files changed, 160 insertions(+)
>  create mode 100644 drivers/gpu/drm/arm/display/komeda/komeda_event.c
> 
> diff --git a/drivers/gpu/drm/arm/display/komeda/Makefile b/drivers/gpu/drm/arm/display/komeda/Makefile
> index 38aa584..3f53d2d 100644
> --- a/drivers/gpu/drm/arm/display/komeda/Makefile
> +++ b/drivers/gpu/drm/arm/display/komeda/Makefile
> @@ -7,6 +7,7 @@ ccflags-y := \
>  komeda-y := \
>  	komeda_drv.o \
>  	komeda_dev.o \
> +	komeda_event.o \
>  	komeda_format_caps.o \
>  	komeda_coeffs.o \
>  	komeda_color_mgmt.o \
> diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_dev.h b/drivers/gpu/drm/arm/display/komeda/komeda_dev.h
> index 096f9f7..e863ec3 100644
> --- a/drivers/gpu/drm/arm/display/komeda/komeda_dev.h
> +++ b/drivers/gpu/drm/arm/display/komeda/komeda_dev.h
> @@ -40,6 +40,17 @@
>  #define KOMEDA_ERR_TTNG			BIT_ULL(30)
>  #define KOMEDA_ERR_TTF			BIT_ULL(31)
>  
> +#define KOMEDA_ERR_EVENTS	\
> +	(KOMEDA_EVENT_URUN	| KOMEDA_EVENT_IBSY	| KOMEDA_EVENT_OVR |\
> +	KOMEDA_ERR_TETO		| KOMEDA_ERR_TEMR	| KOMEDA_ERR_TITR |\
> +	KOMEDA_ERR_CPE		| KOMEDA_ERR_CFGE	| KOMEDA_ERR_AXIE |\
> +	KOMEDA_ERR_ACE0		| KOMEDA_ERR_ACE1	| KOMEDA_ERR_ACE2 |\
> +	KOMEDA_ERR_ACE3		| KOMEDA_ERR_DRIFTTO	| KOMEDA_ERR_FRAMETO |\
> +	KOMEDA_ERR_ZME		| KOMEDA_ERR_MERR	| KOMEDA_ERR_TCF |\
> +	KOMEDA_ERR_TTNG		| KOMEDA_ERR_TTF)
> +
> +#define KOMEDA_WARN_EVENTS	KOMEDA_ERR_CSCE
> +
>  /* malidp device id */
>  enum {
>  	MALI_D71 = 0,
> @@ -207,6 +218,8 @@ struct komeda_dev {
>  
>  struct komeda_dev *dev_to_mdev(struct device *dev);
>  
> +void komeda_print_events(struct komeda_events *evts);
> +
>  int komeda_dev_resume(struct komeda_dev *mdev);
>  int komeda_dev_suspend(struct komeda_dev *mdev);
>  #endif /*_KOMEDA_DEV_H_*/
> diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_event.c b/drivers/gpu/drm/arm/display/komeda/komeda_event.c
> new file mode 100644
> index 0000000..309dbe2
> --- /dev/null
> +++ b/drivers/gpu/drm/arm/display/komeda/komeda_event.c
> @@ -0,0 +1,144 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * (C) COPYRIGHT 2019 ARM Limited. All rights reserved.
> + * Author: James.Qian.Wang <james.qian.wang@arm.com>
> + *
> + */
> +#include <drm/drm_print.h>
> +
> +#include "komeda_dev.h"
> +
> +struct komeda_str {
> +	char *str;
> +	u32 sz;
> +	u32 len;
> +};
> +
> +/* return 0 on success,  < 0 on no space.
> + */
> +static int komeda_sprintf(struct komeda_str *str, const char *fmt, ...)
> +{
> +	va_list args;
> +	int num, free_sz;
> +	int err;
> +
> +	free_sz = str->sz - str->len;
> +	if (free_sz <= 0)
> +		return -ENOSPC;
> +
> +	va_start(args, fmt);
> +
> +	num = vsnprintf(str->str + str->len, free_sz, fmt, args);
> +
> +	va_end(args);
> +
> +	if (num <= free_sz) {
> +		str->len += num;
> +		err = 0;
> +	} else {
> +		str->len = str->sz;
> +		err = -ENOSPC;
> +	}
> +
> +	return err;
> +}
> +
> +static void evt_sprintf(struct komeda_str *str, u64 evt, const char *msg)
> +{
> +	if (evt)
> +		komeda_sprintf(str, msg);
> +}

Why do we need this wrapper?

> +
> +static void evt_str(struct komeda_str *str, u64 events)
> +{
> +	if (events == 0ULL) {
> +		evt_sprintf(str, 1, "None");
> +		return;
> +	}
> +
> +	evt_sprintf(str, events & KOMEDA_EVENT_VSYNC, "VSYNC|");
> +	evt_sprintf(str, events & KOMEDA_EVENT_FLIP, "FLIP|");
> +	evt_sprintf(str, events & KOMEDA_EVENT_EOW, "EOW|");
> +	evt_sprintf(str, events & KOMEDA_EVENT_MODE, "OP-MODE|");
> +
> +	evt_sprintf(str, events & KOMEDA_EVENT_URUN, "UNDERRUN|");
> +	evt_sprintf(str, events & KOMEDA_EVENT_OVR, "OVERRUN|");
> +
> +	/* GLB error */
> +	evt_sprintf(str, events & KOMEDA_ERR_MERR, "MERR|");
> +	evt_sprintf(str, events & KOMEDA_ERR_FRAMETO, "FRAMETO|");
> +
> +	/* DOU error */
> +	evt_sprintf(str, events & KOMEDA_ERR_DRIFTTO, "DRIFTTO|");
> +	evt_sprintf(str, events & KOMEDA_ERR_FRAMETO, "FRAMETO|");
> +	evt_sprintf(str, events & KOMEDA_ERR_TETO, "TETO|");
> +	evt_sprintf(str, events & KOMEDA_ERR_CSCE, "CSCE|");
> +
> +	/* LPU errors or events */
> +	evt_sprintf(str, events & KOMEDA_EVENT_IBSY, "IBSY|");
> +	evt_sprintf(str, events & KOMEDA_ERR_AXIE, "AXIE|");
> +	evt_sprintf(str, events & KOMEDA_ERR_ACE0, "ACE0|");
> +	evt_sprintf(str, events & KOMEDA_ERR_ACE1, "ACE1|");
> +	evt_sprintf(str, events & KOMEDA_ERR_ACE2, "ACE2|");
> +	evt_sprintf(str, events & KOMEDA_ERR_ACE3, "ACE3|");
> +
> +	/* LPU TBU errors*/
> +	evt_sprintf(str, events & KOMEDA_ERR_TCF, "TCF|");
> +	evt_sprintf(str, events & KOMEDA_ERR_TTNG, "TTNG|");
> +	evt_sprintf(str, events & KOMEDA_ERR_TITR, "TITR|");
> +	evt_sprintf(str, events & KOMEDA_ERR_TEMR, "TEMR|");
> +	evt_sprintf(str, events & KOMEDA_ERR_TTF, "TTF|");
> +
> +	/* CU errors*/
> +	evt_sprintf(str, events & KOMEDA_ERR_CPE, "COPROC|");
> +	evt_sprintf(str, events & KOMEDA_ERR_ZME, "ZME|");
> +	evt_sprintf(str, events & KOMEDA_ERR_CFGE, "CFGE|");
> +	evt_sprintf(str, events & KOMEDA_ERR_TEMR, "TEMR|");
> +
> +	if (str->len > 0 && (str->str[str->len - 1] == '|')) {
> +		str->str[str->len - 1] = 0;
> +		str->len--;
> +	}
> +}
> +
> +static bool is_new_frame(struct komeda_events *a)
> +{
> +	return (a->pipes[0] | a->pipes[1]) & KOMEDA_EVENT_FLIP;
> +}
> +
> +void komeda_print_events(struct komeda_events *evts)
> +{
> +	u64 print_evts = KOMEDA_ERR_EVENTS;
> +	static bool en_print = true;
> +
> +	/* reduce the same msg print, only print the first evt for one frame */
> +	if (evts->global || is_new_frame(evts))
> +		en_print = true;
> +	if (!en_print)
> +		return;

When does en_print ever get false?

> +
> +#ifdef DEBUG
> +	print_evts |= KOMEDA_WARN_EVENTS;
> +#endif
> +
> +	if ((evts->global | evts->pipes[0] | evts->pipes[1]) & print_evts) {
> +		#define STR_SZ		128
> +		char msg[STR_SZ];

I've counted about 27 evt_sprintf() calls in evt_str() function, with an
average of 5 characters each, so thats 135 characters printed into a buffer
that is only 128 bytes. Please don't do this!

> +		struct komeda_str str;
> +
> +		str.str = msg;
> +		str.sz  = STR_SZ;
> +		str.len = 0;
> +
> +		komeda_sprintf(&str, "gcu: ");
> +		evt_str(&str, evts->global);
> +		komeda_sprintf(&str, ", pipes[0]: ");
> +		evt_str(&str, evts->pipes[0]);
> +		komeda_sprintf(&str, ", pipes[1]: ");
> +		evt_str(&str, evts->pipes[1]);
> +
> +		DRM_ERROR("err detect: %s\n", msg);
> +
> +		en_print = false;
> +	}
> +}
> diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_kms.c b/drivers/gpu/drm/arm/display/komeda/komeda_kms.c
> index 647bce5..1462bac 100644
> --- a/drivers/gpu/drm/arm/display/komeda/komeda_kms.c
> +++ b/drivers/gpu/drm/arm/display/komeda/komeda_kms.c
> @@ -47,6 +47,8 @@ static irqreturn_t komeda_kms_irq_handler(int irq, void *data)
>  	memset(&evts, 0, sizeof(evts));
>  	status = mdev->funcs->irq_handler(mdev, &evts);
>  
> +	komeda_print_events(&evts);

Calling this function from the IRQ handler is a bad idea. We should use debugfs
if you really want to have a trace of the events, but I personally don't see
value in having this functionality in the kernel at all. You can expose the
value of the evts->global and evts->pipes[] as integers and decode that in
userspace or as a debugfs entry.

Best regards,
Liviu

> +
>  	/* Notify the crtc to handle the events */
>  	for (i = 0; i < kms->n_crtcs; i++)
>  		komeda_crtc_handle_event(&kms->crtcs[i], &evts);
> -- 
> 1.9.1
> 

-- 
====================
| I would like to |
| fix the world,  |
| but they're not |
| giving me the   |
 \ source code!  /
  ---------------
    ¯\_(ツ)_/¯

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [PATCH] drm/komeda: Adds error event print functionality
@ 2019-07-18 13:17   ` Liviu Dudau
  0 siblings, 0 replies; 37+ messages in thread
From: Liviu Dudau @ 2019-07-18 13:17 UTC (permalink / raw)
  To: Lowry Li (Arm Technology China)
  Cc: james qian wang (Arm Technology China),
	maarten.lankhorst, seanpaul, airlied, Brian Starkey,
	Julien Yin (Arm Technology China),
	Jonathan Chai (Arm Technology China),
	Ayan Halder, dri-devel, linux-kernel, nd

On Thu, Jun 27, 2019 at 04:10:36AM +0100, Lowry Li (Arm Technology China) wrote:
> Adds to print the event message when error happens and the same event
> will not be printed until next vsync.
> 
> Signed-off-by: Lowry Li (Arm Technology China) <lowry.li@arm.com>
> ---
>  drivers/gpu/drm/arm/display/komeda/Makefile       |   1 +
>  drivers/gpu/drm/arm/display/komeda/komeda_dev.h   |  13 ++
>  drivers/gpu/drm/arm/display/komeda/komeda_event.c | 144 ++++++++++++++++++++++
>  drivers/gpu/drm/arm/display/komeda/komeda_kms.c   |   2 +
>  4 files changed, 160 insertions(+)
>  create mode 100644 drivers/gpu/drm/arm/display/komeda/komeda_event.c
> 
> diff --git a/drivers/gpu/drm/arm/display/komeda/Makefile b/drivers/gpu/drm/arm/display/komeda/Makefile
> index 38aa584..3f53d2d 100644
> --- a/drivers/gpu/drm/arm/display/komeda/Makefile
> +++ b/drivers/gpu/drm/arm/display/komeda/Makefile
> @@ -7,6 +7,7 @@ ccflags-y := \
>  komeda-y := \
>  	komeda_drv.o \
>  	komeda_dev.o \
> +	komeda_event.o \
>  	komeda_format_caps.o \
>  	komeda_coeffs.o \
>  	komeda_color_mgmt.o \
> diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_dev.h b/drivers/gpu/drm/arm/display/komeda/komeda_dev.h
> index 096f9f7..e863ec3 100644
> --- a/drivers/gpu/drm/arm/display/komeda/komeda_dev.h
> +++ b/drivers/gpu/drm/arm/display/komeda/komeda_dev.h
> @@ -40,6 +40,17 @@
>  #define KOMEDA_ERR_TTNG			BIT_ULL(30)
>  #define KOMEDA_ERR_TTF			BIT_ULL(31)
>  
> +#define KOMEDA_ERR_EVENTS	\
> +	(KOMEDA_EVENT_URUN	| KOMEDA_EVENT_IBSY	| KOMEDA_EVENT_OVR |\
> +	KOMEDA_ERR_TETO		| KOMEDA_ERR_TEMR	| KOMEDA_ERR_TITR |\
> +	KOMEDA_ERR_CPE		| KOMEDA_ERR_CFGE	| KOMEDA_ERR_AXIE |\
> +	KOMEDA_ERR_ACE0		| KOMEDA_ERR_ACE1	| KOMEDA_ERR_ACE2 |\
> +	KOMEDA_ERR_ACE3		| KOMEDA_ERR_DRIFTTO	| KOMEDA_ERR_FRAMETO |\
> +	KOMEDA_ERR_ZME		| KOMEDA_ERR_MERR	| KOMEDA_ERR_TCF |\
> +	KOMEDA_ERR_TTNG		| KOMEDA_ERR_TTF)
> +
> +#define KOMEDA_WARN_EVENTS	KOMEDA_ERR_CSCE
> +
>  /* malidp device id */
>  enum {
>  	MALI_D71 = 0,
> @@ -207,6 +218,8 @@ struct komeda_dev {
>  
>  struct komeda_dev *dev_to_mdev(struct device *dev);
>  
> +void komeda_print_events(struct komeda_events *evts);
> +
>  int komeda_dev_resume(struct komeda_dev *mdev);
>  int komeda_dev_suspend(struct komeda_dev *mdev);
>  #endif /*_KOMEDA_DEV_H_*/
> diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_event.c b/drivers/gpu/drm/arm/display/komeda/komeda_event.c
> new file mode 100644
> index 0000000..309dbe2
> --- /dev/null
> +++ b/drivers/gpu/drm/arm/display/komeda/komeda_event.c
> @@ -0,0 +1,144 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * (C) COPYRIGHT 2019 ARM Limited. All rights reserved.
> + * Author: James.Qian.Wang <james.qian.wang@arm.com>
> + *
> + */
> +#include <drm/drm_print.h>
> +
> +#include "komeda_dev.h"
> +
> +struct komeda_str {
> +	char *str;
> +	u32 sz;
> +	u32 len;
> +};
> +
> +/* return 0 on success,  < 0 on no space.
> + */
> +static int komeda_sprintf(struct komeda_str *str, const char *fmt, ...)
> +{
> +	va_list args;
> +	int num, free_sz;
> +	int err;
> +
> +	free_sz = str->sz - str->len;
> +	if (free_sz <= 0)
> +		return -ENOSPC;
> +
> +	va_start(args, fmt);
> +
> +	num = vsnprintf(str->str + str->len, free_sz, fmt, args);
> +
> +	va_end(args);
> +
> +	if (num <= free_sz) {
> +		str->len += num;
> +		err = 0;
> +	} else {
> +		str->len = str->sz;
> +		err = -ENOSPC;
> +	}
> +
> +	return err;
> +}
> +
> +static void evt_sprintf(struct komeda_str *str, u64 evt, const char *msg)
> +{
> +	if (evt)
> +		komeda_sprintf(str, msg);
> +}

Why do we need this wrapper?

> +
> +static void evt_str(struct komeda_str *str, u64 events)
> +{
> +	if (events == 0ULL) {
> +		evt_sprintf(str, 1, "None");
> +		return;
> +	}
> +
> +	evt_sprintf(str, events & KOMEDA_EVENT_VSYNC, "VSYNC|");
> +	evt_sprintf(str, events & KOMEDA_EVENT_FLIP, "FLIP|");
> +	evt_sprintf(str, events & KOMEDA_EVENT_EOW, "EOW|");
> +	evt_sprintf(str, events & KOMEDA_EVENT_MODE, "OP-MODE|");
> +
> +	evt_sprintf(str, events & KOMEDA_EVENT_URUN, "UNDERRUN|");
> +	evt_sprintf(str, events & KOMEDA_EVENT_OVR, "OVERRUN|");
> +
> +	/* GLB error */
> +	evt_sprintf(str, events & KOMEDA_ERR_MERR, "MERR|");
> +	evt_sprintf(str, events & KOMEDA_ERR_FRAMETO, "FRAMETO|");
> +
> +	/* DOU error */
> +	evt_sprintf(str, events & KOMEDA_ERR_DRIFTTO, "DRIFTTO|");
> +	evt_sprintf(str, events & KOMEDA_ERR_FRAMETO, "FRAMETO|");
> +	evt_sprintf(str, events & KOMEDA_ERR_TETO, "TETO|");
> +	evt_sprintf(str, events & KOMEDA_ERR_CSCE, "CSCE|");
> +
> +	/* LPU errors or events */
> +	evt_sprintf(str, events & KOMEDA_EVENT_IBSY, "IBSY|");
> +	evt_sprintf(str, events & KOMEDA_ERR_AXIE, "AXIE|");
> +	evt_sprintf(str, events & KOMEDA_ERR_ACE0, "ACE0|");
> +	evt_sprintf(str, events & KOMEDA_ERR_ACE1, "ACE1|");
> +	evt_sprintf(str, events & KOMEDA_ERR_ACE2, "ACE2|");
> +	evt_sprintf(str, events & KOMEDA_ERR_ACE3, "ACE3|");
> +
> +	/* LPU TBU errors*/
> +	evt_sprintf(str, events & KOMEDA_ERR_TCF, "TCF|");
> +	evt_sprintf(str, events & KOMEDA_ERR_TTNG, "TTNG|");
> +	evt_sprintf(str, events & KOMEDA_ERR_TITR, "TITR|");
> +	evt_sprintf(str, events & KOMEDA_ERR_TEMR, "TEMR|");
> +	evt_sprintf(str, events & KOMEDA_ERR_TTF, "TTF|");
> +
> +	/* CU errors*/
> +	evt_sprintf(str, events & KOMEDA_ERR_CPE, "COPROC|");
> +	evt_sprintf(str, events & KOMEDA_ERR_ZME, "ZME|");
> +	evt_sprintf(str, events & KOMEDA_ERR_CFGE, "CFGE|");
> +	evt_sprintf(str, events & KOMEDA_ERR_TEMR, "TEMR|");
> +
> +	if (str->len > 0 && (str->str[str->len - 1] == '|')) {
> +		str->str[str->len - 1] = 0;
> +		str->len--;
> +	}
> +}
> +
> +static bool is_new_frame(struct komeda_events *a)
> +{
> +	return (a->pipes[0] | a->pipes[1]) & KOMEDA_EVENT_FLIP;
> +}
> +
> +void komeda_print_events(struct komeda_events *evts)
> +{
> +	u64 print_evts = KOMEDA_ERR_EVENTS;
> +	static bool en_print = true;
> +
> +	/* reduce the same msg print, only print the first evt for one frame */
> +	if (evts->global || is_new_frame(evts))
> +		en_print = true;
> +	if (!en_print)
> +		return;

When does en_print ever get false?

> +
> +#ifdef DEBUG
> +	print_evts |= KOMEDA_WARN_EVENTS;
> +#endif
> +
> +	if ((evts->global | evts->pipes[0] | evts->pipes[1]) & print_evts) {
> +		#define STR_SZ		128
> +		char msg[STR_SZ];

I've counted about 27 evt_sprintf() calls in evt_str() function, with an
average of 5 characters each, so thats 135 characters printed into a buffer
that is only 128 bytes. Please don't do this!

> +		struct komeda_str str;
> +
> +		str.str = msg;
> +		str.sz  = STR_SZ;
> +		str.len = 0;
> +
> +		komeda_sprintf(&str, "gcu: ");
> +		evt_str(&str, evts->global);
> +		komeda_sprintf(&str, ", pipes[0]: ");
> +		evt_str(&str, evts->pipes[0]);
> +		komeda_sprintf(&str, ", pipes[1]: ");
> +		evt_str(&str, evts->pipes[1]);
> +
> +		DRM_ERROR("err detect: %s\n", msg);
> +
> +		en_print = false;
> +	}
> +}
> diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_kms.c b/drivers/gpu/drm/arm/display/komeda/komeda_kms.c
> index 647bce5..1462bac 100644
> --- a/drivers/gpu/drm/arm/display/komeda/komeda_kms.c
> +++ b/drivers/gpu/drm/arm/display/komeda/komeda_kms.c
> @@ -47,6 +47,8 @@ static irqreturn_t komeda_kms_irq_handler(int irq, void *data)
>  	memset(&evts, 0, sizeof(evts));
>  	status = mdev->funcs->irq_handler(mdev, &evts);
>  
> +	komeda_print_events(&evts);

Calling this function from the IRQ handler is a bad idea. We should use debugfs
if you really want to have a trace of the events, but I personally don't see
value in having this functionality in the kernel at all. You can expose the
value of the evts->global and evts->pipes[] as integers and decode that in
userspace or as a debugfs entry.

Best regards,
Liviu

> +
>  	/* Notify the crtc to handle the events */
>  	for (i = 0; i < kms->n_crtcs; i++)
>  		komeda_crtc_handle_event(&kms->crtcs[i], &evts);
> -- 
> 1.9.1
> 

-- 
====================
| I would like to |
| fix the world,  |
| but they're not |
| giving me the   |
 \ source code!  /
  ---------------
    ¯\_(ツ)_/¯

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [PATCH] drm/komeda: Adds error event print functionality
  2019-07-18 13:17   ` Liviu Dudau
@ 2019-07-18 15:23     ` Sean Paul
  -1 siblings, 0 replies; 37+ messages in thread
From: Sean Paul @ 2019-07-18 15:23 UTC (permalink / raw)
  To: Liviu Dudau
  Cc: Lowry Li (Arm Technology China),
	james qian wang (Arm Technology China),
	maarten.lankhorst, seanpaul, airlied, Brian Starkey,
	Julien Yin (Arm Technology China),
	Jonathan Chai (Arm Technology China),
	Ayan Halder, dri-devel, linux-kernel, nd

On Thu, Jul 18, 2019 at 02:17:37PM +0100, Liviu Dudau wrote:
> On Thu, Jun 27, 2019 at 04:10:36AM +0100, Lowry Li (Arm Technology China) wrote:

/snip

> > diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_kms.c b/drivers/gpu/drm/arm/display/komeda/komeda_kms.c
> > index 647bce5..1462bac 100644
> > --- a/drivers/gpu/drm/arm/display/komeda/komeda_kms.c
> > +++ b/drivers/gpu/drm/arm/display/komeda/komeda_kms.c
> > @@ -47,6 +47,8 @@ static irqreturn_t komeda_kms_irq_handler(int irq, void *data)
> >  	memset(&evts, 0, sizeof(evts));
> >  	status = mdev->funcs->irq_handler(mdev, &evts);
> >  
> > +	komeda_print_events(&evts);
> 
> Calling this function from the IRQ handler is a bad idea. We should use debugfs
> if you really want to have a trace of the events, but I personally don't see
> value in having this functionality in the kernel at all. You can expose the
> value of the evts->global and evts->pipes[] as integers and decode that in
> userspace or as a debugfs entry.

Alternatively, consider using kernel trace events. They allow you to selectively
turn on/off certain events and also allow you to customize which data is
recorded and how it's formatted. Seems like a good fit from the quick scan I've
done.

Sean

> 
> Best regards,
> Liviu
> 
> > +
> >  	/* Notify the crtc to handle the events */
> >  	for (i = 0; i < kms->n_crtcs; i++)
> >  		komeda_crtc_handle_event(&kms->crtcs[i], &evts);
> > -- 
> > 1.9.1
> > 
> 
> -- 
> ====================
> | I would like to |
> | fix the world,  |
> | but they're not |
> | giving me the   |
>  \ source code!  /
>   ---------------
>     ¯\_(ツ)_/¯

-- 
Sean Paul, Software Engineer, Google / Chromium OS

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [PATCH] drm/komeda: Adds error event print functionality
@ 2019-07-18 15:23     ` Sean Paul
  0 siblings, 0 replies; 37+ messages in thread
From: Sean Paul @ 2019-07-18 15:23 UTC (permalink / raw)
  To: Liviu Dudau
  Cc: Lowry Li (Arm Technology China),
	james qian wang (Arm Technology China),
	maarten.lankhorst, seanpaul, airlied, Brian Starkey,
	Julien Yin (Arm Technology China),
	Jonathan Chai (Arm Technology China),
	Ayan Halder, dri-devel, linux-kernel, nd

On Thu, Jul 18, 2019 at 02:17:37PM +0100, Liviu Dudau wrote:
> On Thu, Jun 27, 2019 at 04:10:36AM +0100, Lowry Li (Arm Technology China) wrote:

/snip

> > diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_kms.c b/drivers/gpu/drm/arm/display/komeda/komeda_kms.c
> > index 647bce5..1462bac 100644
> > --- a/drivers/gpu/drm/arm/display/komeda/komeda_kms.c
> > +++ b/drivers/gpu/drm/arm/display/komeda/komeda_kms.c
> > @@ -47,6 +47,8 @@ static irqreturn_t komeda_kms_irq_handler(int irq, void *data)
> >  	memset(&evts, 0, sizeof(evts));
> >  	status = mdev->funcs->irq_handler(mdev, &evts);
> >  
> > +	komeda_print_events(&evts);
> 
> Calling this function from the IRQ handler is a bad idea. We should use debugfs
> if you really want to have a trace of the events, but I personally don't see
> value in having this functionality in the kernel at all. You can expose the
> value of the evts->global and evts->pipes[] as integers and decode that in
> userspace or as a debugfs entry.

Alternatively, consider using kernel trace events. They allow you to selectively
turn on/off certain events and also allow you to customize which data is
recorded and how it's formatted. Seems like a good fit from the quick scan I've
done.

Sean

> 
> Best regards,
> Liviu
> 
> > +
> >  	/* Notify the crtc to handle the events */
> >  	for (i = 0; i < kms->n_crtcs; i++)
> >  		komeda_crtc_handle_event(&kms->crtcs[i], &evts);
> > -- 
> > 1.9.1
> > 
> 
> -- 
> ====================
> | I would like to |
> | fix the world,  |
> | but they're not |
> | giving me the   |
>  \ source code!  /
>   ---------------
>     ¯\_(ツ)_/¯

-- 
Sean Paul, Software Engineer, Google / Chromium OS

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [PATCH] drm/komeda: Adds error event print functionality
  2019-07-18 13:17   ` Liviu Dudau
  (?)
  (?)
@ 2019-07-19  9:09   ` Lowry Li (Arm Technology China)
  -1 siblings, 0 replies; 37+ messages in thread
From: Lowry Li (Arm Technology China) @ 2019-07-19  9:09 UTC (permalink / raw)
  To: Liviu Dudau
  Cc: nd, airlied, Jonathan Chai (Arm Technology China),
	linux-kernel, dri-devel, Julien Yin (Arm Technology China),
	seanpaul, james qian wang (Arm Technology China),
	Ayan Halder

Hi Liviu,

On Thu, Jul 18, 2019 at 01:17:37PM +0000, Liviu Dudau wrote:
> On Thu, Jun 27, 2019 at 04:10:36AM +0100, Lowry Li (Arm Technology China) wrote:
> > Adds to print the event message when error happens and the same event
> > will not be printed until next vsync.
> > 
> > Signed-off-by: Lowry Li (Arm Technology China) <lowry.li@arm.com>
> > ---
> >  drivers/gpu/drm/arm/display/komeda/Makefile       |   1 +
> >  drivers/gpu/drm/arm/display/komeda/komeda_dev.h   |  13 ++
> >  drivers/gpu/drm/arm/display/komeda/komeda_event.c | 144 ++++++++++++++++++++++
> >  drivers/gpu/drm/arm/display/komeda/komeda_kms.c   |   2 +
> >  4 files changed, 160 insertions(+)
> >  create mode 100644 drivers/gpu/drm/arm/display/komeda/komeda_event.c
> > 
> > diff --git a/drivers/gpu/drm/arm/display/komeda/Makefile b/drivers/gpu/drm/arm/display/komeda/Makefile
> > index 38aa584..3f53d2d 100644
> > --- a/drivers/gpu/drm/arm/display/komeda/Makefile
> > +++ b/drivers/gpu/drm/arm/display/komeda/Makefile
> > @@ -7,6 +7,7 @@ ccflags-y := \
> >  komeda-y := \
> >  	komeda_drv.o \
> >  	komeda_dev.o \
> > +	komeda_event.o \
> >  	komeda_format_caps.o \
> >  	komeda_coeffs.o \
> >  	komeda_color_mgmt.o \
> > diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_dev.h b/drivers/gpu/drm/arm/display/komeda/komeda_dev.h
> > index 096f9f7..e863ec3 100644
> > --- a/drivers/gpu/drm/arm/display/komeda/komeda_dev.h
> > +++ b/drivers/gpu/drm/arm/display/komeda/komeda_dev.h
> > @@ -40,6 +40,17 @@
> >  #define KOMEDA_ERR_TTNG			BIT_ULL(30)
> >  #define KOMEDA_ERR_TTF			BIT_ULL(31)
> >  
> > +#define KOMEDA_ERR_EVENTS	\
> > +	(KOMEDA_EVENT_URUN	| KOMEDA_EVENT_IBSY	| KOMEDA_EVENT_OVR |\
> > +	KOMEDA_ERR_TETO		| KOMEDA_ERR_TEMR	| KOMEDA_ERR_TITR |\
> > +	KOMEDA_ERR_CPE		| KOMEDA_ERR_CFGE	| KOMEDA_ERR_AXIE |\
> > +	KOMEDA_ERR_ACE0		| KOMEDA_ERR_ACE1	| KOMEDA_ERR_ACE2 |\
> > +	KOMEDA_ERR_ACE3		| KOMEDA_ERR_DRIFTTO	| KOMEDA_ERR_FRAMETO |\
> > +	KOMEDA_ERR_ZME		| KOMEDA_ERR_MERR	| KOMEDA_ERR_TCF |\
> > +	KOMEDA_ERR_TTNG		| KOMEDA_ERR_TTF)
> > +
> > +#define KOMEDA_WARN_EVENTS	KOMEDA_ERR_CSCE
> > +
> >  /* malidp device id */
> >  enum {
> >  	MALI_D71 = 0,
> > @@ -207,6 +218,8 @@ struct komeda_dev {
> >  
> >  struct komeda_dev *dev_to_mdev(struct device *dev);
> >  
> > +void komeda_print_events(struct komeda_events *evts);
> > +
> >  int komeda_dev_resume(struct komeda_dev *mdev);
> >  int komeda_dev_suspend(struct komeda_dev *mdev);
> >  #endif /*_KOMEDA_DEV_H_*/
> > diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_event.c b/drivers/gpu/drm/arm/display/komeda/komeda_event.c
> > new file mode 100644
> > index 0000000..309dbe2
> > --- /dev/null
> > +++ b/drivers/gpu/drm/arm/display/komeda/komeda_event.c
> > @@ -0,0 +1,144 @@
> > +// SPDX-License-Identifier: GPL-2.0
> > +/*
> > + * (C) COPYRIGHT 2019 ARM Limited. All rights reserved.
> > + * Author: James.Qian.Wang <james.qian.wang@arm.com>
> > + *
> > + */
> > +#include <drm/drm_print.h>
> > +
> > +#include "komeda_dev.h"
> > +
> > +struct komeda_str {
> > +	char *str;
> > +	u32 sz;
> > +	u32 len;
> > +};
> > +
> > +/* return 0 on success,  < 0 on no space.
> > + */
> > +static int komeda_sprintf(struct komeda_str *str, const char *fmt, ...)
> > +{
> > +	va_list args;
> > +	int num, free_sz;
> > +	int err;
> > +
> > +	free_sz = str->sz - str->len;
> > +	if (free_sz <= 0)
> > +		return -ENOSPC;
> > +
> > +	va_start(args, fmt);
> > +
> > +	num = vsnprintf(str->str + str->len, free_sz, fmt, args);
> > +
> > +	va_end(args);
> > +
> > +	if (num <= free_sz) {
> > +		str->len += num;
> > +		err = 0;
> > +	} else {
> > +		str->len = str->sz;
> > +		err = -ENOSPC;
> > +	}
> > +
> > +	return err;
> > +}
> > +
> > +static void evt_sprintf(struct komeda_str *str, u64 evt, const char *msg)
> > +{
> > +	if (evt)
> > +		komeda_sprintf(str, msg);
> > +}
> 
> Why do we need this wrapper?
The komeda_sprintf is a generic function and will be used by other
places, while evt_sprintf is working for the detail event msg.

> > +
> > +static void evt_str(struct komeda_str *str, u64 events)
> > +{
> > +	if (events == 0ULL) {
> > +		evt_sprintf(str, 1, "None");
> > +		return;
> > +	}
> > +
> > +	evt_sprintf(str, events & KOMEDA_EVENT_VSYNC, "VSYNC|");
> > +	evt_sprintf(str, events & KOMEDA_EVENT_FLIP, "FLIP|");
> > +	evt_sprintf(str, events & KOMEDA_EVENT_EOW, "EOW|");
> > +	evt_sprintf(str, events & KOMEDA_EVENT_MODE, "OP-MODE|");
> > +
> > +	evt_sprintf(str, events & KOMEDA_EVENT_URUN, "UNDERRUN|");
> > +	evt_sprintf(str, events & KOMEDA_EVENT_OVR, "OVERRUN|");
> > +
> > +	/* GLB error */
> > +	evt_sprintf(str, events & KOMEDA_ERR_MERR, "MERR|");
> > +	evt_sprintf(str, events & KOMEDA_ERR_FRAMETO, "FRAMETO|");
> > +
> > +	/* DOU error */
> > +	evt_sprintf(str, events & KOMEDA_ERR_DRIFTTO, "DRIFTTO|");
> > +	evt_sprintf(str, events & KOMEDA_ERR_FRAMETO, "FRAMETO|");
> > +	evt_sprintf(str, events & KOMEDA_ERR_TETO, "TETO|");
> > +	evt_sprintf(str, events & KOMEDA_ERR_CSCE, "CSCE|");
> > +
> > +	/* LPU errors or events */
> > +	evt_sprintf(str, events & KOMEDA_EVENT_IBSY, "IBSY|");
> > +	evt_sprintf(str, events & KOMEDA_ERR_AXIE, "AXIE|");
> > +	evt_sprintf(str, events & KOMEDA_ERR_ACE0, "ACE0|");
> > +	evt_sprintf(str, events & KOMEDA_ERR_ACE1, "ACE1|");
> > +	evt_sprintf(str, events & KOMEDA_ERR_ACE2, "ACE2|");
> > +	evt_sprintf(str, events & KOMEDA_ERR_ACE3, "ACE3|");
> > +
> > +	/* LPU TBU errors*/
> > +	evt_sprintf(str, events & KOMEDA_ERR_TCF, "TCF|");
> > +	evt_sprintf(str, events & KOMEDA_ERR_TTNG, "TTNG|");
> > +	evt_sprintf(str, events & KOMEDA_ERR_TITR, "TITR|");
> > +	evt_sprintf(str, events & KOMEDA_ERR_TEMR, "TEMR|");
> > +	evt_sprintf(str, events & KOMEDA_ERR_TTF, "TTF|");
> > +
> > +	/* CU errors*/
> > +	evt_sprintf(str, events & KOMEDA_ERR_CPE, "COPROC|");
> > +	evt_sprintf(str, events & KOMEDA_ERR_ZME, "ZME|");
> > +	evt_sprintf(str, events & KOMEDA_ERR_CFGE, "CFGE|");
> > +	evt_sprintf(str, events & KOMEDA_ERR_TEMR, "TEMR|");
> > +
> > +	if (str->len > 0 && (str->str[str->len - 1] == '|')) {
> > +		str->str[str->len - 1] = 0;
> > +		str->len--;
> > +	}
> > +}
> > +
> > +static bool is_new_frame(struct komeda_events *a)
> > +{
> > +	return (a->pipes[0] | a->pipes[1]) & KOMEDA_EVENT_FLIP;
> > +}
> > +
> > +void komeda_print_events(struct komeda_events *evts)
> > +{
> > +	u64 print_evts = KOMEDA_ERR_EVENTS;
> > +	static bool en_print = true;
> > +
> > +	/* reduce the same msg print, only print the first evt for one frame */
> > +	if (evts->global || is_new_frame(evts))
> > +		en_print = true;
> > +	if (!en_print)
> > +		return;
> 
> When does en_print ever get false?
Once the events printed, it will be set false (pls find at the last
line of this function).
> > +
> > +#ifdef DEBUG
> > +	print_evts |= KOMEDA_WARN_EVENTS;
> > +#endif
> > +
> > +	if ((evts->global | evts->pipes[0] | evts->pipes[1]) & print_evts) {
> > +		#define STR_SZ		128
> > +		char msg[STR_SZ];
> 
> I've counted about 27 evt_sprintf() calls in evt_str() function, with an
> average of 5 characters each, so thats 135 characters printed into a buffer
> that is only 128 bytes. Please don't do this!
komeda_sprintf() will check the size and also I thought those evt
will not populat together. But yes, I'd better change this to 256.
Will change this.

> > +		struct komeda_str str;
> > +
> > +		str.str = msg;
> > +		str.sz  = STR_SZ;
> > +		str.len = 0;
> > +
> > +		komeda_sprintf(&str, "gcu: ");
> > +		evt_str(&str, evts->global);
> > +		komeda_sprintf(&str, ", pipes[0]: ");
> > +		evt_str(&str, evts->pipes[0]);
> > +		komeda_sprintf(&str, ", pipes[1]: ");
> > +		evt_str(&str, evts->pipes[1]);
> > +
> > +		DRM_ERROR("err detect: %s\n", msg);
> > +
> > +		en_print = false;
> > +	}
> > +}
> > diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_kms.c b/drivers/gpu/drm/arm/display/komeda/komeda_kms.c
> > index 647bce5..1462bac 100644
> > --- a/drivers/gpu/drm/arm/display/komeda/komeda_kms.c
> > +++ b/drivers/gpu/drm/arm/display/komeda/komeda_kms.c
> > @@ -47,6 +47,8 @@ static irqreturn_t komeda_kms_irq_handler(int irq, void *data)
> >  	memset(&evts, 0, sizeof(evts));
> >  	status = mdev->funcs->irq_handler(mdev, &evts);
> >  
> > +	komeda_print_events(&evts);
> 
> Calling this function from the IRQ handler is a bad idea. We should use debugfs
> if you really want to have a trace of the events, but I personally don't see
> value in having this functionality in the kernel at all. You can expose the
> value of the evts->global and evts->pipes[] as integers and decode that in
> userspace or as a debugfs entry.
> 
> Best regards,
> Liviu

The name of this function is misleading, but this is printing out the
hardware detected errors, from which we can know directly once the
errors happened on the hardware. Like if the driver code was at
bring-up stage, the logs from this layer is helpful. So can we keep
this?

Best regards,
Lowry

> > +
> >  	/* Notify the crtc to handle the events */
> >  	for (i = 0; i < kms->n_crtcs; i++)
> >  		komeda_crtc_handle_event(&kms->crtcs[i], &evts);
> > -- 
> > 1.9.1
> > 
> 
> -- 
> ====================
> | I would like to |
> | fix the world,  |
> | but they're not |
> | giving me the   |
>  \ source code!  /
>   ---------------
>     ¯\_(ツ)_/¯

-- 
Regards,
Lowry
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [PATCH] drm/komeda: Adds error event print functionality
  2019-07-18 15:23     ` Sean Paul
  (?)
@ 2019-07-19  9:31     ` Lowry Li (Arm Technology China)
  -1 siblings, 0 replies; 37+ messages in thread
From: Lowry Li (Arm Technology China) @ 2019-07-19  9:31 UTC (permalink / raw)
  To: Sean Paul
  Cc: nd, airlied, Liviu Dudau, Jonathan Chai (Arm Technology China),
	linux-kernel, dri-devel, Julien Yin (Arm Technology China),
	james qian wang (Arm Technology China),
	seanpaul, Ayan Halder

Hi Sean,

On Thu, Jul 18, 2019 at 11:23:50AM -0400, Sean Paul wrote:
> On Thu, Jul 18, 2019 at 02:17:37PM +0100, Liviu Dudau wrote:
> > On Thu, Jun 27, 2019 at 04:10:36AM +0100, Lowry Li (Arm Technology China) wrote:
> 
> /snip
> 
> > > diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_kms.c b/drivers/gpu/drm/arm/display/komeda/komeda_kms.c
> > > index 647bce5..1462bac 100644
> > > --- a/drivers/gpu/drm/arm/display/komeda/komeda_kms.c
> > > +++ b/drivers/gpu/drm/arm/display/komeda/komeda_kms.c
> > > @@ -47,6 +47,8 @@ static irqreturn_t komeda_kms_irq_handler(int irq, void *data)
> > >  	memset(&evts, 0, sizeof(evts));
> > >  	status = mdev->funcs->irq_handler(mdev, &evts);
> > >  
> > > +	komeda_print_events(&evts);
> > 
> > Calling this function from the IRQ handler is a bad idea. We should use debugfs
> > if you really want to have a trace of the events, but I personally don't see
> > value in having this functionality in the kernel at all. You can expose the
> > value of the evts->global and evts->pipes[] as integers and decode that in
> > userspace or as a debugfs entry.
> 
> Alternatively, consider using kernel trace events. They allow you to selectively
> turn on/off certain events and also allow you to customize which data is
> recorded and how it's formatted. Seems like a good fit from the quick scan I've
> done.
> 
> Sean
>
Yes, finially we want to get both way, using kernel trace events and
meanwhile printing out the hardware detected errors, from which we can
know directly once the errors happened on the hardware.Like intel did,
in intel_cpu_fifo_underrun_irq_handler().
Thanks a lot.

Best Regards,
Lowry
> > 
> > Best regards,
> > Liviu
> > 
> > > +
> > >  	/* Notify the crtc to handle the events */
> > >  	for (i = 0; i < kms->n_crtcs; i++)
> > >  		komeda_crtc_handle_event(&kms->crtcs[i], &evts);
> > > -- 
> > > 1.9.1
> > > 
> > 
> > -- 
> > ====================
> > | I would like to |
> > | fix the world,  |
> > | but they're not |
> > | giving me the   |
> >  \ source code!  /
> >   ---------------
> >     ¯\_(ツ)_/¯
> 
> -- 
> Sean Paul, Software Engineer, Google / Chromium OS

-- 
Regards,
Lowry
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [PATCH] drm/komeda: Adds error event print functionality
       [not found]   ` <20190719090816.GA4133@lowry.li@arm.com>
@ 2019-07-19 11:40       ` Liviu Dudau
  0 siblings, 0 replies; 37+ messages in thread
From: Liviu Dudau @ 2019-07-19 11:40 UTC (permalink / raw)
  To: Lowry Li (Arm Technology China)
  Cc: james qian wang (Arm Technology China),
	maarten.lankhorst, seanpaul, airlied, Brian Starkey,
	Julien Yin (Arm Technology China),
	Jonathan Chai (Arm Technology China),
	Ayan Halder, dri-devel, linux-kernel, nd

On Fri, Jul 19, 2019 at 09:09:30AM +0000, Lowry Li (Arm Technology China) wrote:
> Hi Liviu,
> 
> On Thu, Jul 18, 2019 at 01:17:37PM +0000, Liviu Dudau wrote:
> > On Thu, Jun 27, 2019 at 04:10:36AM +0100, Lowry Li (Arm Technology China) wrote:
> > > Adds to print the event message when error happens and the same event
> > > will not be printed until next vsync.
> > > 
> > > Signed-off-by: Lowry Li (Arm Technology China) <lowry.li@arm.com>
> > > ---
> > >  drivers/gpu/drm/arm/display/komeda/Makefile       |   1 +
> > >  drivers/gpu/drm/arm/display/komeda/komeda_dev.h   |  13 ++
> > >  drivers/gpu/drm/arm/display/komeda/komeda_event.c | 144 ++++++++++++++++++++++
> > >  drivers/gpu/drm/arm/display/komeda/komeda_kms.c   |   2 +
> > >  4 files changed, 160 insertions(+)
> > >  create mode 100644 drivers/gpu/drm/arm/display/komeda/komeda_event.c
> > > 
> > > diff --git a/drivers/gpu/drm/arm/display/komeda/Makefile b/drivers/gpu/drm/arm/display/komeda/Makefile
> > > index 38aa584..3f53d2d 100644
> > > --- a/drivers/gpu/drm/arm/display/komeda/Makefile
> > > +++ b/drivers/gpu/drm/arm/display/komeda/Makefile
> > > @@ -7,6 +7,7 @@ ccflags-y := \
> > >  komeda-y := \
> > >  	komeda_drv.o \
> > >  	komeda_dev.o \
> > > +	komeda_event.o \
> > >  	komeda_format_caps.o \
> > >  	komeda_coeffs.o \
> > >  	komeda_color_mgmt.o \
> > > diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_dev.h b/drivers/gpu/drm/arm/display/komeda/komeda_dev.h
> > > index 096f9f7..e863ec3 100644
> > > --- a/drivers/gpu/drm/arm/display/komeda/komeda_dev.h
> > > +++ b/drivers/gpu/drm/arm/display/komeda/komeda_dev.h
> > > @@ -40,6 +40,17 @@
> > >  #define KOMEDA_ERR_TTNG			BIT_ULL(30)
> > >  #define KOMEDA_ERR_TTF			BIT_ULL(31)
> > >  
> > > +#define KOMEDA_ERR_EVENTS	\
> > > +	(KOMEDA_EVENT_URUN	| KOMEDA_EVENT_IBSY	| KOMEDA_EVENT_OVR |\
> > > +	KOMEDA_ERR_TETO		| KOMEDA_ERR_TEMR	| KOMEDA_ERR_TITR |\
> > > +	KOMEDA_ERR_CPE		| KOMEDA_ERR_CFGE	| KOMEDA_ERR_AXIE |\
> > > +	KOMEDA_ERR_ACE0		| KOMEDA_ERR_ACE1	| KOMEDA_ERR_ACE2 |\
> > > +	KOMEDA_ERR_ACE3		| KOMEDA_ERR_DRIFTTO	| KOMEDA_ERR_FRAMETO |\
> > > +	KOMEDA_ERR_ZME		| KOMEDA_ERR_MERR	| KOMEDA_ERR_TCF |\
> > > +	KOMEDA_ERR_TTNG		| KOMEDA_ERR_TTF)
> > > +
> > > +#define KOMEDA_WARN_EVENTS	KOMEDA_ERR_CSCE
> > > +
> > >  /* malidp device id */
> > >  enum {
> > >  	MALI_D71 = 0,
> > > @@ -207,6 +218,8 @@ struct komeda_dev {
> > >  
> > >  struct komeda_dev *dev_to_mdev(struct device *dev);
> > >  
> > > +void komeda_print_events(struct komeda_events *evts);
> > > +
> > >  int komeda_dev_resume(struct komeda_dev *mdev);
> > >  int komeda_dev_suspend(struct komeda_dev *mdev);
> > >  #endif /*_KOMEDA_DEV_H_*/
> > > diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_event.c b/drivers/gpu/drm/arm/display/komeda/komeda_event.c
> > > new file mode 100644
> > > index 0000000..309dbe2
> > > --- /dev/null
> > > +++ b/drivers/gpu/drm/arm/display/komeda/komeda_event.c
> > > @@ -0,0 +1,144 @@
> > > +// SPDX-License-Identifier: GPL-2.0
> > > +/*
> > > + * (C) COPYRIGHT 2019 ARM Limited. All rights reserved.
> > > + * Author: James.Qian.Wang <james.qian.wang@arm.com>
> > > + *
> > > + */
> > > +#include <drm/drm_print.h>
> > > +
> > > +#include "komeda_dev.h"
> > > +
> > > +struct komeda_str {
> > > +	char *str;
> > > +	u32 sz;
> > > +	u32 len;
> > > +};
> > > +
> > > +/* return 0 on success,  < 0 on no space.
> > > + */
> > > +static int komeda_sprintf(struct komeda_str *str, const char *fmt, ...)
> > > +{
> > > +	va_list args;
> > > +	int num, free_sz;
> > > +	int err;
> > > +
> > > +	free_sz = str->sz - str->len;
> > > +	if (free_sz <= 0)
> > > +		return -ENOSPC;
> > > +
> > > +	va_start(args, fmt);
> > > +
> > > +	num = vsnprintf(str->str + str->len, free_sz, fmt, args);
> > > +
> > > +	va_end(args);
> > > +
> > > +	if (num <= free_sz) {
> > > +		str->len += num;
> > > +		err = 0;
> > > +	} else {
> > > +		str->len = str->sz;
> > > +		err = -ENOSPC;
> > > +	}
> > > +
> > > +	return err;
> > > +}
> > > +
> > > +static void evt_sprintf(struct komeda_str *str, u64 evt, const char *msg)
> > > +{
> > > +	if (evt)
> > > +		komeda_sprintf(str, msg);
> > > +}
> > 
> > Why do we need this wrapper?
> The komeda_sprintf is a generic function and will be used by other
> places, while evt_sprintf is working for the detail event msg.

Yeah, I'm not buying this argument any more. We should not create new functions
just because we want to save typing one if () condition. evt_sprintf does
nothing with the extra evt argument other than checking that it is not zero.

> 
> > > +
> > > +static void evt_str(struct komeda_str *str, u64 events)
> > > +{
> > > +	if (events == 0ULL) {
> > > +		evt_sprintf(str, 1, "None");
> > > +		return;
> > > +	}
> > > +
> > > +	evt_sprintf(str, events & KOMEDA_EVENT_VSYNC, "VSYNC|");
> > > +	evt_sprintf(str, events & KOMEDA_EVENT_FLIP, "FLIP|");
> > > +	evt_sprintf(str, events & KOMEDA_EVENT_EOW, "EOW|");
> > > +	evt_sprintf(str, events & KOMEDA_EVENT_MODE, "OP-MODE|");
> > > +
> > > +	evt_sprintf(str, events & KOMEDA_EVENT_URUN, "UNDERRUN|");
> > > +	evt_sprintf(str, events & KOMEDA_EVENT_OVR, "OVERRUN|");
> > > +
> > > +	/* GLB error */
> > > +	evt_sprintf(str, events & KOMEDA_ERR_MERR, "MERR|");
> > > +	evt_sprintf(str, events & KOMEDA_ERR_FRAMETO, "FRAMETO|");
> > > +
> > > +	/* DOU error */
> > > +	evt_sprintf(str, events & KOMEDA_ERR_DRIFTTO, "DRIFTTO|");
> > > +	evt_sprintf(str, events & KOMEDA_ERR_FRAMETO, "FRAMETO|");
> > > +	evt_sprintf(str, events & KOMEDA_ERR_TETO, "TETO|");
> > > +	evt_sprintf(str, events & KOMEDA_ERR_CSCE, "CSCE|");
> > > +
> > > +	/* LPU errors or events */
> > > +	evt_sprintf(str, events & KOMEDA_EVENT_IBSY, "IBSY|");
> > > +	evt_sprintf(str, events & KOMEDA_ERR_AXIE, "AXIE|");
> > > +	evt_sprintf(str, events & KOMEDA_ERR_ACE0, "ACE0|");
> > > +	evt_sprintf(str, events & KOMEDA_ERR_ACE1, "ACE1|");
> > > +	evt_sprintf(str, events & KOMEDA_ERR_ACE2, "ACE2|");
> > > +	evt_sprintf(str, events & KOMEDA_ERR_ACE3, "ACE3|");
> > > +
> > > +	/* LPU TBU errors*/
> > > +	evt_sprintf(str, events & KOMEDA_ERR_TCF, "TCF|");
> > > +	evt_sprintf(str, events & KOMEDA_ERR_TTNG, "TTNG|");
> > > +	evt_sprintf(str, events & KOMEDA_ERR_TITR, "TITR|");
> > > +	evt_sprintf(str, events & KOMEDA_ERR_TEMR, "TEMR|");
> > > +	evt_sprintf(str, events & KOMEDA_ERR_TTF, "TTF|");
> > > +
> > > +	/* CU errors*/
> > > +	evt_sprintf(str, events & KOMEDA_ERR_CPE, "COPROC|");
> > > +	evt_sprintf(str, events & KOMEDA_ERR_ZME, "ZME|");
> > > +	evt_sprintf(str, events & KOMEDA_ERR_CFGE, "CFGE|");
> > > +	evt_sprintf(str, events & KOMEDA_ERR_TEMR, "TEMR|");
> > > +
> > > +	if (str->len > 0 && (str->str[str->len - 1] == '|')) {
> > > +		str->str[str->len - 1] = 0;
> > > +		str->len--;
> > > +	}
> > > +}
> > > +
> > > +static bool is_new_frame(struct komeda_events *a)
> > > +{
> > > +	return (a->pipes[0] | a->pipes[1]) & KOMEDA_EVENT_FLIP;
> > > +}
> > > +
> > > +void komeda_print_events(struct komeda_events *evts)
> > > +{
> > > +	u64 print_evts = KOMEDA_ERR_EVENTS;
> > > +	static bool en_print = true;
> > > +
> > > +	/* reduce the same msg print, only print the first evt for one frame */
> > > +	if (evts->global || is_new_frame(evts))
> > > +		en_print = true;
> > > +	if (!en_print)
> > > +		return;
> > 
> > When does en_print ever get false?
> Once the events printed, it will be set false (pls find at the last
> line of this function).

What is the point of making en_print a static variable? We print all the time
when we have a global event anyway.


> > > +
> > > +#ifdef DEBUG
> > > +	print_evts |= KOMEDA_WARN_EVENTS;
> > > +#endif
> > > +
> > > +	if ((evts->global | evts->pipes[0] | evts->pipes[1]) & print_evts) {
> > > +		#define STR_SZ		128
> > > +		char msg[STR_SZ];
> > 
> > I've counted about 27 evt_sprintf() calls in evt_str() function, with an
> > average of 5 characters each, so thats 135 characters printed into a buffer
> > that is only 128 bytes. Please don't do this!
> komeda_sprintf() will check the size and also I thought those evt
> will not populat together. But yes, I'd better change this to 256.
> Will change this.
> 
> > > +		struct komeda_str str;
> > > +
> > > +		str.str = msg;
> > > +		str.sz  = STR_SZ;
> > > +		str.len = 0;
> > > +
> > > +		komeda_sprintf(&str, "gcu: ");
> > > +		evt_str(&str, evts->global);
> > > +		komeda_sprintf(&str, ", pipes[0]: ");
> > > +		evt_str(&str, evts->pipes[0]);
> > > +		komeda_sprintf(&str, ", pipes[1]: ");
> > > +		evt_str(&str, evts->pipes[1]);
> > > +
> > > +		DRM_ERROR("err detect: %s\n", msg);
> > > +
> > > +		en_print = false;
> > > +	}
> > > +}
> > > diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_kms.c b/drivers/gpu/drm/arm/display/komeda/komeda_kms.c
> > > index 647bce5..1462bac 100644
> > > --- a/drivers/gpu/drm/arm/display/komeda/komeda_kms.c
> > > +++ b/drivers/gpu/drm/arm/display/komeda/komeda_kms.c
> > > @@ -47,6 +47,8 @@ static irqreturn_t komeda_kms_irq_handler(int irq, void *data)
> > >  	memset(&evts, 0, sizeof(evts));
> > >  	status = mdev->funcs->irq_handler(mdev, &evts);
> > >  
> > > +	komeda_print_events(&evts);
> > 
> > Calling this function from the IRQ handler is a bad idea. We should use debugfs
> > if you really want to have a trace of the events, but I personally don't see
> > value in having this functionality in the kernel at all. You can expose the
> > value of the evts->global and evts->pipes[] as integers and decode that in
> > userspace or as a debugfs entry.
> > 
> > Best regards,
> > Liviu
> 
> The name of this function is misleading, but this is printing out the
> hardware detected errors, from which we can know directly once the
> errors happened on the hardware. Like if the driver code was at
> bring-up stage, the logs from this layer is helpful. So can we keep
> this?

We should probably just collect the global and pipes values and expose
them to userspace so that the printing and decoding of the messages happens
there.

Best regards,
Liviu


> 
> Best regards,
> Lowry
> 
> > > +
> > >  	/* Notify the crtc to handle the events */
> > >  	for (i = 0; i < kms->n_crtcs; i++)
> > >  		komeda_crtc_handle_event(&kms->crtcs[i], &evts);
> > > -- 
> > > 1.9.1
> > > 
> > 
> > -- 
> > ====================
> > | I would like to |
> > | fix the world,  |
> > | but they're not |
> > | giving me the   |
> >  \ source code!  /
> >   ---------------
> >     ¯\_(ツ)_/¯
> 
> -- 
> Regards,
> Lowry

-- 
====================
| I would like to |
| fix the world,  |
| but they're not |
| giving me the   |
 \ source code!  /
  ---------------
    ¯\_(ツ)_/¯

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [PATCH] drm/komeda: Adds error event print functionality
@ 2019-07-19 11:40       ` Liviu Dudau
  0 siblings, 0 replies; 37+ messages in thread
From: Liviu Dudau @ 2019-07-19 11:40 UTC (permalink / raw)
  To: Lowry Li (Arm Technology China)
  Cc: james qian wang (Arm Technology China),
	maarten.lankhorst, seanpaul, airlied, Brian Starkey,
	Julien Yin (Arm Technology China),
	Jonathan Chai (Arm Technology China),
	Ayan Halder, dri-devel, linux-kernel, nd

On Fri, Jul 19, 2019 at 09:09:30AM +0000, Lowry Li (Arm Technology China) wrote:
> Hi Liviu,
> 
> On Thu, Jul 18, 2019 at 01:17:37PM +0000, Liviu Dudau wrote:
> > On Thu, Jun 27, 2019 at 04:10:36AM +0100, Lowry Li (Arm Technology China) wrote:
> > > Adds to print the event message when error happens and the same event
> > > will not be printed until next vsync.
> > > 
> > > Signed-off-by: Lowry Li (Arm Technology China) <lowry.li@arm.com>
> > > ---
> > >  drivers/gpu/drm/arm/display/komeda/Makefile       |   1 +
> > >  drivers/gpu/drm/arm/display/komeda/komeda_dev.h   |  13 ++
> > >  drivers/gpu/drm/arm/display/komeda/komeda_event.c | 144 ++++++++++++++++++++++
> > >  drivers/gpu/drm/arm/display/komeda/komeda_kms.c   |   2 +
> > >  4 files changed, 160 insertions(+)
> > >  create mode 100644 drivers/gpu/drm/arm/display/komeda/komeda_event.c
> > > 
> > > diff --git a/drivers/gpu/drm/arm/display/komeda/Makefile b/drivers/gpu/drm/arm/display/komeda/Makefile
> > > index 38aa584..3f53d2d 100644
> > > --- a/drivers/gpu/drm/arm/display/komeda/Makefile
> > > +++ b/drivers/gpu/drm/arm/display/komeda/Makefile
> > > @@ -7,6 +7,7 @@ ccflags-y := \
> > >  komeda-y := \
> > >  	komeda_drv.o \
> > >  	komeda_dev.o \
> > > +	komeda_event.o \
> > >  	komeda_format_caps.o \
> > >  	komeda_coeffs.o \
> > >  	komeda_color_mgmt.o \
> > > diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_dev.h b/drivers/gpu/drm/arm/display/komeda/komeda_dev.h
> > > index 096f9f7..e863ec3 100644
> > > --- a/drivers/gpu/drm/arm/display/komeda/komeda_dev.h
> > > +++ b/drivers/gpu/drm/arm/display/komeda/komeda_dev.h
> > > @@ -40,6 +40,17 @@
> > >  #define KOMEDA_ERR_TTNG			BIT_ULL(30)
> > >  #define KOMEDA_ERR_TTF			BIT_ULL(31)
> > >  
> > > +#define KOMEDA_ERR_EVENTS	\
> > > +	(KOMEDA_EVENT_URUN	| KOMEDA_EVENT_IBSY	| KOMEDA_EVENT_OVR |\
> > > +	KOMEDA_ERR_TETO		| KOMEDA_ERR_TEMR	| KOMEDA_ERR_TITR |\
> > > +	KOMEDA_ERR_CPE		| KOMEDA_ERR_CFGE	| KOMEDA_ERR_AXIE |\
> > > +	KOMEDA_ERR_ACE0		| KOMEDA_ERR_ACE1	| KOMEDA_ERR_ACE2 |\
> > > +	KOMEDA_ERR_ACE3		| KOMEDA_ERR_DRIFTTO	| KOMEDA_ERR_FRAMETO |\
> > > +	KOMEDA_ERR_ZME		| KOMEDA_ERR_MERR	| KOMEDA_ERR_TCF |\
> > > +	KOMEDA_ERR_TTNG		| KOMEDA_ERR_TTF)
> > > +
> > > +#define KOMEDA_WARN_EVENTS	KOMEDA_ERR_CSCE
> > > +
> > >  /* malidp device id */
> > >  enum {
> > >  	MALI_D71 = 0,
> > > @@ -207,6 +218,8 @@ struct komeda_dev {
> > >  
> > >  struct komeda_dev *dev_to_mdev(struct device *dev);
> > >  
> > > +void komeda_print_events(struct komeda_events *evts);
> > > +
> > >  int komeda_dev_resume(struct komeda_dev *mdev);
> > >  int komeda_dev_suspend(struct komeda_dev *mdev);
> > >  #endif /*_KOMEDA_DEV_H_*/
> > > diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_event.c b/drivers/gpu/drm/arm/display/komeda/komeda_event.c
> > > new file mode 100644
> > > index 0000000..309dbe2
> > > --- /dev/null
> > > +++ b/drivers/gpu/drm/arm/display/komeda/komeda_event.c
> > > @@ -0,0 +1,144 @@
> > > +// SPDX-License-Identifier: GPL-2.0
> > > +/*
> > > + * (C) COPYRIGHT 2019 ARM Limited. All rights reserved.
> > > + * Author: James.Qian.Wang <james.qian.wang@arm.com>
> > > + *
> > > + */
> > > +#include <drm/drm_print.h>
> > > +
> > > +#include "komeda_dev.h"
> > > +
> > > +struct komeda_str {
> > > +	char *str;
> > > +	u32 sz;
> > > +	u32 len;
> > > +};
> > > +
> > > +/* return 0 on success,  < 0 on no space.
> > > + */
> > > +static int komeda_sprintf(struct komeda_str *str, const char *fmt, ...)
> > > +{
> > > +	va_list args;
> > > +	int num, free_sz;
> > > +	int err;
> > > +
> > > +	free_sz = str->sz - str->len;
> > > +	if (free_sz <= 0)
> > > +		return -ENOSPC;
> > > +
> > > +	va_start(args, fmt);
> > > +
> > > +	num = vsnprintf(str->str + str->len, free_sz, fmt, args);
> > > +
> > > +	va_end(args);
> > > +
> > > +	if (num <= free_sz) {
> > > +		str->len += num;
> > > +		err = 0;
> > > +	} else {
> > > +		str->len = str->sz;
> > > +		err = -ENOSPC;
> > > +	}
> > > +
> > > +	return err;
> > > +}
> > > +
> > > +static void evt_sprintf(struct komeda_str *str, u64 evt, const char *msg)
> > > +{
> > > +	if (evt)
> > > +		komeda_sprintf(str, msg);
> > > +}
> > 
> > Why do we need this wrapper?
> The komeda_sprintf is a generic function and will be used by other
> places, while evt_sprintf is working for the detail event msg.

Yeah, I'm not buying this argument any more. We should not create new functions
just because we want to save typing one if () condition. evt_sprintf does
nothing with the extra evt argument other than checking that it is not zero.

> 
> > > +
> > > +static void evt_str(struct komeda_str *str, u64 events)
> > > +{
> > > +	if (events == 0ULL) {
> > > +		evt_sprintf(str, 1, "None");
> > > +		return;
> > > +	}
> > > +
> > > +	evt_sprintf(str, events & KOMEDA_EVENT_VSYNC, "VSYNC|");
> > > +	evt_sprintf(str, events & KOMEDA_EVENT_FLIP, "FLIP|");
> > > +	evt_sprintf(str, events & KOMEDA_EVENT_EOW, "EOW|");
> > > +	evt_sprintf(str, events & KOMEDA_EVENT_MODE, "OP-MODE|");
> > > +
> > > +	evt_sprintf(str, events & KOMEDA_EVENT_URUN, "UNDERRUN|");
> > > +	evt_sprintf(str, events & KOMEDA_EVENT_OVR, "OVERRUN|");
> > > +
> > > +	/* GLB error */
> > > +	evt_sprintf(str, events & KOMEDA_ERR_MERR, "MERR|");
> > > +	evt_sprintf(str, events & KOMEDA_ERR_FRAMETO, "FRAMETO|");
> > > +
> > > +	/* DOU error */
> > > +	evt_sprintf(str, events & KOMEDA_ERR_DRIFTTO, "DRIFTTO|");
> > > +	evt_sprintf(str, events & KOMEDA_ERR_FRAMETO, "FRAMETO|");
> > > +	evt_sprintf(str, events & KOMEDA_ERR_TETO, "TETO|");
> > > +	evt_sprintf(str, events & KOMEDA_ERR_CSCE, "CSCE|");
> > > +
> > > +	/* LPU errors or events */
> > > +	evt_sprintf(str, events & KOMEDA_EVENT_IBSY, "IBSY|");
> > > +	evt_sprintf(str, events & KOMEDA_ERR_AXIE, "AXIE|");
> > > +	evt_sprintf(str, events & KOMEDA_ERR_ACE0, "ACE0|");
> > > +	evt_sprintf(str, events & KOMEDA_ERR_ACE1, "ACE1|");
> > > +	evt_sprintf(str, events & KOMEDA_ERR_ACE2, "ACE2|");
> > > +	evt_sprintf(str, events & KOMEDA_ERR_ACE3, "ACE3|");
> > > +
> > > +	/* LPU TBU errors*/
> > > +	evt_sprintf(str, events & KOMEDA_ERR_TCF, "TCF|");
> > > +	evt_sprintf(str, events & KOMEDA_ERR_TTNG, "TTNG|");
> > > +	evt_sprintf(str, events & KOMEDA_ERR_TITR, "TITR|");
> > > +	evt_sprintf(str, events & KOMEDA_ERR_TEMR, "TEMR|");
> > > +	evt_sprintf(str, events & KOMEDA_ERR_TTF, "TTF|");
> > > +
> > > +	/* CU errors*/
> > > +	evt_sprintf(str, events & KOMEDA_ERR_CPE, "COPROC|");
> > > +	evt_sprintf(str, events & KOMEDA_ERR_ZME, "ZME|");
> > > +	evt_sprintf(str, events & KOMEDA_ERR_CFGE, "CFGE|");
> > > +	evt_sprintf(str, events & KOMEDA_ERR_TEMR, "TEMR|");
> > > +
> > > +	if (str->len > 0 && (str->str[str->len - 1] == '|')) {
> > > +		str->str[str->len - 1] = 0;
> > > +		str->len--;
> > > +	}
> > > +}
> > > +
> > > +static bool is_new_frame(struct komeda_events *a)
> > > +{
> > > +	return (a->pipes[0] | a->pipes[1]) & KOMEDA_EVENT_FLIP;
> > > +}
> > > +
> > > +void komeda_print_events(struct komeda_events *evts)
> > > +{
> > > +	u64 print_evts = KOMEDA_ERR_EVENTS;
> > > +	static bool en_print = true;
> > > +
> > > +	/* reduce the same msg print, only print the first evt for one frame */
> > > +	if (evts->global || is_new_frame(evts))
> > > +		en_print = true;
> > > +	if (!en_print)
> > > +		return;
> > 
> > When does en_print ever get false?
> Once the events printed, it will be set false (pls find at the last
> line of this function).

What is the point of making en_print a static variable? We print all the time
when we have a global event anyway.


> > > +
> > > +#ifdef DEBUG
> > > +	print_evts |= KOMEDA_WARN_EVENTS;
> > > +#endif
> > > +
> > > +	if ((evts->global | evts->pipes[0] | evts->pipes[1]) & print_evts) {
> > > +		#define STR_SZ		128
> > > +		char msg[STR_SZ];
> > 
> > I've counted about 27 evt_sprintf() calls in evt_str() function, with an
> > average of 5 characters each, so thats 135 characters printed into a buffer
> > that is only 128 bytes. Please don't do this!
> komeda_sprintf() will check the size and also I thought those evt
> will not populat together. But yes, I'd better change this to 256.
> Will change this.
> 
> > > +		struct komeda_str str;
> > > +
> > > +		str.str = msg;
> > > +		str.sz  = STR_SZ;
> > > +		str.len = 0;
> > > +
> > > +		komeda_sprintf(&str, "gcu: ");
> > > +		evt_str(&str, evts->global);
> > > +		komeda_sprintf(&str, ", pipes[0]: ");
> > > +		evt_str(&str, evts->pipes[0]);
> > > +		komeda_sprintf(&str, ", pipes[1]: ");
> > > +		evt_str(&str, evts->pipes[1]);
> > > +
> > > +		DRM_ERROR("err detect: %s\n", msg);
> > > +
> > > +		en_print = false;
> > > +	}
> > > +}
> > > diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_kms.c b/drivers/gpu/drm/arm/display/komeda/komeda_kms.c
> > > index 647bce5..1462bac 100644
> > > --- a/drivers/gpu/drm/arm/display/komeda/komeda_kms.c
> > > +++ b/drivers/gpu/drm/arm/display/komeda/komeda_kms.c
> > > @@ -47,6 +47,8 @@ static irqreturn_t komeda_kms_irq_handler(int irq, void *data)
> > >  	memset(&evts, 0, sizeof(evts));
> > >  	status = mdev->funcs->irq_handler(mdev, &evts);
> > >  
> > > +	komeda_print_events(&evts);
> > 
> > Calling this function from the IRQ handler is a bad idea. We should use debugfs
> > if you really want to have a trace of the events, but I personally don't see
> > value in having this functionality in the kernel at all. You can expose the
> > value of the evts->global and evts->pipes[] as integers and decode that in
> > userspace or as a debugfs entry.
> > 
> > Best regards,
> > Liviu
> 
> The name of this function is misleading, but this is printing out the
> hardware detected errors, from which we can know directly once the
> errors happened on the hardware. Like if the driver code was at
> bring-up stage, the logs from this layer is helpful. So can we keep
> this?

We should probably just collect the global and pipes values and expose
them to userspace so that the printing and decoding of the messages happens
there.

Best regards,
Liviu


> 
> Best regards,
> Lowry
> 
> > > +
> > >  	/* Notify the crtc to handle the events */
> > >  	for (i = 0; i < kms->n_crtcs; i++)
> > >  		komeda_crtc_handle_event(&kms->crtcs[i], &evts);
> > > -- 
> > > 1.9.1
> > > 
> > 
> > -- 
> > ====================
> > | I would like to |
> > | fix the world,  |
> > | but they're not |
> > | giving me the   |
> >  \ source code!  /
> >   ---------------
> >     ¯\_(ツ)_/¯
> 
> -- 
> Regards,
> Lowry

-- 
====================
| I would like to |
| fix the world,  |
| but they're not |
| giving me the   |
 \ source code!  /
  ---------------
    ¯\_(ツ)_/¯

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [PATCH] drm/komeda: Adds error event print functionality
  2019-07-19 11:40       ` Liviu Dudau
@ 2019-07-22 11:15         ` james qian wang (Arm Technology China)
  -1 siblings, 0 replies; 37+ messages in thread
From: james qian wang (Arm Technology China) @ 2019-07-22 11:15 UTC (permalink / raw)
  To: Liviu Dudau
  Cc: Lowry Li (Arm Technology China),
	maarten.lankhorst, seanpaul, airlied, Brian Starkey,
	Julien Yin (Arm Technology China),
	Jonathan Chai (Arm Technology China),
	Ayan Halder, dri-devel, linux-kernel, nd

On Fri, Jul 19, 2019 at 11:40:11AM +0000, Liviu Dudau wrote:
> On Fri, Jul 19, 2019 at 09:09:30AM +0000, Lowry Li (Arm Technology China) wrote:
> > Hi Liviu,
> > 
> > On Thu, Jul 18, 2019 at 01:17:37PM +0000, Liviu Dudau wrote:
> > > On Thu, Jun 27, 2019 at 04:10:36AM +0100, Lowry Li (Arm Technology China) wrote:
> > > > Adds to print the event message when error happens and the same event
> > > > will not be printed until next vsync.
> > > > 
> > > > Signed-off-by: Lowry Li (Arm Technology China) <lowry.li@arm.com>
> > > > ---
> > > >  drivers/gpu/drm/arm/display/komeda/Makefile       |   1 +
> > > >  drivers/gpu/drm/arm/display/komeda/komeda_dev.h   |  13 ++
> > > >  drivers/gpu/drm/arm/display/komeda/komeda_event.c | 144 ++++++++++++++++++++++
> > > >  drivers/gpu/drm/arm/display/komeda/komeda_kms.c   |   2 +
> > > >  4 files changed, 160 insertions(+)
> > > >  create mode 100644 drivers/gpu/drm/arm/display/komeda/komeda_event.c
> > > > 
> > > > diff --git a/drivers/gpu/drm/arm/display/komeda/Makefile b/drivers/gpu/drm/arm/display/komeda/Makefile
> > > > index 38aa584..3f53d2d 100644
> > > > --- a/drivers/gpu/drm/arm/display/komeda/Makefile
> > > > +++ b/drivers/gpu/drm/arm/display/komeda/Makefile
> > > > @@ -7,6 +7,7 @@ ccflags-y := \
> > > >  komeda-y := \
> > > >  	komeda_drv.o \
> > > >  	komeda_dev.o \
> > > > +	komeda_event.o \
> > > >  	komeda_format_caps.o \
> > > >  	komeda_coeffs.o \
> > > >  	komeda_color_mgmt.o \
> > > > diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_dev.h b/drivers/gpu/drm/arm/display/komeda/komeda_dev.h
> > > > index 096f9f7..e863ec3 100644
> > > > --- a/drivers/gpu/drm/arm/display/komeda/komeda_dev.h
> > > > +++ b/drivers/gpu/drm/arm/display/komeda/komeda_dev.h
> > > > @@ -40,6 +40,17 @@
> > > >  #define KOMEDA_ERR_TTNG			BIT_ULL(30)
> > > >  #define KOMEDA_ERR_TTF			BIT_ULL(31)
> > > >  
> > > > +#define KOMEDA_ERR_EVENTS	\
> > > > +	(KOMEDA_EVENT_URUN	| KOMEDA_EVENT_IBSY	| KOMEDA_EVENT_OVR |\
> > > > +	KOMEDA_ERR_TETO		| KOMEDA_ERR_TEMR	| KOMEDA_ERR_TITR |\
> > > > +	KOMEDA_ERR_CPE		| KOMEDA_ERR_CFGE	| KOMEDA_ERR_AXIE |\
> > > > +	KOMEDA_ERR_ACE0		| KOMEDA_ERR_ACE1	| KOMEDA_ERR_ACE2 |\
> > > > +	KOMEDA_ERR_ACE3		| KOMEDA_ERR_DRIFTTO	| KOMEDA_ERR_FRAMETO |\
> > > > +	KOMEDA_ERR_ZME		| KOMEDA_ERR_MERR	| KOMEDA_ERR_TCF |\
> > > > +	KOMEDA_ERR_TTNG		| KOMEDA_ERR_TTF)
> > > > +
> > > > +#define KOMEDA_WARN_EVENTS	KOMEDA_ERR_CSCE
> > > > +
> > > >  /* malidp device id */
> > > >  enum {
> > > >  	MALI_D71 = 0,
> > > > @@ -207,6 +218,8 @@ struct komeda_dev {
> > > >  
> > > >  struct komeda_dev *dev_to_mdev(struct device *dev);
> > > >  
> > > > +void komeda_print_events(struct komeda_events *evts);
> > > > +
> > > >  int komeda_dev_resume(struct komeda_dev *mdev);
> > > >  int komeda_dev_suspend(struct komeda_dev *mdev);
> > > >  #endif /*_KOMEDA_DEV_H_*/
> > > > diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_event.c b/drivers/gpu/drm/arm/display/komeda/komeda_event.c
> > > > new file mode 100644
> > > > index 0000000..309dbe2
> > > > --- /dev/null
> > > > +++ b/drivers/gpu/drm/arm/display/komeda/komeda_event.c
> > > > @@ -0,0 +1,144 @@
> > > > +// SPDX-License-Identifier: GPL-2.0
> > > > +/*
> > > > + * (C) COPYRIGHT 2019 ARM Limited. All rights reserved.
> > > > + * Author: James.Qian.Wang <james.qian.wang@arm.com>
> > > > + *
> > > > + */
> > > > +#include <drm/drm_print.h>
> > > > +
> > > > +#include "komeda_dev.h"
> > > > +
> > > > +struct komeda_str {
> > > > +	char *str;
> > > > +	u32 sz;
> > > > +	u32 len;
> > > > +};
> > > > +
> > > > +/* return 0 on success,  < 0 on no space.
> > > > + */
> > > > +static int komeda_sprintf(struct komeda_str *str, const char *fmt, ...)
> > > > +{
> > > > +	va_list args;
> > > > +	int num, free_sz;
> > > > +	int err;
> > > > +
> > > > +	free_sz = str->sz - str->len;
> > > > +	if (free_sz <= 0)
> > > > +		return -ENOSPC;
> > > > +
> > > > +	va_start(args, fmt);
> > > > +
> > > > +	num = vsnprintf(str->str + str->len, free_sz, fmt, args);
> > > > +
> > > > +	va_end(args);
> > > > +
> > > > +	if (num <= free_sz) {
> > > > +		str->len += num;
> > > > +		err = 0;
> > > > +	} else {
> > > > +		str->len = str->sz;
> > > > +		err = -ENOSPC;
> > > > +	}
> > > > +
> > > > +	return err;
> > > > +}
> > > > +
> > > > +static void evt_sprintf(struct komeda_str *str, u64 evt, const char *msg)
> > > > +{
> > > > +	if (evt)
> > > > +		komeda_sprintf(str, msg);
> > > > +}
> > > 
> > > Why do we need this wrapper?
> > The komeda_sprintf is a generic function and will be used by other
> > places, while evt_sprintf is working for the detail event msg.
> 
> Yeah, I'm not buying this argument any more. We should not create new functions
> just because we want to save typing one if () condition. evt_sprintf does
> nothing with the extra evt argument other than checking that it is not zero.

Hi Liviu

But I think we'd better to have this function which can remove
many duplicate if () checks, and makes the code elegant and easy to
read. and I think that why the concept of function has been
introduced.

And in linux we can see lot of functions or MACRO that just for save one
word like:

  static inline void *kzalloc(size_t size, gfp_t flags)
  {
	return kmalloc(size, flags | __GFP_ZERO);
  }

And for this "if () check" specific, I think this is also very popular
in linux like:

  static inline void __rcu_read_lock(void)
  {
 	if (IS_ENABLED(CONFIG_PREEMPT_COUNT))
		preempt_disable();
  }

  static inline void __rcu_read_unlock(void)
  {
	if (IS_ENABLED(CONFIG_PREEMPT_COUNT))
		preempt_enable();
  }

thanks
James

> > 
> > > > +
> > > > +static void evt_str(struct komeda_str *str, u64 events)
> > > > +{
> > > > +	if (events == 0ULL) {
> > > > +		evt_sprintf(str, 1, "None");
> > > > +		return;
> > > > +	}
> > > > +
> > > > +	evt_sprintf(str, events & KOMEDA_EVENT_VSYNC, "VSYNC|");
> > > > +	evt_sprintf(str, events & KOMEDA_EVENT_FLIP, "FLIP|");
> > > > +	evt_sprintf(str, events & KOMEDA_EVENT_EOW, "EOW|");
> > > > +	evt_sprintf(str, events & KOMEDA_EVENT_MODE, "OP-MODE|");
> > > > +
> > > > +	evt_sprintf(str, events & KOMEDA_EVENT_URUN, "UNDERRUN|");
> > > > +	evt_sprintf(str, events & KOMEDA_EVENT_OVR, "OVERRUN|");
> > > > +
> > > > +	/* GLB error */
> > > > +	evt_sprintf(str, events & KOMEDA_ERR_MERR, "MERR|");
> > > > +	evt_sprintf(str, events & KOMEDA_ERR_FRAMETO, "FRAMETO|");
> > > > +
> > > > +	/* DOU error */
> > > > +	evt_sprintf(str, events & KOMEDA_ERR_DRIFTTO, "DRIFTTO|");
> > > > +	evt_sprintf(str, events & KOMEDA_ERR_FRAMETO, "FRAMETO|");
> > > > +	evt_sprintf(str, events & KOMEDA_ERR_TETO, "TETO|");
> > > > +	evt_sprintf(str, events & KOMEDA_ERR_CSCE, "CSCE|");
> > > > +
> > > > +	/* LPU errors or events */
> > > > +	evt_sprintf(str, events & KOMEDA_EVENT_IBSY, "IBSY|");
> > > > +	evt_sprintf(str, events & KOMEDA_ERR_AXIE, "AXIE|");
> > > > +	evt_sprintf(str, events & KOMEDA_ERR_ACE0, "ACE0|");
> > > > +	evt_sprintf(str, events & KOMEDA_ERR_ACE1, "ACE1|");
> > > > +	evt_sprintf(str, events & KOMEDA_ERR_ACE2, "ACE2|");
> > > > +	evt_sprintf(str, events & KOMEDA_ERR_ACE3, "ACE3|");
> > > > +
> > > > +	/* LPU TBU errors*/
> > > > +	evt_sprintf(str, events & KOMEDA_ERR_TCF, "TCF|");
> > > > +	evt_sprintf(str, events & KOMEDA_ERR_TTNG, "TTNG|");
> > > > +	evt_sprintf(str, events & KOMEDA_ERR_TITR, "TITR|");
> > > > +	evt_sprintf(str, events & KOMEDA_ERR_TEMR, "TEMR|");
> > > > +	evt_sprintf(str, events & KOMEDA_ERR_TTF, "TTF|");
> > > > +
> > > > +	/* CU errors*/
> > > > +	evt_sprintf(str, events & KOMEDA_ERR_CPE, "COPROC|");
> > > > +	evt_sprintf(str, events & KOMEDA_ERR_ZME, "ZME|");
> > > > +	evt_sprintf(str, events & KOMEDA_ERR_CFGE, "CFGE|");
> > > > +	evt_sprintf(str, events & KOMEDA_ERR_TEMR, "TEMR|");
> > > > +
> > > > +	if (str->len > 0 && (str->str[str->len - 1] == '|')) {
> > > > +		str->str[str->len - 1] = 0;
> > > > +		str->len--;
> > > > +	}
> > > > +}
> > > > +
> > > > +static bool is_new_frame(struct komeda_events *a)
> > > > +{
> > > > +	return (a->pipes[0] | a->pipes[1]) & KOMEDA_EVENT_FLIP;
> > > > +}
> > > > +
> > > > +void komeda_print_events(struct komeda_events *evts)
> > > > +{
> > > > +	u64 print_evts = KOMEDA_ERR_EVENTS;
> > > > +	static bool en_print = true;
> > > > +
> > > > +	/* reduce the same msg print, only print the first evt for one frame */
> > > > +	if (evts->global || is_new_frame(evts))
> > > > +		en_print = true;
> > > > +	if (!en_print)
> > > > +		return;
> > > 
> > > When does en_print ever get false?
> > Once the events printed, it will be set false (pls find at the last
> > line of this function).
> 
> What is the point of making en_print a static variable? We print all the time
> when we have a global event anyway.

Hi Liviu:

| why make en_print a static.

Consider you commit a scene which may leads a UNDERUN. and it will
trigger HW UNDERRUN in every vsync peroid untill this sceen have been
replace by another scene. for a scene it will trigger same error again
and again. we don't need print them all for a scene one msg is enough.

| we print all the time when we have a global event.
Since we only reduce the duplicate error, but want print all different error.
And per our HW design, the event reported by different component.
this global for collect the GCU error. the pipeline_event is for
LPU/CU/DOU. like UNDERUN which is only DOU error.

and current GCU only have one error type: opmode change error which only
can be happened on when we call change_opmode in crtc_enable/disable.

So don't worry, globl event which can not make en_print has been set to
true in every irq handling.

Thanks
James

> 
> > > > +
> > > > +#ifdef DEBUG
> > > > +	print_evts |= KOMEDA_WARN_EVENTS;
> > > > +#endif
> > > > +
> > > > +	if ((evts->global | evts->pipes[0] | evts->pipes[1]) & print_evts) {
> > > > +		#define STR_SZ		128
> > > > +		char msg[STR_SZ];
> > > 
> > > I've counted about 27 evt_sprintf() calls in evt_str() function, with an
> > > average of 5 characters each, so thats 135 characters printed into a buffer
> > > that is only 128 bytes. Please don't do this!
> > komeda_sprintf() will check the size and also I thought those evt
> > will not populat together. But yes, I'd better change this to 256.
> > Will change this.
> > 
> > > > +		struct komeda_str str;
> > > > +
> > > > +		str.str = msg;
> > > > +		str.sz  = STR_SZ;
> > > > +		str.len = 0;
> > > > +
> > > > +		komeda_sprintf(&str, "gcu: ");
> > > > +		evt_str(&str, evts->global);
> > > > +		komeda_sprintf(&str, ", pipes[0]: ");
> > > > +		evt_str(&str, evts->pipes[0]);
> > > > +		komeda_sprintf(&str, ", pipes[1]: ");
> > > > +		evt_str(&str, evts->pipes[1]);
> > > > +
> > > > +		DRM_ERROR("err detect: %s\n", msg);
> > > > +
> > > > +		en_print = false;
> > > > +	}
> > > > +}
> > > > diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_kms.c b/drivers/gpu/drm/arm/display/komeda/komeda_kms.c
> > > > index 647bce5..1462bac 100644
> > > > --- a/drivers/gpu/drm/arm/display/komeda/komeda_kms.c
> > > > +++ b/drivers/gpu/drm/arm/display/komeda/komeda_kms.c
> > > > @@ -47,6 +47,8 @@ static irqreturn_t komeda_kms_irq_handler(int irq, void *data)
> > > >  	memset(&evts, 0, sizeof(evts));
> > > >  	status = mdev->funcs->irq_handler(mdev, &evts);
> > > >  
> > > > +	komeda_print_events(&evts);
> > > 
> > > Calling this function from the IRQ handler is a bad idea. We should use debugfs
> > > if you really want to have a trace of the events, but I personally don't see
> > > value in having this functionality in the kernel at all. You can expose the
> > > value of the evts->global and evts->pipes[] as integers and decode that in
> > > userspace or as a debugfs entry.
> > > 
> > > Best regards,
> > > Liviu
> > 
> > The name of this function is misleading, but this is printing out the
> > hardware detected errors, from which we can know directly once the
> > errors happened on the hardware. Like if the driver code was at
> > bring-up stage, the logs from this layer is helpful. So can we keep
> > this?
> 
> We should probably just collect the global and pipes values and expose
> them to userspace so that the printing and decoding of the messages happens
> there.
> 
> Best regards,
> Liviu

Hi Liviu:

Any special resons.

Since such error print is not only wanted by us, mostly it is required
and used by our customer to easily capture the problem.
If no special reasons, I want to keep it for avoiding the complaint
from our customer. 

Thanks
James
> 
> > 
> > Best regards,
> > Lowry
> > 
> > > > +
> > > >  	/* Notify the crtc to handle the events */
> > > >  	for (i = 0; i < kms->n_crtcs; i++)
> > > >  		komeda_crtc_handle_event(&kms->crtcs[i], &evts);
> > > > -- 
> > > > 1.9.1
> > > > 
> > > 
> > > -- 
> > > ====================
> > > | I would like to |
> > > | fix the world,  |
> > > | but they're not |
> > > | giving me the   |
> > >  \ source code!  /
> > >   ---------------
> > >     ¯\_(ツ)_/¯
> > 
> > -- 
> > Regards,
> > Lowry
> 
> -- 
> ====================
> | I would like to |
> | fix the world,  |
> | but they're not |
> | giving me the   |
>  \ source code!  /
>   ---------------
>     ¯\_(ツ)_/¯

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [PATCH] drm/komeda: Adds error event print functionality
@ 2019-07-22 11:15         ` james qian wang (Arm Technology China)
  0 siblings, 0 replies; 37+ messages in thread
From: james qian wang (Arm Technology China) @ 2019-07-22 11:15 UTC (permalink / raw)
  To: Liviu Dudau
  Cc: nd, Ayan Halder, airlied, Jonathan Chai (Arm Technology China),
	linux-kernel, dri-devel, Julien Yin (Arm Technology China),
	seanpaul, Lowry Li (Arm Technology China)

On Fri, Jul 19, 2019 at 11:40:11AM +0000, Liviu Dudau wrote:
> On Fri, Jul 19, 2019 at 09:09:30AM +0000, Lowry Li (Arm Technology China) wrote:
> > Hi Liviu,
> > 
> > On Thu, Jul 18, 2019 at 01:17:37PM +0000, Liviu Dudau wrote:
> > > On Thu, Jun 27, 2019 at 04:10:36AM +0100, Lowry Li (Arm Technology China) wrote:
> > > > Adds to print the event message when error happens and the same event
> > > > will not be printed until next vsync.
> > > > 
> > > > Signed-off-by: Lowry Li (Arm Technology China) <lowry.li@arm.com>
> > > > ---
> > > >  drivers/gpu/drm/arm/display/komeda/Makefile       |   1 +
> > > >  drivers/gpu/drm/arm/display/komeda/komeda_dev.h   |  13 ++
> > > >  drivers/gpu/drm/arm/display/komeda/komeda_event.c | 144 ++++++++++++++++++++++
> > > >  drivers/gpu/drm/arm/display/komeda/komeda_kms.c   |   2 +
> > > >  4 files changed, 160 insertions(+)
> > > >  create mode 100644 drivers/gpu/drm/arm/display/komeda/komeda_event.c
> > > > 
> > > > diff --git a/drivers/gpu/drm/arm/display/komeda/Makefile b/drivers/gpu/drm/arm/display/komeda/Makefile
> > > > index 38aa584..3f53d2d 100644
> > > > --- a/drivers/gpu/drm/arm/display/komeda/Makefile
> > > > +++ b/drivers/gpu/drm/arm/display/komeda/Makefile
> > > > @@ -7,6 +7,7 @@ ccflags-y := \
> > > >  komeda-y := \
> > > >  	komeda_drv.o \
> > > >  	komeda_dev.o \
> > > > +	komeda_event.o \
> > > >  	komeda_format_caps.o \
> > > >  	komeda_coeffs.o \
> > > >  	komeda_color_mgmt.o \
> > > > diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_dev.h b/drivers/gpu/drm/arm/display/komeda/komeda_dev.h
> > > > index 096f9f7..e863ec3 100644
> > > > --- a/drivers/gpu/drm/arm/display/komeda/komeda_dev.h
> > > > +++ b/drivers/gpu/drm/arm/display/komeda/komeda_dev.h
> > > > @@ -40,6 +40,17 @@
> > > >  #define KOMEDA_ERR_TTNG			BIT_ULL(30)
> > > >  #define KOMEDA_ERR_TTF			BIT_ULL(31)
> > > >  
> > > > +#define KOMEDA_ERR_EVENTS	\
> > > > +	(KOMEDA_EVENT_URUN	| KOMEDA_EVENT_IBSY	| KOMEDA_EVENT_OVR |\
> > > > +	KOMEDA_ERR_TETO		| KOMEDA_ERR_TEMR	| KOMEDA_ERR_TITR |\
> > > > +	KOMEDA_ERR_CPE		| KOMEDA_ERR_CFGE	| KOMEDA_ERR_AXIE |\
> > > > +	KOMEDA_ERR_ACE0		| KOMEDA_ERR_ACE1	| KOMEDA_ERR_ACE2 |\
> > > > +	KOMEDA_ERR_ACE3		| KOMEDA_ERR_DRIFTTO	| KOMEDA_ERR_FRAMETO |\
> > > > +	KOMEDA_ERR_ZME		| KOMEDA_ERR_MERR	| KOMEDA_ERR_TCF |\
> > > > +	KOMEDA_ERR_TTNG		| KOMEDA_ERR_TTF)
> > > > +
> > > > +#define KOMEDA_WARN_EVENTS	KOMEDA_ERR_CSCE
> > > > +
> > > >  /* malidp device id */
> > > >  enum {
> > > >  	MALI_D71 = 0,
> > > > @@ -207,6 +218,8 @@ struct komeda_dev {
> > > >  
> > > >  struct komeda_dev *dev_to_mdev(struct device *dev);
> > > >  
> > > > +void komeda_print_events(struct komeda_events *evts);
> > > > +
> > > >  int komeda_dev_resume(struct komeda_dev *mdev);
> > > >  int komeda_dev_suspend(struct komeda_dev *mdev);
> > > >  #endif /*_KOMEDA_DEV_H_*/
> > > > diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_event.c b/drivers/gpu/drm/arm/display/komeda/komeda_event.c
> > > > new file mode 100644
> > > > index 0000000..309dbe2
> > > > --- /dev/null
> > > > +++ b/drivers/gpu/drm/arm/display/komeda/komeda_event.c
> > > > @@ -0,0 +1,144 @@
> > > > +// SPDX-License-Identifier: GPL-2.0
> > > > +/*
> > > > + * (C) COPYRIGHT 2019 ARM Limited. All rights reserved.
> > > > + * Author: James.Qian.Wang <james.qian.wang@arm.com>
> > > > + *
> > > > + */
> > > > +#include <drm/drm_print.h>
> > > > +
> > > > +#include "komeda_dev.h"
> > > > +
> > > > +struct komeda_str {
> > > > +	char *str;
> > > > +	u32 sz;
> > > > +	u32 len;
> > > > +};
> > > > +
> > > > +/* return 0 on success,  < 0 on no space.
> > > > + */
> > > > +static int komeda_sprintf(struct komeda_str *str, const char *fmt, ...)
> > > > +{
> > > > +	va_list args;
> > > > +	int num, free_sz;
> > > > +	int err;
> > > > +
> > > > +	free_sz = str->sz - str->len;
> > > > +	if (free_sz <= 0)
> > > > +		return -ENOSPC;
> > > > +
> > > > +	va_start(args, fmt);
> > > > +
> > > > +	num = vsnprintf(str->str + str->len, free_sz, fmt, args);
> > > > +
> > > > +	va_end(args);
> > > > +
> > > > +	if (num <= free_sz) {
> > > > +		str->len += num;
> > > > +		err = 0;
> > > > +	} else {
> > > > +		str->len = str->sz;
> > > > +		err = -ENOSPC;
> > > > +	}
> > > > +
> > > > +	return err;
> > > > +}
> > > > +
> > > > +static void evt_sprintf(struct komeda_str *str, u64 evt, const char *msg)
> > > > +{
> > > > +	if (evt)
> > > > +		komeda_sprintf(str, msg);
> > > > +}
> > > 
> > > Why do we need this wrapper?
> > The komeda_sprintf is a generic function and will be used by other
> > places, while evt_sprintf is working for the detail event msg.
> 
> Yeah, I'm not buying this argument any more. We should not create new functions
> just because we want to save typing one if () condition. evt_sprintf does
> nothing with the extra evt argument other than checking that it is not zero.

Hi Liviu

But I think we'd better to have this function which can remove
many duplicate if () checks, and makes the code elegant and easy to
read. and I think that why the concept of function has been
introduced.

And in linux we can see lot of functions or MACRO that just for save one
word like:

  static inline void *kzalloc(size_t size, gfp_t flags)
  {
	return kmalloc(size, flags | __GFP_ZERO);
  }

And for this "if () check" specific, I think this is also very popular
in linux like:

  static inline void __rcu_read_lock(void)
  {
 	if (IS_ENABLED(CONFIG_PREEMPT_COUNT))
		preempt_disable();
  }

  static inline void __rcu_read_unlock(void)
  {
	if (IS_ENABLED(CONFIG_PREEMPT_COUNT))
		preempt_enable();
  }

thanks
James

> > 
> > > > +
> > > > +static void evt_str(struct komeda_str *str, u64 events)
> > > > +{
> > > > +	if (events == 0ULL) {
> > > > +		evt_sprintf(str, 1, "None");
> > > > +		return;
> > > > +	}
> > > > +
> > > > +	evt_sprintf(str, events & KOMEDA_EVENT_VSYNC, "VSYNC|");
> > > > +	evt_sprintf(str, events & KOMEDA_EVENT_FLIP, "FLIP|");
> > > > +	evt_sprintf(str, events & KOMEDA_EVENT_EOW, "EOW|");
> > > > +	evt_sprintf(str, events & KOMEDA_EVENT_MODE, "OP-MODE|");
> > > > +
> > > > +	evt_sprintf(str, events & KOMEDA_EVENT_URUN, "UNDERRUN|");
> > > > +	evt_sprintf(str, events & KOMEDA_EVENT_OVR, "OVERRUN|");
> > > > +
> > > > +	/* GLB error */
> > > > +	evt_sprintf(str, events & KOMEDA_ERR_MERR, "MERR|");
> > > > +	evt_sprintf(str, events & KOMEDA_ERR_FRAMETO, "FRAMETO|");
> > > > +
> > > > +	/* DOU error */
> > > > +	evt_sprintf(str, events & KOMEDA_ERR_DRIFTTO, "DRIFTTO|");
> > > > +	evt_sprintf(str, events & KOMEDA_ERR_FRAMETO, "FRAMETO|");
> > > > +	evt_sprintf(str, events & KOMEDA_ERR_TETO, "TETO|");
> > > > +	evt_sprintf(str, events & KOMEDA_ERR_CSCE, "CSCE|");
> > > > +
> > > > +	/* LPU errors or events */
> > > > +	evt_sprintf(str, events & KOMEDA_EVENT_IBSY, "IBSY|");
> > > > +	evt_sprintf(str, events & KOMEDA_ERR_AXIE, "AXIE|");
> > > > +	evt_sprintf(str, events & KOMEDA_ERR_ACE0, "ACE0|");
> > > > +	evt_sprintf(str, events & KOMEDA_ERR_ACE1, "ACE1|");
> > > > +	evt_sprintf(str, events & KOMEDA_ERR_ACE2, "ACE2|");
> > > > +	evt_sprintf(str, events & KOMEDA_ERR_ACE3, "ACE3|");
> > > > +
> > > > +	/* LPU TBU errors*/
> > > > +	evt_sprintf(str, events & KOMEDA_ERR_TCF, "TCF|");
> > > > +	evt_sprintf(str, events & KOMEDA_ERR_TTNG, "TTNG|");
> > > > +	evt_sprintf(str, events & KOMEDA_ERR_TITR, "TITR|");
> > > > +	evt_sprintf(str, events & KOMEDA_ERR_TEMR, "TEMR|");
> > > > +	evt_sprintf(str, events & KOMEDA_ERR_TTF, "TTF|");
> > > > +
> > > > +	/* CU errors*/
> > > > +	evt_sprintf(str, events & KOMEDA_ERR_CPE, "COPROC|");
> > > > +	evt_sprintf(str, events & KOMEDA_ERR_ZME, "ZME|");
> > > > +	evt_sprintf(str, events & KOMEDA_ERR_CFGE, "CFGE|");
> > > > +	evt_sprintf(str, events & KOMEDA_ERR_TEMR, "TEMR|");
> > > > +
> > > > +	if (str->len > 0 && (str->str[str->len - 1] == '|')) {
> > > > +		str->str[str->len - 1] = 0;
> > > > +		str->len--;
> > > > +	}
> > > > +}
> > > > +
> > > > +static bool is_new_frame(struct komeda_events *a)
> > > > +{
> > > > +	return (a->pipes[0] | a->pipes[1]) & KOMEDA_EVENT_FLIP;
> > > > +}
> > > > +
> > > > +void komeda_print_events(struct komeda_events *evts)
> > > > +{
> > > > +	u64 print_evts = KOMEDA_ERR_EVENTS;
> > > > +	static bool en_print = true;
> > > > +
> > > > +	/* reduce the same msg print, only print the first evt for one frame */
> > > > +	if (evts->global || is_new_frame(evts))
> > > > +		en_print = true;
> > > > +	if (!en_print)
> > > > +		return;
> > > 
> > > When does en_print ever get false?
> > Once the events printed, it will be set false (pls find at the last
> > line of this function).
> 
> What is the point of making en_print a static variable? We print all the time
> when we have a global event anyway.

Hi Liviu:

| why make en_print a static.

Consider you commit a scene which may leads a UNDERUN. and it will
trigger HW UNDERRUN in every vsync peroid untill this sceen have been
replace by another scene. for a scene it will trigger same error again
and again. we don't need print them all for a scene one msg is enough.

| we print all the time when we have a global event.
Since we only reduce the duplicate error, but want print all different error.
And per our HW design, the event reported by different component.
this global for collect the GCU error. the pipeline_event is for
LPU/CU/DOU. like UNDERUN which is only DOU error.

and current GCU only have one error type: opmode change error which only
can be happened on when we call change_opmode in crtc_enable/disable.

So don't worry, globl event which can not make en_print has been set to
true in every irq handling.

Thanks
James

> 
> > > > +
> > > > +#ifdef DEBUG
> > > > +	print_evts |= KOMEDA_WARN_EVENTS;
> > > > +#endif
> > > > +
> > > > +	if ((evts->global | evts->pipes[0] | evts->pipes[1]) & print_evts) {
> > > > +		#define STR_SZ		128
> > > > +		char msg[STR_SZ];
> > > 
> > > I've counted about 27 evt_sprintf() calls in evt_str() function, with an
> > > average of 5 characters each, so thats 135 characters printed into a buffer
> > > that is only 128 bytes. Please don't do this!
> > komeda_sprintf() will check the size and also I thought those evt
> > will not populat together. But yes, I'd better change this to 256.
> > Will change this.
> > 
> > > > +		struct komeda_str str;
> > > > +
> > > > +		str.str = msg;
> > > > +		str.sz  = STR_SZ;
> > > > +		str.len = 0;
> > > > +
> > > > +		komeda_sprintf(&str, "gcu: ");
> > > > +		evt_str(&str, evts->global);
> > > > +		komeda_sprintf(&str, ", pipes[0]: ");
> > > > +		evt_str(&str, evts->pipes[0]);
> > > > +		komeda_sprintf(&str, ", pipes[1]: ");
> > > > +		evt_str(&str, evts->pipes[1]);
> > > > +
> > > > +		DRM_ERROR("err detect: %s\n", msg);
> > > > +
> > > > +		en_print = false;
> > > > +	}
> > > > +}
> > > > diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_kms.c b/drivers/gpu/drm/arm/display/komeda/komeda_kms.c
> > > > index 647bce5..1462bac 100644
> > > > --- a/drivers/gpu/drm/arm/display/komeda/komeda_kms.c
> > > > +++ b/drivers/gpu/drm/arm/display/komeda/komeda_kms.c
> > > > @@ -47,6 +47,8 @@ static irqreturn_t komeda_kms_irq_handler(int irq, void *data)
> > > >  	memset(&evts, 0, sizeof(evts));
> > > >  	status = mdev->funcs->irq_handler(mdev, &evts);
> > > >  
> > > > +	komeda_print_events(&evts);
> > > 
> > > Calling this function from the IRQ handler is a bad idea. We should use debugfs
> > > if you really want to have a trace of the events, but I personally don't see
> > > value in having this functionality in the kernel at all. You can expose the
> > > value of the evts->global and evts->pipes[] as integers and decode that in
> > > userspace or as a debugfs entry.
> > > 
> > > Best regards,
> > > Liviu
> > 
> > The name of this function is misleading, but this is printing out the
> > hardware detected errors, from which we can know directly once the
> > errors happened on the hardware. Like if the driver code was at
> > bring-up stage, the logs from this layer is helpful. So can we keep
> > this?
> 
> We should probably just collect the global and pipes values and expose
> them to userspace so that the printing and decoding of the messages happens
> there.
> 
> Best regards,
> Liviu

Hi Liviu:

Any special resons.

Since such error print is not only wanted by us, mostly it is required
and used by our customer to easily capture the problem.
If no special reasons, I want to keep it for avoiding the complaint
from our customer. 

Thanks
James
> 
> > 
> > Best regards,
> > Lowry
> > 
> > > > +
> > > >  	/* Notify the crtc to handle the events */
> > > >  	for (i = 0; i < kms->n_crtcs; i++)
> > > >  		komeda_crtc_handle_event(&kms->crtcs[i], &evts);
> > > > -- 
> > > > 1.9.1
> > > > 
> > > 
> > > -- 
> > > ====================
> > > | I would like to |
> > > | fix the world,  |
> > > | but they're not |
> > > | giving me the   |
> > >  \ source code!  /
> > >   ---------------
> > >     ¯\_(ツ)_/¯
> > 
> > -- 
> > Regards,
> > Lowry
> 
> -- 
> ====================
> | I would like to |
> | fix the world,  |
> | but they're not |
> | giving me the   |
>  \ source code!  /
>   ---------------
>     ¯\_(ツ)_/¯
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [PATCH] drm/komeda: Adds error event print functionality
  2019-07-22 11:15         ` james qian wang (Arm Technology China)
@ 2019-07-22 16:18           ` Liviu Dudau
  -1 siblings, 0 replies; 37+ messages in thread
From: Liviu Dudau @ 2019-07-22 16:18 UTC (permalink / raw)
  To: james qian wang (Arm Technology China)
  Cc: Lowry Li (Arm Technology China),
	maarten.lankhorst, seanpaul, airlied, Brian Starkey,
	Julien Yin (Arm Technology China),
	Jonathan Chai (Arm Technology China),
	Ayan Halder, dri-devel, linux-kernel, nd

On Mon, Jul 22, 2019 at 11:15:12AM +0000, james qian wang (Arm Technology China) wrote:
> On Fri, Jul 19, 2019 at 11:40:11AM +0000, Liviu Dudau wrote:
> > On Fri, Jul 19, 2019 at 09:09:30AM +0000, Lowry Li (Arm Technology China) wrote:
> > > Hi Liviu,
> > > 
> > > On Thu, Jul 18, 2019 at 01:17:37PM +0000, Liviu Dudau wrote:
> > > > On Thu, Jun 27, 2019 at 04:10:36AM +0100, Lowry Li (Arm Technology China) wrote:
> > > > > Adds to print the event message when error happens and the same event
> > > > > will not be printed until next vsync.
> > > > > 
> > > > > Signed-off-by: Lowry Li (Arm Technology China) <lowry.li@arm.com>
> > > > > ---
> > > > >  drivers/gpu/drm/arm/display/komeda/Makefile       |   1 +
> > > > >  drivers/gpu/drm/arm/display/komeda/komeda_dev.h   |  13 ++
> > > > >  drivers/gpu/drm/arm/display/komeda/komeda_event.c | 144 ++++++++++++++++++++++
> > > > >  drivers/gpu/drm/arm/display/komeda/komeda_kms.c   |   2 +
> > > > >  4 files changed, 160 insertions(+)
> > > > >  create mode 100644 drivers/gpu/drm/arm/display/komeda/komeda_event.c
> > > > > 
> > > > > diff --git a/drivers/gpu/drm/arm/display/komeda/Makefile b/drivers/gpu/drm/arm/display/komeda/Makefile
> > > > > index 38aa584..3f53d2d 100644
> > > > > --- a/drivers/gpu/drm/arm/display/komeda/Makefile
> > > > > +++ b/drivers/gpu/drm/arm/display/komeda/Makefile
> > > > > @@ -7,6 +7,7 @@ ccflags-y := \
> > > > >  komeda-y := \
> > > > >  	komeda_drv.o \
> > > > >  	komeda_dev.o \
> > > > > +	komeda_event.o \
> > > > >  	komeda_format_caps.o \
> > > > >  	komeda_coeffs.o \
> > > > >  	komeda_color_mgmt.o \
> > > > > diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_dev.h b/drivers/gpu/drm/arm/display/komeda/komeda_dev.h
> > > > > index 096f9f7..e863ec3 100644
> > > > > --- a/drivers/gpu/drm/arm/display/komeda/komeda_dev.h
> > > > > +++ b/drivers/gpu/drm/arm/display/komeda/komeda_dev.h
> > > > > @@ -40,6 +40,17 @@
> > > > >  #define KOMEDA_ERR_TTNG			BIT_ULL(30)
> > > > >  #define KOMEDA_ERR_TTF			BIT_ULL(31)
> > > > >  
> > > > > +#define KOMEDA_ERR_EVENTS	\
> > > > > +	(KOMEDA_EVENT_URUN	| KOMEDA_EVENT_IBSY	| KOMEDA_EVENT_OVR |\
> > > > > +	KOMEDA_ERR_TETO		| KOMEDA_ERR_TEMR	| KOMEDA_ERR_TITR |\
> > > > > +	KOMEDA_ERR_CPE		| KOMEDA_ERR_CFGE	| KOMEDA_ERR_AXIE |\
> > > > > +	KOMEDA_ERR_ACE0		| KOMEDA_ERR_ACE1	| KOMEDA_ERR_ACE2 |\
> > > > > +	KOMEDA_ERR_ACE3		| KOMEDA_ERR_DRIFTTO	| KOMEDA_ERR_FRAMETO |\
> > > > > +	KOMEDA_ERR_ZME		| KOMEDA_ERR_MERR	| KOMEDA_ERR_TCF |\
> > > > > +	KOMEDA_ERR_TTNG		| KOMEDA_ERR_TTF)
> > > > > +
> > > > > +#define KOMEDA_WARN_EVENTS	KOMEDA_ERR_CSCE
> > > > > +
> > > > >  /* malidp device id */
> > > > >  enum {
> > > > >  	MALI_D71 = 0,
> > > > > @@ -207,6 +218,8 @@ struct komeda_dev {
> > > > >  
> > > > >  struct komeda_dev *dev_to_mdev(struct device *dev);
> > > > >  
> > > > > +void komeda_print_events(struct komeda_events *evts);
> > > > > +
> > > > >  int komeda_dev_resume(struct komeda_dev *mdev);
> > > > >  int komeda_dev_suspend(struct komeda_dev *mdev);
> > > > >  #endif /*_KOMEDA_DEV_H_*/
> > > > > diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_event.c b/drivers/gpu/drm/arm/display/komeda/komeda_event.c
> > > > > new file mode 100644
> > > > > index 0000000..309dbe2
> > > > > --- /dev/null
> > > > > +++ b/drivers/gpu/drm/arm/display/komeda/komeda_event.c
> > > > > @@ -0,0 +1,144 @@
> > > > > +// SPDX-License-Identifier: GPL-2.0
> > > > > +/*
> > > > > + * (C) COPYRIGHT 2019 ARM Limited. All rights reserved.
> > > > > + * Author: James.Qian.Wang <james.qian.wang@arm.com>
> > > > > + *
> > > > > + */
> > > > > +#include <drm/drm_print.h>
> > > > > +
> > > > > +#include "komeda_dev.h"
> > > > > +
> > > > > +struct komeda_str {
> > > > > +	char *str;
> > > > > +	u32 sz;
> > > > > +	u32 len;
> > > > > +};
> > > > > +
> > > > > +/* return 0 on success,  < 0 on no space.
> > > > > + */
> > > > > +static int komeda_sprintf(struct komeda_str *str, const char *fmt, ...)
> > > > > +{
> > > > > +	va_list args;
> > > > > +	int num, free_sz;
> > > > > +	int err;
> > > > > +
> > > > > +	free_sz = str->sz - str->len;
> > > > > +	if (free_sz <= 0)
> > > > > +		return -ENOSPC;
> > > > > +
> > > > > +	va_start(args, fmt);
> > > > > +
> > > > > +	num = vsnprintf(str->str + str->len, free_sz, fmt, args);
> > > > > +
> > > > > +	va_end(args);
> > > > > +
> > > > > +	if (num <= free_sz) {
> > > > > +		str->len += num;
> > > > > +		err = 0;
> > > > > +	} else {
> > > > > +		str->len = str->sz;
> > > > > +		err = -ENOSPC;
> > > > > +	}
> > > > > +
> > > > > +	return err;
> > > > > +}
> > > > > +
> > > > > +static void evt_sprintf(struct komeda_str *str, u64 evt, const char *msg)
> > > > > +{
> > > > > +	if (evt)
> > > > > +		komeda_sprintf(str, msg);
> > > > > +}
> > > > 
> > > > Why do we need this wrapper?
> > > The komeda_sprintf is a generic function and will be used by other
> > > places, while evt_sprintf is working for the detail event msg.
> > 
> > Yeah, I'm not buying this argument any more. We should not create new functions
> > just because we want to save typing one if () condition. evt_sprintf does
> > nothing with the extra evt argument other than checking that it is not zero.
> 
> Hi Liviu
> 
> But I think we'd better to have this function which can remove
> many duplicate if () checks, and makes the code elegant and easy to
> read. and I think that why the concept of function has been
> introduced.
> 
> And in linux we can see lot of functions or MACRO that just for save one
> word like:
> 
>   static inline void *kzalloc(size_t size, gfp_t flags)
>   {
> 	return kmalloc(size, flags | __GFP_ZERO);
>   }

This is a different (and valid use) of creating macros. kzalloc() does
something specific (initialises allocated memory with zeros) by using the
generic kmalloc() function. The added __GFP_ZERO has a specific outcome to the
invocation of the wrapped function. evt_sprintf() does nothing of this sort and
it is arguably wrong, as it drops any possibility of passing arguments to the
format string that komeda_sprintf() allows.


> 
> And for this "if () check" specific, I think this is also very popular
> in linux like:
> 
>   static inline void __rcu_read_lock(void)
>   {
>  	if (IS_ENABLED(CONFIG_PREEMPT_COUNT))
> 		preempt_disable();
>   }
> 
>   static inline void __rcu_read_unlock(void)
>   {
> 	if (IS_ENABLED(CONFIG_PREEMPT_COUNT))
> 		preempt_enable();
>   }

These are inline functions wrapping around the fact that a config option might
be disabled. Not really the same thing with what we are talking here.

> 
> thanks
> James
> 
> > > 
> > > > > +
> > > > > +static void evt_str(struct komeda_str *str, u64 events)
> > > > > +{
> > > > > +	if (events == 0ULL) {
> > > > > +		evt_sprintf(str, 1, "None");
> > > > > +		return;
> > > > > +	}
> > > > > +
> > > > > +	evt_sprintf(str, events & KOMEDA_EVENT_VSYNC, "VSYNC|");
> > > > > +	evt_sprintf(str, events & KOMEDA_EVENT_FLIP, "FLIP|");
> > > > > +	evt_sprintf(str, events & KOMEDA_EVENT_EOW, "EOW|");
> > > > > +	evt_sprintf(str, events & KOMEDA_EVENT_MODE, "OP-MODE|");
> > > > > +
> > > > > +	evt_sprintf(str, events & KOMEDA_EVENT_URUN, "UNDERRUN|");
> > > > > +	evt_sprintf(str, events & KOMEDA_EVENT_OVR, "OVERRUN|");
> > > > > +
> > > > > +	/* GLB error */
> > > > > +	evt_sprintf(str, events & KOMEDA_ERR_MERR, "MERR|");
> > > > > +	evt_sprintf(str, events & KOMEDA_ERR_FRAMETO, "FRAMETO|");
> > > > > +
> > > > > +	/* DOU error */
> > > > > +	evt_sprintf(str, events & KOMEDA_ERR_DRIFTTO, "DRIFTTO|");
> > > > > +	evt_sprintf(str, events & KOMEDA_ERR_FRAMETO, "FRAMETO|");
> > > > > +	evt_sprintf(str, events & KOMEDA_ERR_TETO, "TETO|");
> > > > > +	evt_sprintf(str, events & KOMEDA_ERR_CSCE, "CSCE|");
> > > > > +
> > > > > +	/* LPU errors or events */
> > > > > +	evt_sprintf(str, events & KOMEDA_EVENT_IBSY, "IBSY|");
> > > > > +	evt_sprintf(str, events & KOMEDA_ERR_AXIE, "AXIE|");
> > > > > +	evt_sprintf(str, events & KOMEDA_ERR_ACE0, "ACE0|");
> > > > > +	evt_sprintf(str, events & KOMEDA_ERR_ACE1, "ACE1|");
> > > > > +	evt_sprintf(str, events & KOMEDA_ERR_ACE2, "ACE2|");
> > > > > +	evt_sprintf(str, events & KOMEDA_ERR_ACE3, "ACE3|");
> > > > > +
> > > > > +	/* LPU TBU errors*/
> > > > > +	evt_sprintf(str, events & KOMEDA_ERR_TCF, "TCF|");
> > > > > +	evt_sprintf(str, events & KOMEDA_ERR_TTNG, "TTNG|");
> > > > > +	evt_sprintf(str, events & KOMEDA_ERR_TITR, "TITR|");
> > > > > +	evt_sprintf(str, events & KOMEDA_ERR_TEMR, "TEMR|");
> > > > > +	evt_sprintf(str, events & KOMEDA_ERR_TTF, "TTF|");
> > > > > +
> > > > > +	/* CU errors*/
> > > > > +	evt_sprintf(str, events & KOMEDA_ERR_CPE, "COPROC|");
> > > > > +	evt_sprintf(str, events & KOMEDA_ERR_ZME, "ZME|");
> > > > > +	evt_sprintf(str, events & KOMEDA_ERR_CFGE, "CFGE|");
> > > > > +	evt_sprintf(str, events & KOMEDA_ERR_TEMR, "TEMR|");
> > > > > +
> > > > > +	if (str->len > 0 && (str->str[str->len - 1] == '|')) {
> > > > > +		str->str[str->len - 1] = 0;
> > > > > +		str->len--;
> > > > > +	}
> > > > > +}
> > > > > +
> > > > > +static bool is_new_frame(struct komeda_events *a)
> > > > > +{
> > > > > +	return (a->pipes[0] | a->pipes[1]) & KOMEDA_EVENT_FLIP;
> > > > > +}
> > > > > +
> > > > > +void komeda_print_events(struct komeda_events *evts)
> > > > > +{
> > > > > +	u64 print_evts = KOMEDA_ERR_EVENTS;
> > > > > +	static bool en_print = true;
> > > > > +
> > > > > +	/* reduce the same msg print, only print the first evt for one frame */
> > > > > +	if (evts->global || is_new_frame(evts))
> > > > > +		en_print = true;
> > > > > +	if (!en_print)
> > > > > +		return;
> > > > 
> > > > When does en_print ever get false?
> > > Once the events printed, it will be set false (pls find at the last
> > > line of this function).
> > 
> > What is the point of making en_print a static variable? We print all the time
> > when we have a global event anyway.
> 
> Hi Liviu:
> 
> | why make en_print a static.
> 
> Consider you commit a scene which may leads a UNDERUN. and it will
> trigger HW UNDERRUN in every vsync peroid untill this sceen have been
> replace by another scene. for a scene it will trigger same error again
> and again. we don't need print them all for a scene one msg is enough.

The same can be achieved by removing en_print entirely and inverting the top
condition:

	if (!evts->global && !is_new_frame(evts))
		return;

> 
> | we print all the time when we have a global event.
> Since we only reduce the duplicate error, but want print all different error.
> And per our HW design, the event reported by different component.
> this global for collect the GCU error. the pipeline_event is for
> LPU/CU/DOU. like UNDERUN which is only DOU error.
> 
> and current GCU only have one error type: opmode change error which only
> can be happened on when we call change_opmode in crtc_enable/disable.
> 
> So don't worry, globl event which can not make en_print has been set to
> true in every irq handling.

And that's the reason I'm asking why make en_print static if we reset it in
every irq_handling (i.e. when we actually want to print). Does it really need
to be static when we don't actually use the stored state?

Best regards,
Liviu


> 
> Thanks
> James
> 
> > 
> > > > > +
> > > > > +#ifdef DEBUG
> > > > > +	print_evts |= KOMEDA_WARN_EVENTS;
> > > > > +#endif
> > > > > +
> > > > > +	if ((evts->global | evts->pipes[0] | evts->pipes[1]) & print_evts) {
> > > > > +		#define STR_SZ		128
> > > > > +		char msg[STR_SZ];
> > > > 
> > > > I've counted about 27 evt_sprintf() calls in evt_str() function, with an
> > > > average of 5 characters each, so thats 135 characters printed into a buffer
> > > > that is only 128 bytes. Please don't do this!
> > > komeda_sprintf() will check the size and also I thought those evt
> > > will not populat together. But yes, I'd better change this to 256.
> > > Will change this.
> > > 
> > > > > +		struct komeda_str str;
> > > > > +
> > > > > +		str.str = msg;
> > > > > +		str.sz  = STR_SZ;
> > > > > +		str.len = 0;
> > > > > +
> > > > > +		komeda_sprintf(&str, "gcu: ");
> > > > > +		evt_str(&str, evts->global);
> > > > > +		komeda_sprintf(&str, ", pipes[0]: ");
> > > > > +		evt_str(&str, evts->pipes[0]);
> > > > > +		komeda_sprintf(&str, ", pipes[1]: ");
> > > > > +		evt_str(&str, evts->pipes[1]);
> > > > > +
> > > > > +		DRM_ERROR("err detect: %s\n", msg);
> > > > > +
> > > > > +		en_print = false;
> > > > > +	}
> > > > > +}
> > > > > diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_kms.c b/drivers/gpu/drm/arm/display/komeda/komeda_kms.c
> > > > > index 647bce5..1462bac 100644
> > > > > --- a/drivers/gpu/drm/arm/display/komeda/komeda_kms.c
> > > > > +++ b/drivers/gpu/drm/arm/display/komeda/komeda_kms.c
> > > > > @@ -47,6 +47,8 @@ static irqreturn_t komeda_kms_irq_handler(int irq, void *data)
> > > > >  	memset(&evts, 0, sizeof(evts));
> > > > >  	status = mdev->funcs->irq_handler(mdev, &evts);
> > > > >  
> > > > > +	komeda_print_events(&evts);
> > > > 
> > > > Calling this function from the IRQ handler is a bad idea. We should use debugfs
> > > > if you really want to have a trace of the events, but I personally don't see
> > > > value in having this functionality in the kernel at all. You can expose the
> > > > value of the evts->global and evts->pipes[] as integers and decode that in
> > > > userspace or as a debugfs entry.
> > > > 
> > > > Best regards,
> > > > Liviu
> > > 
> > > The name of this function is misleading, but this is printing out the
> > > hardware detected errors, from which we can know directly once the
> > > errors happened on the hardware. Like if the driver code was at
> > > bring-up stage, the logs from this layer is helpful. So can we keep
> > > this?
> > 
> > We should probably just collect the global and pipes values and expose
> > them to userspace so that the printing and decoding of the messages happens
> > there.
> > 
> > Best regards,
> > Liviu
> 
> Hi Liviu:
> 
> Any special resons.
> 
> Since such error print is not only wanted by us, mostly it is required
> and used by our customer to easily capture the problem.
> If no special reasons, I want to keep it for avoiding the complaint
> from our customer. 
> 
> Thanks
> James
> > 
> > > 
> > > Best regards,
> > > Lowry
> > > 
> > > > > +
> > > > >  	/* Notify the crtc to handle the events */
> > > > >  	for (i = 0; i < kms->n_crtcs; i++)
> > > > >  		komeda_crtc_handle_event(&kms->crtcs[i], &evts);
> > > > > -- 
> > > > > 1.9.1
> > > > > 
> > > > 
> > > > -- 
> > > > ====================
> > > > | I would like to |
> > > > | fix the world,  |
> > > > | but they're not |
> > > > | giving me the   |
> > > >  \ source code!  /
> > > >   ---------------
> > > >     ¯\_(ツ)_/¯
> > > 
> > > -- 
> > > Regards,
> > > Lowry
> > 
> > -- 
> > ====================
> > | I would like to |
> > | fix the world,  |
> > | but they're not |
> > | giving me the   |
> >  \ source code!  /
> >   ---------------
> >     ¯\_(ツ)_/¯

-- 
====================
| I would like to |
| fix the world,  |
| but they're not |
| giving me the   |
 \ source code!  /
  ---------------
    ¯\_(ツ)_/¯

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [PATCH] drm/komeda: Adds error event print functionality
@ 2019-07-22 16:18           ` Liviu Dudau
  0 siblings, 0 replies; 37+ messages in thread
From: Liviu Dudau @ 2019-07-22 16:18 UTC (permalink / raw)
  To: james qian wang (Arm Technology China)
  Cc: Lowry Li (Arm Technology China),
	maarten.lankhorst, seanpaul, airlied, Brian Starkey,
	Julien Yin (Arm Technology China),
	Jonathan Chai (Arm Technology China),
	Ayan Halder, dri-devel, linux-kernel, nd

On Mon, Jul 22, 2019 at 11:15:12AM +0000, james qian wang (Arm Technology China) wrote:
> On Fri, Jul 19, 2019 at 11:40:11AM +0000, Liviu Dudau wrote:
> > On Fri, Jul 19, 2019 at 09:09:30AM +0000, Lowry Li (Arm Technology China) wrote:
> > > Hi Liviu,
> > > 
> > > On Thu, Jul 18, 2019 at 01:17:37PM +0000, Liviu Dudau wrote:
> > > > On Thu, Jun 27, 2019 at 04:10:36AM +0100, Lowry Li (Arm Technology China) wrote:
> > > > > Adds to print the event message when error happens and the same event
> > > > > will not be printed until next vsync.
> > > > > 
> > > > > Signed-off-by: Lowry Li (Arm Technology China) <lowry.li@arm.com>
> > > > > ---
> > > > >  drivers/gpu/drm/arm/display/komeda/Makefile       |   1 +
> > > > >  drivers/gpu/drm/arm/display/komeda/komeda_dev.h   |  13 ++
> > > > >  drivers/gpu/drm/arm/display/komeda/komeda_event.c | 144 ++++++++++++++++++++++
> > > > >  drivers/gpu/drm/arm/display/komeda/komeda_kms.c   |   2 +
> > > > >  4 files changed, 160 insertions(+)
> > > > >  create mode 100644 drivers/gpu/drm/arm/display/komeda/komeda_event.c
> > > > > 
> > > > > diff --git a/drivers/gpu/drm/arm/display/komeda/Makefile b/drivers/gpu/drm/arm/display/komeda/Makefile
> > > > > index 38aa584..3f53d2d 100644
> > > > > --- a/drivers/gpu/drm/arm/display/komeda/Makefile
> > > > > +++ b/drivers/gpu/drm/arm/display/komeda/Makefile
> > > > > @@ -7,6 +7,7 @@ ccflags-y := \
> > > > >  komeda-y := \
> > > > >  	komeda_drv.o \
> > > > >  	komeda_dev.o \
> > > > > +	komeda_event.o \
> > > > >  	komeda_format_caps.o \
> > > > >  	komeda_coeffs.o \
> > > > >  	komeda_color_mgmt.o \
> > > > > diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_dev.h b/drivers/gpu/drm/arm/display/komeda/komeda_dev.h
> > > > > index 096f9f7..e863ec3 100644
> > > > > --- a/drivers/gpu/drm/arm/display/komeda/komeda_dev.h
> > > > > +++ b/drivers/gpu/drm/arm/display/komeda/komeda_dev.h
> > > > > @@ -40,6 +40,17 @@
> > > > >  #define KOMEDA_ERR_TTNG			BIT_ULL(30)
> > > > >  #define KOMEDA_ERR_TTF			BIT_ULL(31)
> > > > >  
> > > > > +#define KOMEDA_ERR_EVENTS	\
> > > > > +	(KOMEDA_EVENT_URUN	| KOMEDA_EVENT_IBSY	| KOMEDA_EVENT_OVR |\
> > > > > +	KOMEDA_ERR_TETO		| KOMEDA_ERR_TEMR	| KOMEDA_ERR_TITR |\
> > > > > +	KOMEDA_ERR_CPE		| KOMEDA_ERR_CFGE	| KOMEDA_ERR_AXIE |\
> > > > > +	KOMEDA_ERR_ACE0		| KOMEDA_ERR_ACE1	| KOMEDA_ERR_ACE2 |\
> > > > > +	KOMEDA_ERR_ACE3		| KOMEDA_ERR_DRIFTTO	| KOMEDA_ERR_FRAMETO |\
> > > > > +	KOMEDA_ERR_ZME		| KOMEDA_ERR_MERR	| KOMEDA_ERR_TCF |\
> > > > > +	KOMEDA_ERR_TTNG		| KOMEDA_ERR_TTF)
> > > > > +
> > > > > +#define KOMEDA_WARN_EVENTS	KOMEDA_ERR_CSCE
> > > > > +
> > > > >  /* malidp device id */
> > > > >  enum {
> > > > >  	MALI_D71 = 0,
> > > > > @@ -207,6 +218,8 @@ struct komeda_dev {
> > > > >  
> > > > >  struct komeda_dev *dev_to_mdev(struct device *dev);
> > > > >  
> > > > > +void komeda_print_events(struct komeda_events *evts);
> > > > > +
> > > > >  int komeda_dev_resume(struct komeda_dev *mdev);
> > > > >  int komeda_dev_suspend(struct komeda_dev *mdev);
> > > > >  #endif /*_KOMEDA_DEV_H_*/
> > > > > diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_event.c b/drivers/gpu/drm/arm/display/komeda/komeda_event.c
> > > > > new file mode 100644
> > > > > index 0000000..309dbe2
> > > > > --- /dev/null
> > > > > +++ b/drivers/gpu/drm/arm/display/komeda/komeda_event.c
> > > > > @@ -0,0 +1,144 @@
> > > > > +// SPDX-License-Identifier: GPL-2.0
> > > > > +/*
> > > > > + * (C) COPYRIGHT 2019 ARM Limited. All rights reserved.
> > > > > + * Author: James.Qian.Wang <james.qian.wang@arm.com>
> > > > > + *
> > > > > + */
> > > > > +#include <drm/drm_print.h>
> > > > > +
> > > > > +#include "komeda_dev.h"
> > > > > +
> > > > > +struct komeda_str {
> > > > > +	char *str;
> > > > > +	u32 sz;
> > > > > +	u32 len;
> > > > > +};
> > > > > +
> > > > > +/* return 0 on success,  < 0 on no space.
> > > > > + */
> > > > > +static int komeda_sprintf(struct komeda_str *str, const char *fmt, ...)
> > > > > +{
> > > > > +	va_list args;
> > > > > +	int num, free_sz;
> > > > > +	int err;
> > > > > +
> > > > > +	free_sz = str->sz - str->len;
> > > > > +	if (free_sz <= 0)
> > > > > +		return -ENOSPC;
> > > > > +
> > > > > +	va_start(args, fmt);
> > > > > +
> > > > > +	num = vsnprintf(str->str + str->len, free_sz, fmt, args);
> > > > > +
> > > > > +	va_end(args);
> > > > > +
> > > > > +	if (num <= free_sz) {
> > > > > +		str->len += num;
> > > > > +		err = 0;
> > > > > +	} else {
> > > > > +		str->len = str->sz;
> > > > > +		err = -ENOSPC;
> > > > > +	}
> > > > > +
> > > > > +	return err;
> > > > > +}
> > > > > +
> > > > > +static void evt_sprintf(struct komeda_str *str, u64 evt, const char *msg)
> > > > > +{
> > > > > +	if (evt)
> > > > > +		komeda_sprintf(str, msg);
> > > > > +}
> > > > 
> > > > Why do we need this wrapper?
> > > The komeda_sprintf is a generic function and will be used by other
> > > places, while evt_sprintf is working for the detail event msg.
> > 
> > Yeah, I'm not buying this argument any more. We should not create new functions
> > just because we want to save typing one if () condition. evt_sprintf does
> > nothing with the extra evt argument other than checking that it is not zero.
> 
> Hi Liviu
> 
> But I think we'd better to have this function which can remove
> many duplicate if () checks, and makes the code elegant and easy to
> read. and I think that why the concept of function has been
> introduced.
> 
> And in linux we can see lot of functions or MACRO that just for save one
> word like:
> 
>   static inline void *kzalloc(size_t size, gfp_t flags)
>   {
> 	return kmalloc(size, flags | __GFP_ZERO);
>   }

This is a different (and valid use) of creating macros. kzalloc() does
something specific (initialises allocated memory with zeros) by using the
generic kmalloc() function. The added __GFP_ZERO has a specific outcome to the
invocation of the wrapped function. evt_sprintf() does nothing of this sort and
it is arguably wrong, as it drops any possibility of passing arguments to the
format string that komeda_sprintf() allows.


> 
> And for this "if () check" specific, I think this is also very popular
> in linux like:
> 
>   static inline void __rcu_read_lock(void)
>   {
>  	if (IS_ENABLED(CONFIG_PREEMPT_COUNT))
> 		preempt_disable();
>   }
> 
>   static inline void __rcu_read_unlock(void)
>   {
> 	if (IS_ENABLED(CONFIG_PREEMPT_COUNT))
> 		preempt_enable();
>   }

These are inline functions wrapping around the fact that a config option might
be disabled. Not really the same thing with what we are talking here.

> 
> thanks
> James
> 
> > > 
> > > > > +
> > > > > +static void evt_str(struct komeda_str *str, u64 events)
> > > > > +{
> > > > > +	if (events == 0ULL) {
> > > > > +		evt_sprintf(str, 1, "None");
> > > > > +		return;
> > > > > +	}
> > > > > +
> > > > > +	evt_sprintf(str, events & KOMEDA_EVENT_VSYNC, "VSYNC|");
> > > > > +	evt_sprintf(str, events & KOMEDA_EVENT_FLIP, "FLIP|");
> > > > > +	evt_sprintf(str, events & KOMEDA_EVENT_EOW, "EOW|");
> > > > > +	evt_sprintf(str, events & KOMEDA_EVENT_MODE, "OP-MODE|");
> > > > > +
> > > > > +	evt_sprintf(str, events & KOMEDA_EVENT_URUN, "UNDERRUN|");
> > > > > +	evt_sprintf(str, events & KOMEDA_EVENT_OVR, "OVERRUN|");
> > > > > +
> > > > > +	/* GLB error */
> > > > > +	evt_sprintf(str, events & KOMEDA_ERR_MERR, "MERR|");
> > > > > +	evt_sprintf(str, events & KOMEDA_ERR_FRAMETO, "FRAMETO|");
> > > > > +
> > > > > +	/* DOU error */
> > > > > +	evt_sprintf(str, events & KOMEDA_ERR_DRIFTTO, "DRIFTTO|");
> > > > > +	evt_sprintf(str, events & KOMEDA_ERR_FRAMETO, "FRAMETO|");
> > > > > +	evt_sprintf(str, events & KOMEDA_ERR_TETO, "TETO|");
> > > > > +	evt_sprintf(str, events & KOMEDA_ERR_CSCE, "CSCE|");
> > > > > +
> > > > > +	/* LPU errors or events */
> > > > > +	evt_sprintf(str, events & KOMEDA_EVENT_IBSY, "IBSY|");
> > > > > +	evt_sprintf(str, events & KOMEDA_ERR_AXIE, "AXIE|");
> > > > > +	evt_sprintf(str, events & KOMEDA_ERR_ACE0, "ACE0|");
> > > > > +	evt_sprintf(str, events & KOMEDA_ERR_ACE1, "ACE1|");
> > > > > +	evt_sprintf(str, events & KOMEDA_ERR_ACE2, "ACE2|");
> > > > > +	evt_sprintf(str, events & KOMEDA_ERR_ACE3, "ACE3|");
> > > > > +
> > > > > +	/* LPU TBU errors*/
> > > > > +	evt_sprintf(str, events & KOMEDA_ERR_TCF, "TCF|");
> > > > > +	evt_sprintf(str, events & KOMEDA_ERR_TTNG, "TTNG|");
> > > > > +	evt_sprintf(str, events & KOMEDA_ERR_TITR, "TITR|");
> > > > > +	evt_sprintf(str, events & KOMEDA_ERR_TEMR, "TEMR|");
> > > > > +	evt_sprintf(str, events & KOMEDA_ERR_TTF, "TTF|");
> > > > > +
> > > > > +	/* CU errors*/
> > > > > +	evt_sprintf(str, events & KOMEDA_ERR_CPE, "COPROC|");
> > > > > +	evt_sprintf(str, events & KOMEDA_ERR_ZME, "ZME|");
> > > > > +	evt_sprintf(str, events & KOMEDA_ERR_CFGE, "CFGE|");
> > > > > +	evt_sprintf(str, events & KOMEDA_ERR_TEMR, "TEMR|");
> > > > > +
> > > > > +	if (str->len > 0 && (str->str[str->len - 1] == '|')) {
> > > > > +		str->str[str->len - 1] = 0;
> > > > > +		str->len--;
> > > > > +	}
> > > > > +}
> > > > > +
> > > > > +static bool is_new_frame(struct komeda_events *a)
> > > > > +{
> > > > > +	return (a->pipes[0] | a->pipes[1]) & KOMEDA_EVENT_FLIP;
> > > > > +}
> > > > > +
> > > > > +void komeda_print_events(struct komeda_events *evts)
> > > > > +{
> > > > > +	u64 print_evts = KOMEDA_ERR_EVENTS;
> > > > > +	static bool en_print = true;
> > > > > +
> > > > > +	/* reduce the same msg print, only print the first evt for one frame */
> > > > > +	if (evts->global || is_new_frame(evts))
> > > > > +		en_print = true;
> > > > > +	if (!en_print)
> > > > > +		return;
> > > > 
> > > > When does en_print ever get false?
> > > Once the events printed, it will be set false (pls find at the last
> > > line of this function).
> > 
> > What is the point of making en_print a static variable? We print all the time
> > when we have a global event anyway.
> 
> Hi Liviu:
> 
> | why make en_print a static.
> 
> Consider you commit a scene which may leads a UNDERUN. and it will
> trigger HW UNDERRUN in every vsync peroid untill this sceen have been
> replace by another scene. for a scene it will trigger same error again
> and again. we don't need print them all for a scene one msg is enough.

The same can be achieved by removing en_print entirely and inverting the top
condition:

	if (!evts->global && !is_new_frame(evts))
		return;

> 
> | we print all the time when we have a global event.
> Since we only reduce the duplicate error, but want print all different error.
> And per our HW design, the event reported by different component.
> this global for collect the GCU error. the pipeline_event is for
> LPU/CU/DOU. like UNDERUN which is only DOU error.
> 
> and current GCU only have one error type: opmode change error which only
> can be happened on when we call change_opmode in crtc_enable/disable.
> 
> So don't worry, globl event which can not make en_print has been set to
> true in every irq handling.

And that's the reason I'm asking why make en_print static if we reset it in
every irq_handling (i.e. when we actually want to print). Does it really need
to be static when we don't actually use the stored state?

Best regards,
Liviu


> 
> Thanks
> James
> 
> > 
> > > > > +
> > > > > +#ifdef DEBUG
> > > > > +	print_evts |= KOMEDA_WARN_EVENTS;
> > > > > +#endif
> > > > > +
> > > > > +	if ((evts->global | evts->pipes[0] | evts->pipes[1]) & print_evts) {
> > > > > +		#define STR_SZ		128
> > > > > +		char msg[STR_SZ];
> > > > 
> > > > I've counted about 27 evt_sprintf() calls in evt_str() function, with an
> > > > average of 5 characters each, so thats 135 characters printed into a buffer
> > > > that is only 128 bytes. Please don't do this!
> > > komeda_sprintf() will check the size and also I thought those evt
> > > will not populat together. But yes, I'd better change this to 256.
> > > Will change this.
> > > 
> > > > > +		struct komeda_str str;
> > > > > +
> > > > > +		str.str = msg;
> > > > > +		str.sz  = STR_SZ;
> > > > > +		str.len = 0;
> > > > > +
> > > > > +		komeda_sprintf(&str, "gcu: ");
> > > > > +		evt_str(&str, evts->global);
> > > > > +		komeda_sprintf(&str, ", pipes[0]: ");
> > > > > +		evt_str(&str, evts->pipes[0]);
> > > > > +		komeda_sprintf(&str, ", pipes[1]: ");
> > > > > +		evt_str(&str, evts->pipes[1]);
> > > > > +
> > > > > +		DRM_ERROR("err detect: %s\n", msg);
> > > > > +
> > > > > +		en_print = false;
> > > > > +	}
> > > > > +}
> > > > > diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_kms.c b/drivers/gpu/drm/arm/display/komeda/komeda_kms.c
> > > > > index 647bce5..1462bac 100644
> > > > > --- a/drivers/gpu/drm/arm/display/komeda/komeda_kms.c
> > > > > +++ b/drivers/gpu/drm/arm/display/komeda/komeda_kms.c
> > > > > @@ -47,6 +47,8 @@ static irqreturn_t komeda_kms_irq_handler(int irq, void *data)
> > > > >  	memset(&evts, 0, sizeof(evts));
> > > > >  	status = mdev->funcs->irq_handler(mdev, &evts);
> > > > >  
> > > > > +	komeda_print_events(&evts);
> > > > 
> > > > Calling this function from the IRQ handler is a bad idea. We should use debugfs
> > > > if you really want to have a trace of the events, but I personally don't see
> > > > value in having this functionality in the kernel at all. You can expose the
> > > > value of the evts->global and evts->pipes[] as integers and decode that in
> > > > userspace or as a debugfs entry.
> > > > 
> > > > Best regards,
> > > > Liviu
> > > 
> > > The name of this function is misleading, but this is printing out the
> > > hardware detected errors, from which we can know directly once the
> > > errors happened on the hardware. Like if the driver code was at
> > > bring-up stage, the logs from this layer is helpful. So can we keep
> > > this?
> > 
> > We should probably just collect the global and pipes values and expose
> > them to userspace so that the printing and decoding of the messages happens
> > there.
> > 
> > Best regards,
> > Liviu
> 
> Hi Liviu:
> 
> Any special resons.
> 
> Since such error print is not only wanted by us, mostly it is required
> and used by our customer to easily capture the problem.
> If no special reasons, I want to keep it for avoiding the complaint
> from our customer. 
> 
> Thanks
> James
> > 
> > > 
> > > Best regards,
> > > Lowry
> > > 
> > > > > +
> > > > >  	/* Notify the crtc to handle the events */
> > > > >  	for (i = 0; i < kms->n_crtcs; i++)
> > > > >  		komeda_crtc_handle_event(&kms->crtcs[i], &evts);
> > > > > -- 
> > > > > 1.9.1
> > > > > 
> > > > 
> > > > -- 
> > > > ====================
> > > > | I would like to |
> > > > | fix the world,  |
> > > > | but they're not |
> > > > | giving me the   |
> > > >  \ source code!  /
> > > >   ---------------
> > > >     ¯\_(ツ)_/¯
> > > 
> > > -- 
> > > Regards,
> > > Lowry
> > 
> > -- 
> > ====================
> > | I would like to |
> > | fix the world,  |
> > | but they're not |
> > | giving me the   |
> >  \ source code!  /
> >   ---------------
> >     ¯\_(ツ)_/¯

-- 
====================
| I would like to |
| fix the world,  |
| but they're not |
| giving me the   |
 \ source code!  /
  ---------------
    ¯\_(ツ)_/¯

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [PATCH] drm/komeda: Adds error event print functionality
  2019-07-22 16:18           ` Liviu Dudau
  (?)
@ 2019-07-23  7:37           ` Lowry Li (Arm Technology China)
  -1 siblings, 0 replies; 37+ messages in thread
From: Lowry Li (Arm Technology China) @ 2019-07-23  7:37 UTC (permalink / raw)
  To: Liviu Dudau
  Cc: nd, airlied, Jonathan Chai (Arm Technology China),
	linux-kernel, dri-devel, Julien Yin (Arm Technology China),
	seanpaul, james qian wang (Arm Technology China),
	Ayan Halder

On Mon, Jul 22, 2019 at 04:18:01PM +0000, Liviu Dudau wrote:
> On Mon, Jul 22, 2019 at 11:15:12AM +0000, james qian wang (Arm Technology China) wrote:
> > On Fri, Jul 19, 2019 at 11:40:11AM +0000, Liviu Dudau wrote:
> > > On Fri, Jul 19, 2019 at 09:09:30AM +0000, Lowry Li (Arm Technology China) wrote:
> > > > Hi Liviu,
> > > > 
> > > > On Thu, Jul 18, 2019 at 01:17:37PM +0000, Liviu Dudau wrote:
> > > > > On Thu, Jun 27, 2019 at 04:10:36AM +0100, Lowry Li (Arm Technology China) wrote:
> > > > > > Adds to print the event message when error happens and the same event
> > > > > > will not be printed until next vsync.
> > > > > > 
> > > > > > Signed-off-by: Lowry Li (Arm Technology China) <lowry.li@arm.com>
> > > > > > ---
> > > > > >  drivers/gpu/drm/arm/display/komeda/Makefile       |   1 +
> > > > > >  drivers/gpu/drm/arm/display/komeda/komeda_dev.h   |  13 ++
> > > > > >  drivers/gpu/drm/arm/display/komeda/komeda_event.c | 144 ++++++++++++++++++++++
> > > > > >  drivers/gpu/drm/arm/display/komeda/komeda_kms.c   |   2 +
> > > > > >  4 files changed, 160 insertions(+)
> > > > > >  create mode 100644 drivers/gpu/drm/arm/display/komeda/komeda_event.c
> > > > > > 
> > > > > > diff --git a/drivers/gpu/drm/arm/display/komeda/Makefile b/drivers/gpu/drm/arm/display/komeda/Makefile
> > > > > > index 38aa584..3f53d2d 100644
> > > > > > --- a/drivers/gpu/drm/arm/display/komeda/Makefile
> > > > > > +++ b/drivers/gpu/drm/arm/display/komeda/Makefile
> > > > > > @@ -7,6 +7,7 @@ ccflags-y := \
> > > > > >  komeda-y := \
> > > > > >  	komeda_drv.o \
> > > > > >  	komeda_dev.o \
> > > > > > +	komeda_event.o \
> > > > > >  	komeda_format_caps.o \
> > > > > >  	komeda_coeffs.o \
> > > > > >  	komeda_color_mgmt.o \
> > > > > > diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_dev.h b/drivers/gpu/drm/arm/display/komeda/komeda_dev.h
> > > > > > index 096f9f7..e863ec3 100644
> > > > > > --- a/drivers/gpu/drm/arm/display/komeda/komeda_dev.h
> > > > > > +++ b/drivers/gpu/drm/arm/display/komeda/komeda_dev.h
> > > > > > @@ -40,6 +40,17 @@
> > > > > >  #define KOMEDA_ERR_TTNG			BIT_ULL(30)
> > > > > >  #define KOMEDA_ERR_TTF			BIT_ULL(31)
> > > > > >  
> > > > > > +#define KOMEDA_ERR_EVENTS	\
> > > > > > +	(KOMEDA_EVENT_URUN	| KOMEDA_EVENT_IBSY	| KOMEDA_EVENT_OVR |\
> > > > > > +	KOMEDA_ERR_TETO		| KOMEDA_ERR_TEMR	| KOMEDA_ERR_TITR |\
> > > > > > +	KOMEDA_ERR_CPE		| KOMEDA_ERR_CFGE	| KOMEDA_ERR_AXIE |\
> > > > > > +	KOMEDA_ERR_ACE0		| KOMEDA_ERR_ACE1	| KOMEDA_ERR_ACE2 |\
> > > > > > +	KOMEDA_ERR_ACE3		| KOMEDA_ERR_DRIFTTO	| KOMEDA_ERR_FRAMETO |\
> > > > > > +	KOMEDA_ERR_ZME		| KOMEDA_ERR_MERR	| KOMEDA_ERR_TCF |\
> > > > > > +	KOMEDA_ERR_TTNG		| KOMEDA_ERR_TTF)
> > > > > > +
> > > > > > +#define KOMEDA_WARN_EVENTS	KOMEDA_ERR_CSCE
> > > > > > +
> > > > > >  /* malidp device id */
> > > > > >  enum {
> > > > > >  	MALI_D71 = 0,
> > > > > > @@ -207,6 +218,8 @@ struct komeda_dev {
> > > > > >  
> > > > > >  struct komeda_dev *dev_to_mdev(struct device *dev);
> > > > > >  
> > > > > > +void komeda_print_events(struct komeda_events *evts);
> > > > > > +
> > > > > >  int komeda_dev_resume(struct komeda_dev *mdev);
> > > > > >  int komeda_dev_suspend(struct komeda_dev *mdev);
> > > > > >  #endif /*_KOMEDA_DEV_H_*/
> > > > > > diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_event.c b/drivers/gpu/drm/arm/display/komeda/komeda_event.c
> > > > > > new file mode 100644
> > > > > > index 0000000..309dbe2
> > > > > > --- /dev/null
> > > > > > +++ b/drivers/gpu/drm/arm/display/komeda/komeda_event.c
> > > > > > @@ -0,0 +1,144 @@
> > > > > > +// SPDX-License-Identifier: GPL-2.0
> > > > > > +/*
> > > > > > + * (C) COPYRIGHT 2019 ARM Limited. All rights reserved.
> > > > > > + * Author: James.Qian.Wang <james.qian.wang@arm.com>
> > > > > > + *
> > > > > > + */
> > > > > > +#include <drm/drm_print.h>
> > > > > > +
> > > > > > +#include "komeda_dev.h"
> > > > > > +
> > > > > > +struct komeda_str {
> > > > > > +	char *str;
> > > > > > +	u32 sz;
> > > > > > +	u32 len;
> > > > > > +};
> > > > > > +
> > > > > > +/* return 0 on success,  < 0 on no space.
> > > > > > + */
> > > > > > +static int komeda_sprintf(struct komeda_str *str, const char *fmt, ...)
> > > > > > +{
> > > > > > +	va_list args;
> > > > > > +	int num, free_sz;
> > > > > > +	int err;
> > > > > > +
> > > > > > +	free_sz = str->sz - str->len;
> > > > > > +	if (free_sz <= 0)
> > > > > > +		return -ENOSPC;
> > > > > > +
> > > > > > +	va_start(args, fmt);
> > > > > > +
> > > > > > +	num = vsnprintf(str->str + str->len, free_sz, fmt, args);
> > > > > > +
> > > > > > +	va_end(args);
> > > > > > +
> > > > > > +	if (num <= free_sz) {
> > > > > > +		str->len += num;
> > > > > > +		err = 0;
> > > > > > +	} else {
> > > > > > +		str->len = str->sz;
> > > > > > +		err = -ENOSPC;
> > > > > > +	}
> > > > > > +
> > > > > > +	return err;
> > > > > > +}
> > > > > > +
> > > > > > +static void evt_sprintf(struct komeda_str *str, u64 evt, const char *msg)
> > > > > > +{
> > > > > > +	if (evt)
> > > > > > +		komeda_sprintf(str, msg);
> > > > > > +}
> > > > > 
> > > > > Why do we need this wrapper?
> > > > The komeda_sprintf is a generic function and will be used by other
> > > > places, while evt_sprintf is working for the detail event msg.
> > > 
> > > Yeah, I'm not buying this argument any more. We should not create new functions
> > > just because we want to save typing one if () condition. evt_sprintf does
> > > nothing with the extra evt argument other than checking that it is not zero.
> > 
> > Hi Liviu
> > 
> > But I think we'd better to have this function which can remove
> > many duplicate if () checks, and makes the code elegant and easy to
> > read. and I think that why the concept of function has been
> > introduced.
> > 
> > And in linux we can see lot of functions or MACRO that just for save one
> > word like:
> > 
> >   static inline void *kzalloc(size_t size, gfp_t flags)
> >   {
> > 	return kmalloc(size, flags | __GFP_ZERO);
> >   }
> 
> This is a different (and valid use) of creating macros. kzalloc() does
> something specific (initialises allocated memory with zeros) by using the
> generic kmalloc() function. The added __GFP_ZERO has a specific outcome to the
> invocation of the wrapped function. evt_sprintf() does nothing of this sort and
> it is arguably wrong, as it drops any possibility of passing arguments to the
> format string that komeda_sprintf() allows.

komeda_sprintf(struct komeda_str *str, const char *fmt, ...), will be
treated as a generic function, which may be called from other places,
with the possiblity support of passing arguments to the format string
of it.

evt_sprintf(struct komeda_str *str, u64 evt, const char *msg), is
a wrapper aim to to remove so many duplicate if() checks and make
the code elegant and easy to read.

About "drops any possibility of passing arguments to the format string
that komeda_sprintf() allows". In this wrapper, the 2nd parameter *msg
is already be set and no possible to be a format string, even it calls
komeda_sprintf, which supports passing arguments to the format string.

There are 27 places need check before calling into komeda_sprintf().
So I still think this wrapper is reasonable. It can make the code
elegant and easy to read. May I give another example:

void drm_property_blob_put(struct drm_property_blob *blob)
{
        if (!blob)
                return;

        drm_mode_object_put(&blob->base);
}

Best regards,
Lowry

> > 
> > And for this "if () check" specific, I think this is also very popular
> > in linux like:
> > 
> >   static inline void __rcu_read_lock(void)
> >   {
> >  	if (IS_ENABLED(CONFIG_PREEMPT_COUNT))
> > 		preempt_disable();
> >   }
> > 
> >   static inline void __rcu_read_unlock(void)
> >   {
> > 	if (IS_ENABLED(CONFIG_PREEMPT_COUNT))
> > 		preempt_enable();
> >   }
> 
> These are inline functions wrapping around the fact that a config option might
> be disabled. Not really the same thing with what we are talking here.
> 
> > 
> > thanks
> > James
> > 
> > > > 
> > > > > > +
> > > > > > +static void evt_str(struct komeda_str *str, u64 events)
> > > > > > +{
> > > > > > +	if (events == 0ULL) {
> > > > > > +		evt_sprintf(str, 1, "None");
> > > > > > +		return;
> > > > > > +	}
> > > > > > +
> > > > > > +	evt_sprintf(str, events & KOMEDA_EVENT_VSYNC, "VSYNC|");
> > > > > > +	evt_sprintf(str, events & KOMEDA_EVENT_FLIP, "FLIP|");
> > > > > > +	evt_sprintf(str, events & KOMEDA_EVENT_EOW, "EOW|");
> > > > > > +	evt_sprintf(str, events & KOMEDA_EVENT_MODE, "OP-MODE|");
> > > > > > +
> > > > > > +	evt_sprintf(str, events & KOMEDA_EVENT_URUN, "UNDERRUN|");
> > > > > > +	evt_sprintf(str, events & KOMEDA_EVENT_OVR, "OVERRUN|");
> > > > > > +
> > > > > > +	/* GLB error */
> > > > > > +	evt_sprintf(str, events & KOMEDA_ERR_MERR, "MERR|");
> > > > > > +	evt_sprintf(str, events & KOMEDA_ERR_FRAMETO, "FRAMETO|");
> > > > > > +
> > > > > > +	/* DOU error */
> > > > > > +	evt_sprintf(str, events & KOMEDA_ERR_DRIFTTO, "DRIFTTO|");
> > > > > > +	evt_sprintf(str, events & KOMEDA_ERR_FRAMETO, "FRAMETO|");
> > > > > > +	evt_sprintf(str, events & KOMEDA_ERR_TETO, "TETO|");
> > > > > > +	evt_sprintf(str, events & KOMEDA_ERR_CSCE, "CSCE|");
> > > > > > +
> > > > > > +	/* LPU errors or events */
> > > > > > +	evt_sprintf(str, events & KOMEDA_EVENT_IBSY, "IBSY|");
> > > > > > +	evt_sprintf(str, events & KOMEDA_ERR_AXIE, "AXIE|");
> > > > > > +	evt_sprintf(str, events & KOMEDA_ERR_ACE0, "ACE0|");
> > > > > > +	evt_sprintf(str, events & KOMEDA_ERR_ACE1, "ACE1|");
> > > > > > +	evt_sprintf(str, events & KOMEDA_ERR_ACE2, "ACE2|");
> > > > > > +	evt_sprintf(str, events & KOMEDA_ERR_ACE3, "ACE3|");
> > > > > > +
> > > > > > +	/* LPU TBU errors*/
> > > > > > +	evt_sprintf(str, events & KOMEDA_ERR_TCF, "TCF|");
> > > > > > +	evt_sprintf(str, events & KOMEDA_ERR_TTNG, "TTNG|");
> > > > > > +	evt_sprintf(str, events & KOMEDA_ERR_TITR, "TITR|");
> > > > > > +	evt_sprintf(str, events & KOMEDA_ERR_TEMR, "TEMR|");
> > > > > > +	evt_sprintf(str, events & KOMEDA_ERR_TTF, "TTF|");
> > > > > > +
> > > > > > +	/* CU errors*/
> > > > > > +	evt_sprintf(str, events & KOMEDA_ERR_CPE, "COPROC|");
> > > > > > +	evt_sprintf(str, events & KOMEDA_ERR_ZME, "ZME|");
> > > > > > +	evt_sprintf(str, events & KOMEDA_ERR_CFGE, "CFGE|");
> > > > > > +	evt_sprintf(str, events & KOMEDA_ERR_TEMR, "TEMR|");
> > > > > > +
> > > > > > +	if (str->len > 0 && (str->str[str->len - 1] == '|')) {
> > > > > > +		str->str[str->len - 1] = 0;
> > > > > > +		str->len--;
> > > > > > +	}
> > > > > > +}
> > > > > > +
> > > > > > +static bool is_new_frame(struct komeda_events *a)
> > > > > > +{
> > > > > > +	return (a->pipes[0] | a->pipes[1]) & KOMEDA_EVENT_FLIP;
> > > > > > +}
> > > > > > +
> > > > > > +void komeda_print_events(struct komeda_events *evts)
> > > > > > +{
> > > > > > +	u64 print_evts = KOMEDA_ERR_EVENTS;
> > > > > > +	static bool en_print = true;
> > > > > > +
> > > > > > +	/* reduce the same msg print, only print the first evt for one frame */
> > > > > > +	if (evts->global || is_new_frame(evts))
> > > > > > +		en_print = true;
> > > > > > +	if (!en_print)
> > > > > > +		return;
> > > > > 
> > > > > When does en_print ever get false?
> > > > Once the events printed, it will be set false (pls find at the last
> > > > line of this function).
> > > 
> > > What is the point of making en_print a static variable? We print all the time
> > > when we have a global event anyway.
> > 
> > Hi Liviu:
> > 
> > | why make en_print a static.
> > 
> > Consider you commit a scene which may leads a UNDERUN. and it will
> > trigger HW UNDERRUN in every vsync peroid untill this sceen have been
> > replace by another scene. for a scene it will trigger same error again
> > and again. we don't need print them all for a scene one msg is enough.
> 
> The same can be achieved by removing en_print entirely and inverting the top
> condition:
> 
> 	if (!evts->global && !is_new_frame(evts))
> 		return;

It looks better and will change to this. Thanks a lot for this.
> > 
> > | we print all the time when we have a global event.
> > Since we only reduce the duplicate error, but want print all different error.
> > And per our HW design, the event reported by different component.
> > this global for collect the GCU error. the pipeline_event is for
> > LPU/CU/DOU. like UNDERUN which is only DOU error.
> > 
> > and current GCU only have one error type: opmode change error which only
> > can be happened on when we call change_opmode in crtc_enable/disable.
> > 
> > So don't worry, globl event which can not make en_print has been set to
> > true in every irq handling.
> 
> And that's the reason I'm asking why make en_print static if we reset it in
> every irq_handling (i.e. when we actually want to print). Does it really need
> to be static when we don't actually use the stored state?
> 
> Best regards,
> Liviu
> 
> 
> > 
> > Thanks
> > James
> > 
> > > 
> > > > > > +
> > > > > > +#ifdef DEBUG
> > > > > > +	print_evts |= KOMEDA_WARN_EVENTS;
> > > > > > +#endif
> > > > > > +
> > > > > > +	if ((evts->global | evts->pipes[0] | evts->pipes[1]) & print_evts) {
> > > > > > +		#define STR_SZ		128
> > > > > > +		char msg[STR_SZ];
> > > > > 
> > > > > I've counted about 27 evt_sprintf() calls in evt_str() function, with an
> > > > > average of 5 characters each, so thats 135 characters printed into a buffer
> > > > > that is only 128 bytes. Please don't do this!
> > > > komeda_sprintf() will check the size and also I thought those evt
> > > > will not populat together. But yes, I'd better change this to 256.
> > > > Will change this.
> > > > 
> > > > > > +		struct komeda_str str;
> > > > > > +
> > > > > > +		str.str = msg;
> > > > > > +		str.sz  = STR_SZ;
> > > > > > +		str.len = 0;
> > > > > > +
> > > > > > +		komeda_sprintf(&str, "gcu: ");
> > > > > > +		evt_str(&str, evts->global);
> > > > > > +		komeda_sprintf(&str, ", pipes[0]: ");
> > > > > > +		evt_str(&str, evts->pipes[0]);
> > > > > > +		komeda_sprintf(&str, ", pipes[1]: ");
> > > > > > +		evt_str(&str, evts->pipes[1]);
> > > > > > +
> > > > > > +		DRM_ERROR("err detect: %s\n", msg);
> > > > > > +
> > > > > > +		en_print = false;
> > > > > > +	}
> > > > > > +}
> > > > > > diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_kms.c b/drivers/gpu/drm/arm/display/komeda/komeda_kms.c
> > > > > > index 647bce5..1462bac 100644
> > > > > > --- a/drivers/gpu/drm/arm/display/komeda/komeda_kms.c
> > > > > > +++ b/drivers/gpu/drm/arm/display/komeda/komeda_kms.c
> > > > > > @@ -47,6 +47,8 @@ static irqreturn_t komeda_kms_irq_handler(int irq, void *data)
> > > > > >  	memset(&evts, 0, sizeof(evts));
> > > > > >  	status = mdev->funcs->irq_handler(mdev, &evts);
> > > > > >  
> > > > > > +	komeda_print_events(&evts);
> > > > > 
> > > > > Calling this function from the IRQ handler is a bad idea. We should use debugfs
> > > > > if you really want to have a trace of the events, but I personally don't see
> > > > > value in having this functionality in the kernel at all. You can expose the
> > > > > value of the evts->global and evts->pipes[] as integers and decode that in
> > > > > userspace or as a debugfs entry.
> > > > > 
> > > > > Best regards,
> > > > > Liviu
> > > > 
> > > > The name of this function is misleading, but this is printing out the
> > > > hardware detected errors, from which we can know directly once the
> > > > errors happened on the hardware. Like if the driver code was at
> > > > bring-up stage, the logs from this layer is helpful. So can we keep
> > > > this?
> > > 
> > > We should probably just collect the global and pipes values and expose
> > > them to userspace so that the printing and decoding of the messages happens
> > > there.
> > > 
> > > Best regards,
> > > Liviu
> > 
> > Hi Liviu:
> > 
> > Any special resons.
> > 
> > Since such error print is not only wanted by us, mostly it is required
> > and used by our customer to easily capture the problem.
> > If no special reasons, I want to keep it for avoiding the complaint
> > from our customer. 
> > 
> > Thanks
> > James
> > > 
> > > > 
> > > > Best regards,
> > > > Lowry
> > > > 
> > > > > > +
> > > > > >  	/* Notify the crtc to handle the events */
> > > > > >  	for (i = 0; i < kms->n_crtcs; i++)
> > > > > >  		komeda_crtc_handle_event(&kms->crtcs[i], &evts);
> > > > > > -- 
> > > > > > 1.9.1
> > > > > > 
> > > > > 
> > > > > -- 
> > > > > ====================
> > > > > | I would like to |
> > > > > | fix the world,  |
> > > > > | but they're not |
> > > > > | giving me the   |
> > > > >  \ source code!  /
> > > > >   ---------------
> > > > >     ¯\_(ツ)_/¯
> > > > 
> > > > -- 
> > > > Regards,
> > > > Lowry
> > > 
> > > -- 
> > > ====================
> > > | I would like to |
> > > | fix the world,  |
> > > | but they're not |
> > > | giving me the   |
> > >  \ source code!  /
> > >   ---------------
> > >     ¯\_(ツ)_/¯
> 
> -- 
> ====================
> | I would like to |
> | fix the world,  |
> | but they're not |
> | giving me the   |
>  \ source code!  /
>   ---------------
>     ¯\_(ツ)_/¯

-- 
Regards,
Lowry
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [PATCH] drm/komeda: Adds error event print functionality
       [not found]           ` <20190723073623.GA32666@lowry.li@arm.com>
@ 2019-07-23  8:49               ` Liviu Dudau
  0 siblings, 0 replies; 37+ messages in thread
From: Liviu Dudau @ 2019-07-23  8:49 UTC (permalink / raw)
  To: Lowry Li (Arm Technology China)
  Cc: james qian wang (Arm Technology China),
	maarten.lankhorst, seanpaul, airlied, Brian Starkey,
	Julien Yin (Arm Technology China),
	Jonathan Chai (Arm Technology China),
	Ayan Halder, dri-devel, linux-kernel, nd

On Tue, Jul 23, 2019 at 07:37:42AM +0000, Lowry Li (Arm Technology China) wrote:
> On Mon, Jul 22, 2019 at 04:18:01PM +0000, Liviu Dudau wrote:
> > On Mon, Jul 22, 2019 at 11:15:12AM +0000, james qian wang (Arm Technology China) wrote:
> > > On Fri, Jul 19, 2019 at 11:40:11AM +0000, Liviu Dudau wrote:
> > > > On Fri, Jul 19, 2019 at 09:09:30AM +0000, Lowry Li (Arm Technology China) wrote:
> > > > > Hi Liviu,
> > > > > 
> > > > > On Thu, Jul 18, 2019 at 01:17:37PM +0000, Liviu Dudau wrote:
> > > > > > On Thu, Jun 27, 2019 at 04:10:36AM +0100, Lowry Li (Arm Technology China) wrote:
> > > > > > > Adds to print the event message when error happens and the same event
> > > > > > > will not be printed until next vsync.
> > > > > > > 
> > > > > > > Signed-off-by: Lowry Li (Arm Technology China) <lowry.li@arm.com>
> > > > > > > ---
> > > > > > >  drivers/gpu/drm/arm/display/komeda/Makefile       |   1 +
> > > > > > >  drivers/gpu/drm/arm/display/komeda/komeda_dev.h   |  13 ++
> > > > > > >  drivers/gpu/drm/arm/display/komeda/komeda_event.c | 144 ++++++++++++++++++++++
> > > > > > >  drivers/gpu/drm/arm/display/komeda/komeda_kms.c   |   2 +
> > > > > > >  4 files changed, 160 insertions(+)
> > > > > > >  create mode 100644 drivers/gpu/drm/arm/display/komeda/komeda_event.c
> > > > > > > 
> > > > > > > diff --git a/drivers/gpu/drm/arm/display/komeda/Makefile b/drivers/gpu/drm/arm/display/komeda/Makefile
> > > > > > > index 38aa584..3f53d2d 100644
> > > > > > > --- a/drivers/gpu/drm/arm/display/komeda/Makefile
> > > > > > > +++ b/drivers/gpu/drm/arm/display/komeda/Makefile
> > > > > > > @@ -7,6 +7,7 @@ ccflags-y := \
> > > > > > >  komeda-y := \
> > > > > > >  	komeda_drv.o \
> > > > > > >  	komeda_dev.o \
> > > > > > > +	komeda_event.o \
> > > > > > >  	komeda_format_caps.o \
> > > > > > >  	komeda_coeffs.o \
> > > > > > >  	komeda_color_mgmt.o \
> > > > > > > diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_dev.h b/drivers/gpu/drm/arm/display/komeda/komeda_dev.h
> > > > > > > index 096f9f7..e863ec3 100644
> > > > > > > --- a/drivers/gpu/drm/arm/display/komeda/komeda_dev.h
> > > > > > > +++ b/drivers/gpu/drm/arm/display/komeda/komeda_dev.h
> > > > > > > @@ -40,6 +40,17 @@
> > > > > > >  #define KOMEDA_ERR_TTNG			BIT_ULL(30)
> > > > > > >  #define KOMEDA_ERR_TTF			BIT_ULL(31)
> > > > > > >  
> > > > > > > +#define KOMEDA_ERR_EVENTS	\
> > > > > > > +	(KOMEDA_EVENT_URUN	| KOMEDA_EVENT_IBSY	| KOMEDA_EVENT_OVR |\
> > > > > > > +	KOMEDA_ERR_TETO		| KOMEDA_ERR_TEMR	| KOMEDA_ERR_TITR |\
> > > > > > > +	KOMEDA_ERR_CPE		| KOMEDA_ERR_CFGE	| KOMEDA_ERR_AXIE |\
> > > > > > > +	KOMEDA_ERR_ACE0		| KOMEDA_ERR_ACE1	| KOMEDA_ERR_ACE2 |\
> > > > > > > +	KOMEDA_ERR_ACE3		| KOMEDA_ERR_DRIFTTO	| KOMEDA_ERR_FRAMETO |\
> > > > > > > +	KOMEDA_ERR_ZME		| KOMEDA_ERR_MERR	| KOMEDA_ERR_TCF |\
> > > > > > > +	KOMEDA_ERR_TTNG		| KOMEDA_ERR_TTF)
> > > > > > > +
> > > > > > > +#define KOMEDA_WARN_EVENTS	KOMEDA_ERR_CSCE
> > > > > > > +
> > > > > > >  /* malidp device id */
> > > > > > >  enum {
> > > > > > >  	MALI_D71 = 0,
> > > > > > > @@ -207,6 +218,8 @@ struct komeda_dev {
> > > > > > >  
> > > > > > >  struct komeda_dev *dev_to_mdev(struct device *dev);
> > > > > > >  
> > > > > > > +void komeda_print_events(struct komeda_events *evts);
> > > > > > > +
> > > > > > >  int komeda_dev_resume(struct komeda_dev *mdev);
> > > > > > >  int komeda_dev_suspend(struct komeda_dev *mdev);
> > > > > > >  #endif /*_KOMEDA_DEV_H_*/
> > > > > > > diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_event.c b/drivers/gpu/drm/arm/display/komeda/komeda_event.c
> > > > > > > new file mode 100644
> > > > > > > index 0000000..309dbe2
> > > > > > > --- /dev/null
> > > > > > > +++ b/drivers/gpu/drm/arm/display/komeda/komeda_event.c
> > > > > > > @@ -0,0 +1,144 @@
> > > > > > > +// SPDX-License-Identifier: GPL-2.0
> > > > > > > +/*
> > > > > > > + * (C) COPYRIGHT 2019 ARM Limited. All rights reserved.
> > > > > > > + * Author: James.Qian.Wang <james.qian.wang@arm.com>
> > > > > > > + *
> > > > > > > + */
> > > > > > > +#include <drm/drm_print.h>
> > > > > > > +
> > > > > > > +#include "komeda_dev.h"
> > > > > > > +
> > > > > > > +struct komeda_str {
> > > > > > > +	char *str;
> > > > > > > +	u32 sz;
> > > > > > > +	u32 len;
> > > > > > > +};
> > > > > > > +
> > > > > > > +/* return 0 on success,  < 0 on no space.
> > > > > > > + */
> > > > > > > +static int komeda_sprintf(struct komeda_str *str, const char *fmt, ...)
> > > > > > > +{
> > > > > > > +	va_list args;
> > > > > > > +	int num, free_sz;
> > > > > > > +	int err;
> > > > > > > +
> > > > > > > +	free_sz = str->sz - str->len;
> > > > > > > +	if (free_sz <= 0)
> > > > > > > +		return -ENOSPC;
> > > > > > > +
> > > > > > > +	va_start(args, fmt);
> > > > > > > +
> > > > > > > +	num = vsnprintf(str->str + str->len, free_sz, fmt, args);
> > > > > > > +
> > > > > > > +	va_end(args);
> > > > > > > +
> > > > > > > +	if (num <= free_sz) {
> > > > > > > +		str->len += num;
> > > > > > > +		err = 0;
> > > > > > > +	} else {
> > > > > > > +		str->len = str->sz;
> > > > > > > +		err = -ENOSPC;
> > > > > > > +	}
> > > > > > > +
> > > > > > > +	return err;
> > > > > > > +}
> > > > > > > +
> > > > > > > +static void evt_sprintf(struct komeda_str *str, u64 evt, const char *msg)
> > > > > > > +{
> > > > > > > +	if (evt)
> > > > > > > +		komeda_sprintf(str, msg);
> > > > > > > +}
> > > > > > 
> > > > > > Why do we need this wrapper?
> > > > > The komeda_sprintf is a generic function and will be used by other
> > > > > places, while evt_sprintf is working for the detail event msg.
> > > > 
> > > > Yeah, I'm not buying this argument any more. We should not create new functions
> > > > just because we want to save typing one if () condition. evt_sprintf does
> > > > nothing with the extra evt argument other than checking that it is not zero.
> > > 
> > > Hi Liviu
> > > 
> > > But I think we'd better to have this function which can remove
> > > many duplicate if () checks, and makes the code elegant and easy to
> > > read. and I think that why the concept of function has been
> > > introduced.
> > > 
> > > And in linux we can see lot of functions or MACRO that just for save one
> > > word like:
> > > 
> > >   static inline void *kzalloc(size_t size, gfp_t flags)
> > >   {
> > > 	return kmalloc(size, flags | __GFP_ZERO);
> > >   }
> > 
> > This is a different (and valid use) of creating macros. kzalloc() does
> > something specific (initialises allocated memory with zeros) by using the
> > generic kmalloc() function. The added __GFP_ZERO has a specific outcome to the
> > invocation of the wrapped function. evt_sprintf() does nothing of this sort and
> > it is arguably wrong, as it drops any possibility of passing arguments to the
> > format string that komeda_sprintf() allows.
> 
> komeda_sprintf(struct komeda_str *str, const char *fmt, ...), will be
> treated as a generic function, which may be called from other places,
> with the possiblity support of passing arguments to the format string
> of it.
> 
> evt_sprintf(struct komeda_str *str, u64 evt, const char *msg), is
> a wrapper aim to to remove so many duplicate if() checks and make
> the code elegant and easy to read.
> 
> About "drops any possibility of passing arguments to the format string
> that komeda_sprintf() allows". In this wrapper, the 2nd parameter *msg
> is already be set and no possible to be a format string, even it calls
> komeda_sprintf, which supports passing arguments to the format string.

Should this not be documented above the function?

Anyway, I think we are getting side-tracked. My main argument is that we don't
need this function and evt_str() function *at all*. We should just expose the
events value into debugfs and let userspace decode the bit values.

> 
> There are 27 places need check before calling into komeda_sprintf().
> So I still think this wrapper is reasonable. It can make the code
> elegant and easy to read. May I give another example:

Those 27 calls are also made in an interrupt handler.

Best regards,
Liviu

> 
> void drm_property_blob_put(struct drm_property_blob *blob)
> {
>         if (!blob)
>                 return;
> 
>         drm_mode_object_put(&blob->base);
> }
> 
> Best regards,
> Lowry
> 
> > > 
> > > And for this "if () check" specific, I think this is also very popular
> > > in linux like:
> > > 
> > >   static inline void __rcu_read_lock(void)
> > >   {
> > >  	if (IS_ENABLED(CONFIG_PREEMPT_COUNT))
> > > 		preempt_disable();
> > >   }
> > > 
> > >   static inline void __rcu_read_unlock(void)
> > >   {
> > > 	if (IS_ENABLED(CONFIG_PREEMPT_COUNT))
> > > 		preempt_enable();
> > >   }
> > 
> > These are inline functions wrapping around the fact that a config option might
> > be disabled. Not really the same thing with what we are talking here.
> > 
> > > 
> > > thanks
> > > James
> > > 
> > > > > 
> > > > > > > +
> > > > > > > +static void evt_str(struct komeda_str *str, u64 events)
> > > > > > > +{
> > > > > > > +	if (events == 0ULL) {
> > > > > > > +		evt_sprintf(str, 1, "None");
> > > > > > > +		return;
> > > > > > > +	}
> > > > > > > +
> > > > > > > +	evt_sprintf(str, events & KOMEDA_EVENT_VSYNC, "VSYNC|");
> > > > > > > +	evt_sprintf(str, events & KOMEDA_EVENT_FLIP, "FLIP|");
> > > > > > > +	evt_sprintf(str, events & KOMEDA_EVENT_EOW, "EOW|");
> > > > > > > +	evt_sprintf(str, events & KOMEDA_EVENT_MODE, "OP-MODE|");
> > > > > > > +
> > > > > > > +	evt_sprintf(str, events & KOMEDA_EVENT_URUN, "UNDERRUN|");
> > > > > > > +	evt_sprintf(str, events & KOMEDA_EVENT_OVR, "OVERRUN|");
> > > > > > > +
> > > > > > > +	/* GLB error */
> > > > > > > +	evt_sprintf(str, events & KOMEDA_ERR_MERR, "MERR|");
> > > > > > > +	evt_sprintf(str, events & KOMEDA_ERR_FRAMETO, "FRAMETO|");
> > > > > > > +
> > > > > > > +	/* DOU error */
> > > > > > > +	evt_sprintf(str, events & KOMEDA_ERR_DRIFTTO, "DRIFTTO|");
> > > > > > > +	evt_sprintf(str, events & KOMEDA_ERR_FRAMETO, "FRAMETO|");
> > > > > > > +	evt_sprintf(str, events & KOMEDA_ERR_TETO, "TETO|");
> > > > > > > +	evt_sprintf(str, events & KOMEDA_ERR_CSCE, "CSCE|");
> > > > > > > +
> > > > > > > +	/* LPU errors or events */
> > > > > > > +	evt_sprintf(str, events & KOMEDA_EVENT_IBSY, "IBSY|");
> > > > > > > +	evt_sprintf(str, events & KOMEDA_ERR_AXIE, "AXIE|");
> > > > > > > +	evt_sprintf(str, events & KOMEDA_ERR_ACE0, "ACE0|");
> > > > > > > +	evt_sprintf(str, events & KOMEDA_ERR_ACE1, "ACE1|");
> > > > > > > +	evt_sprintf(str, events & KOMEDA_ERR_ACE2, "ACE2|");
> > > > > > > +	evt_sprintf(str, events & KOMEDA_ERR_ACE3, "ACE3|");
> > > > > > > +
> > > > > > > +	/* LPU TBU errors*/
> > > > > > > +	evt_sprintf(str, events & KOMEDA_ERR_TCF, "TCF|");
> > > > > > > +	evt_sprintf(str, events & KOMEDA_ERR_TTNG, "TTNG|");
> > > > > > > +	evt_sprintf(str, events & KOMEDA_ERR_TITR, "TITR|");
> > > > > > > +	evt_sprintf(str, events & KOMEDA_ERR_TEMR, "TEMR|");
> > > > > > > +	evt_sprintf(str, events & KOMEDA_ERR_TTF, "TTF|");
> > > > > > > +
> > > > > > > +	/* CU errors*/
> > > > > > > +	evt_sprintf(str, events & KOMEDA_ERR_CPE, "COPROC|");
> > > > > > > +	evt_sprintf(str, events & KOMEDA_ERR_ZME, "ZME|");
> > > > > > > +	evt_sprintf(str, events & KOMEDA_ERR_CFGE, "CFGE|");
> > > > > > > +	evt_sprintf(str, events & KOMEDA_ERR_TEMR, "TEMR|");
> > > > > > > +
> > > > > > > +	if (str->len > 0 && (str->str[str->len - 1] == '|')) {
> > > > > > > +		str->str[str->len - 1] = 0;
> > > > > > > +		str->len--;
> > > > > > > +	}
> > > > > > > +}
> > > > > > > +
> > > > > > > +static bool is_new_frame(struct komeda_events *a)
> > > > > > > +{
> > > > > > > +	return (a->pipes[0] | a->pipes[1]) & KOMEDA_EVENT_FLIP;
> > > > > > > +}
> > > > > > > +
> > > > > > > +void komeda_print_events(struct komeda_events *evts)
> > > > > > > +{
> > > > > > > +	u64 print_evts = KOMEDA_ERR_EVENTS;
> > > > > > > +	static bool en_print = true;
> > > > > > > +
> > > > > > > +	/* reduce the same msg print, only print the first evt for one frame */
> > > > > > > +	if (evts->global || is_new_frame(evts))
> > > > > > > +		en_print = true;
> > > > > > > +	if (!en_print)
> > > > > > > +		return;
> > > > > > 
> > > > > > When does en_print ever get false?
> > > > > Once the events printed, it will be set false (pls find at the last
> > > > > line of this function).
> > > > 
> > > > What is the point of making en_print a static variable? We print all the time
> > > > when we have a global event anyway.
> > > 
> > > Hi Liviu:
> > > 
> > > | why make en_print a static.
> > > 
> > > Consider you commit a scene which may leads a UNDERUN. and it will
> > > trigger HW UNDERRUN in every vsync peroid untill this sceen have been
> > > replace by another scene. for a scene it will trigger same error again
> > > and again. we don't need print them all for a scene one msg is enough.
> > 
> > The same can be achieved by removing en_print entirely and inverting the top
> > condition:
> > 
> > 	if (!evts->global && !is_new_frame(evts))
> > 		return;
> 
> It looks better and will change to this. Thanks a lot for this.
> > > 
> > > | we print all the time when we have a global event.
> > > Since we only reduce the duplicate error, but want print all different error.
> > > And per our HW design, the event reported by different component.
> > > this global for collect the GCU error. the pipeline_event is for
> > > LPU/CU/DOU. like UNDERUN which is only DOU error.
> > > 
> > > and current GCU only have one error type: opmode change error which only
> > > can be happened on when we call change_opmode in crtc_enable/disable.
> > > 
> > > So don't worry, globl event which can not make en_print has been set to
> > > true in every irq handling.
> > 
> > And that's the reason I'm asking why make en_print static if we reset it in
> > every irq_handling (i.e. when we actually want to print). Does it really need
> > to be static when we don't actually use the stored state?
> > 
> > Best regards,
> > Liviu
> > 
> > 
> > > 
> > > Thanks
> > > James
> > > 
> > > > 
> > > > > > > +
> > > > > > > +#ifdef DEBUG
> > > > > > > +	print_evts |= KOMEDA_WARN_EVENTS;
> > > > > > > +#endif
> > > > > > > +
> > > > > > > +	if ((evts->global | evts->pipes[0] | evts->pipes[1]) & print_evts) {
> > > > > > > +		#define STR_SZ		128
> > > > > > > +		char msg[STR_SZ];
> > > > > > 
> > > > > > I've counted about 27 evt_sprintf() calls in evt_str() function, with an
> > > > > > average of 5 characters each, so thats 135 characters printed into a buffer
> > > > > > that is only 128 bytes. Please don't do this!
> > > > > komeda_sprintf() will check the size and also I thought those evt
> > > > > will not populat together. But yes, I'd better change this to 256.
> > > > > Will change this.
> > > > > 
> > > > > > > +		struct komeda_str str;
> > > > > > > +
> > > > > > > +		str.str = msg;
> > > > > > > +		str.sz  = STR_SZ;
> > > > > > > +		str.len = 0;
> > > > > > > +
> > > > > > > +		komeda_sprintf(&str, "gcu: ");
> > > > > > > +		evt_str(&str, evts->global);
> > > > > > > +		komeda_sprintf(&str, ", pipes[0]: ");
> > > > > > > +		evt_str(&str, evts->pipes[0]);
> > > > > > > +		komeda_sprintf(&str, ", pipes[1]: ");
> > > > > > > +		evt_str(&str, evts->pipes[1]);
> > > > > > > +
> > > > > > > +		DRM_ERROR("err detect: %s\n", msg);
> > > > > > > +
> > > > > > > +		en_print = false;
> > > > > > > +	}
> > > > > > > +}
> > > > > > > diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_kms.c b/drivers/gpu/drm/arm/display/komeda/komeda_kms.c
> > > > > > > index 647bce5..1462bac 100644
> > > > > > > --- a/drivers/gpu/drm/arm/display/komeda/komeda_kms.c
> > > > > > > +++ b/drivers/gpu/drm/arm/display/komeda/komeda_kms.c
> > > > > > > @@ -47,6 +47,8 @@ static irqreturn_t komeda_kms_irq_handler(int irq, void *data)
> > > > > > >  	memset(&evts, 0, sizeof(evts));
> > > > > > >  	status = mdev->funcs->irq_handler(mdev, &evts);
> > > > > > >  
> > > > > > > +	komeda_print_events(&evts);
> > > > > > 
> > > > > > Calling this function from the IRQ handler is a bad idea. We should use debugfs
> > > > > > if you really want to have a trace of the events, but I personally don't see
> > > > > > value in having this functionality in the kernel at all. You can expose the
> > > > > > value of the evts->global and evts->pipes[] as integers and decode that in
> > > > > > userspace or as a debugfs entry.
> > > > > > 
> > > > > > Best regards,
> > > > > > Liviu
> > > > > 
> > > > > The name of this function is misleading, but this is printing out the
> > > > > hardware detected errors, from which we can know directly once the
> > > > > errors happened on the hardware. Like if the driver code was at
> > > > > bring-up stage, the logs from this layer is helpful. So can we keep
> > > > > this?
> > > > 
> > > > We should probably just collect the global and pipes values and expose
> > > > them to userspace so that the printing and decoding of the messages happens
> > > > there.
> > > > 
> > > > Best regards,
> > > > Liviu
> > > 
> > > Hi Liviu:
> > > 
> > > Any special resons.
> > > 
> > > Since such error print is not only wanted by us, mostly it is required
> > > and used by our customer to easily capture the problem.
> > > If no special reasons, I want to keep it for avoiding the complaint
> > > from our customer. 
> > > 
> > > Thanks
> > > James
> > > > 
> > > > > 
> > > > > Best regards,
> > > > > Lowry
> > > > > 
> > > > > > > +
> > > > > > >  	/* Notify the crtc to handle the events */
> > > > > > >  	for (i = 0; i < kms->n_crtcs; i++)
> > > > > > >  		komeda_crtc_handle_event(&kms->crtcs[i], &evts);
> > > > > > > -- 
> > > > > > > 1.9.1
> > > > > > > 
> > > > > > 
> > > > > > -- 
> > > > > > ====================
> > > > > > | I would like to |
> > > > > > | fix the world,  |
> > > > > > | but they're not |
> > > > > > | giving me the   |
> > > > > >  \ source code!  /
> > > > > >   ---------------
> > > > > >     ¯\_(ツ)_/¯
> > > > > 
> > > > > -- 
> > > > > Regards,
> > > > > Lowry
> > > > 
> > > > -- 
> > > > ====================
> > > > | I would like to |
> > > > | fix the world,  |
> > > > | but they're not |
> > > > | giving me the   |
> > > >  \ source code!  /
> > > >   ---------------
> > > >     ¯\_(ツ)_/¯
> > 
> > -- 
> > ====================
> > | I would like to |
> > | fix the world,  |
> > | but they're not |
> > | giving me the   |
> >  \ source code!  /
> >   ---------------
> >     ¯\_(ツ)_/¯
> 
> -- 
> Regards,
> Lowry

-- 
====================
| I would like to |
| fix the world,  |
| but they're not |
| giving me the   |
 \ source code!  /
  ---------------
    ¯\_(ツ)_/¯

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [PATCH] drm/komeda: Adds error event print functionality
@ 2019-07-23  8:49               ` Liviu Dudau
  0 siblings, 0 replies; 37+ messages in thread
From: Liviu Dudau @ 2019-07-23  8:49 UTC (permalink / raw)
  To: Lowry Li (Arm Technology China)
  Cc: nd, airlied, Jonathan Chai (Arm Technology China),
	linux-kernel, dri-devel, Julien Yin (Arm Technology China),
	seanpaul, james qian wang (Arm Technology China),
	Ayan Halder

On Tue, Jul 23, 2019 at 07:37:42AM +0000, Lowry Li (Arm Technology China) wrote:
> On Mon, Jul 22, 2019 at 04:18:01PM +0000, Liviu Dudau wrote:
> > On Mon, Jul 22, 2019 at 11:15:12AM +0000, james qian wang (Arm Technology China) wrote:
> > > On Fri, Jul 19, 2019 at 11:40:11AM +0000, Liviu Dudau wrote:
> > > > On Fri, Jul 19, 2019 at 09:09:30AM +0000, Lowry Li (Arm Technology China) wrote:
> > > > > Hi Liviu,
> > > > > 
> > > > > On Thu, Jul 18, 2019 at 01:17:37PM +0000, Liviu Dudau wrote:
> > > > > > On Thu, Jun 27, 2019 at 04:10:36AM +0100, Lowry Li (Arm Technology China) wrote:
> > > > > > > Adds to print the event message when error happens and the same event
> > > > > > > will not be printed until next vsync.
> > > > > > > 
> > > > > > > Signed-off-by: Lowry Li (Arm Technology China) <lowry.li@arm.com>
> > > > > > > ---
> > > > > > >  drivers/gpu/drm/arm/display/komeda/Makefile       |   1 +
> > > > > > >  drivers/gpu/drm/arm/display/komeda/komeda_dev.h   |  13 ++
> > > > > > >  drivers/gpu/drm/arm/display/komeda/komeda_event.c | 144 ++++++++++++++++++++++
> > > > > > >  drivers/gpu/drm/arm/display/komeda/komeda_kms.c   |   2 +
> > > > > > >  4 files changed, 160 insertions(+)
> > > > > > >  create mode 100644 drivers/gpu/drm/arm/display/komeda/komeda_event.c
> > > > > > > 
> > > > > > > diff --git a/drivers/gpu/drm/arm/display/komeda/Makefile b/drivers/gpu/drm/arm/display/komeda/Makefile
> > > > > > > index 38aa584..3f53d2d 100644
> > > > > > > --- a/drivers/gpu/drm/arm/display/komeda/Makefile
> > > > > > > +++ b/drivers/gpu/drm/arm/display/komeda/Makefile
> > > > > > > @@ -7,6 +7,7 @@ ccflags-y := \
> > > > > > >  komeda-y := \
> > > > > > >  	komeda_drv.o \
> > > > > > >  	komeda_dev.o \
> > > > > > > +	komeda_event.o \
> > > > > > >  	komeda_format_caps.o \
> > > > > > >  	komeda_coeffs.o \
> > > > > > >  	komeda_color_mgmt.o \
> > > > > > > diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_dev.h b/drivers/gpu/drm/arm/display/komeda/komeda_dev.h
> > > > > > > index 096f9f7..e863ec3 100644
> > > > > > > --- a/drivers/gpu/drm/arm/display/komeda/komeda_dev.h
> > > > > > > +++ b/drivers/gpu/drm/arm/display/komeda/komeda_dev.h
> > > > > > > @@ -40,6 +40,17 @@
> > > > > > >  #define KOMEDA_ERR_TTNG			BIT_ULL(30)
> > > > > > >  #define KOMEDA_ERR_TTF			BIT_ULL(31)
> > > > > > >  
> > > > > > > +#define KOMEDA_ERR_EVENTS	\
> > > > > > > +	(KOMEDA_EVENT_URUN	| KOMEDA_EVENT_IBSY	| KOMEDA_EVENT_OVR |\
> > > > > > > +	KOMEDA_ERR_TETO		| KOMEDA_ERR_TEMR	| KOMEDA_ERR_TITR |\
> > > > > > > +	KOMEDA_ERR_CPE		| KOMEDA_ERR_CFGE	| KOMEDA_ERR_AXIE |\
> > > > > > > +	KOMEDA_ERR_ACE0		| KOMEDA_ERR_ACE1	| KOMEDA_ERR_ACE2 |\
> > > > > > > +	KOMEDA_ERR_ACE3		| KOMEDA_ERR_DRIFTTO	| KOMEDA_ERR_FRAMETO |\
> > > > > > > +	KOMEDA_ERR_ZME		| KOMEDA_ERR_MERR	| KOMEDA_ERR_TCF |\
> > > > > > > +	KOMEDA_ERR_TTNG		| KOMEDA_ERR_TTF)
> > > > > > > +
> > > > > > > +#define KOMEDA_WARN_EVENTS	KOMEDA_ERR_CSCE
> > > > > > > +
> > > > > > >  /* malidp device id */
> > > > > > >  enum {
> > > > > > >  	MALI_D71 = 0,
> > > > > > > @@ -207,6 +218,8 @@ struct komeda_dev {
> > > > > > >  
> > > > > > >  struct komeda_dev *dev_to_mdev(struct device *dev);
> > > > > > >  
> > > > > > > +void komeda_print_events(struct komeda_events *evts);
> > > > > > > +
> > > > > > >  int komeda_dev_resume(struct komeda_dev *mdev);
> > > > > > >  int komeda_dev_suspend(struct komeda_dev *mdev);
> > > > > > >  #endif /*_KOMEDA_DEV_H_*/
> > > > > > > diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_event.c b/drivers/gpu/drm/arm/display/komeda/komeda_event.c
> > > > > > > new file mode 100644
> > > > > > > index 0000000..309dbe2
> > > > > > > --- /dev/null
> > > > > > > +++ b/drivers/gpu/drm/arm/display/komeda/komeda_event.c
> > > > > > > @@ -0,0 +1,144 @@
> > > > > > > +// SPDX-License-Identifier: GPL-2.0
> > > > > > > +/*
> > > > > > > + * (C) COPYRIGHT 2019 ARM Limited. All rights reserved.
> > > > > > > + * Author: James.Qian.Wang <james.qian.wang@arm.com>
> > > > > > > + *
> > > > > > > + */
> > > > > > > +#include <drm/drm_print.h>
> > > > > > > +
> > > > > > > +#include "komeda_dev.h"
> > > > > > > +
> > > > > > > +struct komeda_str {
> > > > > > > +	char *str;
> > > > > > > +	u32 sz;
> > > > > > > +	u32 len;
> > > > > > > +};
> > > > > > > +
> > > > > > > +/* return 0 on success,  < 0 on no space.
> > > > > > > + */
> > > > > > > +static int komeda_sprintf(struct komeda_str *str, const char *fmt, ...)
> > > > > > > +{
> > > > > > > +	va_list args;
> > > > > > > +	int num, free_sz;
> > > > > > > +	int err;
> > > > > > > +
> > > > > > > +	free_sz = str->sz - str->len;
> > > > > > > +	if (free_sz <= 0)
> > > > > > > +		return -ENOSPC;
> > > > > > > +
> > > > > > > +	va_start(args, fmt);
> > > > > > > +
> > > > > > > +	num = vsnprintf(str->str + str->len, free_sz, fmt, args);
> > > > > > > +
> > > > > > > +	va_end(args);
> > > > > > > +
> > > > > > > +	if (num <= free_sz) {
> > > > > > > +		str->len += num;
> > > > > > > +		err = 0;
> > > > > > > +	} else {
> > > > > > > +		str->len = str->sz;
> > > > > > > +		err = -ENOSPC;
> > > > > > > +	}
> > > > > > > +
> > > > > > > +	return err;
> > > > > > > +}
> > > > > > > +
> > > > > > > +static void evt_sprintf(struct komeda_str *str, u64 evt, const char *msg)
> > > > > > > +{
> > > > > > > +	if (evt)
> > > > > > > +		komeda_sprintf(str, msg);
> > > > > > > +}
> > > > > > 
> > > > > > Why do we need this wrapper?
> > > > > The komeda_sprintf is a generic function and will be used by other
> > > > > places, while evt_sprintf is working for the detail event msg.
> > > > 
> > > > Yeah, I'm not buying this argument any more. We should not create new functions
> > > > just because we want to save typing one if () condition. evt_sprintf does
> > > > nothing with the extra evt argument other than checking that it is not zero.
> > > 
> > > Hi Liviu
> > > 
> > > But I think we'd better to have this function which can remove
> > > many duplicate if () checks, and makes the code elegant and easy to
> > > read. and I think that why the concept of function has been
> > > introduced.
> > > 
> > > And in linux we can see lot of functions or MACRO that just for save one
> > > word like:
> > > 
> > >   static inline void *kzalloc(size_t size, gfp_t flags)
> > >   {
> > > 	return kmalloc(size, flags | __GFP_ZERO);
> > >   }
> > 
> > This is a different (and valid use) of creating macros. kzalloc() does
> > something specific (initialises allocated memory with zeros) by using the
> > generic kmalloc() function. The added __GFP_ZERO has a specific outcome to the
> > invocation of the wrapped function. evt_sprintf() does nothing of this sort and
> > it is arguably wrong, as it drops any possibility of passing arguments to the
> > format string that komeda_sprintf() allows.
> 
> komeda_sprintf(struct komeda_str *str, const char *fmt, ...), will be
> treated as a generic function, which may be called from other places,
> with the possiblity support of passing arguments to the format string
> of it.
> 
> evt_sprintf(struct komeda_str *str, u64 evt, const char *msg), is
> a wrapper aim to to remove so many duplicate if() checks and make
> the code elegant and easy to read.
> 
> About "drops any possibility of passing arguments to the format string
> that komeda_sprintf() allows". In this wrapper, the 2nd parameter *msg
> is already be set and no possible to be a format string, even it calls
> komeda_sprintf, which supports passing arguments to the format string.

Should this not be documented above the function?

Anyway, I think we are getting side-tracked. My main argument is that we don't
need this function and evt_str() function *at all*. We should just expose the
events value into debugfs and let userspace decode the bit values.

> 
> There are 27 places need check before calling into komeda_sprintf().
> So I still think this wrapper is reasonable. It can make the code
> elegant and easy to read. May I give another example:

Those 27 calls are also made in an interrupt handler.

Best regards,
Liviu

> 
> void drm_property_blob_put(struct drm_property_blob *blob)
> {
>         if (!blob)
>                 return;
> 
>         drm_mode_object_put(&blob->base);
> }
> 
> Best regards,
> Lowry
> 
> > > 
> > > And for this "if () check" specific, I think this is also very popular
> > > in linux like:
> > > 
> > >   static inline void __rcu_read_lock(void)
> > >   {
> > >  	if (IS_ENABLED(CONFIG_PREEMPT_COUNT))
> > > 		preempt_disable();
> > >   }
> > > 
> > >   static inline void __rcu_read_unlock(void)
> > >   {
> > > 	if (IS_ENABLED(CONFIG_PREEMPT_COUNT))
> > > 		preempt_enable();
> > >   }
> > 
> > These are inline functions wrapping around the fact that a config option might
> > be disabled. Not really the same thing with what we are talking here.
> > 
> > > 
> > > thanks
> > > James
> > > 
> > > > > 
> > > > > > > +
> > > > > > > +static void evt_str(struct komeda_str *str, u64 events)
> > > > > > > +{
> > > > > > > +	if (events == 0ULL) {
> > > > > > > +		evt_sprintf(str, 1, "None");
> > > > > > > +		return;
> > > > > > > +	}
> > > > > > > +
> > > > > > > +	evt_sprintf(str, events & KOMEDA_EVENT_VSYNC, "VSYNC|");
> > > > > > > +	evt_sprintf(str, events & KOMEDA_EVENT_FLIP, "FLIP|");
> > > > > > > +	evt_sprintf(str, events & KOMEDA_EVENT_EOW, "EOW|");
> > > > > > > +	evt_sprintf(str, events & KOMEDA_EVENT_MODE, "OP-MODE|");
> > > > > > > +
> > > > > > > +	evt_sprintf(str, events & KOMEDA_EVENT_URUN, "UNDERRUN|");
> > > > > > > +	evt_sprintf(str, events & KOMEDA_EVENT_OVR, "OVERRUN|");
> > > > > > > +
> > > > > > > +	/* GLB error */
> > > > > > > +	evt_sprintf(str, events & KOMEDA_ERR_MERR, "MERR|");
> > > > > > > +	evt_sprintf(str, events & KOMEDA_ERR_FRAMETO, "FRAMETO|");
> > > > > > > +
> > > > > > > +	/* DOU error */
> > > > > > > +	evt_sprintf(str, events & KOMEDA_ERR_DRIFTTO, "DRIFTTO|");
> > > > > > > +	evt_sprintf(str, events & KOMEDA_ERR_FRAMETO, "FRAMETO|");
> > > > > > > +	evt_sprintf(str, events & KOMEDA_ERR_TETO, "TETO|");
> > > > > > > +	evt_sprintf(str, events & KOMEDA_ERR_CSCE, "CSCE|");
> > > > > > > +
> > > > > > > +	/* LPU errors or events */
> > > > > > > +	evt_sprintf(str, events & KOMEDA_EVENT_IBSY, "IBSY|");
> > > > > > > +	evt_sprintf(str, events & KOMEDA_ERR_AXIE, "AXIE|");
> > > > > > > +	evt_sprintf(str, events & KOMEDA_ERR_ACE0, "ACE0|");
> > > > > > > +	evt_sprintf(str, events & KOMEDA_ERR_ACE1, "ACE1|");
> > > > > > > +	evt_sprintf(str, events & KOMEDA_ERR_ACE2, "ACE2|");
> > > > > > > +	evt_sprintf(str, events & KOMEDA_ERR_ACE3, "ACE3|");
> > > > > > > +
> > > > > > > +	/* LPU TBU errors*/
> > > > > > > +	evt_sprintf(str, events & KOMEDA_ERR_TCF, "TCF|");
> > > > > > > +	evt_sprintf(str, events & KOMEDA_ERR_TTNG, "TTNG|");
> > > > > > > +	evt_sprintf(str, events & KOMEDA_ERR_TITR, "TITR|");
> > > > > > > +	evt_sprintf(str, events & KOMEDA_ERR_TEMR, "TEMR|");
> > > > > > > +	evt_sprintf(str, events & KOMEDA_ERR_TTF, "TTF|");
> > > > > > > +
> > > > > > > +	/* CU errors*/
> > > > > > > +	evt_sprintf(str, events & KOMEDA_ERR_CPE, "COPROC|");
> > > > > > > +	evt_sprintf(str, events & KOMEDA_ERR_ZME, "ZME|");
> > > > > > > +	evt_sprintf(str, events & KOMEDA_ERR_CFGE, "CFGE|");
> > > > > > > +	evt_sprintf(str, events & KOMEDA_ERR_TEMR, "TEMR|");
> > > > > > > +
> > > > > > > +	if (str->len > 0 && (str->str[str->len - 1] == '|')) {
> > > > > > > +		str->str[str->len - 1] = 0;
> > > > > > > +		str->len--;
> > > > > > > +	}
> > > > > > > +}
> > > > > > > +
> > > > > > > +static bool is_new_frame(struct komeda_events *a)
> > > > > > > +{
> > > > > > > +	return (a->pipes[0] | a->pipes[1]) & KOMEDA_EVENT_FLIP;
> > > > > > > +}
> > > > > > > +
> > > > > > > +void komeda_print_events(struct komeda_events *evts)
> > > > > > > +{
> > > > > > > +	u64 print_evts = KOMEDA_ERR_EVENTS;
> > > > > > > +	static bool en_print = true;
> > > > > > > +
> > > > > > > +	/* reduce the same msg print, only print the first evt for one frame */
> > > > > > > +	if (evts->global || is_new_frame(evts))
> > > > > > > +		en_print = true;
> > > > > > > +	if (!en_print)
> > > > > > > +		return;
> > > > > > 
> > > > > > When does en_print ever get false?
> > > > > Once the events printed, it will be set false (pls find at the last
> > > > > line of this function).
> > > > 
> > > > What is the point of making en_print a static variable? We print all the time
> > > > when we have a global event anyway.
> > > 
> > > Hi Liviu:
> > > 
> > > | why make en_print a static.
> > > 
> > > Consider you commit a scene which may leads a UNDERUN. and it will
> > > trigger HW UNDERRUN in every vsync peroid untill this sceen have been
> > > replace by another scene. for a scene it will trigger same error again
> > > and again. we don't need print them all for a scene one msg is enough.
> > 
> > The same can be achieved by removing en_print entirely and inverting the top
> > condition:
> > 
> > 	if (!evts->global && !is_new_frame(evts))
> > 		return;
> 
> It looks better and will change to this. Thanks a lot for this.
> > > 
> > > | we print all the time when we have a global event.
> > > Since we only reduce the duplicate error, but want print all different error.
> > > And per our HW design, the event reported by different component.
> > > this global for collect the GCU error. the pipeline_event is for
> > > LPU/CU/DOU. like UNDERUN which is only DOU error.
> > > 
> > > and current GCU only have one error type: opmode change error which only
> > > can be happened on when we call change_opmode in crtc_enable/disable.
> > > 
> > > So don't worry, globl event which can not make en_print has been set to
> > > true in every irq handling.
> > 
> > And that's the reason I'm asking why make en_print static if we reset it in
> > every irq_handling (i.e. when we actually want to print). Does it really need
> > to be static when we don't actually use the stored state?
> > 
> > Best regards,
> > Liviu
> > 
> > 
> > > 
> > > Thanks
> > > James
> > > 
> > > > 
> > > > > > > +
> > > > > > > +#ifdef DEBUG
> > > > > > > +	print_evts |= KOMEDA_WARN_EVENTS;
> > > > > > > +#endif
> > > > > > > +
> > > > > > > +	if ((evts->global | evts->pipes[0] | evts->pipes[1]) & print_evts) {
> > > > > > > +		#define STR_SZ		128
> > > > > > > +		char msg[STR_SZ];
> > > > > > 
> > > > > > I've counted about 27 evt_sprintf() calls in evt_str() function, with an
> > > > > > average of 5 characters each, so thats 135 characters printed into a buffer
> > > > > > that is only 128 bytes. Please don't do this!
> > > > > komeda_sprintf() will check the size and also I thought those evt
> > > > > will not populat together. But yes, I'd better change this to 256.
> > > > > Will change this.
> > > > > 
> > > > > > > +		struct komeda_str str;
> > > > > > > +
> > > > > > > +		str.str = msg;
> > > > > > > +		str.sz  = STR_SZ;
> > > > > > > +		str.len = 0;
> > > > > > > +
> > > > > > > +		komeda_sprintf(&str, "gcu: ");
> > > > > > > +		evt_str(&str, evts->global);
> > > > > > > +		komeda_sprintf(&str, ", pipes[0]: ");
> > > > > > > +		evt_str(&str, evts->pipes[0]);
> > > > > > > +		komeda_sprintf(&str, ", pipes[1]: ");
> > > > > > > +		evt_str(&str, evts->pipes[1]);
> > > > > > > +
> > > > > > > +		DRM_ERROR("err detect: %s\n", msg);
> > > > > > > +
> > > > > > > +		en_print = false;
> > > > > > > +	}
> > > > > > > +}
> > > > > > > diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_kms.c b/drivers/gpu/drm/arm/display/komeda/komeda_kms.c
> > > > > > > index 647bce5..1462bac 100644
> > > > > > > --- a/drivers/gpu/drm/arm/display/komeda/komeda_kms.c
> > > > > > > +++ b/drivers/gpu/drm/arm/display/komeda/komeda_kms.c
> > > > > > > @@ -47,6 +47,8 @@ static irqreturn_t komeda_kms_irq_handler(int irq, void *data)
> > > > > > >  	memset(&evts, 0, sizeof(evts));
> > > > > > >  	status = mdev->funcs->irq_handler(mdev, &evts);
> > > > > > >  
> > > > > > > +	komeda_print_events(&evts);
> > > > > > 
> > > > > > Calling this function from the IRQ handler is a bad idea. We should use debugfs
> > > > > > if you really want to have a trace of the events, but I personally don't see
> > > > > > value in having this functionality in the kernel at all. You can expose the
> > > > > > value of the evts->global and evts->pipes[] as integers and decode that in
> > > > > > userspace or as a debugfs entry.
> > > > > > 
> > > > > > Best regards,
> > > > > > Liviu
> > > > > 
> > > > > The name of this function is misleading, but this is printing out the
> > > > > hardware detected errors, from which we can know directly once the
> > > > > errors happened on the hardware. Like if the driver code was at
> > > > > bring-up stage, the logs from this layer is helpful. So can we keep
> > > > > this?
> > > > 
> > > > We should probably just collect the global and pipes values and expose
> > > > them to userspace so that the printing and decoding of the messages happens
> > > > there.
> > > > 
> > > > Best regards,
> > > > Liviu
> > > 
> > > Hi Liviu:
> > > 
> > > Any special resons.
> > > 
> > > Since such error print is not only wanted by us, mostly it is required
> > > and used by our customer to easily capture the problem.
> > > If no special reasons, I want to keep it for avoiding the complaint
> > > from our customer. 
> > > 
> > > Thanks
> > > James
> > > > 
> > > > > 
> > > > > Best regards,
> > > > > Lowry
> > > > > 
> > > > > > > +
> > > > > > >  	/* Notify the crtc to handle the events */
> > > > > > >  	for (i = 0; i < kms->n_crtcs; i++)
> > > > > > >  		komeda_crtc_handle_event(&kms->crtcs[i], &evts);
> > > > > > > -- 
> > > > > > > 1.9.1
> > > > > > > 
> > > > > > 
> > > > > > -- 
> > > > > > ====================
> > > > > > | I would like to |
> > > > > > | fix the world,  |
> > > > > > | but they're not |
> > > > > > | giving me the   |
> > > > > >  \ source code!  /
> > > > > >   ---------------
> > > > > >     ¯\_(ツ)_/¯
> > > > > 
> > > > > -- 
> > > > > Regards,
> > > > > Lowry
> > > > 
> > > > -- 
> > > > ====================
> > > > | I would like to |
> > > > | fix the world,  |
> > > > | but they're not |
> > > > | giving me the   |
> > > >  \ source code!  /
> > > >   ---------------
> > > >     ¯\_(ツ)_/¯
> > 
> > -- 
> > ====================
> > | I would like to |
> > | fix the world,  |
> > | but they're not |
> > | giving me the   |
> >  \ source code!  /
> >   ---------------
> >     ¯\_(ツ)_/¯
> 
> -- 
> Regards,
> Lowry

-- 
====================
| I would like to |
| fix the world,  |
| but they're not |
| giving me the   |
 \ source code!  /
  ---------------
    ¯\_(ツ)_/¯
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [PATCH] drm/komeda: Adds error event print functionality
  2019-07-23  8:49               ` Liviu Dudau
  (?)
@ 2019-07-26  3:27               ` Lowry Li (Arm Technology China)
  -1 siblings, 0 replies; 37+ messages in thread
From: Lowry Li (Arm Technology China) @ 2019-07-26  3:27 UTC (permalink / raw)
  To: Liviu Dudau
  Cc: nd, airlied, Jonathan Chai (Arm Technology China),
	linux-kernel, dri-devel, Julien Yin (Arm Technology China),
	seanpaul, james qian wang (Arm Technology China),
	Ayan Halder

On Tue, Jul 23, 2019 at 08:49:11AM +0000, Liviu Dudau wrote:
> On Tue, Jul 23, 2019 at 07:37:42AM +0000, Lowry Li (Arm Technology China) wrote:
> > On Mon, Jul 22, 2019 at 04:18:01PM +0000, Liviu Dudau wrote:
> > > On Mon, Jul 22, 2019 at 11:15:12AM +0000, james qian wang (Arm Technology China) wrote:
> > > > On Fri, Jul 19, 2019 at 11:40:11AM +0000, Liviu Dudau wrote:
> > > > > On Fri, Jul 19, 2019 at 09:09:30AM +0000, Lowry Li (Arm Technology China) wrote:
> > > > > > Hi Liviu,
> > > > > > 
> > > > > > On Thu, Jul 18, 2019 at 01:17:37PM +0000, Liviu Dudau wrote:
> > > > > > > On Thu, Jun 27, 2019 at 04:10:36AM +0100, Lowry Li (Arm Technology China) wrote:
> > > > > > > > Adds to print the event message when error happens and the same event
> > > > > > > > will not be printed until next vsync.
> > > > > > > > 
> > > > > > > > Signed-off-by: Lowry Li (Arm Technology China) <lowry.li@arm.com>
> > > > > > > > ---
> > > > > > > >  drivers/gpu/drm/arm/display/komeda/Makefile       |   1 +
> > > > > > > >  drivers/gpu/drm/arm/display/komeda/komeda_dev.h   |  13 ++
> > > > > > > >  drivers/gpu/drm/arm/display/komeda/komeda_event.c | 144 ++++++++++++++++++++++
> > > > > > > >  drivers/gpu/drm/arm/display/komeda/komeda_kms.c   |   2 +
> > > > > > > >  4 files changed, 160 insertions(+)
> > > > > > > >  create mode 100644 drivers/gpu/drm/arm/display/komeda/komeda_event.c
> > > > > > > > 
> > > > > > > > diff --git a/drivers/gpu/drm/arm/display/komeda/Makefile b/drivers/gpu/drm/arm/display/komeda/Makefile
> > > > > > > > index 38aa584..3f53d2d 100644
> > > > > > > > --- a/drivers/gpu/drm/arm/display/komeda/Makefile
> > > > > > > > +++ b/drivers/gpu/drm/arm/display/komeda/Makefile
> > > > > > > > @@ -7,6 +7,7 @@ ccflags-y := \
> > > > > > > >  komeda-y := \
> > > > > > > >  	komeda_drv.o \
> > > > > > > >  	komeda_dev.o \
> > > > > > > > +	komeda_event.o \
> > > > > > > >  	komeda_format_caps.o \
> > > > > > > >  	komeda_coeffs.o \
> > > > > > > >  	komeda_color_mgmt.o \
> > > > > > > > diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_dev.h b/drivers/gpu/drm/arm/display/komeda/komeda_dev.h
> > > > > > > > index 096f9f7..e863ec3 100644
> > > > > > > > --- a/drivers/gpu/drm/arm/display/komeda/komeda_dev.h
> > > > > > > > +++ b/drivers/gpu/drm/arm/display/komeda/komeda_dev.h
> > > > > > > > @@ -40,6 +40,17 @@
> > > > > > > >  #define KOMEDA_ERR_TTNG			BIT_ULL(30)
> > > > > > > >  #define KOMEDA_ERR_TTF			BIT_ULL(31)
> > > > > > > >  
> > > > > > > > +#define KOMEDA_ERR_EVENTS	\
> > > > > > > > +	(KOMEDA_EVENT_URUN	| KOMEDA_EVENT_IBSY	| KOMEDA_EVENT_OVR |\
> > > > > > > > +	KOMEDA_ERR_TETO		| KOMEDA_ERR_TEMR	| KOMEDA_ERR_TITR |\
> > > > > > > > +	KOMEDA_ERR_CPE		| KOMEDA_ERR_CFGE	| KOMEDA_ERR_AXIE |\
> > > > > > > > +	KOMEDA_ERR_ACE0		| KOMEDA_ERR_ACE1	| KOMEDA_ERR_ACE2 |\
> > > > > > > > +	KOMEDA_ERR_ACE3		| KOMEDA_ERR_DRIFTTO	| KOMEDA_ERR_FRAMETO |\
> > > > > > > > +	KOMEDA_ERR_ZME		| KOMEDA_ERR_MERR	| KOMEDA_ERR_TCF |\
> > > > > > > > +	KOMEDA_ERR_TTNG		| KOMEDA_ERR_TTF)
> > > > > > > > +
> > > > > > > > +#define KOMEDA_WARN_EVENTS	KOMEDA_ERR_CSCE
> > > > > > > > +
> > > > > > > >  /* malidp device id */
> > > > > > > >  enum {
> > > > > > > >  	MALI_D71 = 0,
> > > > > > > > @@ -207,6 +218,8 @@ struct komeda_dev {
> > > > > > > >  
> > > > > > > >  struct komeda_dev *dev_to_mdev(struct device *dev);
> > > > > > > >  
> > > > > > > > +void komeda_print_events(struct komeda_events *evts);
> > > > > > > > +
> > > > > > > >  int komeda_dev_resume(struct komeda_dev *mdev);
> > > > > > > >  int komeda_dev_suspend(struct komeda_dev *mdev);
> > > > > > > >  #endif /*_KOMEDA_DEV_H_*/
> > > > > > > > diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_event.c b/drivers/gpu/drm/arm/display/komeda/komeda_event.c
> > > > > > > > new file mode 100644
> > > > > > > > index 0000000..309dbe2
> > > > > > > > --- /dev/null
> > > > > > > > +++ b/drivers/gpu/drm/arm/display/komeda/komeda_event.c
> > > > > > > > @@ -0,0 +1,144 @@
> > > > > > > > +// SPDX-License-Identifier: GPL-2.0
> > > > > > > > +/*
> > > > > > > > + * (C) COPYRIGHT 2019 ARM Limited. All rights reserved.
> > > > > > > > + * Author: James.Qian.Wang <james.qian.wang@arm.com>
> > > > > > > > + *
> > > > > > > > + */
> > > > > > > > +#include <drm/drm_print.h>
> > > > > > > > +
> > > > > > > > +#include "komeda_dev.h"
> > > > > > > > +
> > > > > > > > +struct komeda_str {
> > > > > > > > +	char *str;
> > > > > > > > +	u32 sz;
> > > > > > > > +	u32 len;
> > > > > > > > +};
> > > > > > > > +
> > > > > > > > +/* return 0 on success,  < 0 on no space.
> > > > > > > > + */
> > > > > > > > +static int komeda_sprintf(struct komeda_str *str, const char *fmt, ...)
> > > > > > > > +{
> > > > > > > > +	va_list args;
> > > > > > > > +	int num, free_sz;
> > > > > > > > +	int err;
> > > > > > > > +
> > > > > > > > +	free_sz = str->sz - str->len;
> > > > > > > > +	if (free_sz <= 0)
> > > > > > > > +		return -ENOSPC;
> > > > > > > > +
> > > > > > > > +	va_start(args, fmt);
> > > > > > > > +
> > > > > > > > +	num = vsnprintf(str->str + str->len, free_sz, fmt, args);
> > > > > > > > +
> > > > > > > > +	va_end(args);
> > > > > > > > +
> > > > > > > > +	if (num <= free_sz) {
> > > > > > > > +		str->len += num;
> > > > > > > > +		err = 0;
> > > > > > > > +	} else {
> > > > > > > > +		str->len = str->sz;
> > > > > > > > +		err = -ENOSPC;
> > > > > > > > +	}
> > > > > > > > +
> > > > > > > > +	return err;
> > > > > > > > +}
> > > > > > > > +
> > > > > > > > +static void evt_sprintf(struct komeda_str *str, u64 evt, const char *msg)
> > > > > > > > +{
> > > > > > > > +	if (evt)
> > > > > > > > +		komeda_sprintf(str, msg);
> > > > > > > > +}
> > > > > > > 
> > > > > > > Why do we need this wrapper?
> > > > > > The komeda_sprintf is a generic function and will be used by other
> > > > > > places, while evt_sprintf is working for the detail event msg.
> > > > > 
> > > > > Yeah, I'm not buying this argument any more. We should not create new functions
> > > > > just because we want to save typing one if () condition. evt_sprintf does
> > > > > nothing with the extra evt argument other than checking that it is not zero.
> > > > 
> > > > Hi Liviu
> > > > 
> > > > But I think we'd better to have this function which can remove
> > > > many duplicate if () checks, and makes the code elegant and easy to
> > > > read. and I think that why the concept of function has been
> > > > introduced.
> > > > 
> > > > And in linux we can see lot of functions or MACRO that just for save one
> > > > word like:
> > > > 
> > > >   static inline void *kzalloc(size_t size, gfp_t flags)
> > > >   {
> > > > 	return kmalloc(size, flags | __GFP_ZERO);
> > > >   }
> > > 
> > > This is a different (and valid use) of creating macros. kzalloc() does
> > > something specific (initialises allocated memory with zeros) by using the
> > > generic kmalloc() function. The added __GFP_ZERO has a specific outcome to the
> > > invocation of the wrapped function. evt_sprintf() does nothing of this sort and
> > > it is arguably wrong, as it drops any possibility of passing arguments to the
> > > format string that komeda_sprintf() allows.
> > 
> > komeda_sprintf(struct komeda_str *str, const char *fmt, ...), will be
> > treated as a generic function, which may be called from other places,
> > with the possiblity support of passing arguments to the format string
> > of it.
> > 
> > evt_sprintf(struct komeda_str *str, u64 evt, const char *msg), is
> > a wrapper aim to to remove so many duplicate if() checks and make
> > the code elegant and easy to read.
> > 
> > About "drops any possibility of passing arguments to the format string
> > that komeda_sprintf() allows". In this wrapper, the 2nd parameter *msg
> > is already be set and no possible to be a format string, even it calls
> > komeda_sprintf, which supports passing arguments to the format string.
> 
> Should this not be documented above the function?
> 
> Anyway, I think we are getting side-tracked. My main argument is that we don't
> need this function and evt_str() function *at all*. We should just expose the
> events value into debugfs and let userspace decode the bit values.

Hi Liviu,

Thanks a lot for your reply. We are glad to accept your suggestion to
remove this. But about this, James also had another concern in his
previous reply.

| "Since such error print is not only wanted by us, mostly it is
| required and used by our customer to easily capture the problem.
| If no special reasons, I want to keep it for avoiding the complaint
| from our customer."

Could you please share your concern.

Best regards,
Lowry

> > 
> > There are 27 places need check before calling into komeda_sprintf().
> > So I still think this wrapper is reasonable. It can make the code
> > elegant and easy to read. May I give another example:
> 
> Those 27 calls are also made in an interrupt handler.
> 
> Best regards,
> Liviu
> 
> > 
> > void drm_property_blob_put(struct drm_property_blob *blob)
> > {
> >         if (!blob)
> >                 return;
> > 
> >         drm_mode_object_put(&blob->base);
> > }
> > 
> > Best regards,
> > Lowry
> > 
> > > > 
> > > > And for this "if () check" specific, I think this is also very popular
> > > > in linux like:
> > > > 
> > > >   static inline void __rcu_read_lock(void)
> > > >   {
> > > >  	if (IS_ENABLED(CONFIG_PREEMPT_COUNT))
> > > > 		preempt_disable();
> > > >   }
> > > > 
> > > >   static inline void __rcu_read_unlock(void)
> > > >   {
> > > > 	if (IS_ENABLED(CONFIG_PREEMPT_COUNT))
> > > > 		preempt_enable();
> > > >   }
> > > 
> > > These are inline functions wrapping around the fact that a config option might
> > > be disabled. Not really the same thing with what we are talking here.
> > > 
> > > > 
> > > > thanks
> > > > James
> > > > 
> > > > > > 
> > > > > > > > +
> > > > > > > > +static void evt_str(struct komeda_str *str, u64 events)
> > > > > > > > +{
> > > > > > > > +	if (events == 0ULL) {
> > > > > > > > +		evt_sprintf(str, 1, "None");
> > > > > > > > +		return;
> > > > > > > > +	}
> > > > > > > > +
> > > > > > > > +	evt_sprintf(str, events & KOMEDA_EVENT_VSYNC, "VSYNC|");
> > > > > > > > +	evt_sprintf(str, events & KOMEDA_EVENT_FLIP, "FLIP|");
> > > > > > > > +	evt_sprintf(str, events & KOMEDA_EVENT_EOW, "EOW|");
> > > > > > > > +	evt_sprintf(str, events & KOMEDA_EVENT_MODE, "OP-MODE|");
> > > > > > > > +
> > > > > > > > +	evt_sprintf(str, events & KOMEDA_EVENT_URUN, "UNDERRUN|");
> > > > > > > > +	evt_sprintf(str, events & KOMEDA_EVENT_OVR, "OVERRUN|");
> > > > > > > > +
> > > > > > > > +	/* GLB error */
> > > > > > > > +	evt_sprintf(str, events & KOMEDA_ERR_MERR, "MERR|");
> > > > > > > > +	evt_sprintf(str, events & KOMEDA_ERR_FRAMETO, "FRAMETO|");
> > > > > > > > +
> > > > > > > > +	/* DOU error */
> > > > > > > > +	evt_sprintf(str, events & KOMEDA_ERR_DRIFTTO, "DRIFTTO|");
> > > > > > > > +	evt_sprintf(str, events & KOMEDA_ERR_FRAMETO, "FRAMETO|");
> > > > > > > > +	evt_sprintf(str, events & KOMEDA_ERR_TETO, "TETO|");
> > > > > > > > +	evt_sprintf(str, events & KOMEDA_ERR_CSCE, "CSCE|");
> > > > > > > > +
> > > > > > > > +	/* LPU errors or events */
> > > > > > > > +	evt_sprintf(str, events & KOMEDA_EVENT_IBSY, "IBSY|");
> > > > > > > > +	evt_sprintf(str, events & KOMEDA_ERR_AXIE, "AXIE|");
> > > > > > > > +	evt_sprintf(str, events & KOMEDA_ERR_ACE0, "ACE0|");
> > > > > > > > +	evt_sprintf(str, events & KOMEDA_ERR_ACE1, "ACE1|");
> > > > > > > > +	evt_sprintf(str, events & KOMEDA_ERR_ACE2, "ACE2|");
> > > > > > > > +	evt_sprintf(str, events & KOMEDA_ERR_ACE3, "ACE3|");
> > > > > > > > +
> > > > > > > > +	/* LPU TBU errors*/
> > > > > > > > +	evt_sprintf(str, events & KOMEDA_ERR_TCF, "TCF|");
> > > > > > > > +	evt_sprintf(str, events & KOMEDA_ERR_TTNG, "TTNG|");
> > > > > > > > +	evt_sprintf(str, events & KOMEDA_ERR_TITR, "TITR|");
> > > > > > > > +	evt_sprintf(str, events & KOMEDA_ERR_TEMR, "TEMR|");
> > > > > > > > +	evt_sprintf(str, events & KOMEDA_ERR_TTF, "TTF|");
> > > > > > > > +
> > > > > > > > +	/* CU errors*/
> > > > > > > > +	evt_sprintf(str, events & KOMEDA_ERR_CPE, "COPROC|");
> > > > > > > > +	evt_sprintf(str, events & KOMEDA_ERR_ZME, "ZME|");
> > > > > > > > +	evt_sprintf(str, events & KOMEDA_ERR_CFGE, "CFGE|");
> > > > > > > > +	evt_sprintf(str, events & KOMEDA_ERR_TEMR, "TEMR|");
> > > > > > > > +
> > > > > > > > +	if (str->len > 0 && (str->str[str->len - 1] == '|')) {
> > > > > > > > +		str->str[str->len - 1] = 0;
> > > > > > > > +		str->len--;
> > > > > > > > +	}
> > > > > > > > +}
> > > > > > > > +
> > > > > > > > +static bool is_new_frame(struct komeda_events *a)
> > > > > > > > +{
> > > > > > > > +	return (a->pipes[0] | a->pipes[1]) & KOMEDA_EVENT_FLIP;
> > > > > > > > +}
> > > > > > > > +
> > > > > > > > +void komeda_print_events(struct komeda_events *evts)
> > > > > > > > +{
> > > > > > > > +	u64 print_evts = KOMEDA_ERR_EVENTS;
> > > > > > > > +	static bool en_print = true;
> > > > > > > > +
> > > > > > > > +	/* reduce the same msg print, only print the first evt for one frame */
> > > > > > > > +	if (evts->global || is_new_frame(evts))
> > > > > > > > +		en_print = true;
> > > > > > > > +	if (!en_print)
> > > > > > > > +		return;
> > > > > > > 
> > > > > > > When does en_print ever get false?
> > > > > > Once the events printed, it will be set false (pls find at the last
> > > > > > line of this function).
> > > > > 
> > > > > What is the point of making en_print a static variable? We print all the time
> > > > > when we have a global event anyway.
> > > > 
> > > > Hi Liviu:
> > > > 
> > > > | why make en_print a static.
> > > > 
> > > > Consider you commit a scene which may leads a UNDERUN. and it will
> > > > trigger HW UNDERRUN in every vsync peroid untill this sceen have been
> > > > replace by another scene. for a scene it will trigger same error again
> > > > and again. we don't need print them all for a scene one msg is enough.
> > > 
> > > The same can be achieved by removing en_print entirely and inverting the top
> > > condition:
> > > 
> > > 	if (!evts->global && !is_new_frame(evts))
> > > 		return;
> > 
> > It looks better and will change to this. Thanks a lot for this.
> > > > 
> > > > | we print all the time when we have a global event.
> > > > Since we only reduce the duplicate error, but want print all different error.
> > > > And per our HW design, the event reported by different component.
> > > > this global for collect the GCU error. the pipeline_event is for
> > > > LPU/CU/DOU. like UNDERUN which is only DOU error.
> > > > 
> > > > and current GCU only have one error type: opmode change error which only
> > > > can be happened on when we call change_opmode in crtc_enable/disable.
> > > > 
> > > > So don't worry, globl event which can not make en_print has been set to
> > > > true in every irq handling.
> > > 
> > > And that's the reason I'm asking why make en_print static if we reset it in
> > > every irq_handling (i.e. when we actually want to print). Does it really need
> > > to be static when we don't actually use the stored state?
> > > 
> > > Best regards,
> > > Liviu
> > > 
> > > 
> > > > 
> > > > Thanks
> > > > James
> > > > 
> > > > > 
> > > > > > > > +
> > > > > > > > +#ifdef DEBUG
> > > > > > > > +	print_evts |= KOMEDA_WARN_EVENTS;
> > > > > > > > +#endif
> > > > > > > > +
> > > > > > > > +	if ((evts->global | evts->pipes[0] | evts->pipes[1]) & print_evts) {
> > > > > > > > +		#define STR_SZ		128
> > > > > > > > +		char msg[STR_SZ];
> > > > > > > 
> > > > > > > I've counted about 27 evt_sprintf() calls in evt_str() function, with an
> > > > > > > average of 5 characters each, so thats 135 characters printed into a buffer
> > > > > > > that is only 128 bytes. Please don't do this!
> > > > > > komeda_sprintf() will check the size and also I thought those evt
> > > > > > will not populat together. But yes, I'd better change this to 256.
> > > > > > Will change this.
> > > > > > 
> > > > > > > > +		struct komeda_str str;
> > > > > > > > +
> > > > > > > > +		str.str = msg;
> > > > > > > > +		str.sz  = STR_SZ;
> > > > > > > > +		str.len = 0;
> > > > > > > > +
> > > > > > > > +		komeda_sprintf(&str, "gcu: ");
> > > > > > > > +		evt_str(&str, evts->global);
> > > > > > > > +		komeda_sprintf(&str, ", pipes[0]: ");
> > > > > > > > +		evt_str(&str, evts->pipes[0]);
> > > > > > > > +		komeda_sprintf(&str, ", pipes[1]: ");
> > > > > > > > +		evt_str(&str, evts->pipes[1]);
> > > > > > > > +
> > > > > > > > +		DRM_ERROR("err detect: %s\n", msg);
> > > > > > > > +
> > > > > > > > +		en_print = false;
> > > > > > > > +	}
> > > > > > > > +}
> > > > > > > > diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_kms.c b/drivers/gpu/drm/arm/display/komeda/komeda_kms.c
> > > > > > > > index 647bce5..1462bac 100644
> > > > > > > > --- a/drivers/gpu/drm/arm/display/komeda/komeda_kms.c
> > > > > > > > +++ b/drivers/gpu/drm/arm/display/komeda/komeda_kms.c
> > > > > > > > @@ -47,6 +47,8 @@ static irqreturn_t komeda_kms_irq_handler(int irq, void *data)
> > > > > > > >  	memset(&evts, 0, sizeof(evts));
> > > > > > > >  	status = mdev->funcs->irq_handler(mdev, &evts);
> > > > > > > >  
> > > > > > > > +	komeda_print_events(&evts);
> > > > > > > 
> > > > > > > Calling this function from the IRQ handler is a bad idea. We should use debugfs
> > > > > > > if you really want to have a trace of the events, but I personally don't see
> > > > > > > value in having this functionality in the kernel at all. You can expose the
> > > > > > > value of the evts->global and evts->pipes[] as integers and decode that in
> > > > > > > userspace or as a debugfs entry.
> > > > > > > 
> > > > > > > Best regards,
> > > > > > > Liviu
> > > > > > 
> > > > > > The name of this function is misleading, but this is printing out the
> > > > > > hardware detected errors, from which we can know directly once the
> > > > > > errors happened on the hardware. Like if the driver code was at
> > > > > > bring-up stage, the logs from this layer is helpful. So can we keep
> > > > > > this?
> > > > > 
> > > > > We should probably just collect the global and pipes values and expose
> > > > > them to userspace so that the printing and decoding of the messages happens
> > > > > there.
> > > > > 
> > > > > Best regards,
> > > > > Liviu
> > > > 
> > > > Hi Liviu:
> > > > 
> > > > Any special resons.
> > > > 
> > > > Since such error print is not only wanted by us, mostly it is required
> > > > and used by our customer to easily capture the problem.
> > > > If no special reasons, I want to keep it for avoiding the complaint
> > > > from our customer. 
> > > > 
> > > > Thanks
> > > > James
> > > > > 
> > > > > > 
> > > > > > Best regards,
> > > > > > Lowry
> > > > > > 
> > > > > > > > +
> > > > > > > >  	/* Notify the crtc to handle the events */
> > > > > > > >  	for (i = 0; i < kms->n_crtcs; i++)
> > > > > > > >  		komeda_crtc_handle_event(&kms->crtcs[i], &evts);
> > > > > > > > -- 
> > > > > > > > 1.9.1
> > > > > > > > 
> > > > > > > 
> > > > > > > -- 
> > > > > > > ====================
> > > > > > > | I would like to |
> > > > > > > | fix the world,  |
> > > > > > > | but they're not |
> > > > > > > | giving me the   |
> > > > > > >  \ source code!  /
> > > > > > >   ---------------
> > > > > > >     ¯\_(ツ)_/¯
> > > > > > 
> > > > > > -- 
> > > > > > Regards,
> > > > > > Lowry
> > > > > 
> > > > > -- 
> > > > > ====================
> > > > > | I would like to |
> > > > > | fix the world,  |
> > > > > | but they're not |
> > > > > | giving me the   |
> > > > >  \ source code!  /
> > > > >   ---------------
> > > > >     ¯\_(ツ)_/¯
> > > 
> > > -- 
> > > ====================
> > > | I would like to |
> > > | fix the world,  |
> > > | but they're not |
> > > | giving me the   |
> > >  \ source code!  /
> > >   ---------------
> > >     ¯\_(ツ)_/¯
> > 
> > -- 
> > Regards,
> > Lowry
> 
> -- 
> ====================
> | I would like to |
> | fix the world,  |
> | but they're not |
> | giving me the   |
>  \ source code!  /
>   ---------------
>     ¯\_(ツ)_/¯

-- 
Regards,
Lowry
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [PATCH] drm/komeda: Adds error event print functionality
  2019-09-17 13:11   ` Daniel Vetter
@ 2019-09-18  1:29     ` james qian wang (Arm Technology China)
  -1 siblings, 0 replies; 37+ messages in thread
From: james qian wang (Arm Technology China) @ 2019-09-18  1:29 UTC (permalink / raw)
  To: Daniel Vetter
  Cc: Lowry Li (Arm Technology China),
	Liviu Dudau, maarten.lankhorst, seanpaul, airlied, Brian Starkey,
	Mihail Atanassov, Ayan Halder,
	Jonathan Chai (Arm Technology China),
	linux-kernel, dri-devel, Julien Yin (Arm Technology China),
	nd

On Tue, Sep 17, 2019 at 03:11:27PM +0200, Daniel Vetter wrote:
> On Fri, Aug 2, 2019 at 11:43 AM Lowry Li (Arm Technology China)
> <Lowry.Li@arm.com> wrote:
> >
> > From: "Lowry Li (Arm Technology China)" <Lowry.Li@arm.com>
> >
> > Adds to print the event message when error happens and the same event
> > will not be printed until next vsync.
> >
> > Changes since v2:
> > 1. Refine komeda_sprintf();
> > 2. Not using STR_SZ macro for the string size in komeda_print_events().
> >
> > Changes since v1:
> > 1. Handling the event print by CONFIG_KOMEDA_ERROR_PRINT;
> > 2. Changing the max string size to 256.
> >
> > Signed-off-by: Lowry Li (Arm Technology China) <lowry.li@arm.com>
> > ---
> >  drivers/gpu/drm/arm/display/Kconfig               |   6 +
> >  drivers/gpu/drm/arm/display/komeda/Makefile       |   2 +
> >  drivers/gpu/drm/arm/display/komeda/komeda_dev.h   |  15 +++
> >  drivers/gpu/drm/arm/display/komeda/komeda_event.c | 140 ++++++++++++++++++++++
> >  drivers/gpu/drm/arm/display/komeda/komeda_kms.c   |   4 +
> >  5 files changed, 167 insertions(+)
> >  create mode 100644 drivers/gpu/drm/arm/display/komeda/komeda_event.c
> >
> > diff --git a/drivers/gpu/drm/arm/display/Kconfig b/drivers/gpu/drm/arm/display/Kconfig
> > index cec0639..e87ff86 100644
> > --- a/drivers/gpu/drm/arm/display/Kconfig
> > +++ b/drivers/gpu/drm/arm/display/Kconfig
> > @@ -12,3 +12,9 @@ config DRM_KOMEDA
> >           Processor driver. It supports the D71 variants of the hardware.
> >
> >           If compiled as a module it will be called komeda.
> > +
> > +config DRM_KOMEDA_ERROR_PRINT
> > +       bool "Enable komeda error print"
> > +       depends on DRM_KOMEDA
> > +       help
> > +         Choose this option to enable error printing.
> > diff --git a/drivers/gpu/drm/arm/display/komeda/Makefile b/drivers/gpu/drm/arm/display/komeda/Makefile
> > index 5c3900c..f095a1c 100644
> > --- a/drivers/gpu/drm/arm/display/komeda/Makefile
> > +++ b/drivers/gpu/drm/arm/display/komeda/Makefile
> > @@ -22,4 +22,6 @@ komeda-y += \
> >         d71/d71_dev.o \
> >         d71/d71_component.o
> >
> > +komeda-$(CONFIG_DRM_KOMEDA_ERROR_PRINT) += komeda_event.o
> > +
> >  obj-$(CONFIG_DRM_KOMEDA) += komeda.o
> > diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_dev.h b/drivers/gpu/drm/arm/display/komeda/komeda_dev.h
> > index d1c86b6..e28e7e6 100644
> > --- a/drivers/gpu/drm/arm/display/komeda/komeda_dev.h
> > +++ b/drivers/gpu/drm/arm/display/komeda/komeda_dev.h
> > @@ -40,6 +40,17 @@
> >  #define KOMEDA_ERR_TTNG                        BIT_ULL(30)
> >  #define KOMEDA_ERR_TTF                 BIT_ULL(31)
> >
> > +#define KOMEDA_ERR_EVENTS      \
> > +       (KOMEDA_EVENT_URUN      | KOMEDA_EVENT_IBSY     | KOMEDA_EVENT_OVR |\
> > +       KOMEDA_ERR_TETO         | KOMEDA_ERR_TEMR       | KOMEDA_ERR_TITR |\
> > +       KOMEDA_ERR_CPE          | KOMEDA_ERR_CFGE       | KOMEDA_ERR_AXIE |\
> > +       KOMEDA_ERR_ACE0         | KOMEDA_ERR_ACE1       | KOMEDA_ERR_ACE2 |\
> > +       KOMEDA_ERR_ACE3         | KOMEDA_ERR_DRIFTTO    | KOMEDA_ERR_FRAMETO |\
> > +       KOMEDA_ERR_ZME          | KOMEDA_ERR_MERR       | KOMEDA_ERR_TCF |\
> > +       KOMEDA_ERR_TTNG         | KOMEDA_ERR_TTF)
> > +
> > +#define KOMEDA_WARN_EVENTS     KOMEDA_ERR_CSCE
> > +
> >  /* malidp device id */
> >  enum {
> >         MALI_D71 = 0,
> > @@ -207,4 +218,8 @@ struct komeda_dev {
> >
> >  struct komeda_dev *dev_to_mdev(struct device *dev);
> >
> > +#ifdef CONFIG_DRM_KOMEDA_ERROR_PRINT
> > +void komeda_print_events(struct komeda_events *evts);
> > +#endif
> > +
> >  #endif /*_KOMEDA_DEV_H_*/
> > diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_event.c b/drivers/gpu/drm/arm/display/komeda/komeda_event.c
> > new file mode 100644
> > index 0000000..a36fb86
> > --- /dev/null
> > +++ b/drivers/gpu/drm/arm/display/komeda/komeda_event.c
> > @@ -0,0 +1,140 @@
> > +// SPDX-License-Identifier: GPL-2.0
> > +/*
> > + * (C) COPYRIGHT 2019 ARM Limited. All rights reserved.
> > + * Author: James.Qian.Wang <james.qian.wang@arm.com>
> > + *
> > + */
> > +#include <drm/drm_print.h>
> > +
> > +#include "komeda_dev.h"
> > +
> > +struct komeda_str {
> > +       char *str;
> > +       u32 sz;
> > +       u32 len;
> > +};
> > +
> > +/* return 0 on success,  < 0 on no space.
> > + */
> > +static int komeda_sprintf(struct komeda_str *str, const char *fmt, ...)
> > +{
> > +       va_list args;
> > +       int num, free_sz;
> > +       int err;
> > +
> > +       free_sz = str->sz - str->len - 1;
> > +       if (free_sz <= 0)
> > +               return -ENOSPC;
> > +
> > +       va_start(args, fmt);
> > +
> > +       num = vsnprintf(str->str + str->len, free_sz, fmt, args);
> > +
> > +       va_end(args);
> > +
> > +       if (num < free_sz) {
> > +               str->len += num;
> > +               err = 0;
> > +       } else {
> > +               str->len = str->sz - 1;
> > +               err = -ENOSPC;
> > +       }
> > +
> > +       return err;
> > +}
> > +
> > +static void evt_sprintf(struct komeda_str *str, u64 evt, const char *msg)
> > +{
> > +       if (evt)
> > +               komeda_sprintf(str, msg);
> > +}
> > +
> > +static void evt_str(struct komeda_str *str, u64 events)
> > +{
> > +       if (events == 0ULL) {
> > +               komeda_sprintf(str, "None");
> > +               return;
> > +       }
> > +
> > +       evt_sprintf(str, events & KOMEDA_EVENT_VSYNC, "VSYNC|");
> > +       evt_sprintf(str, events & KOMEDA_EVENT_FLIP, "FLIP|");
> > +       evt_sprintf(str, events & KOMEDA_EVENT_EOW, "EOW|");
> > +       evt_sprintf(str, events & KOMEDA_EVENT_MODE, "OP-MODE|");
> > +
> > +       evt_sprintf(str, events & KOMEDA_EVENT_URUN, "UNDERRUN|");
> > +       evt_sprintf(str, events & KOMEDA_EVENT_OVR, "OVERRUN|");
> > +
> > +       /* GLB error */
> > +       evt_sprintf(str, events & KOMEDA_ERR_MERR, "MERR|");
> > +       evt_sprintf(str, events & KOMEDA_ERR_FRAMETO, "FRAMETO|");
> > +
> > +       /* DOU error */
> > +       evt_sprintf(str, events & KOMEDA_ERR_DRIFTTO, "DRIFTTO|");
> > +       evt_sprintf(str, events & KOMEDA_ERR_FRAMETO, "FRAMETO|");
> > +       evt_sprintf(str, events & KOMEDA_ERR_TETO, "TETO|");
> > +       evt_sprintf(str, events & KOMEDA_ERR_CSCE, "CSCE|");
> > +
> > +       /* LPU errors or events */
> > +       evt_sprintf(str, events & KOMEDA_EVENT_IBSY, "IBSY|");
> > +       evt_sprintf(str, events & KOMEDA_ERR_AXIE, "AXIE|");
> > +       evt_sprintf(str, events & KOMEDA_ERR_ACE0, "ACE0|");
> > +       evt_sprintf(str, events & KOMEDA_ERR_ACE1, "ACE1|");
> > +       evt_sprintf(str, events & KOMEDA_ERR_ACE2, "ACE2|");
> > +       evt_sprintf(str, events & KOMEDA_ERR_ACE3, "ACE3|");
> > +
> > +       /* LPU TBU errors*/
> > +       evt_sprintf(str, events & KOMEDA_ERR_TCF, "TCF|");
> > +       evt_sprintf(str, events & KOMEDA_ERR_TTNG, "TTNG|");
> > +       evt_sprintf(str, events & KOMEDA_ERR_TITR, "TITR|");
> > +       evt_sprintf(str, events & KOMEDA_ERR_TEMR, "TEMR|");
> > +       evt_sprintf(str, events & KOMEDA_ERR_TTF, "TTF|");
> > +
> > +       /* CU errors*/
> > +       evt_sprintf(str, events & KOMEDA_ERR_CPE, "COPROC|");
> > +       evt_sprintf(str, events & KOMEDA_ERR_ZME, "ZME|");
> > +       evt_sprintf(str, events & KOMEDA_ERR_CFGE, "CFGE|");
> > +       evt_sprintf(str, events & KOMEDA_ERR_TEMR, "TEMR|");
> > +
> > +       if (str->len > 0 && (str->str[str->len - 1] == '|')) {
> > +               str->str[str->len - 1] = 0;
> > +               str->len--;
> > +       }
> > +}
> > +
> > +static bool is_new_frame(struct komeda_events *a)
> > +{
> > +       return (a->pipes[0] | a->pipes[1]) &
> > +              (KOMEDA_EVENT_FLIP | KOMEDA_EVENT_EOW);
> > +}
> > +
> > +void komeda_print_events(struct komeda_events *evts)
> > +{
> > +       u64 print_evts = KOMEDA_ERR_EVENTS;
> > +       static bool en_print = true;
> > +
> > +       /* reduce the same msg print, only print the first evt for one frame */
> > +       if (evts->global || is_new_frame(evts))
> > +               en_print = true;
> > +       if (!en_print)
> > +               return;
> > +
> > +       if ((evts->global | evts->pipes[0] | evts->pipes[1]) & print_evts) {
> > +               char msg[256];
> > +               struct komeda_str str;
> > +
> > +               str.str = msg;
> > +               str.sz  = sizeof(msg);
> > +               str.len = 0;
> > +
> > +               komeda_sprintf(&str, "gcu: ");
> > +               evt_str(&str, evts->global);
> > +               komeda_sprintf(&str, ", pipes[0]: ");
> > +               evt_str(&str, evts->pipes[0]);
> > +               komeda_sprintf(&str, ", pipes[1]: ");
> > +               evt_str(&str, evts->pipes[1]);
> > +
> > +               DRM_ERROR("err detect: %s\n", msg);
> > +
> > +               en_print = false;
> > +       }
> > +}
> > diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_kms.c b/drivers/gpu/drm/arm/display/komeda/komeda_kms.c
> > index 419a8b0..0fafc36 100644
> > --- a/drivers/gpu/drm/arm/display/komeda/komeda_kms.c
> > +++ b/drivers/gpu/drm/arm/display/komeda/komeda_kms.c
> > @@ -47,6 +47,10 @@ static irqreturn_t komeda_kms_irq_handler(int irq, void *data)
> >         memset(&evts, 0, sizeof(evts));
> >         status = mdev->funcs->irq_handler(mdev, &evts);
> >
> > +#ifdef CONFIG_DRM_KOMEDA_ERROR_PRINT
> > +       komeda_print_events(&evts);
> > +#endif
> 
> #ifdef in code is discouraged, the usual way we handle these cases is
> by having a dummy static inline function which does nothing in the
> headers for the case a config option isn't enabled.
> -Daniel

Hi Daniel&Mihail:

If so, since this CONFIG is always enabled for komeda, I'd like to
delete this CONFIG option directly.

thanks
james

> > +
> >         /* Notify the crtc to handle the events */
> >         for (i = 0; i < kms->n_crtcs; i++)
> >                 komeda_crtc_handle_event(&kms->crtcs[i], &evts);
> > --
> > 1.9.1
> >
> > _______________________________________________
> > dri-devel mailing list
> > dri-devel@lists.freedesktop.org
> > https://lists.freedesktop.org/mailman/listinfo/dri-devel
> 
> 
> 
> -- 
> Daniel Vetter
> Software Engineer, Intel Corporation
> +41 (0) 79 365 57 48 - http://blog.ffwll.ch

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [PATCH] drm/komeda: Adds error event print functionality
@ 2019-09-18  1:29     ` james qian wang (Arm Technology China)
  0 siblings, 0 replies; 37+ messages in thread
From: james qian wang (Arm Technology China) @ 2019-09-18  1:29 UTC (permalink / raw)
  To: Daniel Vetter
  Cc: nd, Mihail Atanassov, airlied, Liviu Dudau,
	Jonathan Chai (Arm Technology China),
	linux-kernel, dri-devel, Julien Yin (Arm Technology China),
	Ayan Halder, seanpaul, Lowry Li (Arm Technology China)

On Tue, Sep 17, 2019 at 03:11:27PM +0200, Daniel Vetter wrote:
> On Fri, Aug 2, 2019 at 11:43 AM Lowry Li (Arm Technology China)
> <Lowry.Li@arm.com> wrote:
> >
> > From: "Lowry Li (Arm Technology China)" <Lowry.Li@arm.com>
> >
> > Adds to print the event message when error happens and the same event
> > will not be printed until next vsync.
> >
> > Changes since v2:
> > 1. Refine komeda_sprintf();
> > 2. Not using STR_SZ macro for the string size in komeda_print_events().
> >
> > Changes since v1:
> > 1. Handling the event print by CONFIG_KOMEDA_ERROR_PRINT;
> > 2. Changing the max string size to 256.
> >
> > Signed-off-by: Lowry Li (Arm Technology China) <lowry.li@arm.com>
> > ---
> >  drivers/gpu/drm/arm/display/Kconfig               |   6 +
> >  drivers/gpu/drm/arm/display/komeda/Makefile       |   2 +
> >  drivers/gpu/drm/arm/display/komeda/komeda_dev.h   |  15 +++
> >  drivers/gpu/drm/arm/display/komeda/komeda_event.c | 140 ++++++++++++++++++++++
> >  drivers/gpu/drm/arm/display/komeda/komeda_kms.c   |   4 +
> >  5 files changed, 167 insertions(+)
> >  create mode 100644 drivers/gpu/drm/arm/display/komeda/komeda_event.c
> >
> > diff --git a/drivers/gpu/drm/arm/display/Kconfig b/drivers/gpu/drm/arm/display/Kconfig
> > index cec0639..e87ff86 100644
> > --- a/drivers/gpu/drm/arm/display/Kconfig
> > +++ b/drivers/gpu/drm/arm/display/Kconfig
> > @@ -12,3 +12,9 @@ config DRM_KOMEDA
> >           Processor driver. It supports the D71 variants of the hardware.
> >
> >           If compiled as a module it will be called komeda.
> > +
> > +config DRM_KOMEDA_ERROR_PRINT
> > +       bool "Enable komeda error print"
> > +       depends on DRM_KOMEDA
> > +       help
> > +         Choose this option to enable error printing.
> > diff --git a/drivers/gpu/drm/arm/display/komeda/Makefile b/drivers/gpu/drm/arm/display/komeda/Makefile
> > index 5c3900c..f095a1c 100644
> > --- a/drivers/gpu/drm/arm/display/komeda/Makefile
> > +++ b/drivers/gpu/drm/arm/display/komeda/Makefile
> > @@ -22,4 +22,6 @@ komeda-y += \
> >         d71/d71_dev.o \
> >         d71/d71_component.o
> >
> > +komeda-$(CONFIG_DRM_KOMEDA_ERROR_PRINT) += komeda_event.o
> > +
> >  obj-$(CONFIG_DRM_KOMEDA) += komeda.o
> > diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_dev.h b/drivers/gpu/drm/arm/display/komeda/komeda_dev.h
> > index d1c86b6..e28e7e6 100644
> > --- a/drivers/gpu/drm/arm/display/komeda/komeda_dev.h
> > +++ b/drivers/gpu/drm/arm/display/komeda/komeda_dev.h
> > @@ -40,6 +40,17 @@
> >  #define KOMEDA_ERR_TTNG                        BIT_ULL(30)
> >  #define KOMEDA_ERR_TTF                 BIT_ULL(31)
> >
> > +#define KOMEDA_ERR_EVENTS      \
> > +       (KOMEDA_EVENT_URUN      | KOMEDA_EVENT_IBSY     | KOMEDA_EVENT_OVR |\
> > +       KOMEDA_ERR_TETO         | KOMEDA_ERR_TEMR       | KOMEDA_ERR_TITR |\
> > +       KOMEDA_ERR_CPE          | KOMEDA_ERR_CFGE       | KOMEDA_ERR_AXIE |\
> > +       KOMEDA_ERR_ACE0         | KOMEDA_ERR_ACE1       | KOMEDA_ERR_ACE2 |\
> > +       KOMEDA_ERR_ACE3         | KOMEDA_ERR_DRIFTTO    | KOMEDA_ERR_FRAMETO |\
> > +       KOMEDA_ERR_ZME          | KOMEDA_ERR_MERR       | KOMEDA_ERR_TCF |\
> > +       KOMEDA_ERR_TTNG         | KOMEDA_ERR_TTF)
> > +
> > +#define KOMEDA_WARN_EVENTS     KOMEDA_ERR_CSCE
> > +
> >  /* malidp device id */
> >  enum {
> >         MALI_D71 = 0,
> > @@ -207,4 +218,8 @@ struct komeda_dev {
> >
> >  struct komeda_dev *dev_to_mdev(struct device *dev);
> >
> > +#ifdef CONFIG_DRM_KOMEDA_ERROR_PRINT
> > +void komeda_print_events(struct komeda_events *evts);
> > +#endif
> > +
> >  #endif /*_KOMEDA_DEV_H_*/
> > diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_event.c b/drivers/gpu/drm/arm/display/komeda/komeda_event.c
> > new file mode 100644
> > index 0000000..a36fb86
> > --- /dev/null
> > +++ b/drivers/gpu/drm/arm/display/komeda/komeda_event.c
> > @@ -0,0 +1,140 @@
> > +// SPDX-License-Identifier: GPL-2.0
> > +/*
> > + * (C) COPYRIGHT 2019 ARM Limited. All rights reserved.
> > + * Author: James.Qian.Wang <james.qian.wang@arm.com>
> > + *
> > + */
> > +#include <drm/drm_print.h>
> > +
> > +#include "komeda_dev.h"
> > +
> > +struct komeda_str {
> > +       char *str;
> > +       u32 sz;
> > +       u32 len;
> > +};
> > +
> > +/* return 0 on success,  < 0 on no space.
> > + */
> > +static int komeda_sprintf(struct komeda_str *str, const char *fmt, ...)
> > +{
> > +       va_list args;
> > +       int num, free_sz;
> > +       int err;
> > +
> > +       free_sz = str->sz - str->len - 1;
> > +       if (free_sz <= 0)
> > +               return -ENOSPC;
> > +
> > +       va_start(args, fmt);
> > +
> > +       num = vsnprintf(str->str + str->len, free_sz, fmt, args);
> > +
> > +       va_end(args);
> > +
> > +       if (num < free_sz) {
> > +               str->len += num;
> > +               err = 0;
> > +       } else {
> > +               str->len = str->sz - 1;
> > +               err = -ENOSPC;
> > +       }
> > +
> > +       return err;
> > +}
> > +
> > +static void evt_sprintf(struct komeda_str *str, u64 evt, const char *msg)
> > +{
> > +       if (evt)
> > +               komeda_sprintf(str, msg);
> > +}
> > +
> > +static void evt_str(struct komeda_str *str, u64 events)
> > +{
> > +       if (events == 0ULL) {
> > +               komeda_sprintf(str, "None");
> > +               return;
> > +       }
> > +
> > +       evt_sprintf(str, events & KOMEDA_EVENT_VSYNC, "VSYNC|");
> > +       evt_sprintf(str, events & KOMEDA_EVENT_FLIP, "FLIP|");
> > +       evt_sprintf(str, events & KOMEDA_EVENT_EOW, "EOW|");
> > +       evt_sprintf(str, events & KOMEDA_EVENT_MODE, "OP-MODE|");
> > +
> > +       evt_sprintf(str, events & KOMEDA_EVENT_URUN, "UNDERRUN|");
> > +       evt_sprintf(str, events & KOMEDA_EVENT_OVR, "OVERRUN|");
> > +
> > +       /* GLB error */
> > +       evt_sprintf(str, events & KOMEDA_ERR_MERR, "MERR|");
> > +       evt_sprintf(str, events & KOMEDA_ERR_FRAMETO, "FRAMETO|");
> > +
> > +       /* DOU error */
> > +       evt_sprintf(str, events & KOMEDA_ERR_DRIFTTO, "DRIFTTO|");
> > +       evt_sprintf(str, events & KOMEDA_ERR_FRAMETO, "FRAMETO|");
> > +       evt_sprintf(str, events & KOMEDA_ERR_TETO, "TETO|");
> > +       evt_sprintf(str, events & KOMEDA_ERR_CSCE, "CSCE|");
> > +
> > +       /* LPU errors or events */
> > +       evt_sprintf(str, events & KOMEDA_EVENT_IBSY, "IBSY|");
> > +       evt_sprintf(str, events & KOMEDA_ERR_AXIE, "AXIE|");
> > +       evt_sprintf(str, events & KOMEDA_ERR_ACE0, "ACE0|");
> > +       evt_sprintf(str, events & KOMEDA_ERR_ACE1, "ACE1|");
> > +       evt_sprintf(str, events & KOMEDA_ERR_ACE2, "ACE2|");
> > +       evt_sprintf(str, events & KOMEDA_ERR_ACE3, "ACE3|");
> > +
> > +       /* LPU TBU errors*/
> > +       evt_sprintf(str, events & KOMEDA_ERR_TCF, "TCF|");
> > +       evt_sprintf(str, events & KOMEDA_ERR_TTNG, "TTNG|");
> > +       evt_sprintf(str, events & KOMEDA_ERR_TITR, "TITR|");
> > +       evt_sprintf(str, events & KOMEDA_ERR_TEMR, "TEMR|");
> > +       evt_sprintf(str, events & KOMEDA_ERR_TTF, "TTF|");
> > +
> > +       /* CU errors*/
> > +       evt_sprintf(str, events & KOMEDA_ERR_CPE, "COPROC|");
> > +       evt_sprintf(str, events & KOMEDA_ERR_ZME, "ZME|");
> > +       evt_sprintf(str, events & KOMEDA_ERR_CFGE, "CFGE|");
> > +       evt_sprintf(str, events & KOMEDA_ERR_TEMR, "TEMR|");
> > +
> > +       if (str->len > 0 && (str->str[str->len - 1] == '|')) {
> > +               str->str[str->len - 1] = 0;
> > +               str->len--;
> > +       }
> > +}
> > +
> > +static bool is_new_frame(struct komeda_events *a)
> > +{
> > +       return (a->pipes[0] | a->pipes[1]) &
> > +              (KOMEDA_EVENT_FLIP | KOMEDA_EVENT_EOW);
> > +}
> > +
> > +void komeda_print_events(struct komeda_events *evts)
> > +{
> > +       u64 print_evts = KOMEDA_ERR_EVENTS;
> > +       static bool en_print = true;
> > +
> > +       /* reduce the same msg print, only print the first evt for one frame */
> > +       if (evts->global || is_new_frame(evts))
> > +               en_print = true;
> > +       if (!en_print)
> > +               return;
> > +
> > +       if ((evts->global | evts->pipes[0] | evts->pipes[1]) & print_evts) {
> > +               char msg[256];
> > +               struct komeda_str str;
> > +
> > +               str.str = msg;
> > +               str.sz  = sizeof(msg);
> > +               str.len = 0;
> > +
> > +               komeda_sprintf(&str, "gcu: ");
> > +               evt_str(&str, evts->global);
> > +               komeda_sprintf(&str, ", pipes[0]: ");
> > +               evt_str(&str, evts->pipes[0]);
> > +               komeda_sprintf(&str, ", pipes[1]: ");
> > +               evt_str(&str, evts->pipes[1]);
> > +
> > +               DRM_ERROR("err detect: %s\n", msg);
> > +
> > +               en_print = false;
> > +       }
> > +}
> > diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_kms.c b/drivers/gpu/drm/arm/display/komeda/komeda_kms.c
> > index 419a8b0..0fafc36 100644
> > --- a/drivers/gpu/drm/arm/display/komeda/komeda_kms.c
> > +++ b/drivers/gpu/drm/arm/display/komeda/komeda_kms.c
> > @@ -47,6 +47,10 @@ static irqreturn_t komeda_kms_irq_handler(int irq, void *data)
> >         memset(&evts, 0, sizeof(evts));
> >         status = mdev->funcs->irq_handler(mdev, &evts);
> >
> > +#ifdef CONFIG_DRM_KOMEDA_ERROR_PRINT
> > +       komeda_print_events(&evts);
> > +#endif
> 
> #ifdef in code is discouraged, the usual way we handle these cases is
> by having a dummy static inline function which does nothing in the
> headers for the case a config option isn't enabled.
> -Daniel

Hi Daniel&Mihail:

If so, since this CONFIG is always enabled for komeda, I'd like to
delete this CONFIG option directly.

thanks
james

> > +
> >         /* Notify the crtc to handle the events */
> >         for (i = 0; i < kms->n_crtcs; i++)
> >                 komeda_crtc_handle_event(&kms->crtcs[i], &evts);
> > --
> > 1.9.1
> >
> > _______________________________________________
> > dri-devel mailing list
> > dri-devel@lists.freedesktop.org
> > https://lists.freedesktop.org/mailman/listinfo/dri-devel
> 
> 
> 
> -- 
> Daniel Vetter
> Software Engineer, Intel Corporation
> +41 (0) 79 365 57 48 - http://blog.ffwll.ch
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [PATCH] drm/komeda: Adds error event print functionality
  2019-08-02  9:43 ` Lowry Li (Arm Technology China)
@ 2019-09-17 13:11   ` Daniel Vetter
  -1 siblings, 0 replies; 37+ messages in thread
From: Daniel Vetter @ 2019-09-17 13:11 UTC (permalink / raw)
  To: Lowry Li (Arm Technology China)
  Cc: Liviu Dudau, james qian wang (Arm Technology China),
	maarten.lankhorst, seanpaul, airlied, Brian Starkey,
	Mihail Atanassov, Ayan Halder,
	Jonathan Chai (Arm Technology China),
	linux-kernel, dri-devel, Julien Yin (Arm Technology China),
	nd

On Fri, Aug 2, 2019 at 11:43 AM Lowry Li (Arm Technology China)
<Lowry.Li@arm.com> wrote:
>
> From: "Lowry Li (Arm Technology China)" <Lowry.Li@arm.com>
>
> Adds to print the event message when error happens and the same event
> will not be printed until next vsync.
>
> Changes since v2:
> 1. Refine komeda_sprintf();
> 2. Not using STR_SZ macro for the string size in komeda_print_events().
>
> Changes since v1:
> 1. Handling the event print by CONFIG_KOMEDA_ERROR_PRINT;
> 2. Changing the max string size to 256.
>
> Signed-off-by: Lowry Li (Arm Technology China) <lowry.li@arm.com>
> ---
>  drivers/gpu/drm/arm/display/Kconfig               |   6 +
>  drivers/gpu/drm/arm/display/komeda/Makefile       |   2 +
>  drivers/gpu/drm/arm/display/komeda/komeda_dev.h   |  15 +++
>  drivers/gpu/drm/arm/display/komeda/komeda_event.c | 140 ++++++++++++++++++++++
>  drivers/gpu/drm/arm/display/komeda/komeda_kms.c   |   4 +
>  5 files changed, 167 insertions(+)
>  create mode 100644 drivers/gpu/drm/arm/display/komeda/komeda_event.c
>
> diff --git a/drivers/gpu/drm/arm/display/Kconfig b/drivers/gpu/drm/arm/display/Kconfig
> index cec0639..e87ff86 100644
> --- a/drivers/gpu/drm/arm/display/Kconfig
> +++ b/drivers/gpu/drm/arm/display/Kconfig
> @@ -12,3 +12,9 @@ config DRM_KOMEDA
>           Processor driver. It supports the D71 variants of the hardware.
>
>           If compiled as a module it will be called komeda.
> +
> +config DRM_KOMEDA_ERROR_PRINT
> +       bool "Enable komeda error print"
> +       depends on DRM_KOMEDA
> +       help
> +         Choose this option to enable error printing.
> diff --git a/drivers/gpu/drm/arm/display/komeda/Makefile b/drivers/gpu/drm/arm/display/komeda/Makefile
> index 5c3900c..f095a1c 100644
> --- a/drivers/gpu/drm/arm/display/komeda/Makefile
> +++ b/drivers/gpu/drm/arm/display/komeda/Makefile
> @@ -22,4 +22,6 @@ komeda-y += \
>         d71/d71_dev.o \
>         d71/d71_component.o
>
> +komeda-$(CONFIG_DRM_KOMEDA_ERROR_PRINT) += komeda_event.o
> +
>  obj-$(CONFIG_DRM_KOMEDA) += komeda.o
> diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_dev.h b/drivers/gpu/drm/arm/display/komeda/komeda_dev.h
> index d1c86b6..e28e7e6 100644
> --- a/drivers/gpu/drm/arm/display/komeda/komeda_dev.h
> +++ b/drivers/gpu/drm/arm/display/komeda/komeda_dev.h
> @@ -40,6 +40,17 @@
>  #define KOMEDA_ERR_TTNG                        BIT_ULL(30)
>  #define KOMEDA_ERR_TTF                 BIT_ULL(31)
>
> +#define KOMEDA_ERR_EVENTS      \
> +       (KOMEDA_EVENT_URUN      | KOMEDA_EVENT_IBSY     | KOMEDA_EVENT_OVR |\
> +       KOMEDA_ERR_TETO         | KOMEDA_ERR_TEMR       | KOMEDA_ERR_TITR |\
> +       KOMEDA_ERR_CPE          | KOMEDA_ERR_CFGE       | KOMEDA_ERR_AXIE |\
> +       KOMEDA_ERR_ACE0         | KOMEDA_ERR_ACE1       | KOMEDA_ERR_ACE2 |\
> +       KOMEDA_ERR_ACE3         | KOMEDA_ERR_DRIFTTO    | KOMEDA_ERR_FRAMETO |\
> +       KOMEDA_ERR_ZME          | KOMEDA_ERR_MERR       | KOMEDA_ERR_TCF |\
> +       KOMEDA_ERR_TTNG         | KOMEDA_ERR_TTF)
> +
> +#define KOMEDA_WARN_EVENTS     KOMEDA_ERR_CSCE
> +
>  /* malidp device id */
>  enum {
>         MALI_D71 = 0,
> @@ -207,4 +218,8 @@ struct komeda_dev {
>
>  struct komeda_dev *dev_to_mdev(struct device *dev);
>
> +#ifdef CONFIG_DRM_KOMEDA_ERROR_PRINT
> +void komeda_print_events(struct komeda_events *evts);
> +#endif
> +
>  #endif /*_KOMEDA_DEV_H_*/
> diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_event.c b/drivers/gpu/drm/arm/display/komeda/komeda_event.c
> new file mode 100644
> index 0000000..a36fb86
> --- /dev/null
> +++ b/drivers/gpu/drm/arm/display/komeda/komeda_event.c
> @@ -0,0 +1,140 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * (C) COPYRIGHT 2019 ARM Limited. All rights reserved.
> + * Author: James.Qian.Wang <james.qian.wang@arm.com>
> + *
> + */
> +#include <drm/drm_print.h>
> +
> +#include "komeda_dev.h"
> +
> +struct komeda_str {
> +       char *str;
> +       u32 sz;
> +       u32 len;
> +};
> +
> +/* return 0 on success,  < 0 on no space.
> + */
> +static int komeda_sprintf(struct komeda_str *str, const char *fmt, ...)
> +{
> +       va_list args;
> +       int num, free_sz;
> +       int err;
> +
> +       free_sz = str->sz - str->len - 1;
> +       if (free_sz <= 0)
> +               return -ENOSPC;
> +
> +       va_start(args, fmt);
> +
> +       num = vsnprintf(str->str + str->len, free_sz, fmt, args);
> +
> +       va_end(args);
> +
> +       if (num < free_sz) {
> +               str->len += num;
> +               err = 0;
> +       } else {
> +               str->len = str->sz - 1;
> +               err = -ENOSPC;
> +       }
> +
> +       return err;
> +}
> +
> +static void evt_sprintf(struct komeda_str *str, u64 evt, const char *msg)
> +{
> +       if (evt)
> +               komeda_sprintf(str, msg);
> +}
> +
> +static void evt_str(struct komeda_str *str, u64 events)
> +{
> +       if (events == 0ULL) {
> +               komeda_sprintf(str, "None");
> +               return;
> +       }
> +
> +       evt_sprintf(str, events & KOMEDA_EVENT_VSYNC, "VSYNC|");
> +       evt_sprintf(str, events & KOMEDA_EVENT_FLIP, "FLIP|");
> +       evt_sprintf(str, events & KOMEDA_EVENT_EOW, "EOW|");
> +       evt_sprintf(str, events & KOMEDA_EVENT_MODE, "OP-MODE|");
> +
> +       evt_sprintf(str, events & KOMEDA_EVENT_URUN, "UNDERRUN|");
> +       evt_sprintf(str, events & KOMEDA_EVENT_OVR, "OVERRUN|");
> +
> +       /* GLB error */
> +       evt_sprintf(str, events & KOMEDA_ERR_MERR, "MERR|");
> +       evt_sprintf(str, events & KOMEDA_ERR_FRAMETO, "FRAMETO|");
> +
> +       /* DOU error */
> +       evt_sprintf(str, events & KOMEDA_ERR_DRIFTTO, "DRIFTTO|");
> +       evt_sprintf(str, events & KOMEDA_ERR_FRAMETO, "FRAMETO|");
> +       evt_sprintf(str, events & KOMEDA_ERR_TETO, "TETO|");
> +       evt_sprintf(str, events & KOMEDA_ERR_CSCE, "CSCE|");
> +
> +       /* LPU errors or events */
> +       evt_sprintf(str, events & KOMEDA_EVENT_IBSY, "IBSY|");
> +       evt_sprintf(str, events & KOMEDA_ERR_AXIE, "AXIE|");
> +       evt_sprintf(str, events & KOMEDA_ERR_ACE0, "ACE0|");
> +       evt_sprintf(str, events & KOMEDA_ERR_ACE1, "ACE1|");
> +       evt_sprintf(str, events & KOMEDA_ERR_ACE2, "ACE2|");
> +       evt_sprintf(str, events & KOMEDA_ERR_ACE3, "ACE3|");
> +
> +       /* LPU TBU errors*/
> +       evt_sprintf(str, events & KOMEDA_ERR_TCF, "TCF|");
> +       evt_sprintf(str, events & KOMEDA_ERR_TTNG, "TTNG|");
> +       evt_sprintf(str, events & KOMEDA_ERR_TITR, "TITR|");
> +       evt_sprintf(str, events & KOMEDA_ERR_TEMR, "TEMR|");
> +       evt_sprintf(str, events & KOMEDA_ERR_TTF, "TTF|");
> +
> +       /* CU errors*/
> +       evt_sprintf(str, events & KOMEDA_ERR_CPE, "COPROC|");
> +       evt_sprintf(str, events & KOMEDA_ERR_ZME, "ZME|");
> +       evt_sprintf(str, events & KOMEDA_ERR_CFGE, "CFGE|");
> +       evt_sprintf(str, events & KOMEDA_ERR_TEMR, "TEMR|");
> +
> +       if (str->len > 0 && (str->str[str->len - 1] == '|')) {
> +               str->str[str->len - 1] = 0;
> +               str->len--;
> +       }
> +}
> +
> +static bool is_new_frame(struct komeda_events *a)
> +{
> +       return (a->pipes[0] | a->pipes[1]) &
> +              (KOMEDA_EVENT_FLIP | KOMEDA_EVENT_EOW);
> +}
> +
> +void komeda_print_events(struct komeda_events *evts)
> +{
> +       u64 print_evts = KOMEDA_ERR_EVENTS;
> +       static bool en_print = true;
> +
> +       /* reduce the same msg print, only print the first evt for one frame */
> +       if (evts->global || is_new_frame(evts))
> +               en_print = true;
> +       if (!en_print)
> +               return;
> +
> +       if ((evts->global | evts->pipes[0] | evts->pipes[1]) & print_evts) {
> +               char msg[256];
> +               struct komeda_str str;
> +
> +               str.str = msg;
> +               str.sz  = sizeof(msg);
> +               str.len = 0;
> +
> +               komeda_sprintf(&str, "gcu: ");
> +               evt_str(&str, evts->global);
> +               komeda_sprintf(&str, ", pipes[0]: ");
> +               evt_str(&str, evts->pipes[0]);
> +               komeda_sprintf(&str, ", pipes[1]: ");
> +               evt_str(&str, evts->pipes[1]);
> +
> +               DRM_ERROR("err detect: %s\n", msg);
> +
> +               en_print = false;
> +       }
> +}
> diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_kms.c b/drivers/gpu/drm/arm/display/komeda/komeda_kms.c
> index 419a8b0..0fafc36 100644
> --- a/drivers/gpu/drm/arm/display/komeda/komeda_kms.c
> +++ b/drivers/gpu/drm/arm/display/komeda/komeda_kms.c
> @@ -47,6 +47,10 @@ static irqreturn_t komeda_kms_irq_handler(int irq, void *data)
>         memset(&evts, 0, sizeof(evts));
>         status = mdev->funcs->irq_handler(mdev, &evts);
>
> +#ifdef CONFIG_DRM_KOMEDA_ERROR_PRINT
> +       komeda_print_events(&evts);
> +#endif

#ifdef in code is discouraged, the usual way we handle these cases is
by having a dummy static inline function which does nothing in the
headers for the case a config option isn't enabled.
-Daniel

> +
>         /* Notify the crtc to handle the events */
>         for (i = 0; i < kms->n_crtcs; i++)
>                 komeda_crtc_handle_event(&kms->crtcs[i], &evts);
> --
> 1.9.1
>
> _______________________________________________
> dri-devel mailing list
> dri-devel@lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/dri-devel



-- 
Daniel Vetter
Software Engineer, Intel Corporation
+41 (0) 79 365 57 48 - http://blog.ffwll.ch

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [PATCH] drm/komeda: Adds error event print functionality
@ 2019-09-17 13:11   ` Daniel Vetter
  0 siblings, 0 replies; 37+ messages in thread
From: Daniel Vetter @ 2019-09-17 13:11 UTC (permalink / raw)
  To: Lowry Li (Arm Technology China)
  Cc: nd, Ayan Halder, airlied, Liviu Dudau,
	Jonathan Chai (Arm Technology China),
	linux-kernel, dri-devel, Julien Yin (Arm Technology China),
	james qian wang (Arm Technology China),
	seanpaul, Mihail Atanassov

On Fri, Aug 2, 2019 at 11:43 AM Lowry Li (Arm Technology China)
<Lowry.Li@arm.com> wrote:
>
> From: "Lowry Li (Arm Technology China)" <Lowry.Li@arm.com>
>
> Adds to print the event message when error happens and the same event
> will not be printed until next vsync.
>
> Changes since v2:
> 1. Refine komeda_sprintf();
> 2. Not using STR_SZ macro for the string size in komeda_print_events().
>
> Changes since v1:
> 1. Handling the event print by CONFIG_KOMEDA_ERROR_PRINT;
> 2. Changing the max string size to 256.
>
> Signed-off-by: Lowry Li (Arm Technology China) <lowry.li@arm.com>
> ---
>  drivers/gpu/drm/arm/display/Kconfig               |   6 +
>  drivers/gpu/drm/arm/display/komeda/Makefile       |   2 +
>  drivers/gpu/drm/arm/display/komeda/komeda_dev.h   |  15 +++
>  drivers/gpu/drm/arm/display/komeda/komeda_event.c | 140 ++++++++++++++++++++++
>  drivers/gpu/drm/arm/display/komeda/komeda_kms.c   |   4 +
>  5 files changed, 167 insertions(+)
>  create mode 100644 drivers/gpu/drm/arm/display/komeda/komeda_event.c
>
> diff --git a/drivers/gpu/drm/arm/display/Kconfig b/drivers/gpu/drm/arm/display/Kconfig
> index cec0639..e87ff86 100644
> --- a/drivers/gpu/drm/arm/display/Kconfig
> +++ b/drivers/gpu/drm/arm/display/Kconfig
> @@ -12,3 +12,9 @@ config DRM_KOMEDA
>           Processor driver. It supports the D71 variants of the hardware.
>
>           If compiled as a module it will be called komeda.
> +
> +config DRM_KOMEDA_ERROR_PRINT
> +       bool "Enable komeda error print"
> +       depends on DRM_KOMEDA
> +       help
> +         Choose this option to enable error printing.
> diff --git a/drivers/gpu/drm/arm/display/komeda/Makefile b/drivers/gpu/drm/arm/display/komeda/Makefile
> index 5c3900c..f095a1c 100644
> --- a/drivers/gpu/drm/arm/display/komeda/Makefile
> +++ b/drivers/gpu/drm/arm/display/komeda/Makefile
> @@ -22,4 +22,6 @@ komeda-y += \
>         d71/d71_dev.o \
>         d71/d71_component.o
>
> +komeda-$(CONFIG_DRM_KOMEDA_ERROR_PRINT) += komeda_event.o
> +
>  obj-$(CONFIG_DRM_KOMEDA) += komeda.o
> diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_dev.h b/drivers/gpu/drm/arm/display/komeda/komeda_dev.h
> index d1c86b6..e28e7e6 100644
> --- a/drivers/gpu/drm/arm/display/komeda/komeda_dev.h
> +++ b/drivers/gpu/drm/arm/display/komeda/komeda_dev.h
> @@ -40,6 +40,17 @@
>  #define KOMEDA_ERR_TTNG                        BIT_ULL(30)
>  #define KOMEDA_ERR_TTF                 BIT_ULL(31)
>
> +#define KOMEDA_ERR_EVENTS      \
> +       (KOMEDA_EVENT_URUN      | KOMEDA_EVENT_IBSY     | KOMEDA_EVENT_OVR |\
> +       KOMEDA_ERR_TETO         | KOMEDA_ERR_TEMR       | KOMEDA_ERR_TITR |\
> +       KOMEDA_ERR_CPE          | KOMEDA_ERR_CFGE       | KOMEDA_ERR_AXIE |\
> +       KOMEDA_ERR_ACE0         | KOMEDA_ERR_ACE1       | KOMEDA_ERR_ACE2 |\
> +       KOMEDA_ERR_ACE3         | KOMEDA_ERR_DRIFTTO    | KOMEDA_ERR_FRAMETO |\
> +       KOMEDA_ERR_ZME          | KOMEDA_ERR_MERR       | KOMEDA_ERR_TCF |\
> +       KOMEDA_ERR_TTNG         | KOMEDA_ERR_TTF)
> +
> +#define KOMEDA_WARN_EVENTS     KOMEDA_ERR_CSCE
> +
>  /* malidp device id */
>  enum {
>         MALI_D71 = 0,
> @@ -207,4 +218,8 @@ struct komeda_dev {
>
>  struct komeda_dev *dev_to_mdev(struct device *dev);
>
> +#ifdef CONFIG_DRM_KOMEDA_ERROR_PRINT
> +void komeda_print_events(struct komeda_events *evts);
> +#endif
> +
>  #endif /*_KOMEDA_DEV_H_*/
> diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_event.c b/drivers/gpu/drm/arm/display/komeda/komeda_event.c
> new file mode 100644
> index 0000000..a36fb86
> --- /dev/null
> +++ b/drivers/gpu/drm/arm/display/komeda/komeda_event.c
> @@ -0,0 +1,140 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * (C) COPYRIGHT 2019 ARM Limited. All rights reserved.
> + * Author: James.Qian.Wang <james.qian.wang@arm.com>
> + *
> + */
> +#include <drm/drm_print.h>
> +
> +#include "komeda_dev.h"
> +
> +struct komeda_str {
> +       char *str;
> +       u32 sz;
> +       u32 len;
> +};
> +
> +/* return 0 on success,  < 0 on no space.
> + */
> +static int komeda_sprintf(struct komeda_str *str, const char *fmt, ...)
> +{
> +       va_list args;
> +       int num, free_sz;
> +       int err;
> +
> +       free_sz = str->sz - str->len - 1;
> +       if (free_sz <= 0)
> +               return -ENOSPC;
> +
> +       va_start(args, fmt);
> +
> +       num = vsnprintf(str->str + str->len, free_sz, fmt, args);
> +
> +       va_end(args);
> +
> +       if (num < free_sz) {
> +               str->len += num;
> +               err = 0;
> +       } else {
> +               str->len = str->sz - 1;
> +               err = -ENOSPC;
> +       }
> +
> +       return err;
> +}
> +
> +static void evt_sprintf(struct komeda_str *str, u64 evt, const char *msg)
> +{
> +       if (evt)
> +               komeda_sprintf(str, msg);
> +}
> +
> +static void evt_str(struct komeda_str *str, u64 events)
> +{
> +       if (events == 0ULL) {
> +               komeda_sprintf(str, "None");
> +               return;
> +       }
> +
> +       evt_sprintf(str, events & KOMEDA_EVENT_VSYNC, "VSYNC|");
> +       evt_sprintf(str, events & KOMEDA_EVENT_FLIP, "FLIP|");
> +       evt_sprintf(str, events & KOMEDA_EVENT_EOW, "EOW|");
> +       evt_sprintf(str, events & KOMEDA_EVENT_MODE, "OP-MODE|");
> +
> +       evt_sprintf(str, events & KOMEDA_EVENT_URUN, "UNDERRUN|");
> +       evt_sprintf(str, events & KOMEDA_EVENT_OVR, "OVERRUN|");
> +
> +       /* GLB error */
> +       evt_sprintf(str, events & KOMEDA_ERR_MERR, "MERR|");
> +       evt_sprintf(str, events & KOMEDA_ERR_FRAMETO, "FRAMETO|");
> +
> +       /* DOU error */
> +       evt_sprintf(str, events & KOMEDA_ERR_DRIFTTO, "DRIFTTO|");
> +       evt_sprintf(str, events & KOMEDA_ERR_FRAMETO, "FRAMETO|");
> +       evt_sprintf(str, events & KOMEDA_ERR_TETO, "TETO|");
> +       evt_sprintf(str, events & KOMEDA_ERR_CSCE, "CSCE|");
> +
> +       /* LPU errors or events */
> +       evt_sprintf(str, events & KOMEDA_EVENT_IBSY, "IBSY|");
> +       evt_sprintf(str, events & KOMEDA_ERR_AXIE, "AXIE|");
> +       evt_sprintf(str, events & KOMEDA_ERR_ACE0, "ACE0|");
> +       evt_sprintf(str, events & KOMEDA_ERR_ACE1, "ACE1|");
> +       evt_sprintf(str, events & KOMEDA_ERR_ACE2, "ACE2|");
> +       evt_sprintf(str, events & KOMEDA_ERR_ACE3, "ACE3|");
> +
> +       /* LPU TBU errors*/
> +       evt_sprintf(str, events & KOMEDA_ERR_TCF, "TCF|");
> +       evt_sprintf(str, events & KOMEDA_ERR_TTNG, "TTNG|");
> +       evt_sprintf(str, events & KOMEDA_ERR_TITR, "TITR|");
> +       evt_sprintf(str, events & KOMEDA_ERR_TEMR, "TEMR|");
> +       evt_sprintf(str, events & KOMEDA_ERR_TTF, "TTF|");
> +
> +       /* CU errors*/
> +       evt_sprintf(str, events & KOMEDA_ERR_CPE, "COPROC|");
> +       evt_sprintf(str, events & KOMEDA_ERR_ZME, "ZME|");
> +       evt_sprintf(str, events & KOMEDA_ERR_CFGE, "CFGE|");
> +       evt_sprintf(str, events & KOMEDA_ERR_TEMR, "TEMR|");
> +
> +       if (str->len > 0 && (str->str[str->len - 1] == '|')) {
> +               str->str[str->len - 1] = 0;
> +               str->len--;
> +       }
> +}
> +
> +static bool is_new_frame(struct komeda_events *a)
> +{
> +       return (a->pipes[0] | a->pipes[1]) &
> +              (KOMEDA_EVENT_FLIP | KOMEDA_EVENT_EOW);
> +}
> +
> +void komeda_print_events(struct komeda_events *evts)
> +{
> +       u64 print_evts = KOMEDA_ERR_EVENTS;
> +       static bool en_print = true;
> +
> +       /* reduce the same msg print, only print the first evt for one frame */
> +       if (evts->global || is_new_frame(evts))
> +               en_print = true;
> +       if (!en_print)
> +               return;
> +
> +       if ((evts->global | evts->pipes[0] | evts->pipes[1]) & print_evts) {
> +               char msg[256];
> +               struct komeda_str str;
> +
> +               str.str = msg;
> +               str.sz  = sizeof(msg);
> +               str.len = 0;
> +
> +               komeda_sprintf(&str, "gcu: ");
> +               evt_str(&str, evts->global);
> +               komeda_sprintf(&str, ", pipes[0]: ");
> +               evt_str(&str, evts->pipes[0]);
> +               komeda_sprintf(&str, ", pipes[1]: ");
> +               evt_str(&str, evts->pipes[1]);
> +
> +               DRM_ERROR("err detect: %s\n", msg);
> +
> +               en_print = false;
> +       }
> +}
> diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_kms.c b/drivers/gpu/drm/arm/display/komeda/komeda_kms.c
> index 419a8b0..0fafc36 100644
> --- a/drivers/gpu/drm/arm/display/komeda/komeda_kms.c
> +++ b/drivers/gpu/drm/arm/display/komeda/komeda_kms.c
> @@ -47,6 +47,10 @@ static irqreturn_t komeda_kms_irq_handler(int irq, void *data)
>         memset(&evts, 0, sizeof(evts));
>         status = mdev->funcs->irq_handler(mdev, &evts);
>
> +#ifdef CONFIG_DRM_KOMEDA_ERROR_PRINT
> +       komeda_print_events(&evts);
> +#endif

#ifdef in code is discouraged, the usual way we handle these cases is
by having a dummy static inline function which does nothing in the
headers for the case a config option isn't enabled.
-Daniel

> +
>         /* Notify the crtc to handle the events */
>         for (i = 0; i < kms->n_crtcs; i++)
>                 komeda_crtc_handle_event(&kms->crtcs[i], &evts);
> --
> 1.9.1
>
> _______________________________________________
> dri-devel mailing list
> dri-devel@lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/dri-devel



-- 
Daniel Vetter
Software Engineer, Intel Corporation
+41 (0) 79 365 57 48 - http://blog.ffwll.ch
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [PATCH] drm/komeda: Adds error event print functionality
  2019-08-02 10:05   ` Mihail Atanassov
@ 2019-08-02 10:43     ` james qian wang (Arm Technology China)
  -1 siblings, 0 replies; 37+ messages in thread
From: james qian wang (Arm Technology China) @ 2019-08-02 10:43 UTC (permalink / raw)
  To: Mihail Atanassov
  Cc: Lowry Li (Arm Technology China),
	Liviu Dudau, maarten.lankhorst, seanpaul, airlied, Brian Starkey,
	Julien Yin (Arm Technology China),
	Jonathan Chai (Arm Technology China),
	Ayan Halder, dri-devel, linux-kernel, nd

On Fri, Aug 02, 2019 at 06:05:08PM +0800, Mihail Atanassov wrote:
> On Friday, 2 August 2019 10:43:10 BST Lowry Li (Arm Technology China) wrote:
> > From: "Lowry Li (Arm Technology China)" <Lowry.Li@arm.com>
> > 
> > Adds to print the event message when error happens and the same event
> > will not be printed until next vsync.
> > 
> > Changes since v2:
> > 1. Refine komeda_sprintf();
> > 2. Not using STR_SZ macro for the string size in komeda_print_events().
> > 
> > Changes since v1:
> > 1. Handling the event print by CONFIG_KOMEDA_ERROR_PRINT;
> > 2. Changing the max string size to 256.
> > 
> > Signed-off-by: Lowry Li (Arm Technology China) <lowry.li@arm.com>
> 
> Reviewed-by: Mihail Atanassov <mihail.atanassov@arm.com>
> 
> BR,
> Mihail

looks good to me.

Reviewed-by: James Qian Wang (Arm Technology China) <james.qian.wang@arm.com>

> 
> > ---
> >  drivers/gpu/drm/arm/display/Kconfig               |   6 +
> >  drivers/gpu/drm/arm/display/komeda/Makefile       |   2 +
> >  drivers/gpu/drm/arm/display/komeda/komeda_dev.h   |  15 +++
> >  drivers/gpu/drm/arm/display/komeda/komeda_event.c | 140
> > ++++++++++++++++++++++ drivers/gpu/drm/arm/display/komeda/komeda_kms.c   | 
> >  4 +
> >  5 files changed, 167 insertions(+)
> >  create mode 100644 drivers/gpu/drm/arm/display/komeda/komeda_event.c
> > 
> > diff --git a/drivers/gpu/drm/arm/display/Kconfig
> > b/drivers/gpu/drm/arm/display/Kconfig index cec0639..e87ff86 100644
> > --- a/drivers/gpu/drm/arm/display/Kconfig
> > +++ b/drivers/gpu/drm/arm/display/Kconfig
> > @@ -12,3 +12,9 @@ config DRM_KOMEDA
> >  	  Processor driver. It supports the D71 variants of the hardware.
> > 
> >  	  If compiled as a module it will be called komeda.
> > +
> > +config DRM_KOMEDA_ERROR_PRINT
> > +	bool "Enable komeda error print"
> > +	depends on DRM_KOMEDA
> > +	help
> > +	  Choose this option to enable error printing.
> > diff --git a/drivers/gpu/drm/arm/display/komeda/Makefile
> > b/drivers/gpu/drm/arm/display/komeda/Makefile index 5c3900c..f095a1c 100644
> > --- a/drivers/gpu/drm/arm/display/komeda/Makefile
> > +++ b/drivers/gpu/drm/arm/display/komeda/Makefile
> > @@ -22,4 +22,6 @@ komeda-y += \
> >  	d71/d71_dev.o \
> >  	d71/d71_component.o
> > 
> > +komeda-$(CONFIG_DRM_KOMEDA_ERROR_PRINT) += komeda_event.o
> > +
> >  obj-$(CONFIG_DRM_KOMEDA) += komeda.o
> > diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_dev.h
> > b/drivers/gpu/drm/arm/display/komeda/komeda_dev.h index d1c86b6..e28e7e6
> > 100644
> > --- a/drivers/gpu/drm/arm/display/komeda/komeda_dev.h
> > +++ b/drivers/gpu/drm/arm/display/komeda/komeda_dev.h
> > @@ -40,6 +40,17 @@
> >  #define KOMEDA_ERR_TTNG			BIT_ULL(30)
> >  #define KOMEDA_ERR_TTF			BIT_ULL(31)
> > 
> > +#define KOMEDA_ERR_EVENTS	\
> > +	(KOMEDA_EVENT_URUN	| KOMEDA_EVENT_IBSY	| KOMEDA_EVENT_OVR |
> \
> > +	KOMEDA_ERR_TETO		| KOMEDA_ERR_TEMR	| 
> KOMEDA_ERR_TITR |\
> > +	KOMEDA_ERR_CPE		| KOMEDA_ERR_CFGE	| 
> KOMEDA_ERR_AXIE |\
> > +	KOMEDA_ERR_ACE0		| KOMEDA_ERR_ACE1	| 
> KOMEDA_ERR_ACE2 |\
> > +	KOMEDA_ERR_ACE3		| KOMEDA_ERR_DRIFTTO	| 
> KOMEDA_ERR_FRAMETO |\
> > +	KOMEDA_ERR_ZME		| KOMEDA_ERR_MERR	| 
> KOMEDA_ERR_TCF |\
> > +	KOMEDA_ERR_TTNG		| KOMEDA_ERR_TTF)
> > +
> > +#define KOMEDA_WARN_EVENTS	KOMEDA_ERR_CSCE
> > +
> >  /* malidp device id */
> >  enum {
> >  	MALI_D71 = 0,
> > @@ -207,4 +218,8 @@ struct komeda_dev {
> > 
> >  struct komeda_dev *dev_to_mdev(struct device *dev);
> > 
> > +#ifdef CONFIG_DRM_KOMEDA_ERROR_PRINT
> > +void komeda_print_events(struct komeda_events *evts);
> > +#endif
> > +
> >  #endif /*_KOMEDA_DEV_H_*/
> > diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_event.c
> > b/drivers/gpu/drm/arm/display/komeda/komeda_event.c new file mode 100644
> > index 0000000..a36fb86
> > --- /dev/null
> > +++ b/drivers/gpu/drm/arm/display/komeda/komeda_event.c
> > @@ -0,0 +1,140 @@
> > +// SPDX-License-Identifier: GPL-2.0
> > +/*
> > + * (C) COPYRIGHT 2019 ARM Limited. All rights reserved.
> > + * Author: James.Qian.Wang <james.qian.wang@arm.com>
> > + *
> > + */
> > +#include <drm/drm_print.h>
> > +
> > +#include "komeda_dev.h"
> > +
> > +struct komeda_str {
> > +	char *str;
> > +	u32 sz;
> > +	u32 len;
> > +};
> > +
> > +/* return 0 on success,  < 0 on no space.
> > + */
> > +static int komeda_sprintf(struct komeda_str *str, const char *fmt, ...)
> > +{
> > +	va_list args;
> > +	int num, free_sz;
> > +	int err;
> > +
> > +	free_sz = str->sz - str->len - 1;
> > +	if (free_sz <= 0)
> > +		return -ENOSPC;
> > +
> > +	va_start(args, fmt);
> > +
> > +	num = vsnprintf(str->str + str->len, free_sz, fmt, args);
> > +
> > +	va_end(args);
> > +
> > +	if (num < free_sz) {
> > +		str->len += num;
> > +		err = 0;
> > +	} else {
> > +		str->len = str->sz - 1;
> > +		err = -ENOSPC;
> > +	}
> > +
> > +	return err;
> > +}
> > +
> > +static void evt_sprintf(struct komeda_str *str, u64 evt, const char *msg)
> > +{
> > +	if (evt)
> > +		komeda_sprintf(str, msg);
> > +}
> > +
> > +static void evt_str(struct komeda_str *str, u64 events)
> > +{
> > +	if (events == 0ULL) {
> > +		komeda_sprintf(str, "None");
> > +		return;
> > +	}
> > +
> > +	evt_sprintf(str, events & KOMEDA_EVENT_VSYNC, "VSYNC|");
> > +	evt_sprintf(str, events & KOMEDA_EVENT_FLIP, "FLIP|");
> > +	evt_sprintf(str, events & KOMEDA_EVENT_EOW, "EOW|");
> > +	evt_sprintf(str, events & KOMEDA_EVENT_MODE, "OP-MODE|");
> > +
> > +	evt_sprintf(str, events & KOMEDA_EVENT_URUN, "UNDERRUN|");
> > +	evt_sprintf(str, events & KOMEDA_EVENT_OVR, "OVERRUN|");
> > +
> > +	/* GLB error */
> > +	evt_sprintf(str, events & KOMEDA_ERR_MERR, "MERR|");
> > +	evt_sprintf(str, events & KOMEDA_ERR_FRAMETO, "FRAMETO|");
> > +
> > +	/* DOU error */
> > +	evt_sprintf(str, events & KOMEDA_ERR_DRIFTTO, "DRIFTTO|");
> > +	evt_sprintf(str, events & KOMEDA_ERR_FRAMETO, "FRAMETO|");
> > +	evt_sprintf(str, events & KOMEDA_ERR_TETO, "TETO|");
> > +	evt_sprintf(str, events & KOMEDA_ERR_CSCE, "CSCE|");
> > +
> > +	/* LPU errors or events */
> > +	evt_sprintf(str, events & KOMEDA_EVENT_IBSY, "IBSY|");
> > +	evt_sprintf(str, events & KOMEDA_ERR_AXIE, "AXIE|");
> > +	evt_sprintf(str, events & KOMEDA_ERR_ACE0, "ACE0|");
> > +	evt_sprintf(str, events & KOMEDA_ERR_ACE1, "ACE1|");
> > +	evt_sprintf(str, events & KOMEDA_ERR_ACE2, "ACE2|");
> > +	evt_sprintf(str, events & KOMEDA_ERR_ACE3, "ACE3|");
> > +
> > +	/* LPU TBU errors*/
> > +	evt_sprintf(str, events & KOMEDA_ERR_TCF, "TCF|");
> > +	evt_sprintf(str, events & KOMEDA_ERR_TTNG, "TTNG|");
> > +	evt_sprintf(str, events & KOMEDA_ERR_TITR, "TITR|");
> > +	evt_sprintf(str, events & KOMEDA_ERR_TEMR, "TEMR|");
> > +	evt_sprintf(str, events & KOMEDA_ERR_TTF, "TTF|");
> > +
> > +	/* CU errors*/
> > +	evt_sprintf(str, events & KOMEDA_ERR_CPE, "COPROC|");
> > +	evt_sprintf(str, events & KOMEDA_ERR_ZME, "ZME|");
> > +	evt_sprintf(str, events & KOMEDA_ERR_CFGE, "CFGE|");
> > +	evt_sprintf(str, events & KOMEDA_ERR_TEMR, "TEMR|");
> > +
> > +	if (str->len > 0 && (str->str[str->len - 1] == '|')) {
> > +		str->str[str->len - 1] = 0;
> > +		str->len--;
> > +	}
> > +}
> > +
> > +static bool is_new_frame(struct komeda_events *a)
> > +{
> > +	return (a->pipes[0] | a->pipes[1]) &
> > +	       (KOMEDA_EVENT_FLIP | KOMEDA_EVENT_EOW);
> > +}
> > +
> > +void komeda_print_events(struct komeda_events *evts)
> > +{
> > +	u64 print_evts = KOMEDA_ERR_EVENTS;
> > +	static bool en_print = true;
> > +
> > +	/* reduce the same msg print, only print the first evt for one 
> frame */
> > +	if (evts->global || is_new_frame(evts))
> > +		en_print = true;
> > +	if (!en_print)
> > +		return;
> > +
> > +	if ((evts->global | evts->pipes[0] | evts->pipes[1]) & print_evts) 
> {
> > +		char msg[256];
> > +		struct komeda_str str;
> > +
> > +		str.str = msg;
> > +		str.sz  = sizeof(msg);
> > +		str.len = 0;
> > +
> > +		komeda_sprintf(&str, "gcu: ");
> > +		evt_str(&str, evts->global);
> > +		komeda_sprintf(&str, ", pipes[0]: ");
> > +		evt_str(&str, evts->pipes[0]);
> > +		komeda_sprintf(&str, ", pipes[1]: ");
> > +		evt_str(&str, evts->pipes[1]);
> > +
> > +		DRM_ERROR("err detect: %s\n", msg);
> > +
> > +		en_print = false;
> > +	}
> > +}
> > diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_kms.c
> > b/drivers/gpu/drm/arm/display/komeda/komeda_kms.c index 419a8b0..0fafc36
> > 100644
> > --- a/drivers/gpu/drm/arm/display/komeda/komeda_kms.c
> > +++ b/drivers/gpu/drm/arm/display/komeda/komeda_kms.c
> > @@ -47,6 +47,10 @@ static irqreturn_t komeda_kms_irq_handler(int irq, void
> > *data) memset(&evts, 0, sizeof(evts));
> >  	status = mdev->funcs->irq_handler(mdev, &evts);
> > 
> > +#ifdef CONFIG_DRM_KOMEDA_ERROR_PRINT
> > +	komeda_print_events(&evts);
> > +#endif
> > +
> >  	/* Notify the crtc to handle the events */
> >  	for (i = 0; i < kms->n_crtcs; i++)
> >  		komeda_crtc_handle_event(&kms->crtcs[i], &evts);
> 
> 
> 

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [PATCH] drm/komeda: Adds error event print functionality
@ 2019-08-02 10:43     ` james qian wang (Arm Technology China)
  0 siblings, 0 replies; 37+ messages in thread
From: james qian wang (Arm Technology China) @ 2019-08-02 10:43 UTC (permalink / raw)
  To: Mihail Atanassov
  Cc: nd, Ayan Halder, airlied, Liviu Dudau,
	Jonathan Chai (Arm Technology China),
	linux-kernel, dri-devel, Julien Yin (Arm Technology China),
	seanpaul, Lowry Li (Arm Technology China)

On Fri, Aug 02, 2019 at 06:05:08PM +0800, Mihail Atanassov wrote:
> On Friday, 2 August 2019 10:43:10 BST Lowry Li (Arm Technology China) wrote:
> > From: "Lowry Li (Arm Technology China)" <Lowry.Li@arm.com>
> > 
> > Adds to print the event message when error happens and the same event
> > will not be printed until next vsync.
> > 
> > Changes since v2:
> > 1. Refine komeda_sprintf();
> > 2. Not using STR_SZ macro for the string size in komeda_print_events().
> > 
> > Changes since v1:
> > 1. Handling the event print by CONFIG_KOMEDA_ERROR_PRINT;
> > 2. Changing the max string size to 256.
> > 
> > Signed-off-by: Lowry Li (Arm Technology China) <lowry.li@arm.com>
> 
> Reviewed-by: Mihail Atanassov <mihail.atanassov@arm.com>
> 
> BR,
> Mihail

looks good to me.

Reviewed-by: James Qian Wang (Arm Technology China) <james.qian.wang@arm.com>

> 
> > ---
> >  drivers/gpu/drm/arm/display/Kconfig               |   6 +
> >  drivers/gpu/drm/arm/display/komeda/Makefile       |   2 +
> >  drivers/gpu/drm/arm/display/komeda/komeda_dev.h   |  15 +++
> >  drivers/gpu/drm/arm/display/komeda/komeda_event.c | 140
> > ++++++++++++++++++++++ drivers/gpu/drm/arm/display/komeda/komeda_kms.c   | 
> >  4 +
> >  5 files changed, 167 insertions(+)
> >  create mode 100644 drivers/gpu/drm/arm/display/komeda/komeda_event.c
> > 
> > diff --git a/drivers/gpu/drm/arm/display/Kconfig
> > b/drivers/gpu/drm/arm/display/Kconfig index cec0639..e87ff86 100644
> > --- a/drivers/gpu/drm/arm/display/Kconfig
> > +++ b/drivers/gpu/drm/arm/display/Kconfig
> > @@ -12,3 +12,9 @@ config DRM_KOMEDA
> >  	  Processor driver. It supports the D71 variants of the hardware.
> > 
> >  	  If compiled as a module it will be called komeda.
> > +
> > +config DRM_KOMEDA_ERROR_PRINT
> > +	bool "Enable komeda error print"
> > +	depends on DRM_KOMEDA
> > +	help
> > +	  Choose this option to enable error printing.
> > diff --git a/drivers/gpu/drm/arm/display/komeda/Makefile
> > b/drivers/gpu/drm/arm/display/komeda/Makefile index 5c3900c..f095a1c 100644
> > --- a/drivers/gpu/drm/arm/display/komeda/Makefile
> > +++ b/drivers/gpu/drm/arm/display/komeda/Makefile
> > @@ -22,4 +22,6 @@ komeda-y += \
> >  	d71/d71_dev.o \
> >  	d71/d71_component.o
> > 
> > +komeda-$(CONFIG_DRM_KOMEDA_ERROR_PRINT) += komeda_event.o
> > +
> >  obj-$(CONFIG_DRM_KOMEDA) += komeda.o
> > diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_dev.h
> > b/drivers/gpu/drm/arm/display/komeda/komeda_dev.h index d1c86b6..e28e7e6
> > 100644
> > --- a/drivers/gpu/drm/arm/display/komeda/komeda_dev.h
> > +++ b/drivers/gpu/drm/arm/display/komeda/komeda_dev.h
> > @@ -40,6 +40,17 @@
> >  #define KOMEDA_ERR_TTNG			BIT_ULL(30)
> >  #define KOMEDA_ERR_TTF			BIT_ULL(31)
> > 
> > +#define KOMEDA_ERR_EVENTS	\
> > +	(KOMEDA_EVENT_URUN	| KOMEDA_EVENT_IBSY	| KOMEDA_EVENT_OVR |
> \
> > +	KOMEDA_ERR_TETO		| KOMEDA_ERR_TEMR	| 
> KOMEDA_ERR_TITR |\
> > +	KOMEDA_ERR_CPE		| KOMEDA_ERR_CFGE	| 
> KOMEDA_ERR_AXIE |\
> > +	KOMEDA_ERR_ACE0		| KOMEDA_ERR_ACE1	| 
> KOMEDA_ERR_ACE2 |\
> > +	KOMEDA_ERR_ACE3		| KOMEDA_ERR_DRIFTTO	| 
> KOMEDA_ERR_FRAMETO |\
> > +	KOMEDA_ERR_ZME		| KOMEDA_ERR_MERR	| 
> KOMEDA_ERR_TCF |\
> > +	KOMEDA_ERR_TTNG		| KOMEDA_ERR_TTF)
> > +
> > +#define KOMEDA_WARN_EVENTS	KOMEDA_ERR_CSCE
> > +
> >  /* malidp device id */
> >  enum {
> >  	MALI_D71 = 0,
> > @@ -207,4 +218,8 @@ struct komeda_dev {
> > 
> >  struct komeda_dev *dev_to_mdev(struct device *dev);
> > 
> > +#ifdef CONFIG_DRM_KOMEDA_ERROR_PRINT
> > +void komeda_print_events(struct komeda_events *evts);
> > +#endif
> > +
> >  #endif /*_KOMEDA_DEV_H_*/
> > diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_event.c
> > b/drivers/gpu/drm/arm/display/komeda/komeda_event.c new file mode 100644
> > index 0000000..a36fb86
> > --- /dev/null
> > +++ b/drivers/gpu/drm/arm/display/komeda/komeda_event.c
> > @@ -0,0 +1,140 @@
> > +// SPDX-License-Identifier: GPL-2.0
> > +/*
> > + * (C) COPYRIGHT 2019 ARM Limited. All rights reserved.
> > + * Author: James.Qian.Wang <james.qian.wang@arm.com>
> > + *
> > + */
> > +#include <drm/drm_print.h>
> > +
> > +#include "komeda_dev.h"
> > +
> > +struct komeda_str {
> > +	char *str;
> > +	u32 sz;
> > +	u32 len;
> > +};
> > +
> > +/* return 0 on success,  < 0 on no space.
> > + */
> > +static int komeda_sprintf(struct komeda_str *str, const char *fmt, ...)
> > +{
> > +	va_list args;
> > +	int num, free_sz;
> > +	int err;
> > +
> > +	free_sz = str->sz - str->len - 1;
> > +	if (free_sz <= 0)
> > +		return -ENOSPC;
> > +
> > +	va_start(args, fmt);
> > +
> > +	num = vsnprintf(str->str + str->len, free_sz, fmt, args);
> > +
> > +	va_end(args);
> > +
> > +	if (num < free_sz) {
> > +		str->len += num;
> > +		err = 0;
> > +	} else {
> > +		str->len = str->sz - 1;
> > +		err = -ENOSPC;
> > +	}
> > +
> > +	return err;
> > +}
> > +
> > +static void evt_sprintf(struct komeda_str *str, u64 evt, const char *msg)
> > +{
> > +	if (evt)
> > +		komeda_sprintf(str, msg);
> > +}
> > +
> > +static void evt_str(struct komeda_str *str, u64 events)
> > +{
> > +	if (events == 0ULL) {
> > +		komeda_sprintf(str, "None");
> > +		return;
> > +	}
> > +
> > +	evt_sprintf(str, events & KOMEDA_EVENT_VSYNC, "VSYNC|");
> > +	evt_sprintf(str, events & KOMEDA_EVENT_FLIP, "FLIP|");
> > +	evt_sprintf(str, events & KOMEDA_EVENT_EOW, "EOW|");
> > +	evt_sprintf(str, events & KOMEDA_EVENT_MODE, "OP-MODE|");
> > +
> > +	evt_sprintf(str, events & KOMEDA_EVENT_URUN, "UNDERRUN|");
> > +	evt_sprintf(str, events & KOMEDA_EVENT_OVR, "OVERRUN|");
> > +
> > +	/* GLB error */
> > +	evt_sprintf(str, events & KOMEDA_ERR_MERR, "MERR|");
> > +	evt_sprintf(str, events & KOMEDA_ERR_FRAMETO, "FRAMETO|");
> > +
> > +	/* DOU error */
> > +	evt_sprintf(str, events & KOMEDA_ERR_DRIFTTO, "DRIFTTO|");
> > +	evt_sprintf(str, events & KOMEDA_ERR_FRAMETO, "FRAMETO|");
> > +	evt_sprintf(str, events & KOMEDA_ERR_TETO, "TETO|");
> > +	evt_sprintf(str, events & KOMEDA_ERR_CSCE, "CSCE|");
> > +
> > +	/* LPU errors or events */
> > +	evt_sprintf(str, events & KOMEDA_EVENT_IBSY, "IBSY|");
> > +	evt_sprintf(str, events & KOMEDA_ERR_AXIE, "AXIE|");
> > +	evt_sprintf(str, events & KOMEDA_ERR_ACE0, "ACE0|");
> > +	evt_sprintf(str, events & KOMEDA_ERR_ACE1, "ACE1|");
> > +	evt_sprintf(str, events & KOMEDA_ERR_ACE2, "ACE2|");
> > +	evt_sprintf(str, events & KOMEDA_ERR_ACE3, "ACE3|");
> > +
> > +	/* LPU TBU errors*/
> > +	evt_sprintf(str, events & KOMEDA_ERR_TCF, "TCF|");
> > +	evt_sprintf(str, events & KOMEDA_ERR_TTNG, "TTNG|");
> > +	evt_sprintf(str, events & KOMEDA_ERR_TITR, "TITR|");
> > +	evt_sprintf(str, events & KOMEDA_ERR_TEMR, "TEMR|");
> > +	evt_sprintf(str, events & KOMEDA_ERR_TTF, "TTF|");
> > +
> > +	/* CU errors*/
> > +	evt_sprintf(str, events & KOMEDA_ERR_CPE, "COPROC|");
> > +	evt_sprintf(str, events & KOMEDA_ERR_ZME, "ZME|");
> > +	evt_sprintf(str, events & KOMEDA_ERR_CFGE, "CFGE|");
> > +	evt_sprintf(str, events & KOMEDA_ERR_TEMR, "TEMR|");
> > +
> > +	if (str->len > 0 && (str->str[str->len - 1] == '|')) {
> > +		str->str[str->len - 1] = 0;
> > +		str->len--;
> > +	}
> > +}
> > +
> > +static bool is_new_frame(struct komeda_events *a)
> > +{
> > +	return (a->pipes[0] | a->pipes[1]) &
> > +	       (KOMEDA_EVENT_FLIP | KOMEDA_EVENT_EOW);
> > +}
> > +
> > +void komeda_print_events(struct komeda_events *evts)
> > +{
> > +	u64 print_evts = KOMEDA_ERR_EVENTS;
> > +	static bool en_print = true;
> > +
> > +	/* reduce the same msg print, only print the first evt for one 
> frame */
> > +	if (evts->global || is_new_frame(evts))
> > +		en_print = true;
> > +	if (!en_print)
> > +		return;
> > +
> > +	if ((evts->global | evts->pipes[0] | evts->pipes[1]) & print_evts) 
> {
> > +		char msg[256];
> > +		struct komeda_str str;
> > +
> > +		str.str = msg;
> > +		str.sz  = sizeof(msg);
> > +		str.len = 0;
> > +
> > +		komeda_sprintf(&str, "gcu: ");
> > +		evt_str(&str, evts->global);
> > +		komeda_sprintf(&str, ", pipes[0]: ");
> > +		evt_str(&str, evts->pipes[0]);
> > +		komeda_sprintf(&str, ", pipes[1]: ");
> > +		evt_str(&str, evts->pipes[1]);
> > +
> > +		DRM_ERROR("err detect: %s\n", msg);
> > +
> > +		en_print = false;
> > +	}
> > +}
> > diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_kms.c
> > b/drivers/gpu/drm/arm/display/komeda/komeda_kms.c index 419a8b0..0fafc36
> > 100644
> > --- a/drivers/gpu/drm/arm/display/komeda/komeda_kms.c
> > +++ b/drivers/gpu/drm/arm/display/komeda/komeda_kms.c
> > @@ -47,6 +47,10 @@ static irqreturn_t komeda_kms_irq_handler(int irq, void
> > *data) memset(&evts, 0, sizeof(evts));
> >  	status = mdev->funcs->irq_handler(mdev, &evts);
> > 
> > +#ifdef CONFIG_DRM_KOMEDA_ERROR_PRINT
> > +	komeda_print_events(&evts);
> > +#endif
> > +
> >  	/* Notify the crtc to handle the events */
> >  	for (i = 0; i < kms->n_crtcs; i++)
> >  		komeda_crtc_handle_event(&kms->crtcs[i], &evts);
> 
> 
> 
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [PATCH] drm/komeda: Adds error event print functionality
  2019-08-02  9:43 ` Lowry Li (Arm Technology China)
@ 2019-08-02 10:05   ` Mihail Atanassov
  -1 siblings, 0 replies; 37+ messages in thread
From: Mihail Atanassov @ 2019-08-02 10:05 UTC (permalink / raw)
  To: Lowry Li (Arm Technology China)
  Cc: Liviu Dudau, james qian wang (Arm Technology China),
	maarten.lankhorst, seanpaul, airlied, Brian Starkey,
	Julien Yin (Arm Technology China),
	Jonathan Chai (Arm Technology China),
	Ayan Halder, dri-devel, linux-kernel, nd

On Friday, 2 August 2019 10:43:10 BST Lowry Li (Arm Technology China) wrote:
> From: "Lowry Li (Arm Technology China)" <Lowry.Li@arm.com>
> 
> Adds to print the event message when error happens and the same event
> will not be printed until next vsync.
> 
> Changes since v2:
> 1. Refine komeda_sprintf();
> 2. Not using STR_SZ macro for the string size in komeda_print_events().
> 
> Changes since v1:
> 1. Handling the event print by CONFIG_KOMEDA_ERROR_PRINT;
> 2. Changing the max string size to 256.
> 
> Signed-off-by: Lowry Li (Arm Technology China) <lowry.li@arm.com>

Reviewed-by: Mihail Atanassov <mihail.atanassov@arm.com>

BR,
Mihail

> ---
>  drivers/gpu/drm/arm/display/Kconfig               |   6 +
>  drivers/gpu/drm/arm/display/komeda/Makefile       |   2 +
>  drivers/gpu/drm/arm/display/komeda/komeda_dev.h   |  15 +++
>  drivers/gpu/drm/arm/display/komeda/komeda_event.c | 140
> ++++++++++++++++++++++ drivers/gpu/drm/arm/display/komeda/komeda_kms.c   | 
>  4 +
>  5 files changed, 167 insertions(+)
>  create mode 100644 drivers/gpu/drm/arm/display/komeda/komeda_event.c
> 
> diff --git a/drivers/gpu/drm/arm/display/Kconfig
> b/drivers/gpu/drm/arm/display/Kconfig index cec0639..e87ff86 100644
> --- a/drivers/gpu/drm/arm/display/Kconfig
> +++ b/drivers/gpu/drm/arm/display/Kconfig
> @@ -12,3 +12,9 @@ config DRM_KOMEDA
>  	  Processor driver. It supports the D71 variants of the hardware.
> 
>  	  If compiled as a module it will be called komeda.
> +
> +config DRM_KOMEDA_ERROR_PRINT
> +	bool "Enable komeda error print"
> +	depends on DRM_KOMEDA
> +	help
> +	  Choose this option to enable error printing.
> diff --git a/drivers/gpu/drm/arm/display/komeda/Makefile
> b/drivers/gpu/drm/arm/display/komeda/Makefile index 5c3900c..f095a1c 100644
> --- a/drivers/gpu/drm/arm/display/komeda/Makefile
> +++ b/drivers/gpu/drm/arm/display/komeda/Makefile
> @@ -22,4 +22,6 @@ komeda-y += \
>  	d71/d71_dev.o \
>  	d71/d71_component.o
> 
> +komeda-$(CONFIG_DRM_KOMEDA_ERROR_PRINT) += komeda_event.o
> +
>  obj-$(CONFIG_DRM_KOMEDA) += komeda.o
> diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_dev.h
> b/drivers/gpu/drm/arm/display/komeda/komeda_dev.h index d1c86b6..e28e7e6
> 100644
> --- a/drivers/gpu/drm/arm/display/komeda/komeda_dev.h
> +++ b/drivers/gpu/drm/arm/display/komeda/komeda_dev.h
> @@ -40,6 +40,17 @@
>  #define KOMEDA_ERR_TTNG			BIT_ULL(30)
>  #define KOMEDA_ERR_TTF			BIT_ULL(31)
> 
> +#define KOMEDA_ERR_EVENTS	\
> +	(KOMEDA_EVENT_URUN	| KOMEDA_EVENT_IBSY	| KOMEDA_EVENT_OVR |
\
> +	KOMEDA_ERR_TETO		| KOMEDA_ERR_TEMR	| 
KOMEDA_ERR_TITR |\
> +	KOMEDA_ERR_CPE		| KOMEDA_ERR_CFGE	| 
KOMEDA_ERR_AXIE |\
> +	KOMEDA_ERR_ACE0		| KOMEDA_ERR_ACE1	| 
KOMEDA_ERR_ACE2 |\
> +	KOMEDA_ERR_ACE3		| KOMEDA_ERR_DRIFTTO	| 
KOMEDA_ERR_FRAMETO |\
> +	KOMEDA_ERR_ZME		| KOMEDA_ERR_MERR	| 
KOMEDA_ERR_TCF |\
> +	KOMEDA_ERR_TTNG		| KOMEDA_ERR_TTF)
> +
> +#define KOMEDA_WARN_EVENTS	KOMEDA_ERR_CSCE
> +
>  /* malidp device id */
>  enum {
>  	MALI_D71 = 0,
> @@ -207,4 +218,8 @@ struct komeda_dev {
> 
>  struct komeda_dev *dev_to_mdev(struct device *dev);
> 
> +#ifdef CONFIG_DRM_KOMEDA_ERROR_PRINT
> +void komeda_print_events(struct komeda_events *evts);
> +#endif
> +
>  #endif /*_KOMEDA_DEV_H_*/
> diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_event.c
> b/drivers/gpu/drm/arm/display/komeda/komeda_event.c new file mode 100644
> index 0000000..a36fb86
> --- /dev/null
> +++ b/drivers/gpu/drm/arm/display/komeda/komeda_event.c
> @@ -0,0 +1,140 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * (C) COPYRIGHT 2019 ARM Limited. All rights reserved.
> + * Author: James.Qian.Wang <james.qian.wang@arm.com>
> + *
> + */
> +#include <drm/drm_print.h>
> +
> +#include "komeda_dev.h"
> +
> +struct komeda_str {
> +	char *str;
> +	u32 sz;
> +	u32 len;
> +};
> +
> +/* return 0 on success,  < 0 on no space.
> + */
> +static int komeda_sprintf(struct komeda_str *str, const char *fmt, ...)
> +{
> +	va_list args;
> +	int num, free_sz;
> +	int err;
> +
> +	free_sz = str->sz - str->len - 1;
> +	if (free_sz <= 0)
> +		return -ENOSPC;
> +
> +	va_start(args, fmt);
> +
> +	num = vsnprintf(str->str + str->len, free_sz, fmt, args);
> +
> +	va_end(args);
> +
> +	if (num < free_sz) {
> +		str->len += num;
> +		err = 0;
> +	} else {
> +		str->len = str->sz - 1;
> +		err = -ENOSPC;
> +	}
> +
> +	return err;
> +}
> +
> +static void evt_sprintf(struct komeda_str *str, u64 evt, const char *msg)
> +{
> +	if (evt)
> +		komeda_sprintf(str, msg);
> +}
> +
> +static void evt_str(struct komeda_str *str, u64 events)
> +{
> +	if (events == 0ULL) {
> +		komeda_sprintf(str, "None");
> +		return;
> +	}
> +
> +	evt_sprintf(str, events & KOMEDA_EVENT_VSYNC, "VSYNC|");
> +	evt_sprintf(str, events & KOMEDA_EVENT_FLIP, "FLIP|");
> +	evt_sprintf(str, events & KOMEDA_EVENT_EOW, "EOW|");
> +	evt_sprintf(str, events & KOMEDA_EVENT_MODE, "OP-MODE|");
> +
> +	evt_sprintf(str, events & KOMEDA_EVENT_URUN, "UNDERRUN|");
> +	evt_sprintf(str, events & KOMEDA_EVENT_OVR, "OVERRUN|");
> +
> +	/* GLB error */
> +	evt_sprintf(str, events & KOMEDA_ERR_MERR, "MERR|");
> +	evt_sprintf(str, events & KOMEDA_ERR_FRAMETO, "FRAMETO|");
> +
> +	/* DOU error */
> +	evt_sprintf(str, events & KOMEDA_ERR_DRIFTTO, "DRIFTTO|");
> +	evt_sprintf(str, events & KOMEDA_ERR_FRAMETO, "FRAMETO|");
> +	evt_sprintf(str, events & KOMEDA_ERR_TETO, "TETO|");
> +	evt_sprintf(str, events & KOMEDA_ERR_CSCE, "CSCE|");
> +
> +	/* LPU errors or events */
> +	evt_sprintf(str, events & KOMEDA_EVENT_IBSY, "IBSY|");
> +	evt_sprintf(str, events & KOMEDA_ERR_AXIE, "AXIE|");
> +	evt_sprintf(str, events & KOMEDA_ERR_ACE0, "ACE0|");
> +	evt_sprintf(str, events & KOMEDA_ERR_ACE1, "ACE1|");
> +	evt_sprintf(str, events & KOMEDA_ERR_ACE2, "ACE2|");
> +	evt_sprintf(str, events & KOMEDA_ERR_ACE3, "ACE3|");
> +
> +	/* LPU TBU errors*/
> +	evt_sprintf(str, events & KOMEDA_ERR_TCF, "TCF|");
> +	evt_sprintf(str, events & KOMEDA_ERR_TTNG, "TTNG|");
> +	evt_sprintf(str, events & KOMEDA_ERR_TITR, "TITR|");
> +	evt_sprintf(str, events & KOMEDA_ERR_TEMR, "TEMR|");
> +	evt_sprintf(str, events & KOMEDA_ERR_TTF, "TTF|");
> +
> +	/* CU errors*/
> +	evt_sprintf(str, events & KOMEDA_ERR_CPE, "COPROC|");
> +	evt_sprintf(str, events & KOMEDA_ERR_ZME, "ZME|");
> +	evt_sprintf(str, events & KOMEDA_ERR_CFGE, "CFGE|");
> +	evt_sprintf(str, events & KOMEDA_ERR_TEMR, "TEMR|");
> +
> +	if (str->len > 0 && (str->str[str->len - 1] == '|')) {
> +		str->str[str->len - 1] = 0;
> +		str->len--;
> +	}
> +}
> +
> +static bool is_new_frame(struct komeda_events *a)
> +{
> +	return (a->pipes[0] | a->pipes[1]) &
> +	       (KOMEDA_EVENT_FLIP | KOMEDA_EVENT_EOW);
> +}
> +
> +void komeda_print_events(struct komeda_events *evts)
> +{
> +	u64 print_evts = KOMEDA_ERR_EVENTS;
> +	static bool en_print = true;
> +
> +	/* reduce the same msg print, only print the first evt for one 
frame */
> +	if (evts->global || is_new_frame(evts))
> +		en_print = true;
> +	if (!en_print)
> +		return;
> +
> +	if ((evts->global | evts->pipes[0] | evts->pipes[1]) & print_evts) 
{
> +		char msg[256];
> +		struct komeda_str str;
> +
> +		str.str = msg;
> +		str.sz  = sizeof(msg);
> +		str.len = 0;
> +
> +		komeda_sprintf(&str, "gcu: ");
> +		evt_str(&str, evts->global);
> +		komeda_sprintf(&str, ", pipes[0]: ");
> +		evt_str(&str, evts->pipes[0]);
> +		komeda_sprintf(&str, ", pipes[1]: ");
> +		evt_str(&str, evts->pipes[1]);
> +
> +		DRM_ERROR("err detect: %s\n", msg);
> +
> +		en_print = false;
> +	}
> +}
> diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_kms.c
> b/drivers/gpu/drm/arm/display/komeda/komeda_kms.c index 419a8b0..0fafc36
> 100644
> --- a/drivers/gpu/drm/arm/display/komeda/komeda_kms.c
> +++ b/drivers/gpu/drm/arm/display/komeda/komeda_kms.c
> @@ -47,6 +47,10 @@ static irqreturn_t komeda_kms_irq_handler(int irq, void
> *data) memset(&evts, 0, sizeof(evts));
>  	status = mdev->funcs->irq_handler(mdev, &evts);
> 
> +#ifdef CONFIG_DRM_KOMEDA_ERROR_PRINT
> +	komeda_print_events(&evts);
> +#endif
> +
>  	/* Notify the crtc to handle the events */
>  	for (i = 0; i < kms->n_crtcs; i++)
>  		komeda_crtc_handle_event(&kms->crtcs[i], &evts);





^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [PATCH] drm/komeda: Adds error event print functionality
@ 2019-08-02 10:05   ` Mihail Atanassov
  0 siblings, 0 replies; 37+ messages in thread
From: Mihail Atanassov @ 2019-08-02 10:05 UTC (permalink / raw)
  To: Lowry Li (Arm Technology China)
  Cc: nd, airlied, Liviu Dudau, Jonathan Chai (Arm Technology China),
	linux-kernel, dri-devel, Julien Yin (Arm Technology China),
	james qian wang (Arm Technology China),
	seanpaul, Ayan Halder

On Friday, 2 August 2019 10:43:10 BST Lowry Li (Arm Technology China) wrote:
> From: "Lowry Li (Arm Technology China)" <Lowry.Li@arm.com>
> 
> Adds to print the event message when error happens and the same event
> will not be printed until next vsync.
> 
> Changes since v2:
> 1. Refine komeda_sprintf();
> 2. Not using STR_SZ macro for the string size in komeda_print_events().
> 
> Changes since v1:
> 1. Handling the event print by CONFIG_KOMEDA_ERROR_PRINT;
> 2. Changing the max string size to 256.
> 
> Signed-off-by: Lowry Li (Arm Technology China) <lowry.li@arm.com>

Reviewed-by: Mihail Atanassov <mihail.atanassov@arm.com>

BR,
Mihail

> ---
>  drivers/gpu/drm/arm/display/Kconfig               |   6 +
>  drivers/gpu/drm/arm/display/komeda/Makefile       |   2 +
>  drivers/gpu/drm/arm/display/komeda/komeda_dev.h   |  15 +++
>  drivers/gpu/drm/arm/display/komeda/komeda_event.c | 140
> ++++++++++++++++++++++ drivers/gpu/drm/arm/display/komeda/komeda_kms.c   | 
>  4 +
>  5 files changed, 167 insertions(+)
>  create mode 100644 drivers/gpu/drm/arm/display/komeda/komeda_event.c
> 
> diff --git a/drivers/gpu/drm/arm/display/Kconfig
> b/drivers/gpu/drm/arm/display/Kconfig index cec0639..e87ff86 100644
> --- a/drivers/gpu/drm/arm/display/Kconfig
> +++ b/drivers/gpu/drm/arm/display/Kconfig
> @@ -12,3 +12,9 @@ config DRM_KOMEDA
>  	  Processor driver. It supports the D71 variants of the hardware.
> 
>  	  If compiled as a module it will be called komeda.
> +
> +config DRM_KOMEDA_ERROR_PRINT
> +	bool "Enable komeda error print"
> +	depends on DRM_KOMEDA
> +	help
> +	  Choose this option to enable error printing.
> diff --git a/drivers/gpu/drm/arm/display/komeda/Makefile
> b/drivers/gpu/drm/arm/display/komeda/Makefile index 5c3900c..f095a1c 100644
> --- a/drivers/gpu/drm/arm/display/komeda/Makefile
> +++ b/drivers/gpu/drm/arm/display/komeda/Makefile
> @@ -22,4 +22,6 @@ komeda-y += \
>  	d71/d71_dev.o \
>  	d71/d71_component.o
> 
> +komeda-$(CONFIG_DRM_KOMEDA_ERROR_PRINT) += komeda_event.o
> +
>  obj-$(CONFIG_DRM_KOMEDA) += komeda.o
> diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_dev.h
> b/drivers/gpu/drm/arm/display/komeda/komeda_dev.h index d1c86b6..e28e7e6
> 100644
> --- a/drivers/gpu/drm/arm/display/komeda/komeda_dev.h
> +++ b/drivers/gpu/drm/arm/display/komeda/komeda_dev.h
> @@ -40,6 +40,17 @@
>  #define KOMEDA_ERR_TTNG			BIT_ULL(30)
>  #define KOMEDA_ERR_TTF			BIT_ULL(31)
> 
> +#define KOMEDA_ERR_EVENTS	\
> +	(KOMEDA_EVENT_URUN	| KOMEDA_EVENT_IBSY	| KOMEDA_EVENT_OVR |
\
> +	KOMEDA_ERR_TETO		| KOMEDA_ERR_TEMR	| 
KOMEDA_ERR_TITR |\
> +	KOMEDA_ERR_CPE		| KOMEDA_ERR_CFGE	| 
KOMEDA_ERR_AXIE |\
> +	KOMEDA_ERR_ACE0		| KOMEDA_ERR_ACE1	| 
KOMEDA_ERR_ACE2 |\
> +	KOMEDA_ERR_ACE3		| KOMEDA_ERR_DRIFTTO	| 
KOMEDA_ERR_FRAMETO |\
> +	KOMEDA_ERR_ZME		| KOMEDA_ERR_MERR	| 
KOMEDA_ERR_TCF |\
> +	KOMEDA_ERR_TTNG		| KOMEDA_ERR_TTF)
> +
> +#define KOMEDA_WARN_EVENTS	KOMEDA_ERR_CSCE
> +
>  /* malidp device id */
>  enum {
>  	MALI_D71 = 0,
> @@ -207,4 +218,8 @@ struct komeda_dev {
> 
>  struct komeda_dev *dev_to_mdev(struct device *dev);
> 
> +#ifdef CONFIG_DRM_KOMEDA_ERROR_PRINT
> +void komeda_print_events(struct komeda_events *evts);
> +#endif
> +
>  #endif /*_KOMEDA_DEV_H_*/
> diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_event.c
> b/drivers/gpu/drm/arm/display/komeda/komeda_event.c new file mode 100644
> index 0000000..a36fb86
> --- /dev/null
> +++ b/drivers/gpu/drm/arm/display/komeda/komeda_event.c
> @@ -0,0 +1,140 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * (C) COPYRIGHT 2019 ARM Limited. All rights reserved.
> + * Author: James.Qian.Wang <james.qian.wang@arm.com>
> + *
> + */
> +#include <drm/drm_print.h>
> +
> +#include "komeda_dev.h"
> +
> +struct komeda_str {
> +	char *str;
> +	u32 sz;
> +	u32 len;
> +};
> +
> +/* return 0 on success,  < 0 on no space.
> + */
> +static int komeda_sprintf(struct komeda_str *str, const char *fmt, ...)
> +{
> +	va_list args;
> +	int num, free_sz;
> +	int err;
> +
> +	free_sz = str->sz - str->len - 1;
> +	if (free_sz <= 0)
> +		return -ENOSPC;
> +
> +	va_start(args, fmt);
> +
> +	num = vsnprintf(str->str + str->len, free_sz, fmt, args);
> +
> +	va_end(args);
> +
> +	if (num < free_sz) {
> +		str->len += num;
> +		err = 0;
> +	} else {
> +		str->len = str->sz - 1;
> +		err = -ENOSPC;
> +	}
> +
> +	return err;
> +}
> +
> +static void evt_sprintf(struct komeda_str *str, u64 evt, const char *msg)
> +{
> +	if (evt)
> +		komeda_sprintf(str, msg);
> +}
> +
> +static void evt_str(struct komeda_str *str, u64 events)
> +{
> +	if (events == 0ULL) {
> +		komeda_sprintf(str, "None");
> +		return;
> +	}
> +
> +	evt_sprintf(str, events & KOMEDA_EVENT_VSYNC, "VSYNC|");
> +	evt_sprintf(str, events & KOMEDA_EVENT_FLIP, "FLIP|");
> +	evt_sprintf(str, events & KOMEDA_EVENT_EOW, "EOW|");
> +	evt_sprintf(str, events & KOMEDA_EVENT_MODE, "OP-MODE|");
> +
> +	evt_sprintf(str, events & KOMEDA_EVENT_URUN, "UNDERRUN|");
> +	evt_sprintf(str, events & KOMEDA_EVENT_OVR, "OVERRUN|");
> +
> +	/* GLB error */
> +	evt_sprintf(str, events & KOMEDA_ERR_MERR, "MERR|");
> +	evt_sprintf(str, events & KOMEDA_ERR_FRAMETO, "FRAMETO|");
> +
> +	/* DOU error */
> +	evt_sprintf(str, events & KOMEDA_ERR_DRIFTTO, "DRIFTTO|");
> +	evt_sprintf(str, events & KOMEDA_ERR_FRAMETO, "FRAMETO|");
> +	evt_sprintf(str, events & KOMEDA_ERR_TETO, "TETO|");
> +	evt_sprintf(str, events & KOMEDA_ERR_CSCE, "CSCE|");
> +
> +	/* LPU errors or events */
> +	evt_sprintf(str, events & KOMEDA_EVENT_IBSY, "IBSY|");
> +	evt_sprintf(str, events & KOMEDA_ERR_AXIE, "AXIE|");
> +	evt_sprintf(str, events & KOMEDA_ERR_ACE0, "ACE0|");
> +	evt_sprintf(str, events & KOMEDA_ERR_ACE1, "ACE1|");
> +	evt_sprintf(str, events & KOMEDA_ERR_ACE2, "ACE2|");
> +	evt_sprintf(str, events & KOMEDA_ERR_ACE3, "ACE3|");
> +
> +	/* LPU TBU errors*/
> +	evt_sprintf(str, events & KOMEDA_ERR_TCF, "TCF|");
> +	evt_sprintf(str, events & KOMEDA_ERR_TTNG, "TTNG|");
> +	evt_sprintf(str, events & KOMEDA_ERR_TITR, "TITR|");
> +	evt_sprintf(str, events & KOMEDA_ERR_TEMR, "TEMR|");
> +	evt_sprintf(str, events & KOMEDA_ERR_TTF, "TTF|");
> +
> +	/* CU errors*/
> +	evt_sprintf(str, events & KOMEDA_ERR_CPE, "COPROC|");
> +	evt_sprintf(str, events & KOMEDA_ERR_ZME, "ZME|");
> +	evt_sprintf(str, events & KOMEDA_ERR_CFGE, "CFGE|");
> +	evt_sprintf(str, events & KOMEDA_ERR_TEMR, "TEMR|");
> +
> +	if (str->len > 0 && (str->str[str->len - 1] == '|')) {
> +		str->str[str->len - 1] = 0;
> +		str->len--;
> +	}
> +}
> +
> +static bool is_new_frame(struct komeda_events *a)
> +{
> +	return (a->pipes[0] | a->pipes[1]) &
> +	       (KOMEDA_EVENT_FLIP | KOMEDA_EVENT_EOW);
> +}
> +
> +void komeda_print_events(struct komeda_events *evts)
> +{
> +	u64 print_evts = KOMEDA_ERR_EVENTS;
> +	static bool en_print = true;
> +
> +	/* reduce the same msg print, only print the first evt for one 
frame */
> +	if (evts->global || is_new_frame(evts))
> +		en_print = true;
> +	if (!en_print)
> +		return;
> +
> +	if ((evts->global | evts->pipes[0] | evts->pipes[1]) & print_evts) 
{
> +		char msg[256];
> +		struct komeda_str str;
> +
> +		str.str = msg;
> +		str.sz  = sizeof(msg);
> +		str.len = 0;
> +
> +		komeda_sprintf(&str, "gcu: ");
> +		evt_str(&str, evts->global);
> +		komeda_sprintf(&str, ", pipes[0]: ");
> +		evt_str(&str, evts->pipes[0]);
> +		komeda_sprintf(&str, ", pipes[1]: ");
> +		evt_str(&str, evts->pipes[1]);
> +
> +		DRM_ERROR("err detect: %s\n", msg);
> +
> +		en_print = false;
> +	}
> +}
> diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_kms.c
> b/drivers/gpu/drm/arm/display/komeda/komeda_kms.c index 419a8b0..0fafc36
> 100644
> --- a/drivers/gpu/drm/arm/display/komeda/komeda_kms.c
> +++ b/drivers/gpu/drm/arm/display/komeda/komeda_kms.c
> @@ -47,6 +47,10 @@ static irqreturn_t komeda_kms_irq_handler(int irq, void
> *data) memset(&evts, 0, sizeof(evts));
>  	status = mdev->funcs->irq_handler(mdev, &evts);
> 
> +#ifdef CONFIG_DRM_KOMEDA_ERROR_PRINT
> +	komeda_print_events(&evts);
> +#endif
> +
>  	/* Notify the crtc to handle the events */
>  	for (i = 0; i < kms->n_crtcs; i++)
>  		komeda_crtc_handle_event(&kms->crtcs[i], &evts);




_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 37+ messages in thread

* [PATCH] drm/komeda: Adds error event print functionality
@ 2019-08-02  9:43 ` Lowry Li (Arm Technology China)
  0 siblings, 0 replies; 37+ messages in thread
From: Lowry Li (Arm Technology China) @ 2019-08-02  9:43 UTC (permalink / raw)
  To: Liviu Dudau, james qian wang (Arm Technology China),
	maarten.lankhorst, seanpaul, airlied, Brian Starkey,
	Mihail Atanassov
  Cc: Julien Yin (Arm Technology China),
	Jonathan Chai (Arm Technology China),
	Ayan Halder, dri-devel, linux-kernel, nd,
	Lowry Li (Arm Technology China), Lowry Li (Arm Technology China)

From: "Lowry Li (Arm Technology China)" <Lowry.Li@arm.com>

Adds to print the event message when error happens and the same event
will not be printed until next vsync.

Changes since v2:
1. Refine komeda_sprintf();
2. Not using STR_SZ macro for the string size in komeda_print_events().

Changes since v1:
1. Handling the event print by CONFIG_KOMEDA_ERROR_PRINT;
2. Changing the max string size to 256.

Signed-off-by: Lowry Li (Arm Technology China) <lowry.li@arm.com>
---
 drivers/gpu/drm/arm/display/Kconfig               |   6 +
 drivers/gpu/drm/arm/display/komeda/Makefile       |   2 +
 drivers/gpu/drm/arm/display/komeda/komeda_dev.h   |  15 +++
 drivers/gpu/drm/arm/display/komeda/komeda_event.c | 140 ++++++++++++++++++++++
 drivers/gpu/drm/arm/display/komeda/komeda_kms.c   |   4 +
 5 files changed, 167 insertions(+)
 create mode 100644 drivers/gpu/drm/arm/display/komeda/komeda_event.c

diff --git a/drivers/gpu/drm/arm/display/Kconfig b/drivers/gpu/drm/arm/display/Kconfig
index cec0639..e87ff86 100644
--- a/drivers/gpu/drm/arm/display/Kconfig
+++ b/drivers/gpu/drm/arm/display/Kconfig
@@ -12,3 +12,9 @@ config DRM_KOMEDA
 	  Processor driver. It supports the D71 variants of the hardware.
 
 	  If compiled as a module it will be called komeda.
+
+config DRM_KOMEDA_ERROR_PRINT
+	bool "Enable komeda error print"
+	depends on DRM_KOMEDA
+	help
+	  Choose this option to enable error printing.
diff --git a/drivers/gpu/drm/arm/display/komeda/Makefile b/drivers/gpu/drm/arm/display/komeda/Makefile
index 5c3900c..f095a1c 100644
--- a/drivers/gpu/drm/arm/display/komeda/Makefile
+++ b/drivers/gpu/drm/arm/display/komeda/Makefile
@@ -22,4 +22,6 @@ komeda-y += \
 	d71/d71_dev.o \
 	d71/d71_component.o
 
+komeda-$(CONFIG_DRM_KOMEDA_ERROR_PRINT) += komeda_event.o
+
 obj-$(CONFIG_DRM_KOMEDA) += komeda.o
diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_dev.h b/drivers/gpu/drm/arm/display/komeda/komeda_dev.h
index d1c86b6..e28e7e6 100644
--- a/drivers/gpu/drm/arm/display/komeda/komeda_dev.h
+++ b/drivers/gpu/drm/arm/display/komeda/komeda_dev.h
@@ -40,6 +40,17 @@
 #define KOMEDA_ERR_TTNG			BIT_ULL(30)
 #define KOMEDA_ERR_TTF			BIT_ULL(31)
 
+#define KOMEDA_ERR_EVENTS	\
+	(KOMEDA_EVENT_URUN	| KOMEDA_EVENT_IBSY	| KOMEDA_EVENT_OVR |\
+	KOMEDA_ERR_TETO		| KOMEDA_ERR_TEMR	| KOMEDA_ERR_TITR |\
+	KOMEDA_ERR_CPE		| KOMEDA_ERR_CFGE	| KOMEDA_ERR_AXIE |\
+	KOMEDA_ERR_ACE0		| KOMEDA_ERR_ACE1	| KOMEDA_ERR_ACE2 |\
+	KOMEDA_ERR_ACE3		| KOMEDA_ERR_DRIFTTO	| KOMEDA_ERR_FRAMETO |\
+	KOMEDA_ERR_ZME		| KOMEDA_ERR_MERR	| KOMEDA_ERR_TCF |\
+	KOMEDA_ERR_TTNG		| KOMEDA_ERR_TTF)
+
+#define KOMEDA_WARN_EVENTS	KOMEDA_ERR_CSCE
+
 /* malidp device id */
 enum {
 	MALI_D71 = 0,
@@ -207,4 +218,8 @@ struct komeda_dev {
 
 struct komeda_dev *dev_to_mdev(struct device *dev);
 
+#ifdef CONFIG_DRM_KOMEDA_ERROR_PRINT
+void komeda_print_events(struct komeda_events *evts);
+#endif
+
 #endif /*_KOMEDA_DEV_H_*/
diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_event.c b/drivers/gpu/drm/arm/display/komeda/komeda_event.c
new file mode 100644
index 0000000..a36fb86
--- /dev/null
+++ b/drivers/gpu/drm/arm/display/komeda/komeda_event.c
@@ -0,0 +1,140 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * (C) COPYRIGHT 2019 ARM Limited. All rights reserved.
+ * Author: James.Qian.Wang <james.qian.wang@arm.com>
+ *
+ */
+#include <drm/drm_print.h>
+
+#include "komeda_dev.h"
+
+struct komeda_str {
+	char *str;
+	u32 sz;
+	u32 len;
+};
+
+/* return 0 on success,  < 0 on no space.
+ */
+static int komeda_sprintf(struct komeda_str *str, const char *fmt, ...)
+{
+	va_list args;
+	int num, free_sz;
+	int err;
+
+	free_sz = str->sz - str->len - 1;
+	if (free_sz <= 0)
+		return -ENOSPC;
+
+	va_start(args, fmt);
+
+	num = vsnprintf(str->str + str->len, free_sz, fmt, args);
+
+	va_end(args);
+
+	if (num < free_sz) {
+		str->len += num;
+		err = 0;
+	} else {
+		str->len = str->sz - 1;
+		err = -ENOSPC;
+	}
+
+	return err;
+}
+
+static void evt_sprintf(struct komeda_str *str, u64 evt, const char *msg)
+{
+	if (evt)
+		komeda_sprintf(str, msg);
+}
+
+static void evt_str(struct komeda_str *str, u64 events)
+{
+	if (events == 0ULL) {
+		komeda_sprintf(str, "None");
+		return;
+	}
+
+	evt_sprintf(str, events & KOMEDA_EVENT_VSYNC, "VSYNC|");
+	evt_sprintf(str, events & KOMEDA_EVENT_FLIP, "FLIP|");
+	evt_sprintf(str, events & KOMEDA_EVENT_EOW, "EOW|");
+	evt_sprintf(str, events & KOMEDA_EVENT_MODE, "OP-MODE|");
+
+	evt_sprintf(str, events & KOMEDA_EVENT_URUN, "UNDERRUN|");
+	evt_sprintf(str, events & KOMEDA_EVENT_OVR, "OVERRUN|");
+
+	/* GLB error */
+	evt_sprintf(str, events & KOMEDA_ERR_MERR, "MERR|");
+	evt_sprintf(str, events & KOMEDA_ERR_FRAMETO, "FRAMETO|");
+
+	/* DOU error */
+	evt_sprintf(str, events & KOMEDA_ERR_DRIFTTO, "DRIFTTO|");
+	evt_sprintf(str, events & KOMEDA_ERR_FRAMETO, "FRAMETO|");
+	evt_sprintf(str, events & KOMEDA_ERR_TETO, "TETO|");
+	evt_sprintf(str, events & KOMEDA_ERR_CSCE, "CSCE|");
+
+	/* LPU errors or events */
+	evt_sprintf(str, events & KOMEDA_EVENT_IBSY, "IBSY|");
+	evt_sprintf(str, events & KOMEDA_ERR_AXIE, "AXIE|");
+	evt_sprintf(str, events & KOMEDA_ERR_ACE0, "ACE0|");
+	evt_sprintf(str, events & KOMEDA_ERR_ACE1, "ACE1|");
+	evt_sprintf(str, events & KOMEDA_ERR_ACE2, "ACE2|");
+	evt_sprintf(str, events & KOMEDA_ERR_ACE3, "ACE3|");
+
+	/* LPU TBU errors*/
+	evt_sprintf(str, events & KOMEDA_ERR_TCF, "TCF|");
+	evt_sprintf(str, events & KOMEDA_ERR_TTNG, "TTNG|");
+	evt_sprintf(str, events & KOMEDA_ERR_TITR, "TITR|");
+	evt_sprintf(str, events & KOMEDA_ERR_TEMR, "TEMR|");
+	evt_sprintf(str, events & KOMEDA_ERR_TTF, "TTF|");
+
+	/* CU errors*/
+	evt_sprintf(str, events & KOMEDA_ERR_CPE, "COPROC|");
+	evt_sprintf(str, events & KOMEDA_ERR_ZME, "ZME|");
+	evt_sprintf(str, events & KOMEDA_ERR_CFGE, "CFGE|");
+	evt_sprintf(str, events & KOMEDA_ERR_TEMR, "TEMR|");
+
+	if (str->len > 0 && (str->str[str->len - 1] == '|')) {
+		str->str[str->len - 1] = 0;
+		str->len--;
+	}
+}
+
+static bool is_new_frame(struct komeda_events *a)
+{
+	return (a->pipes[0] | a->pipes[1]) &
+	       (KOMEDA_EVENT_FLIP | KOMEDA_EVENT_EOW);
+}
+
+void komeda_print_events(struct komeda_events *evts)
+{
+	u64 print_evts = KOMEDA_ERR_EVENTS;
+	static bool en_print = true;
+
+	/* reduce the same msg print, only print the first evt for one frame */
+	if (evts->global || is_new_frame(evts))
+		en_print = true;
+	if (!en_print)
+		return;
+
+	if ((evts->global | evts->pipes[0] | evts->pipes[1]) & print_evts) {
+		char msg[256];
+		struct komeda_str str;
+
+		str.str = msg;
+		str.sz  = sizeof(msg);
+		str.len = 0;
+
+		komeda_sprintf(&str, "gcu: ");
+		evt_str(&str, evts->global);
+		komeda_sprintf(&str, ", pipes[0]: ");
+		evt_str(&str, evts->pipes[0]);
+		komeda_sprintf(&str, ", pipes[1]: ");
+		evt_str(&str, evts->pipes[1]);
+
+		DRM_ERROR("err detect: %s\n", msg);
+
+		en_print = false;
+	}
+}
diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_kms.c b/drivers/gpu/drm/arm/display/komeda/komeda_kms.c
index 419a8b0..0fafc36 100644
--- a/drivers/gpu/drm/arm/display/komeda/komeda_kms.c
+++ b/drivers/gpu/drm/arm/display/komeda/komeda_kms.c
@@ -47,6 +47,10 @@ static irqreturn_t komeda_kms_irq_handler(int irq, void *data)
 	memset(&evts, 0, sizeof(evts));
 	status = mdev->funcs->irq_handler(mdev, &evts);
 
+#ifdef CONFIG_DRM_KOMEDA_ERROR_PRINT
+	komeda_print_events(&evts);
+#endif
+
 	/* Notify the crtc to handle the events */
 	for (i = 0; i < kms->n_crtcs; i++)
 		komeda_crtc_handle_event(&kms->crtcs[i], &evts);
-- 
1.9.1


^ permalink raw reply related	[flat|nested] 37+ messages in thread

* [PATCH] drm/komeda: Adds error event print functionality
@ 2019-08-02  9:43 ` Lowry Li (Arm Technology China)
  0 siblings, 0 replies; 37+ messages in thread
From: Lowry Li (Arm Technology China) @ 2019-08-02  9:43 UTC (permalink / raw)
  To: Liviu Dudau, james qian wang (Arm Technology China),
	maarten.lankhorst, seanpaul, airlied, Brian Starkey,
	Mihail Atanassov
  Cc: Julien Yin (Arm Technology China),
	Jonathan Chai (Arm Technology China),
	Ayan Halder, dri-devel, linux-kernel, nd,
	Lowry Li (Arm Technology China)

From: "Lowry Li (Arm Technology China)" <Lowry.Li@arm.com>

Adds to print the event message when error happens and the same event
will not be printed until next vsync.

Changes since v2:
1. Refine komeda_sprintf();
2. Not using STR_SZ macro for the string size in komeda_print_events().

Changes since v1:
1. Handling the event print by CONFIG_KOMEDA_ERROR_PRINT;
2. Changing the max string size to 256.

Signed-off-by: Lowry Li (Arm Technology China) <lowry.li@arm.com>
---
 drivers/gpu/drm/arm/display/Kconfig               |   6 +
 drivers/gpu/drm/arm/display/komeda/Makefile       |   2 +
 drivers/gpu/drm/arm/display/komeda/komeda_dev.h   |  15 +++
 drivers/gpu/drm/arm/display/komeda/komeda_event.c | 140 ++++++++++++++++++++++
 drivers/gpu/drm/arm/display/komeda/komeda_kms.c   |   4 +
 5 files changed, 167 insertions(+)
 create mode 100644 drivers/gpu/drm/arm/display/komeda/komeda_event.c

diff --git a/drivers/gpu/drm/arm/display/Kconfig b/drivers/gpu/drm/arm/display/Kconfig
index cec0639..e87ff86 100644
--- a/drivers/gpu/drm/arm/display/Kconfig
+++ b/drivers/gpu/drm/arm/display/Kconfig
@@ -12,3 +12,9 @@ config DRM_KOMEDA
 	  Processor driver. It supports the D71 variants of the hardware.
 
 	  If compiled as a module it will be called komeda.
+
+config DRM_KOMEDA_ERROR_PRINT
+	bool "Enable komeda error print"
+	depends on DRM_KOMEDA
+	help
+	  Choose this option to enable error printing.
diff --git a/drivers/gpu/drm/arm/display/komeda/Makefile b/drivers/gpu/drm/arm/display/komeda/Makefile
index 5c3900c..f095a1c 100644
--- a/drivers/gpu/drm/arm/display/komeda/Makefile
+++ b/drivers/gpu/drm/arm/display/komeda/Makefile
@@ -22,4 +22,6 @@ komeda-y += \
 	d71/d71_dev.o \
 	d71/d71_component.o
 
+komeda-$(CONFIG_DRM_KOMEDA_ERROR_PRINT) += komeda_event.o
+
 obj-$(CONFIG_DRM_KOMEDA) += komeda.o
diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_dev.h b/drivers/gpu/drm/arm/display/komeda/komeda_dev.h
index d1c86b6..e28e7e6 100644
--- a/drivers/gpu/drm/arm/display/komeda/komeda_dev.h
+++ b/drivers/gpu/drm/arm/display/komeda/komeda_dev.h
@@ -40,6 +40,17 @@
 #define KOMEDA_ERR_TTNG			BIT_ULL(30)
 #define KOMEDA_ERR_TTF			BIT_ULL(31)
 
+#define KOMEDA_ERR_EVENTS	\
+	(KOMEDA_EVENT_URUN	| KOMEDA_EVENT_IBSY	| KOMEDA_EVENT_OVR |\
+	KOMEDA_ERR_TETO		| KOMEDA_ERR_TEMR	| KOMEDA_ERR_TITR |\
+	KOMEDA_ERR_CPE		| KOMEDA_ERR_CFGE	| KOMEDA_ERR_AXIE |\
+	KOMEDA_ERR_ACE0		| KOMEDA_ERR_ACE1	| KOMEDA_ERR_ACE2 |\
+	KOMEDA_ERR_ACE3		| KOMEDA_ERR_DRIFTTO	| KOMEDA_ERR_FRAMETO |\
+	KOMEDA_ERR_ZME		| KOMEDA_ERR_MERR	| KOMEDA_ERR_TCF |\
+	KOMEDA_ERR_TTNG		| KOMEDA_ERR_TTF)
+
+#define KOMEDA_WARN_EVENTS	KOMEDA_ERR_CSCE
+
 /* malidp device id */
 enum {
 	MALI_D71 = 0,
@@ -207,4 +218,8 @@ struct komeda_dev {
 
 struct komeda_dev *dev_to_mdev(struct device *dev);
 
+#ifdef CONFIG_DRM_KOMEDA_ERROR_PRINT
+void komeda_print_events(struct komeda_events *evts);
+#endif
+
 #endif /*_KOMEDA_DEV_H_*/
diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_event.c b/drivers/gpu/drm/arm/display/komeda/komeda_event.c
new file mode 100644
index 0000000..a36fb86
--- /dev/null
+++ b/drivers/gpu/drm/arm/display/komeda/komeda_event.c
@@ -0,0 +1,140 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * (C) COPYRIGHT 2019 ARM Limited. All rights reserved.
+ * Author: James.Qian.Wang <james.qian.wang@arm.com>
+ *
+ */
+#include <drm/drm_print.h>
+
+#include "komeda_dev.h"
+
+struct komeda_str {
+	char *str;
+	u32 sz;
+	u32 len;
+};
+
+/* return 0 on success,  < 0 on no space.
+ */
+static int komeda_sprintf(struct komeda_str *str, const char *fmt, ...)
+{
+	va_list args;
+	int num, free_sz;
+	int err;
+
+	free_sz = str->sz - str->len - 1;
+	if (free_sz <= 0)
+		return -ENOSPC;
+
+	va_start(args, fmt);
+
+	num = vsnprintf(str->str + str->len, free_sz, fmt, args);
+
+	va_end(args);
+
+	if (num < free_sz) {
+		str->len += num;
+		err = 0;
+	} else {
+		str->len = str->sz - 1;
+		err = -ENOSPC;
+	}
+
+	return err;
+}
+
+static void evt_sprintf(struct komeda_str *str, u64 evt, const char *msg)
+{
+	if (evt)
+		komeda_sprintf(str, msg);
+}
+
+static void evt_str(struct komeda_str *str, u64 events)
+{
+	if (events == 0ULL) {
+		komeda_sprintf(str, "None");
+		return;
+	}
+
+	evt_sprintf(str, events & KOMEDA_EVENT_VSYNC, "VSYNC|");
+	evt_sprintf(str, events & KOMEDA_EVENT_FLIP, "FLIP|");
+	evt_sprintf(str, events & KOMEDA_EVENT_EOW, "EOW|");
+	evt_sprintf(str, events & KOMEDA_EVENT_MODE, "OP-MODE|");
+
+	evt_sprintf(str, events & KOMEDA_EVENT_URUN, "UNDERRUN|");
+	evt_sprintf(str, events & KOMEDA_EVENT_OVR, "OVERRUN|");
+
+	/* GLB error */
+	evt_sprintf(str, events & KOMEDA_ERR_MERR, "MERR|");
+	evt_sprintf(str, events & KOMEDA_ERR_FRAMETO, "FRAMETO|");
+
+	/* DOU error */
+	evt_sprintf(str, events & KOMEDA_ERR_DRIFTTO, "DRIFTTO|");
+	evt_sprintf(str, events & KOMEDA_ERR_FRAMETO, "FRAMETO|");
+	evt_sprintf(str, events & KOMEDA_ERR_TETO, "TETO|");
+	evt_sprintf(str, events & KOMEDA_ERR_CSCE, "CSCE|");
+
+	/* LPU errors or events */
+	evt_sprintf(str, events & KOMEDA_EVENT_IBSY, "IBSY|");
+	evt_sprintf(str, events & KOMEDA_ERR_AXIE, "AXIE|");
+	evt_sprintf(str, events & KOMEDA_ERR_ACE0, "ACE0|");
+	evt_sprintf(str, events & KOMEDA_ERR_ACE1, "ACE1|");
+	evt_sprintf(str, events & KOMEDA_ERR_ACE2, "ACE2|");
+	evt_sprintf(str, events & KOMEDA_ERR_ACE3, "ACE3|");
+
+	/* LPU TBU errors*/
+	evt_sprintf(str, events & KOMEDA_ERR_TCF, "TCF|");
+	evt_sprintf(str, events & KOMEDA_ERR_TTNG, "TTNG|");
+	evt_sprintf(str, events & KOMEDA_ERR_TITR, "TITR|");
+	evt_sprintf(str, events & KOMEDA_ERR_TEMR, "TEMR|");
+	evt_sprintf(str, events & KOMEDA_ERR_TTF, "TTF|");
+
+	/* CU errors*/
+	evt_sprintf(str, events & KOMEDA_ERR_CPE, "COPROC|");
+	evt_sprintf(str, events & KOMEDA_ERR_ZME, "ZME|");
+	evt_sprintf(str, events & KOMEDA_ERR_CFGE, "CFGE|");
+	evt_sprintf(str, events & KOMEDA_ERR_TEMR, "TEMR|");
+
+	if (str->len > 0 && (str->str[str->len - 1] == '|')) {
+		str->str[str->len - 1] = 0;
+		str->len--;
+	}
+}
+
+static bool is_new_frame(struct komeda_events *a)
+{
+	return (a->pipes[0] | a->pipes[1]) &
+	       (KOMEDA_EVENT_FLIP | KOMEDA_EVENT_EOW);
+}
+
+void komeda_print_events(struct komeda_events *evts)
+{
+	u64 print_evts = KOMEDA_ERR_EVENTS;
+	static bool en_print = true;
+
+	/* reduce the same msg print, only print the first evt for one frame */
+	if (evts->global || is_new_frame(evts))
+		en_print = true;
+	if (!en_print)
+		return;
+
+	if ((evts->global | evts->pipes[0] | evts->pipes[1]) & print_evts) {
+		char msg[256];
+		struct komeda_str str;
+
+		str.str = msg;
+		str.sz  = sizeof(msg);
+		str.len = 0;
+
+		komeda_sprintf(&str, "gcu: ");
+		evt_str(&str, evts->global);
+		komeda_sprintf(&str, ", pipes[0]: ");
+		evt_str(&str, evts->pipes[0]);
+		komeda_sprintf(&str, ", pipes[1]: ");
+		evt_str(&str, evts->pipes[1]);
+
+		DRM_ERROR("err detect: %s\n", msg);
+
+		en_print = false;
+	}
+}
diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_kms.c b/drivers/gpu/drm/arm/display/komeda/komeda_kms.c
index 419a8b0..0fafc36 100644
--- a/drivers/gpu/drm/arm/display/komeda/komeda_kms.c
+++ b/drivers/gpu/drm/arm/display/komeda/komeda_kms.c
@@ -47,6 +47,10 @@ static irqreturn_t komeda_kms_irq_handler(int irq, void *data)
 	memset(&evts, 0, sizeof(evts));
 	status = mdev->funcs->irq_handler(mdev, &evts);
 
+#ifdef CONFIG_DRM_KOMEDA_ERROR_PRINT
+	komeda_print_events(&evts);
+#endif
+
 	/* Notify the crtc to handle the events */
 	for (i = 0; i < kms->n_crtcs; i++)
 		komeda_crtc_handle_event(&kms->crtcs[i], &evts);
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 37+ messages in thread

* Re: [PATCH] drm/komeda: Adds error event print functionality
  2019-08-01 14:48   ` Mihail Atanassov
  (?)
@ 2019-08-02  9:34   ` Lowry Li (Arm Technology China)
  -1 siblings, 0 replies; 37+ messages in thread
From: Lowry Li (Arm Technology China) @ 2019-08-02  9:34 UTC (permalink / raw)
  To: Mihail Atanassov
  Cc: nd, airlied, Liviu Dudau, Jonathan Chai (Arm Technology China),
	linux-kernel, dri-devel, Julien Yin (Arm Technology China),
	james qian wang (Arm Technology China),
	seanpaul, Ayan Halder

Hi Mihail,
On Thu, Aug 01, 2019 at 10:48:45PM +0800, Mihail Atanassov wrote:
> Hi Lowry,
> 
> On Thursday, 1 August 2019 12:37:15 BST Lowry Li (Arm Technology China) wrote:
> > From: "Lowry Li (Arm Technology China)" <Lowry.Li@arm.com>
> > 
> > Adds to print the event message when error happens and the same event
> > will not be printed until next vsync.
> > 
> > Changes since v1:
> > 1. Handling the event print by CONFIG_KOMEDA_ERROR_PRINT;
> > 2. Changing the max string size to 256.
> > 
> > Signed-off-by: Lowry Li (Arm Technology China) <lowry.li@arm.com>
> > ---
> >  drivers/gpu/drm/arm/display/Kconfig               |   6 +
> >  drivers/gpu/drm/arm/display/komeda/Makefile       |   2 +
> >  drivers/gpu/drm/arm/display/komeda/komeda_dev.h   |  15 +++
> >  drivers/gpu/drm/arm/display/komeda/komeda_event.c | 141
> > ++++++++++++++++++++++ drivers/gpu/drm/arm/display/komeda/komeda_kms.c   | 
> >  4 +
> >  5 files changed, 168 insertions(+)
> >  create mode 100644 drivers/gpu/drm/arm/display/komeda/komeda_event.c
> > 
> > diff --git a/drivers/gpu/drm/arm/display/Kconfig
> > b/drivers/gpu/drm/arm/display/Kconfig index cec0639..e87ff86 100644
> > --- a/drivers/gpu/drm/arm/display/Kconfig
> > +++ b/drivers/gpu/drm/arm/display/Kconfig
> > @@ -12,3 +12,9 @@ config DRM_KOMEDA
> >  	  Processor driver. It supports the D71 variants of the hardware.
> > 
> >  	  If compiled as a module it will be called komeda.
> > +
> > +config DRM_KOMEDA_ERROR_PRINT
> > +	bool "Enable komeda error print"
> > +	depends on DRM_KOMEDA
> > +	help
> > +	  Choose this option to enable error printing.
> > diff --git a/drivers/gpu/drm/arm/display/komeda/Makefile
> > b/drivers/gpu/drm/arm/display/komeda/Makefile index 5c3900c..f095a1c 100644
> > --- a/drivers/gpu/drm/arm/display/komeda/Makefile
> > +++ b/drivers/gpu/drm/arm/display/komeda/Makefile
> > @@ -22,4 +22,6 @@ komeda-y += \
> >  	d71/d71_dev.o \
> >  	d71/d71_component.o
> > 
> > +komeda-$(CONFIG_DRM_KOMEDA_ERROR_PRINT) += komeda_event.o
> > +
> >  obj-$(CONFIG_DRM_KOMEDA) += komeda.o
> > diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_dev.h
> > b/drivers/gpu/drm/arm/display/komeda/komeda_dev.h index d1c86b6..e28e7e6
> > 100644
> > --- a/drivers/gpu/drm/arm/display/komeda/komeda_dev.h
> > +++ b/drivers/gpu/drm/arm/display/komeda/komeda_dev.h
> > @@ -40,6 +40,17 @@
> >  #define KOMEDA_ERR_TTNG			BIT_ULL(30)
> >  #define KOMEDA_ERR_TTF			BIT_ULL(31)
> > 
> > +#define KOMEDA_ERR_EVENTS	\
> > +	(KOMEDA_EVENT_URUN	| KOMEDA_EVENT_IBSY	| KOMEDA_EVENT_OVR |
> \
> > +	KOMEDA_ERR_TETO		| KOMEDA_ERR_TEMR	| 
> KOMEDA_ERR_TITR |\
> > +	KOMEDA_ERR_CPE		| KOMEDA_ERR_CFGE	| 
> KOMEDA_ERR_AXIE |\
> > +	KOMEDA_ERR_ACE0		| KOMEDA_ERR_ACE1	| 
> KOMEDA_ERR_ACE2 |\
> > +	KOMEDA_ERR_ACE3		| KOMEDA_ERR_DRIFTTO	| 
> KOMEDA_ERR_FRAMETO |\
> > +	KOMEDA_ERR_ZME		| KOMEDA_ERR_MERR	| 
> KOMEDA_ERR_TCF |\
> > +	KOMEDA_ERR_TTNG		| KOMEDA_ERR_TTF)
> > +
> > +#define KOMEDA_WARN_EVENTS	KOMEDA_ERR_CSCE
> > +
> >  /* malidp device id */
> >  enum {
> >  	MALI_D71 = 0,
> > @@ -207,4 +218,8 @@ struct komeda_dev {
> > 
> >  struct komeda_dev *dev_to_mdev(struct device *dev);
> > 
> > +#ifdef CONFIG_DRM_KOMEDA_ERROR_PRINT
> > +void komeda_print_events(struct komeda_events *evts);
> > +#endif
> > +
> >  #endif /*_KOMEDA_DEV_H_*/
> > diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_event.c
> > b/drivers/gpu/drm/arm/display/komeda/komeda_event.c new file mode 100644
> > index 0000000..57b60cd
> > --- /dev/null
> > +++ b/drivers/gpu/drm/arm/display/komeda/komeda_event.c
> > @@ -0,0 +1,141 @@
> > +// SPDX-License-Identifier: GPL-2.0
> > +/*
> > + * (C) COPYRIGHT 2019 ARM Limited. All rights reserved.
> > + * Author: James.Qian.Wang <james.qian.wang@arm.com>
> > + *
> > + */
> > +#include <drm/drm_print.h>
> > +
> > +#include "komeda_dev.h"
> > +
> > +struct komeda_str {
> > +	char *str;
> > +	u32 sz;
> > +	u32 len;
> > +};
> > +
> > +/* return 0 on success,  < 0 on no space.
> > + */
> > +static int komeda_sprintf(struct komeda_str *str, const char *fmt, ...)
> The lack of '\0'-termination in the truncation case is quite disconcerting, 
> especially since vsnprintf does it. This would be quite surprising to the 
> casual passer-by.
Thanks a lot for the comments. Will refine accordingly and send a new
patch.
> > +{
> > +	va_list args;
> > +	int num, free_sz;
> > +	int err;
> > +
> > +	free_sz = str->sz - str->len;
> That's off by 1, you need to account for the null byte.
> > +	if (free_sz <= 0)
> > +		return -ENOSPC;
> > +
> > +	va_start(args, fmt);
> > +
> > +	num = vsnprintf(str->str + str->len, free_sz, fmt, args);
> > +
> > +	va_end(args);
> > +
> > +	if (num <= free_sz) {
> Strictly less than. To quote from the doc of vsnprintf: 
> """ [...] If the return is greater than or equal to @size, the resulting 
> string is truncated. """
> > +		str->len += num;
> > +		err = 0;
> > +	} else {
> > +		str->len = str->sz;
> Off by 1 here, too.
> > +		err = -ENOSPC;
> That error code isn't used anywhere, so there's no value to having it in the 
> current version of this patch. Either check the error code somewhere 
> downstream and handle it, or change that to an actionable message for the 
> person reading the kernel log. As it stands truncation is completely silent.
Better keep this code and treat as an basic util func. For this case,
the string size is big enough. I tried to print a err msg/log at
calling place, but it is a dead code which will not go into. So still
suggest keep the current.
> > +	}
> > +
> > +	return err;
> > +}
> > +
> > +static void evt_sprintf(struct komeda_str *str, u64 evt, const char *msg)
> > +{
> > +	if (evt)
> > +		komeda_sprintf(str, msg);
> > +}
> > +
> > +static void evt_str(struct komeda_str *str, u64 events)
> > +{
> > +	if (events == 0ULL) {
> > +		evt_sprintf(str, 1, "None");
> [nit] Call `komeda_sprintf(str, "None")` directly?
Yes, will change to it :-)
> > +		return;
> > +	}
> > +
> > +	evt_sprintf(str, events & KOMEDA_EVENT_VSYNC, "VSYNC|");
> > +	evt_sprintf(str, events & KOMEDA_EVENT_FLIP, "FLIP|");
> > +	evt_sprintf(str, events & KOMEDA_EVENT_EOW, "EOW|");
> > +	evt_sprintf(str, events & KOMEDA_EVENT_MODE, "OP-MODE|");
> > +
> > +	evt_sprintf(str, events & KOMEDA_EVENT_URUN, "UNDERRUN|");
> > +	evt_sprintf(str, events & KOMEDA_EVENT_OVR, "OVERRUN|");
> > +
> > +	/* GLB error */
> > +	evt_sprintf(str, events & KOMEDA_ERR_MERR, "MERR|");
> > +	evt_sprintf(str, events & KOMEDA_ERR_FRAMETO, "FRAMETO|");
> > +
> > +	/* DOU error */
> > +	evt_sprintf(str, events & KOMEDA_ERR_DRIFTTO, "DRIFTTO|");
> > +	evt_sprintf(str, events & KOMEDA_ERR_FRAMETO, "FRAMETO|");
> > +	evt_sprintf(str, events & KOMEDA_ERR_TETO, "TETO|");
> > +	evt_sprintf(str, events & KOMEDA_ERR_CSCE, "CSCE|");
> > +
> > +	/* LPU errors or events */
> > +	evt_sprintf(str, events & KOMEDA_EVENT_IBSY, "IBSY|");
> > +	evt_sprintf(str, events & KOMEDA_ERR_AXIE, "AXIE|");
> > +	evt_sprintf(str, events & KOMEDA_ERR_ACE0, "ACE0|");
> > +	evt_sprintf(str, events & KOMEDA_ERR_ACE1, "ACE1|");
> > +	evt_sprintf(str, events & KOMEDA_ERR_ACE2, "ACE2|");
> > +	evt_sprintf(str, events & KOMEDA_ERR_ACE3, "ACE3|");
> > +
> > +	/* LPU TBU errors*/
> > +	evt_sprintf(str, events & KOMEDA_ERR_TCF, "TCF|");
> > +	evt_sprintf(str, events & KOMEDA_ERR_TTNG, "TTNG|");
> > +	evt_sprintf(str, events & KOMEDA_ERR_TITR, "TITR|");
> > +	evt_sprintf(str, events & KOMEDA_ERR_TEMR, "TEMR|");
> > +	evt_sprintf(str, events & KOMEDA_ERR_TTF, "TTF|");
> > +
> > +	/* CU errors*/
> > +	evt_sprintf(str, events & KOMEDA_ERR_CPE, "COPROC|");
> > +	evt_sprintf(str, events & KOMEDA_ERR_ZME, "ZME|");
> > +	evt_sprintf(str, events & KOMEDA_ERR_CFGE, "CFGE|");
> > +	evt_sprintf(str, events & KOMEDA_ERR_TEMR, "TEMR|");
> > +
> > +	if (str->len > 0 && (str->str[str->len - 1] == '|')) {
> > +		str->str[str->len - 1] = 0;
> > +		str->len--;
> > +	}
> > +}
> > +
> > +static bool is_new_frame(struct komeda_events *a)
> > +{
> > +	return (a->pipes[0] | a->pipes[1]) &
> > +	       (KOMEDA_EVENT_FLIP | KOMEDA_EVENT_EOW);
> > +}
> > +
> > +void komeda_print_events(struct komeda_events *evts)
> > +{
> > +	u64 print_evts = KOMEDA_ERR_EVENTS;
> > +	static bool en_print = true;
> > +
> > +	/* reduce the same msg print, only print the first evt for one 
> frame */
> > +	if (evts->global || is_new_frame(evts))
> > +		en_print = true;
> > +	if (!en_print)
> > +		return;
> > +
> > +	if ((evts->global | evts->pipes[0] | evts->pipes[1]) & print_evts) 
> {
> > +		#define STR_SZ		256
> [nit] I'd undef that once it's no longer needed
Will not use macro here.
> > +		char msg[STR_SZ];
> > +		struct komeda_str str;
> > +
> > +		str.str = msg;
> > +		str.sz  = STR_SZ;
> > +		str.len = 0;
> > +
> > +		komeda_sprintf(&str, "gcu: ");
> > +		evt_str(&str, evts->global);
> > +		komeda_sprintf(&str, ", pipes[0]: ");
> > +		evt_str(&str, evts->pipes[0]);
> > +		komeda_sprintf(&str, ", pipes[1]: ");
> > +		evt_str(&str, evts->pipes[1]);
> > +
> > +		DRM_ERROR("err detect: %s\n", msg);
> > +
> > +		en_print = false;
> > +	}
> > +}
> > diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_kms.c
> > b/drivers/gpu/drm/arm/display/komeda/komeda_kms.c index 419a8b0..0fafc36
> > 100644
> > --- a/drivers/gpu/drm/arm/display/komeda/komeda_kms.c
> > +++ b/drivers/gpu/drm/arm/display/komeda/komeda_kms.c
> > @@ -47,6 +47,10 @@ static irqreturn_t komeda_kms_irq_handler(int irq, void
> > *data) memset(&evts, 0, sizeof(evts));
> >  	status = mdev->funcs->irq_handler(mdev, &evts);
> > 
> > +#ifdef CONFIG_DRM_KOMEDA_ERROR_PRINT
> > +	komeda_print_events(&evts);
> > +#endif
> > +
> >  	/* Notify the crtc to handle the events */
> >  	for (i = 0; i < kms->n_crtcs; i++)
> >  		komeda_crtc_handle_event(&kms->crtcs[i], &evts);
> 
> BR,
> Mihail
> 

-- 
Regards,
Lowry
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [PATCH] drm/komeda: Adds error event print functionality
  2019-08-01 11:37 ` Lowry Li (Arm Technology China)
@ 2019-08-01 14:48   ` Mihail Atanassov
  -1 siblings, 0 replies; 37+ messages in thread
From: Mihail Atanassov @ 2019-08-01 14:48 UTC (permalink / raw)
  To: dri-devel
  Cc: Lowry Li (Arm Technology China),
	Liviu Dudau, james qian wang (Arm Technology China),
	maarten.lankhorst, seanpaul, airlied, Brian Starkey, Ayan Halder,
	Jonathan Chai (Arm Technology China),
	linux-kernel, Julien Yin (Arm Technology China),
	nd

Hi Lowry,

On Thursday, 1 August 2019 12:37:15 BST Lowry Li (Arm Technology China) wrote:
> From: "Lowry Li (Arm Technology China)" <Lowry.Li@arm.com>
> 
> Adds to print the event message when error happens and the same event
> will not be printed until next vsync.
> 
> Changes since v1:
> 1. Handling the event print by CONFIG_KOMEDA_ERROR_PRINT;
> 2. Changing the max string size to 256.
> 
> Signed-off-by: Lowry Li (Arm Technology China) <lowry.li@arm.com>
> ---
>  drivers/gpu/drm/arm/display/Kconfig               |   6 +
>  drivers/gpu/drm/arm/display/komeda/Makefile       |   2 +
>  drivers/gpu/drm/arm/display/komeda/komeda_dev.h   |  15 +++
>  drivers/gpu/drm/arm/display/komeda/komeda_event.c | 141
> ++++++++++++++++++++++ drivers/gpu/drm/arm/display/komeda/komeda_kms.c   | 
>  4 +
>  5 files changed, 168 insertions(+)
>  create mode 100644 drivers/gpu/drm/arm/display/komeda/komeda_event.c
> 
> diff --git a/drivers/gpu/drm/arm/display/Kconfig
> b/drivers/gpu/drm/arm/display/Kconfig index cec0639..e87ff86 100644
> --- a/drivers/gpu/drm/arm/display/Kconfig
> +++ b/drivers/gpu/drm/arm/display/Kconfig
> @@ -12,3 +12,9 @@ config DRM_KOMEDA
>  	  Processor driver. It supports the D71 variants of the hardware.
> 
>  	  If compiled as a module it will be called komeda.
> +
> +config DRM_KOMEDA_ERROR_PRINT
> +	bool "Enable komeda error print"
> +	depends on DRM_KOMEDA
> +	help
> +	  Choose this option to enable error printing.
> diff --git a/drivers/gpu/drm/arm/display/komeda/Makefile
> b/drivers/gpu/drm/arm/display/komeda/Makefile index 5c3900c..f095a1c 100644
> --- a/drivers/gpu/drm/arm/display/komeda/Makefile
> +++ b/drivers/gpu/drm/arm/display/komeda/Makefile
> @@ -22,4 +22,6 @@ komeda-y += \
>  	d71/d71_dev.o \
>  	d71/d71_component.o
> 
> +komeda-$(CONFIG_DRM_KOMEDA_ERROR_PRINT) += komeda_event.o
> +
>  obj-$(CONFIG_DRM_KOMEDA) += komeda.o
> diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_dev.h
> b/drivers/gpu/drm/arm/display/komeda/komeda_dev.h index d1c86b6..e28e7e6
> 100644
> --- a/drivers/gpu/drm/arm/display/komeda/komeda_dev.h
> +++ b/drivers/gpu/drm/arm/display/komeda/komeda_dev.h
> @@ -40,6 +40,17 @@
>  #define KOMEDA_ERR_TTNG			BIT_ULL(30)
>  #define KOMEDA_ERR_TTF			BIT_ULL(31)
> 
> +#define KOMEDA_ERR_EVENTS	\
> +	(KOMEDA_EVENT_URUN	| KOMEDA_EVENT_IBSY	| KOMEDA_EVENT_OVR |
\
> +	KOMEDA_ERR_TETO		| KOMEDA_ERR_TEMR	| 
KOMEDA_ERR_TITR |\
> +	KOMEDA_ERR_CPE		| KOMEDA_ERR_CFGE	| 
KOMEDA_ERR_AXIE |\
> +	KOMEDA_ERR_ACE0		| KOMEDA_ERR_ACE1	| 
KOMEDA_ERR_ACE2 |\
> +	KOMEDA_ERR_ACE3		| KOMEDA_ERR_DRIFTTO	| 
KOMEDA_ERR_FRAMETO |\
> +	KOMEDA_ERR_ZME		| KOMEDA_ERR_MERR	| 
KOMEDA_ERR_TCF |\
> +	KOMEDA_ERR_TTNG		| KOMEDA_ERR_TTF)
> +
> +#define KOMEDA_WARN_EVENTS	KOMEDA_ERR_CSCE
> +
>  /* malidp device id */
>  enum {
>  	MALI_D71 = 0,
> @@ -207,4 +218,8 @@ struct komeda_dev {
> 
>  struct komeda_dev *dev_to_mdev(struct device *dev);
> 
> +#ifdef CONFIG_DRM_KOMEDA_ERROR_PRINT
> +void komeda_print_events(struct komeda_events *evts);
> +#endif
> +
>  #endif /*_KOMEDA_DEV_H_*/
> diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_event.c
> b/drivers/gpu/drm/arm/display/komeda/komeda_event.c new file mode 100644
> index 0000000..57b60cd
> --- /dev/null
> +++ b/drivers/gpu/drm/arm/display/komeda/komeda_event.c
> @@ -0,0 +1,141 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * (C) COPYRIGHT 2019 ARM Limited. All rights reserved.
> + * Author: James.Qian.Wang <james.qian.wang@arm.com>
> + *
> + */
> +#include <drm/drm_print.h>
> +
> +#include "komeda_dev.h"
> +
> +struct komeda_str {
> +	char *str;
> +	u32 sz;
> +	u32 len;
> +};
> +
> +/* return 0 on success,  < 0 on no space.
> + */
> +static int komeda_sprintf(struct komeda_str *str, const char *fmt, ...)
The lack of '\0'-termination in the truncation case is quite disconcerting, 
especially since vsnprintf does it. This would be quite surprising to the 
casual passer-by.
> +{
> +	va_list args;
> +	int num, free_sz;
> +	int err;
> +
> +	free_sz = str->sz - str->len;
That's off by 1, you need to account for the null byte.
> +	if (free_sz <= 0)
> +		return -ENOSPC;
> +
> +	va_start(args, fmt);
> +
> +	num = vsnprintf(str->str + str->len, free_sz, fmt, args);
> +
> +	va_end(args);
> +
> +	if (num <= free_sz) {
Strictly less than. To quote from the doc of vsnprintf: 
""" [...] If the return is greater than or equal to @size, the resulting 
string is truncated. """
> +		str->len += num;
> +		err = 0;
> +	} else {
> +		str->len = str->sz;
Off by 1 here, too.
> +		err = -ENOSPC;
That error code isn't used anywhere, so there's no value to having it in the 
current version of this patch. Either check the error code somewhere 
downstream and handle it, or change that to an actionable message for the 
person reading the kernel log. As it stands truncation is completely silent.
> +	}
> +
> +	return err;
> +}
> +
> +static void evt_sprintf(struct komeda_str *str, u64 evt, const char *msg)
> +{
> +	if (evt)
> +		komeda_sprintf(str, msg);
> +}
> +
> +static void evt_str(struct komeda_str *str, u64 events)
> +{
> +	if (events == 0ULL) {
> +		evt_sprintf(str, 1, "None");
[nit] Call `komeda_sprintf(str, "None")` directly?
> +		return;
> +	}
> +
> +	evt_sprintf(str, events & KOMEDA_EVENT_VSYNC, "VSYNC|");
> +	evt_sprintf(str, events & KOMEDA_EVENT_FLIP, "FLIP|");
> +	evt_sprintf(str, events & KOMEDA_EVENT_EOW, "EOW|");
> +	evt_sprintf(str, events & KOMEDA_EVENT_MODE, "OP-MODE|");
> +
> +	evt_sprintf(str, events & KOMEDA_EVENT_URUN, "UNDERRUN|");
> +	evt_sprintf(str, events & KOMEDA_EVENT_OVR, "OVERRUN|");
> +
> +	/* GLB error */
> +	evt_sprintf(str, events & KOMEDA_ERR_MERR, "MERR|");
> +	evt_sprintf(str, events & KOMEDA_ERR_FRAMETO, "FRAMETO|");
> +
> +	/* DOU error */
> +	evt_sprintf(str, events & KOMEDA_ERR_DRIFTTO, "DRIFTTO|");
> +	evt_sprintf(str, events & KOMEDA_ERR_FRAMETO, "FRAMETO|");
> +	evt_sprintf(str, events & KOMEDA_ERR_TETO, "TETO|");
> +	evt_sprintf(str, events & KOMEDA_ERR_CSCE, "CSCE|");
> +
> +	/* LPU errors or events */
> +	evt_sprintf(str, events & KOMEDA_EVENT_IBSY, "IBSY|");
> +	evt_sprintf(str, events & KOMEDA_ERR_AXIE, "AXIE|");
> +	evt_sprintf(str, events & KOMEDA_ERR_ACE0, "ACE0|");
> +	evt_sprintf(str, events & KOMEDA_ERR_ACE1, "ACE1|");
> +	evt_sprintf(str, events & KOMEDA_ERR_ACE2, "ACE2|");
> +	evt_sprintf(str, events & KOMEDA_ERR_ACE3, "ACE3|");
> +
> +	/* LPU TBU errors*/
> +	evt_sprintf(str, events & KOMEDA_ERR_TCF, "TCF|");
> +	evt_sprintf(str, events & KOMEDA_ERR_TTNG, "TTNG|");
> +	evt_sprintf(str, events & KOMEDA_ERR_TITR, "TITR|");
> +	evt_sprintf(str, events & KOMEDA_ERR_TEMR, "TEMR|");
> +	evt_sprintf(str, events & KOMEDA_ERR_TTF, "TTF|");
> +
> +	/* CU errors*/
> +	evt_sprintf(str, events & KOMEDA_ERR_CPE, "COPROC|");
> +	evt_sprintf(str, events & KOMEDA_ERR_ZME, "ZME|");
> +	evt_sprintf(str, events & KOMEDA_ERR_CFGE, "CFGE|");
> +	evt_sprintf(str, events & KOMEDA_ERR_TEMR, "TEMR|");
> +
> +	if (str->len > 0 && (str->str[str->len - 1] == '|')) {
> +		str->str[str->len - 1] = 0;
> +		str->len--;
> +	}
> +}
> +
> +static bool is_new_frame(struct komeda_events *a)
> +{
> +	return (a->pipes[0] | a->pipes[1]) &
> +	       (KOMEDA_EVENT_FLIP | KOMEDA_EVENT_EOW);
> +}
> +
> +void komeda_print_events(struct komeda_events *evts)
> +{
> +	u64 print_evts = KOMEDA_ERR_EVENTS;
> +	static bool en_print = true;
> +
> +	/* reduce the same msg print, only print the first evt for one 
frame */
> +	if (evts->global || is_new_frame(evts))
> +		en_print = true;
> +	if (!en_print)
> +		return;
> +
> +	if ((evts->global | evts->pipes[0] | evts->pipes[1]) & print_evts) 
{
> +		#define STR_SZ		256
[nit] I'd undef that once it's no longer needed
> +		char msg[STR_SZ];
> +		struct komeda_str str;
> +
> +		str.str = msg;
> +		str.sz  = STR_SZ;
> +		str.len = 0;
> +
> +		komeda_sprintf(&str, "gcu: ");
> +		evt_str(&str, evts->global);
> +		komeda_sprintf(&str, ", pipes[0]: ");
> +		evt_str(&str, evts->pipes[0]);
> +		komeda_sprintf(&str, ", pipes[1]: ");
> +		evt_str(&str, evts->pipes[1]);
> +
> +		DRM_ERROR("err detect: %s\n", msg);
> +
> +		en_print = false;
> +	}
> +}
> diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_kms.c
> b/drivers/gpu/drm/arm/display/komeda/komeda_kms.c index 419a8b0..0fafc36
> 100644
> --- a/drivers/gpu/drm/arm/display/komeda/komeda_kms.c
> +++ b/drivers/gpu/drm/arm/display/komeda/komeda_kms.c
> @@ -47,6 +47,10 @@ static irqreturn_t komeda_kms_irq_handler(int irq, void
> *data) memset(&evts, 0, sizeof(evts));
>  	status = mdev->funcs->irq_handler(mdev, &evts);
> 
> +#ifdef CONFIG_DRM_KOMEDA_ERROR_PRINT
> +	komeda_print_events(&evts);
> +#endif
> +
>  	/* Notify the crtc to handle the events */
>  	for (i = 0; i < kms->n_crtcs; i++)
>  		komeda_crtc_handle_event(&kms->crtcs[i], &evts);

BR,
Mihail



^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [PATCH] drm/komeda: Adds error event print functionality
@ 2019-08-01 14:48   ` Mihail Atanassov
  0 siblings, 0 replies; 37+ messages in thread
From: Mihail Atanassov @ 2019-08-01 14:48 UTC (permalink / raw)
  To: dri-devel
  Cc: nd, Ayan Halder, airlied, Liviu Dudau,
	Jonathan Chai (Arm Technology China),
	linux-kernel, Julien Yin (Arm Technology China),
	james qian wang (Arm Technology China),
	seanpaul, Lowry Li (Arm Technology China)

Hi Lowry,

On Thursday, 1 August 2019 12:37:15 BST Lowry Li (Arm Technology China) wrote:
> From: "Lowry Li (Arm Technology China)" <Lowry.Li@arm.com>
> 
> Adds to print the event message when error happens and the same event
> will not be printed until next vsync.
> 
> Changes since v1:
> 1. Handling the event print by CONFIG_KOMEDA_ERROR_PRINT;
> 2. Changing the max string size to 256.
> 
> Signed-off-by: Lowry Li (Arm Technology China) <lowry.li@arm.com>
> ---
>  drivers/gpu/drm/arm/display/Kconfig               |   6 +
>  drivers/gpu/drm/arm/display/komeda/Makefile       |   2 +
>  drivers/gpu/drm/arm/display/komeda/komeda_dev.h   |  15 +++
>  drivers/gpu/drm/arm/display/komeda/komeda_event.c | 141
> ++++++++++++++++++++++ drivers/gpu/drm/arm/display/komeda/komeda_kms.c   | 
>  4 +
>  5 files changed, 168 insertions(+)
>  create mode 100644 drivers/gpu/drm/arm/display/komeda/komeda_event.c
> 
> diff --git a/drivers/gpu/drm/arm/display/Kconfig
> b/drivers/gpu/drm/arm/display/Kconfig index cec0639..e87ff86 100644
> --- a/drivers/gpu/drm/arm/display/Kconfig
> +++ b/drivers/gpu/drm/arm/display/Kconfig
> @@ -12,3 +12,9 @@ config DRM_KOMEDA
>  	  Processor driver. It supports the D71 variants of the hardware.
> 
>  	  If compiled as a module it will be called komeda.
> +
> +config DRM_KOMEDA_ERROR_PRINT
> +	bool "Enable komeda error print"
> +	depends on DRM_KOMEDA
> +	help
> +	  Choose this option to enable error printing.
> diff --git a/drivers/gpu/drm/arm/display/komeda/Makefile
> b/drivers/gpu/drm/arm/display/komeda/Makefile index 5c3900c..f095a1c 100644
> --- a/drivers/gpu/drm/arm/display/komeda/Makefile
> +++ b/drivers/gpu/drm/arm/display/komeda/Makefile
> @@ -22,4 +22,6 @@ komeda-y += \
>  	d71/d71_dev.o \
>  	d71/d71_component.o
> 
> +komeda-$(CONFIG_DRM_KOMEDA_ERROR_PRINT) += komeda_event.o
> +
>  obj-$(CONFIG_DRM_KOMEDA) += komeda.o
> diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_dev.h
> b/drivers/gpu/drm/arm/display/komeda/komeda_dev.h index d1c86b6..e28e7e6
> 100644
> --- a/drivers/gpu/drm/arm/display/komeda/komeda_dev.h
> +++ b/drivers/gpu/drm/arm/display/komeda/komeda_dev.h
> @@ -40,6 +40,17 @@
>  #define KOMEDA_ERR_TTNG			BIT_ULL(30)
>  #define KOMEDA_ERR_TTF			BIT_ULL(31)
> 
> +#define KOMEDA_ERR_EVENTS	\
> +	(KOMEDA_EVENT_URUN	| KOMEDA_EVENT_IBSY	| KOMEDA_EVENT_OVR |
\
> +	KOMEDA_ERR_TETO		| KOMEDA_ERR_TEMR	| 
KOMEDA_ERR_TITR |\
> +	KOMEDA_ERR_CPE		| KOMEDA_ERR_CFGE	| 
KOMEDA_ERR_AXIE |\
> +	KOMEDA_ERR_ACE0		| KOMEDA_ERR_ACE1	| 
KOMEDA_ERR_ACE2 |\
> +	KOMEDA_ERR_ACE3		| KOMEDA_ERR_DRIFTTO	| 
KOMEDA_ERR_FRAMETO |\
> +	KOMEDA_ERR_ZME		| KOMEDA_ERR_MERR	| 
KOMEDA_ERR_TCF |\
> +	KOMEDA_ERR_TTNG		| KOMEDA_ERR_TTF)
> +
> +#define KOMEDA_WARN_EVENTS	KOMEDA_ERR_CSCE
> +
>  /* malidp device id */
>  enum {
>  	MALI_D71 = 0,
> @@ -207,4 +218,8 @@ struct komeda_dev {
> 
>  struct komeda_dev *dev_to_mdev(struct device *dev);
> 
> +#ifdef CONFIG_DRM_KOMEDA_ERROR_PRINT
> +void komeda_print_events(struct komeda_events *evts);
> +#endif
> +
>  #endif /*_KOMEDA_DEV_H_*/
> diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_event.c
> b/drivers/gpu/drm/arm/display/komeda/komeda_event.c new file mode 100644
> index 0000000..57b60cd
> --- /dev/null
> +++ b/drivers/gpu/drm/arm/display/komeda/komeda_event.c
> @@ -0,0 +1,141 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * (C) COPYRIGHT 2019 ARM Limited. All rights reserved.
> + * Author: James.Qian.Wang <james.qian.wang@arm.com>
> + *
> + */
> +#include <drm/drm_print.h>
> +
> +#include "komeda_dev.h"
> +
> +struct komeda_str {
> +	char *str;
> +	u32 sz;
> +	u32 len;
> +};
> +
> +/* return 0 on success,  < 0 on no space.
> + */
> +static int komeda_sprintf(struct komeda_str *str, const char *fmt, ...)
The lack of '\0'-termination in the truncation case is quite disconcerting, 
especially since vsnprintf does it. This would be quite surprising to the 
casual passer-by.
> +{
> +	va_list args;
> +	int num, free_sz;
> +	int err;
> +
> +	free_sz = str->sz - str->len;
That's off by 1, you need to account for the null byte.
> +	if (free_sz <= 0)
> +		return -ENOSPC;
> +
> +	va_start(args, fmt);
> +
> +	num = vsnprintf(str->str + str->len, free_sz, fmt, args);
> +
> +	va_end(args);
> +
> +	if (num <= free_sz) {
Strictly less than. To quote from the doc of vsnprintf: 
""" [...] If the return is greater than or equal to @size, the resulting 
string is truncated. """
> +		str->len += num;
> +		err = 0;
> +	} else {
> +		str->len = str->sz;
Off by 1 here, too.
> +		err = -ENOSPC;
That error code isn't used anywhere, so there's no value to having it in the 
current version of this patch. Either check the error code somewhere 
downstream and handle it, or change that to an actionable message for the 
person reading the kernel log. As it stands truncation is completely silent.
> +	}
> +
> +	return err;
> +}
> +
> +static void evt_sprintf(struct komeda_str *str, u64 evt, const char *msg)
> +{
> +	if (evt)
> +		komeda_sprintf(str, msg);
> +}
> +
> +static void evt_str(struct komeda_str *str, u64 events)
> +{
> +	if (events == 0ULL) {
> +		evt_sprintf(str, 1, "None");
[nit] Call `komeda_sprintf(str, "None")` directly?
> +		return;
> +	}
> +
> +	evt_sprintf(str, events & KOMEDA_EVENT_VSYNC, "VSYNC|");
> +	evt_sprintf(str, events & KOMEDA_EVENT_FLIP, "FLIP|");
> +	evt_sprintf(str, events & KOMEDA_EVENT_EOW, "EOW|");
> +	evt_sprintf(str, events & KOMEDA_EVENT_MODE, "OP-MODE|");
> +
> +	evt_sprintf(str, events & KOMEDA_EVENT_URUN, "UNDERRUN|");
> +	evt_sprintf(str, events & KOMEDA_EVENT_OVR, "OVERRUN|");
> +
> +	/* GLB error */
> +	evt_sprintf(str, events & KOMEDA_ERR_MERR, "MERR|");
> +	evt_sprintf(str, events & KOMEDA_ERR_FRAMETO, "FRAMETO|");
> +
> +	/* DOU error */
> +	evt_sprintf(str, events & KOMEDA_ERR_DRIFTTO, "DRIFTTO|");
> +	evt_sprintf(str, events & KOMEDA_ERR_FRAMETO, "FRAMETO|");
> +	evt_sprintf(str, events & KOMEDA_ERR_TETO, "TETO|");
> +	evt_sprintf(str, events & KOMEDA_ERR_CSCE, "CSCE|");
> +
> +	/* LPU errors or events */
> +	evt_sprintf(str, events & KOMEDA_EVENT_IBSY, "IBSY|");
> +	evt_sprintf(str, events & KOMEDA_ERR_AXIE, "AXIE|");
> +	evt_sprintf(str, events & KOMEDA_ERR_ACE0, "ACE0|");
> +	evt_sprintf(str, events & KOMEDA_ERR_ACE1, "ACE1|");
> +	evt_sprintf(str, events & KOMEDA_ERR_ACE2, "ACE2|");
> +	evt_sprintf(str, events & KOMEDA_ERR_ACE3, "ACE3|");
> +
> +	/* LPU TBU errors*/
> +	evt_sprintf(str, events & KOMEDA_ERR_TCF, "TCF|");
> +	evt_sprintf(str, events & KOMEDA_ERR_TTNG, "TTNG|");
> +	evt_sprintf(str, events & KOMEDA_ERR_TITR, "TITR|");
> +	evt_sprintf(str, events & KOMEDA_ERR_TEMR, "TEMR|");
> +	evt_sprintf(str, events & KOMEDA_ERR_TTF, "TTF|");
> +
> +	/* CU errors*/
> +	evt_sprintf(str, events & KOMEDA_ERR_CPE, "COPROC|");
> +	evt_sprintf(str, events & KOMEDA_ERR_ZME, "ZME|");
> +	evt_sprintf(str, events & KOMEDA_ERR_CFGE, "CFGE|");
> +	evt_sprintf(str, events & KOMEDA_ERR_TEMR, "TEMR|");
> +
> +	if (str->len > 0 && (str->str[str->len - 1] == '|')) {
> +		str->str[str->len - 1] = 0;
> +		str->len--;
> +	}
> +}
> +
> +static bool is_new_frame(struct komeda_events *a)
> +{
> +	return (a->pipes[0] | a->pipes[1]) &
> +	       (KOMEDA_EVENT_FLIP | KOMEDA_EVENT_EOW);
> +}
> +
> +void komeda_print_events(struct komeda_events *evts)
> +{
> +	u64 print_evts = KOMEDA_ERR_EVENTS;
> +	static bool en_print = true;
> +
> +	/* reduce the same msg print, only print the first evt for one 
frame */
> +	if (evts->global || is_new_frame(evts))
> +		en_print = true;
> +	if (!en_print)
> +		return;
> +
> +	if ((evts->global | evts->pipes[0] | evts->pipes[1]) & print_evts) 
{
> +		#define STR_SZ		256
[nit] I'd undef that once it's no longer needed
> +		char msg[STR_SZ];
> +		struct komeda_str str;
> +
> +		str.str = msg;
> +		str.sz  = STR_SZ;
> +		str.len = 0;
> +
> +		komeda_sprintf(&str, "gcu: ");
> +		evt_str(&str, evts->global);
> +		komeda_sprintf(&str, ", pipes[0]: ");
> +		evt_str(&str, evts->pipes[0]);
> +		komeda_sprintf(&str, ", pipes[1]: ");
> +		evt_str(&str, evts->pipes[1]);
> +
> +		DRM_ERROR("err detect: %s\n", msg);
> +
> +		en_print = false;
> +	}
> +}
> diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_kms.c
> b/drivers/gpu/drm/arm/display/komeda/komeda_kms.c index 419a8b0..0fafc36
> 100644
> --- a/drivers/gpu/drm/arm/display/komeda/komeda_kms.c
> +++ b/drivers/gpu/drm/arm/display/komeda/komeda_kms.c
> @@ -47,6 +47,10 @@ static irqreturn_t komeda_kms_irq_handler(int irq, void
> *data) memset(&evts, 0, sizeof(evts));
>  	status = mdev->funcs->irq_handler(mdev, &evts);
> 
> +#ifdef CONFIG_DRM_KOMEDA_ERROR_PRINT
> +	komeda_print_events(&evts);
> +#endif
> +
>  	/* Notify the crtc to handle the events */
>  	for (i = 0; i < kms->n_crtcs; i++)
>  		komeda_crtc_handle_event(&kms->crtcs[i], &evts);

BR,
Mihail


_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [PATCH] drm/komeda: Adds error event print functionality
  2019-08-01 11:37 ` Lowry Li (Arm Technology China)
@ 2019-08-01 13:52   ` Liviu Dudau
  -1 siblings, 0 replies; 37+ messages in thread
From: Liviu Dudau @ 2019-08-01 13:52 UTC (permalink / raw)
  To: Lowry Li (Arm Technology China)
  Cc: james qian wang (Arm Technology China),
	maarten.lankhorst, seanpaul, airlied, Brian Starkey,
	Julien Yin (Arm Technology China),
	Jonathan Chai (Arm Technology China),
	Ayan Halder, dri-devel, linux-kernel, nd

On Thu, Aug 01, 2019 at 11:37:15AM +0000, Lowry Li (Arm Technology China) wrote:
> From: "Lowry Li (Arm Technology China)" <Lowry.Li@arm.com>
> 
> Adds to print the event message when error happens and the same event
> will not be printed until next vsync.
> 
> Changes since v1:
> 1. Handling the event print by CONFIG_KOMEDA_ERROR_PRINT;
> 2. Changing the max string size to 256.
> 
> Signed-off-by: Lowry Li (Arm Technology China) <lowry.li@arm.com>

Reviewed-by: Liviu Dudau <liviu.dudau@arm.com>

Best regards,
Liviu

> ---
>  drivers/gpu/drm/arm/display/Kconfig               |   6 +
>  drivers/gpu/drm/arm/display/komeda/Makefile       |   2 +
>  drivers/gpu/drm/arm/display/komeda/komeda_dev.h   |  15 +++
>  drivers/gpu/drm/arm/display/komeda/komeda_event.c | 141 ++++++++++++++++++++++
>  drivers/gpu/drm/arm/display/komeda/komeda_kms.c   |   4 +
>  5 files changed, 168 insertions(+)
>  create mode 100644 drivers/gpu/drm/arm/display/komeda/komeda_event.c
> 
> diff --git a/drivers/gpu/drm/arm/display/Kconfig b/drivers/gpu/drm/arm/display/Kconfig
> index cec0639..e87ff86 100644
> --- a/drivers/gpu/drm/arm/display/Kconfig
> +++ b/drivers/gpu/drm/arm/display/Kconfig
> @@ -12,3 +12,9 @@ config DRM_KOMEDA
>  	  Processor driver. It supports the D71 variants of the hardware.
>  
>  	  If compiled as a module it will be called komeda.
> +
> +config DRM_KOMEDA_ERROR_PRINT
> +	bool "Enable komeda error print"
> +	depends on DRM_KOMEDA
> +	help
> +	  Choose this option to enable error printing.
> diff --git a/drivers/gpu/drm/arm/display/komeda/Makefile b/drivers/gpu/drm/arm/display/komeda/Makefile
> index 5c3900c..f095a1c 100644
> --- a/drivers/gpu/drm/arm/display/komeda/Makefile
> +++ b/drivers/gpu/drm/arm/display/komeda/Makefile
> @@ -22,4 +22,6 @@ komeda-y += \
>  	d71/d71_dev.o \
>  	d71/d71_component.o
>  
> +komeda-$(CONFIG_DRM_KOMEDA_ERROR_PRINT) += komeda_event.o
> +
>  obj-$(CONFIG_DRM_KOMEDA) += komeda.o
> diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_dev.h b/drivers/gpu/drm/arm/display/komeda/komeda_dev.h
> index d1c86b6..e28e7e6 100644
> --- a/drivers/gpu/drm/arm/display/komeda/komeda_dev.h
> +++ b/drivers/gpu/drm/arm/display/komeda/komeda_dev.h
> @@ -40,6 +40,17 @@
>  #define KOMEDA_ERR_TTNG			BIT_ULL(30)
>  #define KOMEDA_ERR_TTF			BIT_ULL(31)
>  
> +#define KOMEDA_ERR_EVENTS	\
> +	(KOMEDA_EVENT_URUN	| KOMEDA_EVENT_IBSY	| KOMEDA_EVENT_OVR |\
> +	KOMEDA_ERR_TETO		| KOMEDA_ERR_TEMR	| KOMEDA_ERR_TITR |\
> +	KOMEDA_ERR_CPE		| KOMEDA_ERR_CFGE	| KOMEDA_ERR_AXIE |\
> +	KOMEDA_ERR_ACE0		| KOMEDA_ERR_ACE1	| KOMEDA_ERR_ACE2 |\
> +	KOMEDA_ERR_ACE3		| KOMEDA_ERR_DRIFTTO	| KOMEDA_ERR_FRAMETO |\
> +	KOMEDA_ERR_ZME		| KOMEDA_ERR_MERR	| KOMEDA_ERR_TCF |\
> +	KOMEDA_ERR_TTNG		| KOMEDA_ERR_TTF)
> +
> +#define KOMEDA_WARN_EVENTS	KOMEDA_ERR_CSCE
> +
>  /* malidp device id */
>  enum {
>  	MALI_D71 = 0,
> @@ -207,4 +218,8 @@ struct komeda_dev {
>  
>  struct komeda_dev *dev_to_mdev(struct device *dev);
>  
> +#ifdef CONFIG_DRM_KOMEDA_ERROR_PRINT
> +void komeda_print_events(struct komeda_events *evts);
> +#endif
> +
>  #endif /*_KOMEDA_DEV_H_*/
> diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_event.c b/drivers/gpu/drm/arm/display/komeda/komeda_event.c
> new file mode 100644
> index 0000000..57b60cd
> --- /dev/null
> +++ b/drivers/gpu/drm/arm/display/komeda/komeda_event.c
> @@ -0,0 +1,141 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * (C) COPYRIGHT 2019 ARM Limited. All rights reserved.
> + * Author: James.Qian.Wang <james.qian.wang@arm.com>
> + *
> + */
> +#include <drm/drm_print.h>
> +
> +#include "komeda_dev.h"
> +
> +struct komeda_str {
> +	char *str;
> +	u32 sz;
> +	u32 len;
> +};
> +
> +/* return 0 on success,  < 0 on no space.
> + */
> +static int komeda_sprintf(struct komeda_str *str, const char *fmt, ...)
> +{
> +	va_list args;
> +	int num, free_sz;
> +	int err;
> +
> +	free_sz = str->sz - str->len;
> +	if (free_sz <= 0)
> +		return -ENOSPC;
> +
> +	va_start(args, fmt);
> +
> +	num = vsnprintf(str->str + str->len, free_sz, fmt, args);
> +
> +	va_end(args);
> +
> +	if (num <= free_sz) {
> +		str->len += num;
> +		err = 0;
> +	} else {
> +		str->len = str->sz;
> +		err = -ENOSPC;
> +	}
> +
> +	return err;
> +}
> +
> +static void evt_sprintf(struct komeda_str *str, u64 evt, const char *msg)
> +{
> +	if (evt)
> +		komeda_sprintf(str, msg);
> +}
> +
> +static void evt_str(struct komeda_str *str, u64 events)
> +{
> +	if (events == 0ULL) {
> +		evt_sprintf(str, 1, "None");
> +		return;
> +	}
> +
> +	evt_sprintf(str, events & KOMEDA_EVENT_VSYNC, "VSYNC|");
> +	evt_sprintf(str, events & KOMEDA_EVENT_FLIP, "FLIP|");
> +	evt_sprintf(str, events & KOMEDA_EVENT_EOW, "EOW|");
> +	evt_sprintf(str, events & KOMEDA_EVENT_MODE, "OP-MODE|");
> +
> +	evt_sprintf(str, events & KOMEDA_EVENT_URUN, "UNDERRUN|");
> +	evt_sprintf(str, events & KOMEDA_EVENT_OVR, "OVERRUN|");
> +
> +	/* GLB error */
> +	evt_sprintf(str, events & KOMEDA_ERR_MERR, "MERR|");
> +	evt_sprintf(str, events & KOMEDA_ERR_FRAMETO, "FRAMETO|");
> +
> +	/* DOU error */
> +	evt_sprintf(str, events & KOMEDA_ERR_DRIFTTO, "DRIFTTO|");
> +	evt_sprintf(str, events & KOMEDA_ERR_FRAMETO, "FRAMETO|");
> +	evt_sprintf(str, events & KOMEDA_ERR_TETO, "TETO|");
> +	evt_sprintf(str, events & KOMEDA_ERR_CSCE, "CSCE|");
> +
> +	/* LPU errors or events */
> +	evt_sprintf(str, events & KOMEDA_EVENT_IBSY, "IBSY|");
> +	evt_sprintf(str, events & KOMEDA_ERR_AXIE, "AXIE|");
> +	evt_sprintf(str, events & KOMEDA_ERR_ACE0, "ACE0|");
> +	evt_sprintf(str, events & KOMEDA_ERR_ACE1, "ACE1|");
> +	evt_sprintf(str, events & KOMEDA_ERR_ACE2, "ACE2|");
> +	evt_sprintf(str, events & KOMEDA_ERR_ACE3, "ACE3|");
> +
> +	/* LPU TBU errors*/
> +	evt_sprintf(str, events & KOMEDA_ERR_TCF, "TCF|");
> +	evt_sprintf(str, events & KOMEDA_ERR_TTNG, "TTNG|");
> +	evt_sprintf(str, events & KOMEDA_ERR_TITR, "TITR|");
> +	evt_sprintf(str, events & KOMEDA_ERR_TEMR, "TEMR|");
> +	evt_sprintf(str, events & KOMEDA_ERR_TTF, "TTF|");
> +
> +	/* CU errors*/
> +	evt_sprintf(str, events & KOMEDA_ERR_CPE, "COPROC|");
> +	evt_sprintf(str, events & KOMEDA_ERR_ZME, "ZME|");
> +	evt_sprintf(str, events & KOMEDA_ERR_CFGE, "CFGE|");
> +	evt_sprintf(str, events & KOMEDA_ERR_TEMR, "TEMR|");
> +
> +	if (str->len > 0 && (str->str[str->len - 1] == '|')) {
> +		str->str[str->len - 1] = 0;
> +		str->len--;
> +	}
> +}
> +
> +static bool is_new_frame(struct komeda_events *a)
> +{
> +	return (a->pipes[0] | a->pipes[1]) &
> +	       (KOMEDA_EVENT_FLIP | KOMEDA_EVENT_EOW);
> +}
> +
> +void komeda_print_events(struct komeda_events *evts)
> +{
> +	u64 print_evts = KOMEDA_ERR_EVENTS;
> +	static bool en_print = true;
> +
> +	/* reduce the same msg print, only print the first evt for one frame */
> +	if (evts->global || is_new_frame(evts))
> +		en_print = true;
> +	if (!en_print)
> +		return;
> +
> +	if ((evts->global | evts->pipes[0] | evts->pipes[1]) & print_evts) {
> +		#define STR_SZ		256
> +		char msg[STR_SZ];
> +		struct komeda_str str;
> +
> +		str.str = msg;
> +		str.sz  = STR_SZ;
> +		str.len = 0;
> +
> +		komeda_sprintf(&str, "gcu: ");
> +		evt_str(&str, evts->global);
> +		komeda_sprintf(&str, ", pipes[0]: ");
> +		evt_str(&str, evts->pipes[0]);
> +		komeda_sprintf(&str, ", pipes[1]: ");
> +		evt_str(&str, evts->pipes[1]);
> +
> +		DRM_ERROR("err detect: %s\n", msg);
> +
> +		en_print = false;
> +	}
> +}
> diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_kms.c b/drivers/gpu/drm/arm/display/komeda/komeda_kms.c
> index 419a8b0..0fafc36 100644
> --- a/drivers/gpu/drm/arm/display/komeda/komeda_kms.c
> +++ b/drivers/gpu/drm/arm/display/komeda/komeda_kms.c
> @@ -47,6 +47,10 @@ static irqreturn_t komeda_kms_irq_handler(int irq, void *data)
>  	memset(&evts, 0, sizeof(evts));
>  	status = mdev->funcs->irq_handler(mdev, &evts);
>  
> +#ifdef CONFIG_DRM_KOMEDA_ERROR_PRINT
> +	komeda_print_events(&evts);
> +#endif
> +
>  	/* Notify the crtc to handle the events */
>  	for (i = 0; i < kms->n_crtcs; i++)
>  		komeda_crtc_handle_event(&kms->crtcs[i], &evts);
> -- 
> 1.9.1
> 

-- 
====================
| I would like to |
| fix the world,  |
| but they're not |
| giving me the   |
 \ source code!  /
  ---------------
    ¯\_(ツ)_/¯

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [PATCH] drm/komeda: Adds error event print functionality
@ 2019-08-01 13:52   ` Liviu Dudau
  0 siblings, 0 replies; 37+ messages in thread
From: Liviu Dudau @ 2019-08-01 13:52 UTC (permalink / raw)
  To: Lowry Li (Arm Technology China)
  Cc: james qian wang (Arm Technology China),
	maarten.lankhorst, seanpaul, airlied, Brian Starkey,
	Julien Yin (Arm Technology China),
	Jonathan Chai (Arm Technology China),
	Ayan Halder, dri-devel, linux-kernel, nd

On Thu, Aug 01, 2019 at 11:37:15AM +0000, Lowry Li (Arm Technology China) wrote:
> From: "Lowry Li (Arm Technology China)" <Lowry.Li@arm.com>
> 
> Adds to print the event message when error happens and the same event
> will not be printed until next vsync.
> 
> Changes since v1:
> 1. Handling the event print by CONFIG_KOMEDA_ERROR_PRINT;
> 2. Changing the max string size to 256.
> 
> Signed-off-by: Lowry Li (Arm Technology China) <lowry.li@arm.com>

Reviewed-by: Liviu Dudau <liviu.dudau@arm.com>

Best regards,
Liviu

> ---
>  drivers/gpu/drm/arm/display/Kconfig               |   6 +
>  drivers/gpu/drm/arm/display/komeda/Makefile       |   2 +
>  drivers/gpu/drm/arm/display/komeda/komeda_dev.h   |  15 +++
>  drivers/gpu/drm/arm/display/komeda/komeda_event.c | 141 ++++++++++++++++++++++
>  drivers/gpu/drm/arm/display/komeda/komeda_kms.c   |   4 +
>  5 files changed, 168 insertions(+)
>  create mode 100644 drivers/gpu/drm/arm/display/komeda/komeda_event.c
> 
> diff --git a/drivers/gpu/drm/arm/display/Kconfig b/drivers/gpu/drm/arm/display/Kconfig
> index cec0639..e87ff86 100644
> --- a/drivers/gpu/drm/arm/display/Kconfig
> +++ b/drivers/gpu/drm/arm/display/Kconfig
> @@ -12,3 +12,9 @@ config DRM_KOMEDA
>  	  Processor driver. It supports the D71 variants of the hardware.
>  
>  	  If compiled as a module it will be called komeda.
> +
> +config DRM_KOMEDA_ERROR_PRINT
> +	bool "Enable komeda error print"
> +	depends on DRM_KOMEDA
> +	help
> +	  Choose this option to enable error printing.
> diff --git a/drivers/gpu/drm/arm/display/komeda/Makefile b/drivers/gpu/drm/arm/display/komeda/Makefile
> index 5c3900c..f095a1c 100644
> --- a/drivers/gpu/drm/arm/display/komeda/Makefile
> +++ b/drivers/gpu/drm/arm/display/komeda/Makefile
> @@ -22,4 +22,6 @@ komeda-y += \
>  	d71/d71_dev.o \
>  	d71/d71_component.o
>  
> +komeda-$(CONFIG_DRM_KOMEDA_ERROR_PRINT) += komeda_event.o
> +
>  obj-$(CONFIG_DRM_KOMEDA) += komeda.o
> diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_dev.h b/drivers/gpu/drm/arm/display/komeda/komeda_dev.h
> index d1c86b6..e28e7e6 100644
> --- a/drivers/gpu/drm/arm/display/komeda/komeda_dev.h
> +++ b/drivers/gpu/drm/arm/display/komeda/komeda_dev.h
> @@ -40,6 +40,17 @@
>  #define KOMEDA_ERR_TTNG			BIT_ULL(30)
>  #define KOMEDA_ERR_TTF			BIT_ULL(31)
>  
> +#define KOMEDA_ERR_EVENTS	\
> +	(KOMEDA_EVENT_URUN	| KOMEDA_EVENT_IBSY	| KOMEDA_EVENT_OVR |\
> +	KOMEDA_ERR_TETO		| KOMEDA_ERR_TEMR	| KOMEDA_ERR_TITR |\
> +	KOMEDA_ERR_CPE		| KOMEDA_ERR_CFGE	| KOMEDA_ERR_AXIE |\
> +	KOMEDA_ERR_ACE0		| KOMEDA_ERR_ACE1	| KOMEDA_ERR_ACE2 |\
> +	KOMEDA_ERR_ACE3		| KOMEDA_ERR_DRIFTTO	| KOMEDA_ERR_FRAMETO |\
> +	KOMEDA_ERR_ZME		| KOMEDA_ERR_MERR	| KOMEDA_ERR_TCF |\
> +	KOMEDA_ERR_TTNG		| KOMEDA_ERR_TTF)
> +
> +#define KOMEDA_WARN_EVENTS	KOMEDA_ERR_CSCE
> +
>  /* malidp device id */
>  enum {
>  	MALI_D71 = 0,
> @@ -207,4 +218,8 @@ struct komeda_dev {
>  
>  struct komeda_dev *dev_to_mdev(struct device *dev);
>  
> +#ifdef CONFIG_DRM_KOMEDA_ERROR_PRINT
> +void komeda_print_events(struct komeda_events *evts);
> +#endif
> +
>  #endif /*_KOMEDA_DEV_H_*/
> diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_event.c b/drivers/gpu/drm/arm/display/komeda/komeda_event.c
> new file mode 100644
> index 0000000..57b60cd
> --- /dev/null
> +++ b/drivers/gpu/drm/arm/display/komeda/komeda_event.c
> @@ -0,0 +1,141 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * (C) COPYRIGHT 2019 ARM Limited. All rights reserved.
> + * Author: James.Qian.Wang <james.qian.wang@arm.com>
> + *
> + */
> +#include <drm/drm_print.h>
> +
> +#include "komeda_dev.h"
> +
> +struct komeda_str {
> +	char *str;
> +	u32 sz;
> +	u32 len;
> +};
> +
> +/* return 0 on success,  < 0 on no space.
> + */
> +static int komeda_sprintf(struct komeda_str *str, const char *fmt, ...)
> +{
> +	va_list args;
> +	int num, free_sz;
> +	int err;
> +
> +	free_sz = str->sz - str->len;
> +	if (free_sz <= 0)
> +		return -ENOSPC;
> +
> +	va_start(args, fmt);
> +
> +	num = vsnprintf(str->str + str->len, free_sz, fmt, args);
> +
> +	va_end(args);
> +
> +	if (num <= free_sz) {
> +		str->len += num;
> +		err = 0;
> +	} else {
> +		str->len = str->sz;
> +		err = -ENOSPC;
> +	}
> +
> +	return err;
> +}
> +
> +static void evt_sprintf(struct komeda_str *str, u64 evt, const char *msg)
> +{
> +	if (evt)
> +		komeda_sprintf(str, msg);
> +}
> +
> +static void evt_str(struct komeda_str *str, u64 events)
> +{
> +	if (events == 0ULL) {
> +		evt_sprintf(str, 1, "None");
> +		return;
> +	}
> +
> +	evt_sprintf(str, events & KOMEDA_EVENT_VSYNC, "VSYNC|");
> +	evt_sprintf(str, events & KOMEDA_EVENT_FLIP, "FLIP|");
> +	evt_sprintf(str, events & KOMEDA_EVENT_EOW, "EOW|");
> +	evt_sprintf(str, events & KOMEDA_EVENT_MODE, "OP-MODE|");
> +
> +	evt_sprintf(str, events & KOMEDA_EVENT_URUN, "UNDERRUN|");
> +	evt_sprintf(str, events & KOMEDA_EVENT_OVR, "OVERRUN|");
> +
> +	/* GLB error */
> +	evt_sprintf(str, events & KOMEDA_ERR_MERR, "MERR|");
> +	evt_sprintf(str, events & KOMEDA_ERR_FRAMETO, "FRAMETO|");
> +
> +	/* DOU error */
> +	evt_sprintf(str, events & KOMEDA_ERR_DRIFTTO, "DRIFTTO|");
> +	evt_sprintf(str, events & KOMEDA_ERR_FRAMETO, "FRAMETO|");
> +	evt_sprintf(str, events & KOMEDA_ERR_TETO, "TETO|");
> +	evt_sprintf(str, events & KOMEDA_ERR_CSCE, "CSCE|");
> +
> +	/* LPU errors or events */
> +	evt_sprintf(str, events & KOMEDA_EVENT_IBSY, "IBSY|");
> +	evt_sprintf(str, events & KOMEDA_ERR_AXIE, "AXIE|");
> +	evt_sprintf(str, events & KOMEDA_ERR_ACE0, "ACE0|");
> +	evt_sprintf(str, events & KOMEDA_ERR_ACE1, "ACE1|");
> +	evt_sprintf(str, events & KOMEDA_ERR_ACE2, "ACE2|");
> +	evt_sprintf(str, events & KOMEDA_ERR_ACE3, "ACE3|");
> +
> +	/* LPU TBU errors*/
> +	evt_sprintf(str, events & KOMEDA_ERR_TCF, "TCF|");
> +	evt_sprintf(str, events & KOMEDA_ERR_TTNG, "TTNG|");
> +	evt_sprintf(str, events & KOMEDA_ERR_TITR, "TITR|");
> +	evt_sprintf(str, events & KOMEDA_ERR_TEMR, "TEMR|");
> +	evt_sprintf(str, events & KOMEDA_ERR_TTF, "TTF|");
> +
> +	/* CU errors*/
> +	evt_sprintf(str, events & KOMEDA_ERR_CPE, "COPROC|");
> +	evt_sprintf(str, events & KOMEDA_ERR_ZME, "ZME|");
> +	evt_sprintf(str, events & KOMEDA_ERR_CFGE, "CFGE|");
> +	evt_sprintf(str, events & KOMEDA_ERR_TEMR, "TEMR|");
> +
> +	if (str->len > 0 && (str->str[str->len - 1] == '|')) {
> +		str->str[str->len - 1] = 0;
> +		str->len--;
> +	}
> +}
> +
> +static bool is_new_frame(struct komeda_events *a)
> +{
> +	return (a->pipes[0] | a->pipes[1]) &
> +	       (KOMEDA_EVENT_FLIP | KOMEDA_EVENT_EOW);
> +}
> +
> +void komeda_print_events(struct komeda_events *evts)
> +{
> +	u64 print_evts = KOMEDA_ERR_EVENTS;
> +	static bool en_print = true;
> +
> +	/* reduce the same msg print, only print the first evt for one frame */
> +	if (evts->global || is_new_frame(evts))
> +		en_print = true;
> +	if (!en_print)
> +		return;
> +
> +	if ((evts->global | evts->pipes[0] | evts->pipes[1]) & print_evts) {
> +		#define STR_SZ		256
> +		char msg[STR_SZ];
> +		struct komeda_str str;
> +
> +		str.str = msg;
> +		str.sz  = STR_SZ;
> +		str.len = 0;
> +
> +		komeda_sprintf(&str, "gcu: ");
> +		evt_str(&str, evts->global);
> +		komeda_sprintf(&str, ", pipes[0]: ");
> +		evt_str(&str, evts->pipes[0]);
> +		komeda_sprintf(&str, ", pipes[1]: ");
> +		evt_str(&str, evts->pipes[1]);
> +
> +		DRM_ERROR("err detect: %s\n", msg);
> +
> +		en_print = false;
> +	}
> +}
> diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_kms.c b/drivers/gpu/drm/arm/display/komeda/komeda_kms.c
> index 419a8b0..0fafc36 100644
> --- a/drivers/gpu/drm/arm/display/komeda/komeda_kms.c
> +++ b/drivers/gpu/drm/arm/display/komeda/komeda_kms.c
> @@ -47,6 +47,10 @@ static irqreturn_t komeda_kms_irq_handler(int irq, void *data)
>  	memset(&evts, 0, sizeof(evts));
>  	status = mdev->funcs->irq_handler(mdev, &evts);
>  
> +#ifdef CONFIG_DRM_KOMEDA_ERROR_PRINT
> +	komeda_print_events(&evts);
> +#endif
> +
>  	/* Notify the crtc to handle the events */
>  	for (i = 0; i < kms->n_crtcs; i++)
>  		komeda_crtc_handle_event(&kms->crtcs[i], &evts);
> -- 
> 1.9.1
> 

-- 
====================
| I would like to |
| fix the world,  |
| but they're not |
| giving me the   |
 \ source code!  /
  ---------------
    ¯\_(ツ)_/¯

^ permalink raw reply	[flat|nested] 37+ messages in thread

* [PATCH] drm/komeda: Adds error event print functionality
@ 2019-08-01 11:37 ` Lowry Li (Arm Technology China)
  0 siblings, 0 replies; 37+ messages in thread
From: Lowry Li (Arm Technology China) @ 2019-08-01 11:37 UTC (permalink / raw)
  To: Liviu Dudau, james qian wang (Arm Technology China),
	maarten.lankhorst, seanpaul, airlied, Brian Starkey
  Cc: Julien Yin (Arm Technology China),
	Jonathan Chai (Arm Technology China),
	Ayan Halder, dri-devel, linux-kernel, nd

From: "Lowry Li (Arm Technology China)" <Lowry.Li@arm.com>

Adds to print the event message when error happens and the same event
will not be printed until next vsync.

Changes since v1:
1. Handling the event print by CONFIG_KOMEDA_ERROR_PRINT;
2. Changing the max string size to 256.

Signed-off-by: Lowry Li (Arm Technology China) <lowry.li@arm.com>
---
 drivers/gpu/drm/arm/display/Kconfig               |   6 +
 drivers/gpu/drm/arm/display/komeda/Makefile       |   2 +
 drivers/gpu/drm/arm/display/komeda/komeda_dev.h   |  15 +++
 drivers/gpu/drm/arm/display/komeda/komeda_event.c | 141 ++++++++++++++++++++++
 drivers/gpu/drm/arm/display/komeda/komeda_kms.c   |   4 +
 5 files changed, 168 insertions(+)
 create mode 100644 drivers/gpu/drm/arm/display/komeda/komeda_event.c

diff --git a/drivers/gpu/drm/arm/display/Kconfig b/drivers/gpu/drm/arm/display/Kconfig
index cec0639..e87ff86 100644
--- a/drivers/gpu/drm/arm/display/Kconfig
+++ b/drivers/gpu/drm/arm/display/Kconfig
@@ -12,3 +12,9 @@ config DRM_KOMEDA
 	  Processor driver. It supports the D71 variants of the hardware.
 
 	  If compiled as a module it will be called komeda.
+
+config DRM_KOMEDA_ERROR_PRINT
+	bool "Enable komeda error print"
+	depends on DRM_KOMEDA
+	help
+	  Choose this option to enable error printing.
diff --git a/drivers/gpu/drm/arm/display/komeda/Makefile b/drivers/gpu/drm/arm/display/komeda/Makefile
index 5c3900c..f095a1c 100644
--- a/drivers/gpu/drm/arm/display/komeda/Makefile
+++ b/drivers/gpu/drm/arm/display/komeda/Makefile
@@ -22,4 +22,6 @@ komeda-y += \
 	d71/d71_dev.o \
 	d71/d71_component.o
 
+komeda-$(CONFIG_DRM_KOMEDA_ERROR_PRINT) += komeda_event.o
+
 obj-$(CONFIG_DRM_KOMEDA) += komeda.o
diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_dev.h b/drivers/gpu/drm/arm/display/komeda/komeda_dev.h
index d1c86b6..e28e7e6 100644
--- a/drivers/gpu/drm/arm/display/komeda/komeda_dev.h
+++ b/drivers/gpu/drm/arm/display/komeda/komeda_dev.h
@@ -40,6 +40,17 @@
 #define KOMEDA_ERR_TTNG			BIT_ULL(30)
 #define KOMEDA_ERR_TTF			BIT_ULL(31)
 
+#define KOMEDA_ERR_EVENTS	\
+	(KOMEDA_EVENT_URUN	| KOMEDA_EVENT_IBSY	| KOMEDA_EVENT_OVR |\
+	KOMEDA_ERR_TETO		| KOMEDA_ERR_TEMR	| KOMEDA_ERR_TITR |\
+	KOMEDA_ERR_CPE		| KOMEDA_ERR_CFGE	| KOMEDA_ERR_AXIE |\
+	KOMEDA_ERR_ACE0		| KOMEDA_ERR_ACE1	| KOMEDA_ERR_ACE2 |\
+	KOMEDA_ERR_ACE3		| KOMEDA_ERR_DRIFTTO	| KOMEDA_ERR_FRAMETO |\
+	KOMEDA_ERR_ZME		| KOMEDA_ERR_MERR	| KOMEDA_ERR_TCF |\
+	KOMEDA_ERR_TTNG		| KOMEDA_ERR_TTF)
+
+#define KOMEDA_WARN_EVENTS	KOMEDA_ERR_CSCE
+
 /* malidp device id */
 enum {
 	MALI_D71 = 0,
@@ -207,4 +218,8 @@ struct komeda_dev {
 
 struct komeda_dev *dev_to_mdev(struct device *dev);
 
+#ifdef CONFIG_DRM_KOMEDA_ERROR_PRINT
+void komeda_print_events(struct komeda_events *evts);
+#endif
+
 #endif /*_KOMEDA_DEV_H_*/
diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_event.c b/drivers/gpu/drm/arm/display/komeda/komeda_event.c
new file mode 100644
index 0000000..57b60cd
--- /dev/null
+++ b/drivers/gpu/drm/arm/display/komeda/komeda_event.c
@@ -0,0 +1,141 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * (C) COPYRIGHT 2019 ARM Limited. All rights reserved.
+ * Author: James.Qian.Wang <james.qian.wang@arm.com>
+ *
+ */
+#include <drm/drm_print.h>
+
+#include "komeda_dev.h"
+
+struct komeda_str {
+	char *str;
+	u32 sz;
+	u32 len;
+};
+
+/* return 0 on success,  < 0 on no space.
+ */
+static int komeda_sprintf(struct komeda_str *str, const char *fmt, ...)
+{
+	va_list args;
+	int num, free_sz;
+	int err;
+
+	free_sz = str->sz - str->len;
+	if (free_sz <= 0)
+		return -ENOSPC;
+
+	va_start(args, fmt);
+
+	num = vsnprintf(str->str + str->len, free_sz, fmt, args);
+
+	va_end(args);
+
+	if (num <= free_sz) {
+		str->len += num;
+		err = 0;
+	} else {
+		str->len = str->sz;
+		err = -ENOSPC;
+	}
+
+	return err;
+}
+
+static void evt_sprintf(struct komeda_str *str, u64 evt, const char *msg)
+{
+	if (evt)
+		komeda_sprintf(str, msg);
+}
+
+static void evt_str(struct komeda_str *str, u64 events)
+{
+	if (events == 0ULL) {
+		evt_sprintf(str, 1, "None");
+		return;
+	}
+
+	evt_sprintf(str, events & KOMEDA_EVENT_VSYNC, "VSYNC|");
+	evt_sprintf(str, events & KOMEDA_EVENT_FLIP, "FLIP|");
+	evt_sprintf(str, events & KOMEDA_EVENT_EOW, "EOW|");
+	evt_sprintf(str, events & KOMEDA_EVENT_MODE, "OP-MODE|");
+
+	evt_sprintf(str, events & KOMEDA_EVENT_URUN, "UNDERRUN|");
+	evt_sprintf(str, events & KOMEDA_EVENT_OVR, "OVERRUN|");
+
+	/* GLB error */
+	evt_sprintf(str, events & KOMEDA_ERR_MERR, "MERR|");
+	evt_sprintf(str, events & KOMEDA_ERR_FRAMETO, "FRAMETO|");
+
+	/* DOU error */
+	evt_sprintf(str, events & KOMEDA_ERR_DRIFTTO, "DRIFTTO|");
+	evt_sprintf(str, events & KOMEDA_ERR_FRAMETO, "FRAMETO|");
+	evt_sprintf(str, events & KOMEDA_ERR_TETO, "TETO|");
+	evt_sprintf(str, events & KOMEDA_ERR_CSCE, "CSCE|");
+
+	/* LPU errors or events */
+	evt_sprintf(str, events & KOMEDA_EVENT_IBSY, "IBSY|");
+	evt_sprintf(str, events & KOMEDA_ERR_AXIE, "AXIE|");
+	evt_sprintf(str, events & KOMEDA_ERR_ACE0, "ACE0|");
+	evt_sprintf(str, events & KOMEDA_ERR_ACE1, "ACE1|");
+	evt_sprintf(str, events & KOMEDA_ERR_ACE2, "ACE2|");
+	evt_sprintf(str, events & KOMEDA_ERR_ACE3, "ACE3|");
+
+	/* LPU TBU errors*/
+	evt_sprintf(str, events & KOMEDA_ERR_TCF, "TCF|");
+	evt_sprintf(str, events & KOMEDA_ERR_TTNG, "TTNG|");
+	evt_sprintf(str, events & KOMEDA_ERR_TITR, "TITR|");
+	evt_sprintf(str, events & KOMEDA_ERR_TEMR, "TEMR|");
+	evt_sprintf(str, events & KOMEDA_ERR_TTF, "TTF|");
+
+	/* CU errors*/
+	evt_sprintf(str, events & KOMEDA_ERR_CPE, "COPROC|");
+	evt_sprintf(str, events & KOMEDA_ERR_ZME, "ZME|");
+	evt_sprintf(str, events & KOMEDA_ERR_CFGE, "CFGE|");
+	evt_sprintf(str, events & KOMEDA_ERR_TEMR, "TEMR|");
+
+	if (str->len > 0 && (str->str[str->len - 1] == '|')) {
+		str->str[str->len - 1] = 0;
+		str->len--;
+	}
+}
+
+static bool is_new_frame(struct komeda_events *a)
+{
+	return (a->pipes[0] | a->pipes[1]) &
+	       (KOMEDA_EVENT_FLIP | KOMEDA_EVENT_EOW);
+}
+
+void komeda_print_events(struct komeda_events *evts)
+{
+	u64 print_evts = KOMEDA_ERR_EVENTS;
+	static bool en_print = true;
+
+	/* reduce the same msg print, only print the first evt for one frame */
+	if (evts->global || is_new_frame(evts))
+		en_print = true;
+	if (!en_print)
+		return;
+
+	if ((evts->global | evts->pipes[0] | evts->pipes[1]) & print_evts) {
+		#define STR_SZ		256
+		char msg[STR_SZ];
+		struct komeda_str str;
+
+		str.str = msg;
+		str.sz  = STR_SZ;
+		str.len = 0;
+
+		komeda_sprintf(&str, "gcu: ");
+		evt_str(&str, evts->global);
+		komeda_sprintf(&str, ", pipes[0]: ");
+		evt_str(&str, evts->pipes[0]);
+		komeda_sprintf(&str, ", pipes[1]: ");
+		evt_str(&str, evts->pipes[1]);
+
+		DRM_ERROR("err detect: %s\n", msg);
+
+		en_print = false;
+	}
+}
diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_kms.c b/drivers/gpu/drm/arm/display/komeda/komeda_kms.c
index 419a8b0..0fafc36 100644
--- a/drivers/gpu/drm/arm/display/komeda/komeda_kms.c
+++ b/drivers/gpu/drm/arm/display/komeda/komeda_kms.c
@@ -47,6 +47,10 @@ static irqreturn_t komeda_kms_irq_handler(int irq, void *data)
 	memset(&evts, 0, sizeof(evts));
 	status = mdev->funcs->irq_handler(mdev, &evts);
 
+#ifdef CONFIG_DRM_KOMEDA_ERROR_PRINT
+	komeda_print_events(&evts);
+#endif
+
 	/* Notify the crtc to handle the events */
 	for (i = 0; i < kms->n_crtcs; i++)
 		komeda_crtc_handle_event(&kms->crtcs[i], &evts);
-- 
1.9.1


^ permalink raw reply related	[flat|nested] 37+ messages in thread

* [PATCH] drm/komeda: Adds error event print functionality
@ 2019-08-01 11:37 ` Lowry Li (Arm Technology China)
  0 siblings, 0 replies; 37+ messages in thread
From: Lowry Li (Arm Technology China) @ 2019-08-01 11:37 UTC (permalink / raw)
  To: Liviu Dudau, james qian wang (Arm Technology China),
	maarten.lankhorst, seanpaul, airlied, Brian Starkey
  Cc: Ayan Halder, Jonathan Chai (Arm Technology China),
	linux-kernel, dri-devel, Julien Yin (Arm Technology China),
	nd

From: "Lowry Li (Arm Technology China)" <Lowry.Li@arm.com>

Adds to print the event message when error happens and the same event
will not be printed until next vsync.

Changes since v1:
1. Handling the event print by CONFIG_KOMEDA_ERROR_PRINT;
2. Changing the max string size to 256.

Signed-off-by: Lowry Li (Arm Technology China) <lowry.li@arm.com>
---
 drivers/gpu/drm/arm/display/Kconfig               |   6 +
 drivers/gpu/drm/arm/display/komeda/Makefile       |   2 +
 drivers/gpu/drm/arm/display/komeda/komeda_dev.h   |  15 +++
 drivers/gpu/drm/arm/display/komeda/komeda_event.c | 141 ++++++++++++++++++++++
 drivers/gpu/drm/arm/display/komeda/komeda_kms.c   |   4 +
 5 files changed, 168 insertions(+)
 create mode 100644 drivers/gpu/drm/arm/display/komeda/komeda_event.c

diff --git a/drivers/gpu/drm/arm/display/Kconfig b/drivers/gpu/drm/arm/display/Kconfig
index cec0639..e87ff86 100644
--- a/drivers/gpu/drm/arm/display/Kconfig
+++ b/drivers/gpu/drm/arm/display/Kconfig
@@ -12,3 +12,9 @@ config DRM_KOMEDA
 	  Processor driver. It supports the D71 variants of the hardware.
 
 	  If compiled as a module it will be called komeda.
+
+config DRM_KOMEDA_ERROR_PRINT
+	bool "Enable komeda error print"
+	depends on DRM_KOMEDA
+	help
+	  Choose this option to enable error printing.
diff --git a/drivers/gpu/drm/arm/display/komeda/Makefile b/drivers/gpu/drm/arm/display/komeda/Makefile
index 5c3900c..f095a1c 100644
--- a/drivers/gpu/drm/arm/display/komeda/Makefile
+++ b/drivers/gpu/drm/arm/display/komeda/Makefile
@@ -22,4 +22,6 @@ komeda-y += \
 	d71/d71_dev.o \
 	d71/d71_component.o
 
+komeda-$(CONFIG_DRM_KOMEDA_ERROR_PRINT) += komeda_event.o
+
 obj-$(CONFIG_DRM_KOMEDA) += komeda.o
diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_dev.h b/drivers/gpu/drm/arm/display/komeda/komeda_dev.h
index d1c86b6..e28e7e6 100644
--- a/drivers/gpu/drm/arm/display/komeda/komeda_dev.h
+++ b/drivers/gpu/drm/arm/display/komeda/komeda_dev.h
@@ -40,6 +40,17 @@
 #define KOMEDA_ERR_TTNG			BIT_ULL(30)
 #define KOMEDA_ERR_TTF			BIT_ULL(31)
 
+#define KOMEDA_ERR_EVENTS	\
+	(KOMEDA_EVENT_URUN	| KOMEDA_EVENT_IBSY	| KOMEDA_EVENT_OVR |\
+	KOMEDA_ERR_TETO		| KOMEDA_ERR_TEMR	| KOMEDA_ERR_TITR |\
+	KOMEDA_ERR_CPE		| KOMEDA_ERR_CFGE	| KOMEDA_ERR_AXIE |\
+	KOMEDA_ERR_ACE0		| KOMEDA_ERR_ACE1	| KOMEDA_ERR_ACE2 |\
+	KOMEDA_ERR_ACE3		| KOMEDA_ERR_DRIFTTO	| KOMEDA_ERR_FRAMETO |\
+	KOMEDA_ERR_ZME		| KOMEDA_ERR_MERR	| KOMEDA_ERR_TCF |\
+	KOMEDA_ERR_TTNG		| KOMEDA_ERR_TTF)
+
+#define KOMEDA_WARN_EVENTS	KOMEDA_ERR_CSCE
+
 /* malidp device id */
 enum {
 	MALI_D71 = 0,
@@ -207,4 +218,8 @@ struct komeda_dev {
 
 struct komeda_dev *dev_to_mdev(struct device *dev);
 
+#ifdef CONFIG_DRM_KOMEDA_ERROR_PRINT
+void komeda_print_events(struct komeda_events *evts);
+#endif
+
 #endif /*_KOMEDA_DEV_H_*/
diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_event.c b/drivers/gpu/drm/arm/display/komeda/komeda_event.c
new file mode 100644
index 0000000..57b60cd
--- /dev/null
+++ b/drivers/gpu/drm/arm/display/komeda/komeda_event.c
@@ -0,0 +1,141 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * (C) COPYRIGHT 2019 ARM Limited. All rights reserved.
+ * Author: James.Qian.Wang <james.qian.wang@arm.com>
+ *
+ */
+#include <drm/drm_print.h>
+
+#include "komeda_dev.h"
+
+struct komeda_str {
+	char *str;
+	u32 sz;
+	u32 len;
+};
+
+/* return 0 on success,  < 0 on no space.
+ */
+static int komeda_sprintf(struct komeda_str *str, const char *fmt, ...)
+{
+	va_list args;
+	int num, free_sz;
+	int err;
+
+	free_sz = str->sz - str->len;
+	if (free_sz <= 0)
+		return -ENOSPC;
+
+	va_start(args, fmt);
+
+	num = vsnprintf(str->str + str->len, free_sz, fmt, args);
+
+	va_end(args);
+
+	if (num <= free_sz) {
+		str->len += num;
+		err = 0;
+	} else {
+		str->len = str->sz;
+		err = -ENOSPC;
+	}
+
+	return err;
+}
+
+static void evt_sprintf(struct komeda_str *str, u64 evt, const char *msg)
+{
+	if (evt)
+		komeda_sprintf(str, msg);
+}
+
+static void evt_str(struct komeda_str *str, u64 events)
+{
+	if (events == 0ULL) {
+		evt_sprintf(str, 1, "None");
+		return;
+	}
+
+	evt_sprintf(str, events & KOMEDA_EVENT_VSYNC, "VSYNC|");
+	evt_sprintf(str, events & KOMEDA_EVENT_FLIP, "FLIP|");
+	evt_sprintf(str, events & KOMEDA_EVENT_EOW, "EOW|");
+	evt_sprintf(str, events & KOMEDA_EVENT_MODE, "OP-MODE|");
+
+	evt_sprintf(str, events & KOMEDA_EVENT_URUN, "UNDERRUN|");
+	evt_sprintf(str, events & KOMEDA_EVENT_OVR, "OVERRUN|");
+
+	/* GLB error */
+	evt_sprintf(str, events & KOMEDA_ERR_MERR, "MERR|");
+	evt_sprintf(str, events & KOMEDA_ERR_FRAMETO, "FRAMETO|");
+
+	/* DOU error */
+	evt_sprintf(str, events & KOMEDA_ERR_DRIFTTO, "DRIFTTO|");
+	evt_sprintf(str, events & KOMEDA_ERR_FRAMETO, "FRAMETO|");
+	evt_sprintf(str, events & KOMEDA_ERR_TETO, "TETO|");
+	evt_sprintf(str, events & KOMEDA_ERR_CSCE, "CSCE|");
+
+	/* LPU errors or events */
+	evt_sprintf(str, events & KOMEDA_EVENT_IBSY, "IBSY|");
+	evt_sprintf(str, events & KOMEDA_ERR_AXIE, "AXIE|");
+	evt_sprintf(str, events & KOMEDA_ERR_ACE0, "ACE0|");
+	evt_sprintf(str, events & KOMEDA_ERR_ACE1, "ACE1|");
+	evt_sprintf(str, events & KOMEDA_ERR_ACE2, "ACE2|");
+	evt_sprintf(str, events & KOMEDA_ERR_ACE3, "ACE3|");
+
+	/* LPU TBU errors*/
+	evt_sprintf(str, events & KOMEDA_ERR_TCF, "TCF|");
+	evt_sprintf(str, events & KOMEDA_ERR_TTNG, "TTNG|");
+	evt_sprintf(str, events & KOMEDA_ERR_TITR, "TITR|");
+	evt_sprintf(str, events & KOMEDA_ERR_TEMR, "TEMR|");
+	evt_sprintf(str, events & KOMEDA_ERR_TTF, "TTF|");
+
+	/* CU errors*/
+	evt_sprintf(str, events & KOMEDA_ERR_CPE, "COPROC|");
+	evt_sprintf(str, events & KOMEDA_ERR_ZME, "ZME|");
+	evt_sprintf(str, events & KOMEDA_ERR_CFGE, "CFGE|");
+	evt_sprintf(str, events & KOMEDA_ERR_TEMR, "TEMR|");
+
+	if (str->len > 0 && (str->str[str->len - 1] == '|')) {
+		str->str[str->len - 1] = 0;
+		str->len--;
+	}
+}
+
+static bool is_new_frame(struct komeda_events *a)
+{
+	return (a->pipes[0] | a->pipes[1]) &
+	       (KOMEDA_EVENT_FLIP | KOMEDA_EVENT_EOW);
+}
+
+void komeda_print_events(struct komeda_events *evts)
+{
+	u64 print_evts = KOMEDA_ERR_EVENTS;
+	static bool en_print = true;
+
+	/* reduce the same msg print, only print the first evt for one frame */
+	if (evts->global || is_new_frame(evts))
+		en_print = true;
+	if (!en_print)
+		return;
+
+	if ((evts->global | evts->pipes[0] | evts->pipes[1]) & print_evts) {
+		#define STR_SZ		256
+		char msg[STR_SZ];
+		struct komeda_str str;
+
+		str.str = msg;
+		str.sz  = STR_SZ;
+		str.len = 0;
+
+		komeda_sprintf(&str, "gcu: ");
+		evt_str(&str, evts->global);
+		komeda_sprintf(&str, ", pipes[0]: ");
+		evt_str(&str, evts->pipes[0]);
+		komeda_sprintf(&str, ", pipes[1]: ");
+		evt_str(&str, evts->pipes[1]);
+
+		DRM_ERROR("err detect: %s\n", msg);
+
+		en_print = false;
+	}
+}
diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_kms.c b/drivers/gpu/drm/arm/display/komeda/komeda_kms.c
index 419a8b0..0fafc36 100644
--- a/drivers/gpu/drm/arm/display/komeda/komeda_kms.c
+++ b/drivers/gpu/drm/arm/display/komeda/komeda_kms.c
@@ -47,6 +47,10 @@ static irqreturn_t komeda_kms_irq_handler(int irq, void *data)
 	memset(&evts, 0, sizeof(evts));
 	status = mdev->funcs->irq_handler(mdev, &evts);
 
+#ifdef CONFIG_DRM_KOMEDA_ERROR_PRINT
+	komeda_print_events(&evts);
+#endif
+
 	/* Notify the crtc to handle the events */
 	for (i = 0; i < kms->n_crtcs; i++)
 		komeda_crtc_handle_event(&kms->crtcs[i], &evts);
-- 
1.9.1

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 37+ messages in thread

end of thread, other threads:[~2019-09-18  1:30 UTC | newest]

Thread overview: 37+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-06-27  3:10 [PATCH] drm/komeda: Adds error event print functionality Lowry Li (Arm Technology China)
2019-06-27  3:10 ` Lowry Li (Arm Technology China)
2019-06-27  9:22 ` james qian wang (Arm Technology China)
2019-06-27  9:22   ` james qian wang (Arm Technology China)
2019-07-18 13:17 ` Liviu Dudau
2019-07-18 13:17   ` Liviu Dudau
2019-07-18 15:23   ` Sean Paul
2019-07-18 15:23     ` Sean Paul
2019-07-19  9:31     ` Lowry Li (Arm Technology China)
2019-07-19  9:09   ` Lowry Li (Arm Technology China)
     [not found]   ` <20190719090816.GA4133@lowry.li@arm.com>
2019-07-19 11:40     ` Liviu Dudau
2019-07-19 11:40       ` Liviu Dudau
2019-07-22 11:15       ` james qian wang (Arm Technology China)
2019-07-22 11:15         ` james qian wang (Arm Technology China)
2019-07-22 16:18         ` Liviu Dudau
2019-07-22 16:18           ` Liviu Dudau
2019-07-23  7:37           ` Lowry Li (Arm Technology China)
     [not found]           ` <20190723073623.GA32666@lowry.li@arm.com>
2019-07-23  8:49             ` Liviu Dudau
2019-07-23  8:49               ` Liviu Dudau
2019-07-26  3:27               ` Lowry Li (Arm Technology China)
2019-08-01 11:37 Lowry Li (Arm Technology China)
2019-08-01 11:37 ` Lowry Li (Arm Technology China)
2019-08-01 13:52 ` Liviu Dudau
2019-08-01 13:52   ` Liviu Dudau
2019-08-01 14:48 ` Mihail Atanassov
2019-08-01 14:48   ` Mihail Atanassov
2019-08-02  9:34   ` Lowry Li (Arm Technology China)
2019-08-02  9:43 Lowry Li (Arm Technology China)
2019-08-02  9:43 ` Lowry Li (Arm Technology China)
2019-08-02 10:05 ` Mihail Atanassov
2019-08-02 10:05   ` Mihail Atanassov
2019-08-02 10:43   ` james qian wang (Arm Technology China)
2019-08-02 10:43     ` james qian wang (Arm Technology China)
2019-09-17 13:11 ` Daniel Vetter
2019-09-17 13:11   ` Daniel Vetter
2019-09-18  1:29   ` james qian wang (Arm Technology China)
2019-09-18  1:29     ` james qian wang (Arm Technology China)

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.