diff mbox series

[3/6] drm/msm/dpu: allow just single IRQ callback

Message ID 20220201151056.2480055-4-dmitry.baryshkov@linaro.org
State Superseded
Headers show
Series drm/msm/dpu: simplify IRQ helpers | expand

Commit Message

Dmitry Baryshkov Feb. 1, 2022, 3:10 p.m. UTC
DPU interrupts code allows multiple callbacks per interrut. In reality
none of the interrupts is shared between blocks (and will probably never
be). Drop support for registering multiple callbacks per interrupt to
simplify interrupt handling code.

Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
---
 drivers/gpu/drm/msm/disp/dpu1/dpu_core_irq.h  |  16 +-
 drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c   |   7 +-
 .../gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h  |   2 +-
 .../drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c  |  10 +-
 .../drm/msm/disp/dpu1/dpu_encoder_phys_vid.c  |   6 +-
 .../gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.c | 140 ++++++------------
 .../gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.h |  12 +-
 drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h       |  12 --
 drivers/gpu/drm/msm/disp/dpu1/dpu_trace.h     |  12 +-
 9 files changed, 75 insertions(+), 142 deletions(-)

Comments

kernel test robot Feb. 1, 2022, 10:14 p.m. UTC | #1
Hi Dmitry,

Thank you for the patch! Yet something to improve:

[auto build test ERROR on drm/drm-next]
[also build test ERROR on v5.17-rc2 next-20220201]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch]

url:    https://github.com/0day-ci/linux/commits/Dmitry-Baryshkov/drm-msm-dpu-simplify-IRQ-helpers/20220201-231430
base:   git://anongit.freedesktop.org/drm/drm drm-next
config: s390-randconfig-r044-20220130 (https://download.01.org/0day-ci/archive/20220202/202202020613.VjszN4M6-lkp@intel.com/config)
compiler: s390-linux-gcc (GCC) 11.2.0
reproduce (this is a W=1 build):
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # https://github.com/0day-ci/linux/commit/c3da64f5022acf9d942f497a3e3cff092648d6c3
        git remote add linux-review https://github.com/0day-ci/linux
        git fetch --no-tags linux-review Dmitry-Baryshkov/drm-msm-dpu-simplify-IRQ-helpers/20220201-231430
        git checkout c3da64f5022acf9d942f497a3e3cff092648d6c3
        # save the config file to linux build tree
        mkdir build_dir
        COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-11.2.0 make.cross O=build_dir ARCH=s390 SHELL=/bin/bash drivers/gpu/drm/msm/

If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <lkp@intel.com>

All errors (new ones prefixed by >>):

   In file included from include/trace/define_trace.h:102,
                    from drivers/gpu/drm/msm/disp/dpu1/dpu_trace.h:973,
                    from drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c:34:
   drivers/gpu/drm/msm/disp/dpu1/./dpu_trace.h: In function 'ftrace_test_probe_dpu_core_irq_unregister_callback':
   include/trace/trace_events.h:870:42: error: passing argument 1 of 'check_trace_callback_type_dpu_core_irq_unregister_callback' from incompatible pointer type [-Werror=incompatible-pointer-types]
     870 |         check_trace_callback_type_##call(trace_event_raw_event_##template); \
         |                                          ^~~~~~~~~~~~~~~~~~~~~~
         |                                          |
         |                                          void (*)(void *, int,  void *)
   drivers/gpu/drm/msm/disp/dpu1/./dpu_trace.h:892:1: note: in expansion of macro 'DEFINE_EVENT'
     892 | DEFINE_EVENT(dpu_core_irq_callback_template, dpu_core_irq_unregister_callback,
         | ^~~~~~~~~~~~
   In file included from drivers/gpu/drm/msm/disp/dpu1/dpu_trace.h:10,
                    from drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c:34:
   include/linux/tracepoint.h:279:49: note: expected 'void (*)(void *, int)' but argument is of type 'void (*)(void *, int,  void *)'
     279 |         check_trace_callback_type_##name(void (*cb)(data_proto))        \
         |                                          ~~~~~~~^~~~~~~~~~~~~~~
   include/linux/tracepoint.h:419:9: note: in expansion of macro '__DECLARE_TRACE'
     419 |         __DECLARE_TRACE(name, PARAMS(proto), PARAMS(args),              \
         |         ^~~~~~~~~~~~~~~
   include/linux/tracepoint.h:542:9: note: in expansion of macro 'DECLARE_TRACE'
     542 |         DECLARE_TRACE(name, PARAMS(proto), PARAMS(args))
         |         ^~~~~~~~~~~~~
   drivers/gpu/drm/msm/disp/dpu1/dpu_trace.h:892:1: note: in expansion of macro 'DEFINE_EVENT'
     892 | DEFINE_EVENT(dpu_core_irq_callback_template, dpu_core_irq_unregister_callback,
         | ^~~~~~~~~~~~
   In file included from include/trace/define_trace.h:103,
                    from drivers/gpu/drm/msm/disp/dpu1/dpu_trace.h:973,
                    from drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c:34:
   drivers/gpu/drm/msm/disp/dpu1/./dpu_trace.h: In function 'perf_test_probe_dpu_core_irq_unregister_callback':
>> include/trace/perf.h:99:42: error: passing argument 1 of 'check_trace_callback_type_dpu_core_irq_unregister_callback' from incompatible pointer type [-Werror=incompatible-pointer-types]
      99 |         check_trace_callback_type_##call(perf_trace_##template);        \
         |                                          ^~~~~~~~~~~
         |                                          |
         |                                          void (*)(void *, int,  void *)
   drivers/gpu/drm/msm/disp/dpu1/./dpu_trace.h:892:1: note: in expansion of macro 'DEFINE_EVENT'
     892 | DEFINE_EVENT(dpu_core_irq_callback_template, dpu_core_irq_unregister_callback,
         | ^~~~~~~~~~~~
   In file included from drivers/gpu/drm/msm/disp/dpu1/dpu_trace.h:10,
                    from drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c:34:
   include/linux/tracepoint.h:279:49: note: expected 'void (*)(void *, int)' but argument is of type 'void (*)(void *, int,  void *)'
     279 |         check_trace_callback_type_##name(void (*cb)(data_proto))        \
         |                                          ~~~~~~~^~~~~~~~~~~~~~~
   include/linux/tracepoint.h:419:9: note: in expansion of macro '__DECLARE_TRACE'
     419 |         __DECLARE_TRACE(name, PARAMS(proto), PARAMS(args),              \
         |         ^~~~~~~~~~~~~~~
   include/linux/tracepoint.h:542:9: note: in expansion of macro 'DECLARE_TRACE'
     542 |         DECLARE_TRACE(name, PARAMS(proto), PARAMS(args))
         |         ^~~~~~~~~~~~~
   drivers/gpu/drm/msm/disp/dpu1/dpu_trace.h:892:1: note: in expansion of macro 'DEFINE_EVENT'
     892 | DEFINE_EVENT(dpu_core_irq_callback_template, dpu_core_irq_unregister_callback,
         | ^~~~~~~~~~~~
   cc1: some warnings being treated as errors


vim +/check_trace_callback_type_dpu_core_irq_unregister_callback +99 include/trace/perf.h

ee53bbd172571c Steven Rostedt (Red Hat  2015-04-29   89) 
ee53bbd172571c Steven Rostedt (Red Hat  2015-04-29   90) /*
ee53bbd172571c Steven Rostedt (Red Hat  2015-04-29   91)  * This part is compiled out, it is only here as a build time check
ee53bbd172571c Steven Rostedt (Red Hat  2015-04-29   92)  * to make sure that if the tracepoint handling changes, the
ee53bbd172571c Steven Rostedt (Red Hat  2015-04-29   93)  * perf probe will fail to compile unless it too is updated.
ee53bbd172571c Steven Rostedt (Red Hat  2015-04-29   94)  */
ee53bbd172571c Steven Rostedt (Red Hat  2015-04-29   95) #undef DEFINE_EVENT
ee53bbd172571c Steven Rostedt (Red Hat  2015-04-29   96) #define DEFINE_EVENT(template, call, proto, args)			\
ee53bbd172571c Steven Rostedt (Red Hat  2015-04-29   97) static inline void perf_test_probe_##call(void)				\
ee53bbd172571c Steven Rostedt (Red Hat  2015-04-29   98) {									\
ee53bbd172571c Steven Rostedt (Red Hat  2015-04-29  @99) 	check_trace_callback_type_##call(perf_trace_##template);	\
ee53bbd172571c Steven Rostedt (Red Hat  2015-04-29  100) }
ee53bbd172571c Steven Rostedt (Red Hat  2015-04-29  101) 

---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org
kernel test robot Feb. 1, 2022, 10:54 p.m. UTC | #2
Hi Dmitry,

Thank you for the patch! Yet something to improve:

[auto build test ERROR on drm/drm-next]
[also build test ERROR on v5.17-rc2 next-20220201]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch]

url:    https://github.com/0day-ci/linux/commits/Dmitry-Baryshkov/drm-msm-dpu-simplify-IRQ-helpers/20220201-231430
base:   git://anongit.freedesktop.org/drm/drm drm-next
config: arc-randconfig-r043-20220130 (https://download.01.org/0day-ci/archive/20220202/202202020658.FJTV4CAp-lkp@intel.com/config)
compiler: arc-elf-gcc (GCC) 11.2.0
reproduce (this is a W=1 build):
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # https://github.com/0day-ci/linux/commit/c3da64f5022acf9d942f497a3e3cff092648d6c3
        git remote add linux-review https://github.com/0day-ci/linux
        git fetch --no-tags linux-review Dmitry-Baryshkov/drm-msm-dpu-simplify-IRQ-helpers/20220201-231430
        git checkout c3da64f5022acf9d942f497a3e3cff092648d6c3
        # save the config file to linux build tree
        mkdir build_dir
        COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-11.2.0 make.cross O=build_dir ARCH=arc SHELL=/bin/bash drivers/gpu/drm/

If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <lkp@intel.com>

All errors (new ones prefixed by >>):

   In file included from include/trace/define_trace.h:102,
                    from drivers/gpu/drm/msm/disp/dpu1/dpu_trace.h:973,
                    from drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c:34:
   drivers/gpu/drm/msm/disp/dpu1/./dpu_trace.h: In function 'ftrace_test_probe_dpu_core_irq_unregister_callback':
>> include/trace/trace_events.h:870:42: error: passing argument 1 of 'check_trace_callback_type_dpu_core_irq_unregister_callback' from incompatible pointer type [-Werror=incompatible-pointer-types]
     870 |         check_trace_callback_type_##call(trace_event_raw_event_##template); \
         |                                          ^~~~~~~~~~~~~~~~~~~~~~
         |                                          |
         |                                          void (*)(void *, int,  void *)
   drivers/gpu/drm/msm/disp/dpu1/./dpu_trace.h:892:1: note: in expansion of macro 'DEFINE_EVENT'
     892 | DEFINE_EVENT(dpu_core_irq_callback_template, dpu_core_irq_unregister_callback,
         | ^~~~~~~~~~~~
   In file included from drivers/gpu/drm/msm/disp/dpu1/dpu_trace.h:10,
                    from drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c:34:
   include/linux/tracepoint.h:279:49: note: expected 'void (*)(void *, int)' but argument is of type 'void (*)(void *, int,  void *)'
     279 |         check_trace_callback_type_##name(void (*cb)(data_proto))        \
         |                                          ~~~~~~~^~~~~~~~~~~~~~~
   include/linux/tracepoint.h:419:9: note: in expansion of macro '__DECLARE_TRACE'
     419 |         __DECLARE_TRACE(name, PARAMS(proto), PARAMS(args),              \
         |         ^~~~~~~~~~~~~~~
   include/linux/tracepoint.h:542:9: note: in expansion of macro 'DECLARE_TRACE'
     542 |         DECLARE_TRACE(name, PARAMS(proto), PARAMS(args))
         |         ^~~~~~~~~~~~~
   drivers/gpu/drm/msm/disp/dpu1/dpu_trace.h:892:1: note: in expansion of macro 'DEFINE_EVENT'
     892 | DEFINE_EVENT(dpu_core_irq_callback_template, dpu_core_irq_unregister_callback,
         | ^~~~~~~~~~~~
   cc1: some warnings being treated as errors


vim +/check_trace_callback_type_dpu_core_irq_unregister_callback +870 include/trace/trace_events.h

46ac51822a6a0b8 Steven Rostedt (Red Hat  2015-09-23  830) 
46ac51822a6a0b8 Steven Rostedt (Red Hat  2015-09-23  831) #undef DECLARE_EVENT_CLASS
46ac51822a6a0b8 Steven Rostedt (Red Hat  2015-09-23  832) #define DECLARE_EVENT_CLASS(call, proto, args, tstruct, assign, print)	\
46ac51822a6a0b8 Steven Rostedt (Red Hat  2015-09-23  833) 									\
46ac51822a6a0b8 Steven Rostedt (Red Hat  2015-09-23  834) static notrace void							\
46ac51822a6a0b8 Steven Rostedt (Red Hat  2015-09-23  835) trace_event_raw_event_##call(void *__data, proto)			\
46ac51822a6a0b8 Steven Rostedt (Red Hat  2015-09-23  836) {									\
46ac51822a6a0b8 Steven Rostedt (Red Hat  2015-09-23  837) 	struct trace_event_file *trace_file = __data;			\
46ac51822a6a0b8 Steven Rostedt (Red Hat  2015-09-23  838) 	struct trace_event_data_offsets_##call __maybe_unused __data_offsets;\
46ac51822a6a0b8 Steven Rostedt (Red Hat  2015-09-23  839) 	struct trace_event_buffer fbuffer;				\
46ac51822a6a0b8 Steven Rostedt (Red Hat  2015-09-23  840) 	struct trace_event_raw_##call *entry;				\
46ac51822a6a0b8 Steven Rostedt (Red Hat  2015-09-23  841) 	int __data_size;						\
46ac51822a6a0b8 Steven Rostedt (Red Hat  2015-09-23  842) 									\
46ac51822a6a0b8 Steven Rostedt (Red Hat  2015-09-23  843) 	if (trace_trigger_soft_disabled(trace_file))			\
46ac51822a6a0b8 Steven Rostedt (Red Hat  2015-09-23  844) 		return;							\
46ac51822a6a0b8 Steven Rostedt (Red Hat  2015-09-23  845) 									\
46ac51822a6a0b8 Steven Rostedt (Red Hat  2015-09-23  846) 	__data_size = trace_event_get_offsets_##call(&__data_offsets, args); \
46ac51822a6a0b8 Steven Rostedt (Red Hat  2015-09-23  847) 									\
46ac51822a6a0b8 Steven Rostedt (Red Hat  2015-09-23  848) 	entry = trace_event_buffer_reserve(&fbuffer, trace_file,	\
46ac51822a6a0b8 Steven Rostedt (Red Hat  2015-09-23  849) 				 sizeof(*entry) + __data_size);		\
46ac51822a6a0b8 Steven Rostedt (Red Hat  2015-09-23  850) 									\
46ac51822a6a0b8 Steven Rostedt (Red Hat  2015-09-23  851) 	if (!entry)							\
46ac51822a6a0b8 Steven Rostedt (Red Hat  2015-09-23  852) 		return;							\
46ac51822a6a0b8 Steven Rostedt (Red Hat  2015-09-23  853) 									\
46ac51822a6a0b8 Steven Rostedt (Red Hat  2015-09-23  854) 	tstruct								\
46ac51822a6a0b8 Steven Rostedt (Red Hat  2015-09-23  855) 									\
46ac51822a6a0b8 Steven Rostedt (Red Hat  2015-09-23  856) 	{ assign; }							\
46ac51822a6a0b8 Steven Rostedt (Red Hat  2015-09-23  857) 									\
46ac51822a6a0b8 Steven Rostedt (Red Hat  2015-09-23  858) 	trace_event_buffer_commit(&fbuffer);				\
46ac51822a6a0b8 Steven Rostedt (Red Hat  2015-09-23  859) }
46ac51822a6a0b8 Steven Rostedt (Red Hat  2015-09-23  860) /*
46ac51822a6a0b8 Steven Rostedt (Red Hat  2015-09-23  861)  * The ftrace_test_probe is compiled out, it is only here as a build time check
46ac51822a6a0b8 Steven Rostedt (Red Hat  2015-09-23  862)  * to make sure that if the tracepoint handling changes, the ftrace probe will
46ac51822a6a0b8 Steven Rostedt (Red Hat  2015-09-23  863)  * fail to compile unless it too is updated.
46ac51822a6a0b8 Steven Rostedt (Red Hat  2015-09-23  864)  */
46ac51822a6a0b8 Steven Rostedt (Red Hat  2015-09-23  865) 
46ac51822a6a0b8 Steven Rostedt (Red Hat  2015-09-23  866) #undef DEFINE_EVENT
46ac51822a6a0b8 Steven Rostedt (Red Hat  2015-09-23  867) #define DEFINE_EVENT(template, call, proto, args)			\
46ac51822a6a0b8 Steven Rostedt (Red Hat  2015-09-23  868) static inline void ftrace_test_probe_##call(void)			\
46ac51822a6a0b8 Steven Rostedt (Red Hat  2015-09-23  869) {									\
46ac51822a6a0b8 Steven Rostedt (Red Hat  2015-09-23 @870) 	check_trace_callback_type_##call(trace_event_raw_event_##template); \
46ac51822a6a0b8 Steven Rostedt (Red Hat  2015-09-23  871) }
46ac51822a6a0b8 Steven Rostedt (Red Hat  2015-09-23  872) 

---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org
Abhinav Kumar Feb. 15, 2022, 11:58 p.m. UTC | #3
On 2/1/2022 7:10 AM, Dmitry Baryshkov wrote:
> DPU interrupts code allows multiple callbacks per interrut. In reality
> none of the interrupts is shared between blocks (and will probably never
> be). Drop support for registering multiple callbacks per interrupt to
> simplify interrupt handling code.
> 
> Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>

I think this has some kbot issues, will ack once those are addressed.

> ---
>   drivers/gpu/drm/msm/disp/dpu1/dpu_core_irq.h  |  16 +-
>   drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c   |   7 +-
>   .../gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h  |   2 +-
>   .../drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c  |  10 +-
>   .../drm/msm/disp/dpu1/dpu_encoder_phys_vid.c  |   6 +-
>   .../gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.c | 140 ++++++------------
>   .../gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.h |  12 +-
>   drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h       |  12 --
>   drivers/gpu/drm/msm/disp/dpu1/dpu_trace.h     |  12 +-
>   9 files changed, 75 insertions(+), 142 deletions(-)
> 
> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_core_irq.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_core_irq.h
> index 6dce5d89f817..b5b6e7031fb9 100644
> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_core_irq.h
> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_core_irq.h
> @@ -44,10 +44,8 @@ u32 dpu_core_irq_read(
>    *                             interrupt
>    * @dpu_kms:		DPU handle
>    * @irq_idx:		irq index
> - * @irq_cb:		IRQ callback structure, containing callback function
> - *			and argument. Passing NULL for irq_cb will unregister
> - *			the callback for the given irq_idx
> - *			This must exist until un-registration.
> + * @irq_cb:		IRQ callback funcion.
> + * @irq_arg:		IRQ callback argument.
>    * @return:		0 for success registering callback, otherwise failure
>    *
>    * This function supports registration of multiple callbacks for each interrupt.
> @@ -55,25 +53,21 @@ u32 dpu_core_irq_read(
>   int dpu_core_irq_register_callback(
>   		struct dpu_kms *dpu_kms,
>   		int irq_idx,
> -		struct dpu_irq_callback *irq_cb);
> +		void (*irq_cb)(void *arg, int irq_idx),
> +		void *irq_arg);
>   
>   /**
>    * dpu_core_irq_unregister_callback - For unregistering callback function on IRQ
>    *                             interrupt
>    * @dpu_kms:		DPU handle
>    * @irq_idx:		irq index
> - * @irq_cb:		IRQ callback structure, containing callback function
> - *			and argument. Passing NULL for irq_cb will unregister
> - *			the callback for the given irq_idx
> - *			This must match with registration.
>    * @return:		0 for success registering callback, otherwise failure
>    *
>    * This function supports registration of multiple callbacks for each interrupt.
>    */
>   int dpu_core_irq_unregister_callback(
>   		struct dpu_kms *dpu_kms,
> -		int irq_idx,
> -		struct dpu_irq_callback *irq_cb);
> +		int irq_idx);
>   
>   /**
>    * dpu_debugfs_core_irq_init - register core irq debugfs
> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
> index 5576b8a3e6ee..17ca149e7dcd 100644
> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
> @@ -311,7 +311,7 @@ int dpu_encoder_helper_wait_for_irq(struct dpu_encoder_phys *phys_enc,
>   				      phys_enc->hw_pp->idx - PINGPONG_0,
>   				      atomic_read(wait_info->atomic_cnt));
>   			local_irq_save(flags);
> -			irq->cb.func(phys_enc, irq->irq_idx);
> +			irq->func(phys_enc, irq->irq_idx);
>   			local_irq_restore(flags);
>   			ret = 0;
>   		} else {
> @@ -352,7 +352,7 @@ int dpu_encoder_helper_register_irq(struct dpu_encoder_phys *phys_enc,
>   	}
>   
>   	ret = dpu_core_irq_register_callback(phys_enc->dpu_kms, irq->irq_idx,
> -			&irq->cb);
> +			irq->func, phys_enc);
>   	if (ret) {
>   		DPU_ERROR_PHYS(phys_enc,
>   			"failed to register IRQ callback for %s\n",
> @@ -383,8 +383,7 @@ int dpu_encoder_helper_unregister_irq(struct dpu_encoder_phys *phys_enc,
>   		return 0;
>   	}
>   
> -	ret = dpu_core_irq_unregister_callback(phys_enc->dpu_kms, irq->irq_idx,
> -			&irq->cb);
> +	ret = dpu_core_irq_unregister_callback(phys_enc->dpu_kms, irq->irq_idx);
>   	if (ret) {
>   		DRM_ERROR("unreg cb fail id=%u, intr=%d, irq=%d ret=%d",
>   			  DRMID(phys_enc->parent), intr_idx,
> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h
> index e7270eb6b84b..80d87871fd94 100644
> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h
> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h
> @@ -174,7 +174,7 @@ struct dpu_encoder_irq {
>   	const char *name;
>   	enum dpu_intr_idx intr_idx;
>   	int irq_idx;
> -	struct dpu_irq_callback cb;
> +	void (*func)(void *arg, int irq_idx);
>   };
>   
>   /**
> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c
> index 34a6940d12c5..a0652bdcf59b 100644
> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c
> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c
> @@ -782,30 +782,28 @@ struct dpu_encoder_phys *dpu_encoder_phys_cmd_init(
>   	phys_enc->enable_state = DPU_ENC_DISABLED;
>   	for (i = 0; i < INTR_IDX_MAX; i++) {
>   		irq = &phys_enc->irq[i];
> -		INIT_LIST_HEAD(&irq->cb.list);
>   		irq->irq_idx = -EINVAL;
> -		irq->cb.arg = phys_enc;
>   	}
>   
>   	irq = &phys_enc->irq[INTR_IDX_CTL_START];
>   	irq->name = "ctl_start";
>   	irq->intr_idx = INTR_IDX_CTL_START;
> -	irq->cb.func = dpu_encoder_phys_cmd_ctl_start_irq;
> +	irq->func = dpu_encoder_phys_cmd_ctl_start_irq;
>   
>   	irq = &phys_enc->irq[INTR_IDX_PINGPONG];
>   	irq->name = "pp_done";
>   	irq->intr_idx = INTR_IDX_PINGPONG;
> -	irq->cb.func = dpu_encoder_phys_cmd_pp_tx_done_irq;
> +	irq->func = dpu_encoder_phys_cmd_pp_tx_done_irq;
>   
>   	irq = &phys_enc->irq[INTR_IDX_RDPTR];
>   	irq->name = "pp_rd_ptr";
>   	irq->intr_idx = INTR_IDX_RDPTR;
> -	irq->cb.func = dpu_encoder_phys_cmd_pp_rd_ptr_irq;
> +	irq->func = dpu_encoder_phys_cmd_pp_rd_ptr_irq;
>   
>   	irq = &phys_enc->irq[INTR_IDX_UNDERRUN];
>   	irq->name = "underrun";
>   	irq->intr_idx = INTR_IDX_UNDERRUN;
> -	irq->cb.func = dpu_encoder_phys_cmd_underrun_irq;
> +	irq->func = dpu_encoder_phys_cmd_underrun_irq;
>   
>   	atomic_set(&phys_enc->vblank_refcount, 0);
>   	atomic_set(&phys_enc->pending_kickoff_cnt, 0);
> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c
> index ddd9d89cd456..407e45e2010b 100644
> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c
> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c
> @@ -725,20 +725,18 @@ struct dpu_encoder_phys *dpu_encoder_phys_vid_init(
>   	phys_enc->enc_spinlock = p->enc_spinlock;
>   	for (i = 0; i < INTR_IDX_MAX; i++) {
>   		irq = &phys_enc->irq[i];
> -		INIT_LIST_HEAD(&irq->cb.list);
>   		irq->irq_idx = -EINVAL;
> -		irq->cb.arg = phys_enc;
>   	}
>   
>   	irq = &phys_enc->irq[INTR_IDX_VSYNC];
>   	irq->name = "vsync_irq";
>   	irq->intr_idx = INTR_IDX_VSYNC;
> -	irq->cb.func = dpu_encoder_phys_vid_vblank_irq;
> +	irq->func = dpu_encoder_phys_vid_vblank_irq;
>   
>   	irq = &phys_enc->irq[INTR_IDX_UNDERRUN];
>   	irq->name = "underrun";
>   	irq->intr_idx = INTR_IDX_UNDERRUN;
> -	irq->cb.func = dpu_encoder_phys_vid_underrun_irq;
> +	irq->func = dpu_encoder_phys_vid_underrun_irq;
>   
>   	atomic_set(&phys_enc->vblank_refcount, 0);
>   	atomic_set(&phys_enc->pending_kickoff_cnt, 0);
> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.c
> index 85404c9ab4e1..8297498f2279 100644
> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.c
> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.c
> @@ -145,21 +145,17 @@ static const struct dpu_intr_reg dpu_intr_set[] = {
>    */
>   static void dpu_core_irq_callback_handler(struct dpu_kms *dpu_kms, int irq_idx)
>   {
> -	struct dpu_irq_callback *cb;
> -
>   	VERB("irq_idx=%d\n", irq_idx);
>   
> -	if (list_empty(&dpu_kms->hw_intr->irq_cb_tbl[irq_idx]))
> +	if (!dpu_kms->hw_intr->irq_tbl[irq_idx].cb)
>   		DRM_ERROR("no registered cb, idx:%d\n", irq_idx);
>   
> -	atomic_inc(&dpu_kms->hw_intr->irq_counts[irq_idx]);
> +	atomic_inc(&dpu_kms->hw_intr->irq_tbl[irq_idx].count);
>   
>   	/*
>   	 * Perform registered function callback
>   	 */
> -	list_for_each_entry(cb, &dpu_kms->hw_intr->irq_cb_tbl[irq_idx], list)
> -		if (cb->func)
> -			cb->func(cb->arg, irq_idx);
> +	dpu_kms->hw_intr->irq_tbl[irq_idx].cb(dpu_kms->hw_intr->irq_tbl[irq_idx].arg, irq_idx);
>   }
>   
>   irqreturn_t dpu_core_irq(struct msm_kms *kms)
> @@ -408,24 +404,18 @@ struct dpu_hw_intr *dpu_hw_intr_init(void __iomem *addr,
>   		struct dpu_mdss_cfg *m)
>   {
>   	struct dpu_hw_intr *intr;
> +	int nirq = MDP_INTR_MAX * 32;
>   
>   	if (!addr || !m)
>   		return ERR_PTR(-EINVAL);
>   
> -	intr = kzalloc(sizeof(*intr), GFP_KERNEL);
> +	intr = kzalloc(struct_size(intr, irq_tbl, nirq), GFP_KERNEL);
>   	if (!intr)
>   		return ERR_PTR(-ENOMEM);
>   
>   	__intr_offset(m, addr, &intr->hw);
>   
> -	intr->total_irqs = ARRAY_SIZE(dpu_intr_set) * 32;
> -
> -	intr->cache_irq_mask = kcalloc(ARRAY_SIZE(dpu_intr_set), sizeof(u32),
> -			GFP_KERNEL);
> -	if (intr->cache_irq_mask == NULL) {
> -		kfree(intr);
> -		return ERR_PTR(-ENOMEM);
> -	}
> +	intr->total_irqs = nirq;
>   
>   	intr->irq_mask = m->mdss_irqs;
>   
> @@ -436,31 +426,19 @@ struct dpu_hw_intr *dpu_hw_intr_init(void __iomem *addr,
>   
>   void dpu_hw_intr_destroy(struct dpu_hw_intr *intr)
>   {
> -	if (intr) {
> -		kfree(intr->cache_irq_mask);
> -
> -		kfree(intr->irq_cb_tbl);
> -		kfree(intr->irq_counts);
> -
> +	if (intr)
>   		kfree(intr);
> -	}
>   }
>   
>   int dpu_core_irq_register_callback(struct dpu_kms *dpu_kms, int irq_idx,
> -		struct dpu_irq_callback *register_irq_cb)
> +		void (*irq_cb)(void *arg, int irq_idx),
> +		void *irq_arg)
>   {
>   	unsigned long irq_flags;
> +	int ret;
>   
> -	if (!dpu_kms->hw_intr->irq_cb_tbl) {
> -		DPU_ERROR("invalid params\n");
> -		return -EINVAL;
> -	}
> -
> -	if (!register_irq_cb || !register_irq_cb->func) {
> -		DPU_ERROR("invalid irq_cb:%d func:%d\n",
> -				register_irq_cb != NULL,
> -				register_irq_cb ?
> -					register_irq_cb->func != NULL : -1);
> +	if (!irq_cb) {
> +		DPU_ERROR("invalid ird_idx:%d irq_cb:%ps\n", irq_idx, irq_cb);
>   		return -EINVAL;
>   	}
>   
> @@ -472,41 +450,32 @@ int dpu_core_irq_register_callback(struct dpu_kms *dpu_kms, int irq_idx,
>   	VERB("[%pS] irq_idx=%d\n", __builtin_return_address(0), irq_idx);
>   
>   	spin_lock_irqsave(&dpu_kms->hw_intr->irq_lock, irq_flags);
> -	trace_dpu_core_irq_register_callback(irq_idx, register_irq_cb);
> -	list_del_init(&register_irq_cb->list);
> -	list_add_tail(&register_irq_cb->list,
> -			&dpu_kms->hw_intr->irq_cb_tbl[irq_idx]);
> -	if (list_is_first(&register_irq_cb->list,
> -			&dpu_kms->hw_intr->irq_cb_tbl[irq_idx])) {
> -		int ret = dpu_hw_intr_enable_irq_locked(
> +
> +	if (unlikely(WARN_ON(dpu_kms->hw_intr->irq_tbl[irq_idx].cb))) {
> +		spin_unlock_irqrestore(&dpu_kms->hw_intr->irq_lock, irq_flags);
> +
> +		return -EBUSY;
> +	}
> +
> +	trace_dpu_core_irq_register_callback(irq_idx, irq_cb);
> +	dpu_kms->hw_intr->irq_tbl[irq_idx].arg = irq_arg;
> +	dpu_kms->hw_intr->irq_tbl[irq_idx].cb = irq_cb;
> +
> +	ret = dpu_hw_intr_enable_irq_locked(
>   				dpu_kms->hw_intr,
>   				irq_idx);
> -		if (ret)
> -			DPU_ERROR("Fail to enable IRQ for irq_idx:%d\n",
> +	if (ret)
> +		DPU_ERROR("Fail to enable IRQ for irq_idx:%d\n",
>   					irq_idx);
> -	}
>   	spin_unlock_irqrestore(&dpu_kms->hw_intr->irq_lock, irq_flags);
>   
>   	return 0;
>   }
>   
> -int dpu_core_irq_unregister_callback(struct dpu_kms *dpu_kms, int irq_idx,
> -		struct dpu_irq_callback *register_irq_cb)
> +int dpu_core_irq_unregister_callback(struct dpu_kms *dpu_kms, int irq_idx)
>   {
>   	unsigned long irq_flags;
> -
> -	if (!dpu_kms->hw_intr->irq_cb_tbl) {
> -		DPU_ERROR("invalid params\n");
> -		return -EINVAL;
> -	}
> -
> -	if (!register_irq_cb || !register_irq_cb->func) {
> -		DPU_ERROR("invalid irq_cb:%d func:%d\n",
> -				register_irq_cb != NULL,
> -				register_irq_cb ?
> -					register_irq_cb->func != NULL : -1);
> -		return -EINVAL;
> -	}
> +	int ret;
>   
>   	if (irq_idx < 0 || irq_idx >= dpu_kms->hw_intr->total_irqs) {
>   		DPU_ERROR("invalid IRQ index: [%d]\n", irq_idx);
> @@ -516,18 +485,16 @@ int dpu_core_irq_unregister_callback(struct dpu_kms *dpu_kms, int irq_idx,
>   	VERB("[%pS] irq_idx=%d\n", __builtin_return_address(0), irq_idx);
>   
>   	spin_lock_irqsave(&dpu_kms->hw_intr->irq_lock, irq_flags);
> -	trace_dpu_core_irq_unregister_callback(irq_idx, register_irq_cb);
> -	list_del_init(&register_irq_cb->list);
> -	/* empty callback list but interrupt is still enabled */
> -	if (list_empty(&dpu_kms->hw_intr->irq_cb_tbl[irq_idx])) {
> -		int ret = dpu_hw_intr_disable_irq_locked(
> -				dpu_kms->hw_intr,
> -				irq_idx);
> -		if (ret)
> -			DPU_ERROR("Fail to disable IRQ for irq_idx:%d\n",
> -					irq_idx);
> -		VERB("irq_idx=%d ret=%d\n", irq_idx, ret);
> -	}
> +	trace_dpu_core_irq_unregister_callback(irq_idx);
> +
> +	ret = dpu_hw_intr_disable_irq_locked(dpu_kms->hw_intr, irq_idx);
> +	if (ret)
> +		DPU_ERROR("Fail to disable IRQ for irq_idx:%d: %d\n",
> +					irq_idx, ret);
> +
> +	dpu_kms->hw_intr->irq_tbl[irq_idx].cb = NULL;
> +	dpu_kms->hw_intr->irq_tbl[irq_idx].arg = NULL;
> +
>   	spin_unlock_irqrestore(&dpu_kms->hw_intr->irq_lock, irq_flags);
>   
>   	return 0;
> @@ -537,24 +504,18 @@ int dpu_core_irq_unregister_callback(struct dpu_kms *dpu_kms, int irq_idx,
>   static int dpu_debugfs_core_irq_show(struct seq_file *s, void *v)
>   {
>   	struct dpu_kms *dpu_kms = s->private;
> -	struct dpu_irq_callback *cb;
>   	unsigned long irq_flags;
> -	int i, irq_count, cb_count;
> -
> -	if (WARN_ON(!dpu_kms->hw_intr->irq_cb_tbl))
> -		return 0;
> +	int i, irq_count;
> +	void *cb;
>   
>   	for (i = 0; i < dpu_kms->hw_intr->total_irqs; i++) {
>   		spin_lock_irqsave(&dpu_kms->hw_intr->irq_lock, irq_flags);
> -		cb_count = 0;
> -		irq_count = atomic_read(&dpu_kms->hw_intr->irq_counts[i]);
> -		list_for_each_entry(cb, &dpu_kms->hw_intr->irq_cb_tbl[i], list)
> -			cb_count++;
> +		irq_count = atomic_read(&dpu_kms->hw_intr->irq_tbl[i].count);
> +		cb = dpu_kms->hw_intr->irq_tbl[i].cb;
>   		spin_unlock_irqrestore(&dpu_kms->hw_intr->irq_lock, irq_flags);
>   
> -		if (irq_count || cb_count)
> -			seq_printf(s, "idx:%d irq:%d cb:%d\n",
> -					i, irq_count, cb_count);
> +		if (irq_count || cb)
> +			seq_printf(s, "idx:%d irq:%d cb:%ps\n", i, irq_count, cb);
>   	}
>   
>   	return 0;
> @@ -580,15 +541,8 @@ void dpu_core_irq_preinstall(struct msm_kms *kms)
>   	dpu_disable_all_irqs(dpu_kms);
>   	pm_runtime_put_sync(&dpu_kms->pdev->dev);
>   
> -	/* Create irq callbacks for all possible irq_idx */
> -	dpu_kms->hw_intr->irq_cb_tbl = kcalloc(dpu_kms->hw_intr->total_irqs,
> -			sizeof(struct list_head), GFP_KERNEL);
> -	dpu_kms->hw_intr->irq_counts = kcalloc(dpu_kms->hw_intr->total_irqs,
> -			sizeof(atomic_t), GFP_KERNEL);
> -	for (i = 0; i < dpu_kms->hw_intr->total_irqs; i++) {
> -		INIT_LIST_HEAD(&dpu_kms->hw_intr->irq_cb_tbl[i]);
> -		atomic_set(&dpu_kms->hw_intr->irq_counts[i], 0);
> -	}
> +	for (i = 0; i < dpu_kms->hw_intr->total_irqs; i++)
> +		atomic_set(&dpu_kms->hw_intr->irq_tbl[i].count, 0);
>   }
>   
>   void dpu_core_irq_uninstall(struct msm_kms *kms)
> @@ -598,7 +552,7 @@ void dpu_core_irq_uninstall(struct msm_kms *kms)
>   
>   	pm_runtime_get_sync(&dpu_kms->pdev->dev);
>   	for (i = 0; i < dpu_kms->hw_intr->total_irqs; i++)
> -		if (!list_empty(&dpu_kms->hw_intr->irq_cb_tbl[i]))
> +		if (dpu_kms->hw_intr->irq_tbl[i].cb)
>   			DPU_ERROR("irq_idx=%d still enabled/registered\n", i);
>   
>   	dpu_clear_irqs(dpu_kms);
> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.h
> index 1ab75cccd145..3136c1d260f8 100644
> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.h
> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.h
> @@ -43,19 +43,21 @@ enum dpu_hw_intr_reg {
>    * @save_irq_status:  array of IRQ status reg storage created during init
>    * @total_irqs: total number of irq_idx mapped in the hw_interrupts
>    * @irq_lock:         spinlock for accessing IRQ resources
> - * @irq_cb_tbl:       array of IRQ callbacks lists
> - * @irq_counts:       array of IRQ counts
> + * @irq_cb_tbl:       array of IRQ callbacks
>    */
>   struct dpu_hw_intr {
>   	struct dpu_hw_blk_reg_map hw;
> -	u32 *cache_irq_mask;
> +	u32 cache_irq_mask[MDP_INTR_MAX];
>   	u32 *save_irq_status;
>   	u32 total_irqs;
>   	spinlock_t irq_lock;
>   	unsigned long irq_mask;
>   
> -	struct list_head *irq_cb_tbl;
> -	atomic_t *irq_counts;
> +	struct {
> +		void (*cb)(void *arg, int irq_idx);
> +		void *arg;
> +		atomic_t count;
> +	} irq_tbl[];
>   };
>   
>   /**
> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h
> index 2d385b4b7f5e..b6371f1d554c 100644
> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h
> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h
> @@ -66,18 +66,6 @@
>   
>   #define DPU_NAME_SIZE  12
>   
> -/*
> - * struct dpu_irq_callback - IRQ callback handlers
> - * @list: list to callback
> - * @func: intr handler
> - * @arg: argument for the handler
> - */
> -struct dpu_irq_callback {
> -	struct list_head list;
> -	void (*func)(void *arg, int irq_idx);
> -	void *arg;
> -};
> -
>   struct dpu_kms {
>   	struct msm_kms base;
>   	struct drm_device *dev;
> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_trace.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_trace.h
> index 54d74341e690..91fa4d3fd63f 100644
> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_trace.h
> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_trace.h
> @@ -872,26 +872,26 @@ TRACE_EVENT(dpu_pp_connect_ext_te,
>   );
>   
>   DECLARE_EVENT_CLASS(dpu_core_irq_callback_template,
> -	TP_PROTO(int irq_idx, struct dpu_irq_callback *callback),
> +	TP_PROTO(int irq_idx, void *callback),
>   	TP_ARGS(irq_idx, callback),
>   	TP_STRUCT__entry(
>   		__field(	int,				irq_idx	)
> -		__field(	struct dpu_irq_callback *,	callback)
> +		__field(	void *,				callback)
>   	),
>   	TP_fast_assign(
>   		__entry->irq_idx = irq_idx;
>   		__entry->callback = callback;
>   	),
> -	TP_printk("irq_idx:%d callback:%pK", __entry->irq_idx,
> +	TP_printk("irq_idx:%d callback:%ps", __entry->irq_idx,
>   		  __entry->callback)
>   );
>   DEFINE_EVENT(dpu_core_irq_callback_template, dpu_core_irq_register_callback,
> -	TP_PROTO(int irq_idx, struct dpu_irq_callback *callback),
> +	TP_PROTO(int irq_idx, void *callback),
>   	TP_ARGS(irq_idx, callback)
>   );
>   DEFINE_EVENT(dpu_core_irq_callback_template, dpu_core_irq_unregister_callback,
> -	TP_PROTO(int irq_idx, struct dpu_irq_callback *callback),
> -	TP_ARGS(irq_idx, callback)
> +	TP_PROTO(int irq_idx),
> +	TP_ARGS(irq_idx)
>   );
>   
>   TRACE_EVENT(dpu_core_perf_update_clk,
diff mbox series

Patch

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_core_irq.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_core_irq.h
index 6dce5d89f817..b5b6e7031fb9 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_core_irq.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_core_irq.h
@@ -44,10 +44,8 @@  u32 dpu_core_irq_read(
  *                             interrupt
  * @dpu_kms:		DPU handle
  * @irq_idx:		irq index
- * @irq_cb:		IRQ callback structure, containing callback function
- *			and argument. Passing NULL for irq_cb will unregister
- *			the callback for the given irq_idx
- *			This must exist until un-registration.
+ * @irq_cb:		IRQ callback funcion.
+ * @irq_arg:		IRQ callback argument.
  * @return:		0 for success registering callback, otherwise failure
  *
  * This function supports registration of multiple callbacks for each interrupt.
@@ -55,25 +53,21 @@  u32 dpu_core_irq_read(
 int dpu_core_irq_register_callback(
 		struct dpu_kms *dpu_kms,
 		int irq_idx,
-		struct dpu_irq_callback *irq_cb);
+		void (*irq_cb)(void *arg, int irq_idx),
+		void *irq_arg);
 
 /**
  * dpu_core_irq_unregister_callback - For unregistering callback function on IRQ
  *                             interrupt
  * @dpu_kms:		DPU handle
  * @irq_idx:		irq index
- * @irq_cb:		IRQ callback structure, containing callback function
- *			and argument. Passing NULL for irq_cb will unregister
- *			the callback for the given irq_idx
- *			This must match with registration.
  * @return:		0 for success registering callback, otherwise failure
  *
  * This function supports registration of multiple callbacks for each interrupt.
  */
 int dpu_core_irq_unregister_callback(
 		struct dpu_kms *dpu_kms,
-		int irq_idx,
-		struct dpu_irq_callback *irq_cb);
+		int irq_idx);
 
 /**
  * dpu_debugfs_core_irq_init - register core irq debugfs
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
index 5576b8a3e6ee..17ca149e7dcd 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
@@ -311,7 +311,7 @@  int dpu_encoder_helper_wait_for_irq(struct dpu_encoder_phys *phys_enc,
 				      phys_enc->hw_pp->idx - PINGPONG_0,
 				      atomic_read(wait_info->atomic_cnt));
 			local_irq_save(flags);
-			irq->cb.func(phys_enc, irq->irq_idx);
+			irq->func(phys_enc, irq->irq_idx);
 			local_irq_restore(flags);
 			ret = 0;
 		} else {
@@ -352,7 +352,7 @@  int dpu_encoder_helper_register_irq(struct dpu_encoder_phys *phys_enc,
 	}
 
 	ret = dpu_core_irq_register_callback(phys_enc->dpu_kms, irq->irq_idx,
-			&irq->cb);
+			irq->func, phys_enc);
 	if (ret) {
 		DPU_ERROR_PHYS(phys_enc,
 			"failed to register IRQ callback for %s\n",
@@ -383,8 +383,7 @@  int dpu_encoder_helper_unregister_irq(struct dpu_encoder_phys *phys_enc,
 		return 0;
 	}
 
-	ret = dpu_core_irq_unregister_callback(phys_enc->dpu_kms, irq->irq_idx,
-			&irq->cb);
+	ret = dpu_core_irq_unregister_callback(phys_enc->dpu_kms, irq->irq_idx);
 	if (ret) {
 		DRM_ERROR("unreg cb fail id=%u, intr=%d, irq=%d ret=%d",
 			  DRMID(phys_enc->parent), intr_idx,
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h
index e7270eb6b84b..80d87871fd94 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h
@@ -174,7 +174,7 @@  struct dpu_encoder_irq {
 	const char *name;
 	enum dpu_intr_idx intr_idx;
 	int irq_idx;
-	struct dpu_irq_callback cb;
+	void (*func)(void *arg, int irq_idx);
 };
 
 /**
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c
index 34a6940d12c5..a0652bdcf59b 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c
@@ -782,30 +782,28 @@  struct dpu_encoder_phys *dpu_encoder_phys_cmd_init(
 	phys_enc->enable_state = DPU_ENC_DISABLED;
 	for (i = 0; i < INTR_IDX_MAX; i++) {
 		irq = &phys_enc->irq[i];
-		INIT_LIST_HEAD(&irq->cb.list);
 		irq->irq_idx = -EINVAL;
-		irq->cb.arg = phys_enc;
 	}
 
 	irq = &phys_enc->irq[INTR_IDX_CTL_START];
 	irq->name = "ctl_start";
 	irq->intr_idx = INTR_IDX_CTL_START;
-	irq->cb.func = dpu_encoder_phys_cmd_ctl_start_irq;
+	irq->func = dpu_encoder_phys_cmd_ctl_start_irq;
 
 	irq = &phys_enc->irq[INTR_IDX_PINGPONG];
 	irq->name = "pp_done";
 	irq->intr_idx = INTR_IDX_PINGPONG;
-	irq->cb.func = dpu_encoder_phys_cmd_pp_tx_done_irq;
+	irq->func = dpu_encoder_phys_cmd_pp_tx_done_irq;
 
 	irq = &phys_enc->irq[INTR_IDX_RDPTR];
 	irq->name = "pp_rd_ptr";
 	irq->intr_idx = INTR_IDX_RDPTR;
-	irq->cb.func = dpu_encoder_phys_cmd_pp_rd_ptr_irq;
+	irq->func = dpu_encoder_phys_cmd_pp_rd_ptr_irq;
 
 	irq = &phys_enc->irq[INTR_IDX_UNDERRUN];
 	irq->name = "underrun";
 	irq->intr_idx = INTR_IDX_UNDERRUN;
-	irq->cb.func = dpu_encoder_phys_cmd_underrun_irq;
+	irq->func = dpu_encoder_phys_cmd_underrun_irq;
 
 	atomic_set(&phys_enc->vblank_refcount, 0);
 	atomic_set(&phys_enc->pending_kickoff_cnt, 0);
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c
index ddd9d89cd456..407e45e2010b 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c
@@ -725,20 +725,18 @@  struct dpu_encoder_phys *dpu_encoder_phys_vid_init(
 	phys_enc->enc_spinlock = p->enc_spinlock;
 	for (i = 0; i < INTR_IDX_MAX; i++) {
 		irq = &phys_enc->irq[i];
-		INIT_LIST_HEAD(&irq->cb.list);
 		irq->irq_idx = -EINVAL;
-		irq->cb.arg = phys_enc;
 	}
 
 	irq = &phys_enc->irq[INTR_IDX_VSYNC];
 	irq->name = "vsync_irq";
 	irq->intr_idx = INTR_IDX_VSYNC;
-	irq->cb.func = dpu_encoder_phys_vid_vblank_irq;
+	irq->func = dpu_encoder_phys_vid_vblank_irq;
 
 	irq = &phys_enc->irq[INTR_IDX_UNDERRUN];
 	irq->name = "underrun";
 	irq->intr_idx = INTR_IDX_UNDERRUN;
-	irq->cb.func = dpu_encoder_phys_vid_underrun_irq;
+	irq->func = dpu_encoder_phys_vid_underrun_irq;
 
 	atomic_set(&phys_enc->vblank_refcount, 0);
 	atomic_set(&phys_enc->pending_kickoff_cnt, 0);
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.c
index 85404c9ab4e1..8297498f2279 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.c
@@ -145,21 +145,17 @@  static const struct dpu_intr_reg dpu_intr_set[] = {
  */
 static void dpu_core_irq_callback_handler(struct dpu_kms *dpu_kms, int irq_idx)
 {
-	struct dpu_irq_callback *cb;
-
 	VERB("irq_idx=%d\n", irq_idx);
 
-	if (list_empty(&dpu_kms->hw_intr->irq_cb_tbl[irq_idx]))
+	if (!dpu_kms->hw_intr->irq_tbl[irq_idx].cb)
 		DRM_ERROR("no registered cb, idx:%d\n", irq_idx);
 
-	atomic_inc(&dpu_kms->hw_intr->irq_counts[irq_idx]);
+	atomic_inc(&dpu_kms->hw_intr->irq_tbl[irq_idx].count);
 
 	/*
 	 * Perform registered function callback
 	 */
-	list_for_each_entry(cb, &dpu_kms->hw_intr->irq_cb_tbl[irq_idx], list)
-		if (cb->func)
-			cb->func(cb->arg, irq_idx);
+	dpu_kms->hw_intr->irq_tbl[irq_idx].cb(dpu_kms->hw_intr->irq_tbl[irq_idx].arg, irq_idx);
 }
 
 irqreturn_t dpu_core_irq(struct msm_kms *kms)
@@ -408,24 +404,18 @@  struct dpu_hw_intr *dpu_hw_intr_init(void __iomem *addr,
 		struct dpu_mdss_cfg *m)
 {
 	struct dpu_hw_intr *intr;
+	int nirq = MDP_INTR_MAX * 32;
 
 	if (!addr || !m)
 		return ERR_PTR(-EINVAL);
 
-	intr = kzalloc(sizeof(*intr), GFP_KERNEL);
+	intr = kzalloc(struct_size(intr, irq_tbl, nirq), GFP_KERNEL);
 	if (!intr)
 		return ERR_PTR(-ENOMEM);
 
 	__intr_offset(m, addr, &intr->hw);
 
-	intr->total_irqs = ARRAY_SIZE(dpu_intr_set) * 32;
-
-	intr->cache_irq_mask = kcalloc(ARRAY_SIZE(dpu_intr_set), sizeof(u32),
-			GFP_KERNEL);
-	if (intr->cache_irq_mask == NULL) {
-		kfree(intr);
-		return ERR_PTR(-ENOMEM);
-	}
+	intr->total_irqs = nirq;
 
 	intr->irq_mask = m->mdss_irqs;
 
@@ -436,31 +426,19 @@  struct dpu_hw_intr *dpu_hw_intr_init(void __iomem *addr,
 
 void dpu_hw_intr_destroy(struct dpu_hw_intr *intr)
 {
-	if (intr) {
-		kfree(intr->cache_irq_mask);
-
-		kfree(intr->irq_cb_tbl);
-		kfree(intr->irq_counts);
-
+	if (intr)
 		kfree(intr);
-	}
 }
 
 int dpu_core_irq_register_callback(struct dpu_kms *dpu_kms, int irq_idx,
-		struct dpu_irq_callback *register_irq_cb)
+		void (*irq_cb)(void *arg, int irq_idx),
+		void *irq_arg)
 {
 	unsigned long irq_flags;
+	int ret;
 
-	if (!dpu_kms->hw_intr->irq_cb_tbl) {
-		DPU_ERROR("invalid params\n");
-		return -EINVAL;
-	}
-
-	if (!register_irq_cb || !register_irq_cb->func) {
-		DPU_ERROR("invalid irq_cb:%d func:%d\n",
-				register_irq_cb != NULL,
-				register_irq_cb ?
-					register_irq_cb->func != NULL : -1);
+	if (!irq_cb) {
+		DPU_ERROR("invalid ird_idx:%d irq_cb:%ps\n", irq_idx, irq_cb);
 		return -EINVAL;
 	}
 
@@ -472,41 +450,32 @@  int dpu_core_irq_register_callback(struct dpu_kms *dpu_kms, int irq_idx,
 	VERB("[%pS] irq_idx=%d\n", __builtin_return_address(0), irq_idx);
 
 	spin_lock_irqsave(&dpu_kms->hw_intr->irq_lock, irq_flags);
-	trace_dpu_core_irq_register_callback(irq_idx, register_irq_cb);
-	list_del_init(&register_irq_cb->list);
-	list_add_tail(&register_irq_cb->list,
-			&dpu_kms->hw_intr->irq_cb_tbl[irq_idx]);
-	if (list_is_first(&register_irq_cb->list,
-			&dpu_kms->hw_intr->irq_cb_tbl[irq_idx])) {
-		int ret = dpu_hw_intr_enable_irq_locked(
+
+	if (unlikely(WARN_ON(dpu_kms->hw_intr->irq_tbl[irq_idx].cb))) {
+		spin_unlock_irqrestore(&dpu_kms->hw_intr->irq_lock, irq_flags);
+
+		return -EBUSY;
+	}
+
+	trace_dpu_core_irq_register_callback(irq_idx, irq_cb);
+	dpu_kms->hw_intr->irq_tbl[irq_idx].arg = irq_arg;
+	dpu_kms->hw_intr->irq_tbl[irq_idx].cb = irq_cb;
+
+	ret = dpu_hw_intr_enable_irq_locked(
 				dpu_kms->hw_intr,
 				irq_idx);
-		if (ret)
-			DPU_ERROR("Fail to enable IRQ for irq_idx:%d\n",
+	if (ret)
+		DPU_ERROR("Fail to enable IRQ for irq_idx:%d\n",
 					irq_idx);
-	}
 	spin_unlock_irqrestore(&dpu_kms->hw_intr->irq_lock, irq_flags);
 
 	return 0;
 }
 
-int dpu_core_irq_unregister_callback(struct dpu_kms *dpu_kms, int irq_idx,
-		struct dpu_irq_callback *register_irq_cb)
+int dpu_core_irq_unregister_callback(struct dpu_kms *dpu_kms, int irq_idx)
 {
 	unsigned long irq_flags;
-
-	if (!dpu_kms->hw_intr->irq_cb_tbl) {
-		DPU_ERROR("invalid params\n");
-		return -EINVAL;
-	}
-
-	if (!register_irq_cb || !register_irq_cb->func) {
-		DPU_ERROR("invalid irq_cb:%d func:%d\n",
-				register_irq_cb != NULL,
-				register_irq_cb ?
-					register_irq_cb->func != NULL : -1);
-		return -EINVAL;
-	}
+	int ret;
 
 	if (irq_idx < 0 || irq_idx >= dpu_kms->hw_intr->total_irqs) {
 		DPU_ERROR("invalid IRQ index: [%d]\n", irq_idx);
@@ -516,18 +485,16 @@  int dpu_core_irq_unregister_callback(struct dpu_kms *dpu_kms, int irq_idx,
 	VERB("[%pS] irq_idx=%d\n", __builtin_return_address(0), irq_idx);
 
 	spin_lock_irqsave(&dpu_kms->hw_intr->irq_lock, irq_flags);
-	trace_dpu_core_irq_unregister_callback(irq_idx, register_irq_cb);
-	list_del_init(&register_irq_cb->list);
-	/* empty callback list but interrupt is still enabled */
-	if (list_empty(&dpu_kms->hw_intr->irq_cb_tbl[irq_idx])) {
-		int ret = dpu_hw_intr_disable_irq_locked(
-				dpu_kms->hw_intr,
-				irq_idx);
-		if (ret)
-			DPU_ERROR("Fail to disable IRQ for irq_idx:%d\n",
-					irq_idx);
-		VERB("irq_idx=%d ret=%d\n", irq_idx, ret);
-	}
+	trace_dpu_core_irq_unregister_callback(irq_idx);
+
+	ret = dpu_hw_intr_disable_irq_locked(dpu_kms->hw_intr, irq_idx);
+	if (ret)
+		DPU_ERROR("Fail to disable IRQ for irq_idx:%d: %d\n",
+					irq_idx, ret);
+
+	dpu_kms->hw_intr->irq_tbl[irq_idx].cb = NULL;
+	dpu_kms->hw_intr->irq_tbl[irq_idx].arg = NULL;
+
 	spin_unlock_irqrestore(&dpu_kms->hw_intr->irq_lock, irq_flags);
 
 	return 0;
@@ -537,24 +504,18 @@  int dpu_core_irq_unregister_callback(struct dpu_kms *dpu_kms, int irq_idx,
 static int dpu_debugfs_core_irq_show(struct seq_file *s, void *v)
 {
 	struct dpu_kms *dpu_kms = s->private;
-	struct dpu_irq_callback *cb;
 	unsigned long irq_flags;
-	int i, irq_count, cb_count;
-
-	if (WARN_ON(!dpu_kms->hw_intr->irq_cb_tbl))
-		return 0;
+	int i, irq_count;
+	void *cb;
 
 	for (i = 0; i < dpu_kms->hw_intr->total_irqs; i++) {
 		spin_lock_irqsave(&dpu_kms->hw_intr->irq_lock, irq_flags);
-		cb_count = 0;
-		irq_count = atomic_read(&dpu_kms->hw_intr->irq_counts[i]);
-		list_for_each_entry(cb, &dpu_kms->hw_intr->irq_cb_tbl[i], list)
-			cb_count++;
+		irq_count = atomic_read(&dpu_kms->hw_intr->irq_tbl[i].count);
+		cb = dpu_kms->hw_intr->irq_tbl[i].cb;
 		spin_unlock_irqrestore(&dpu_kms->hw_intr->irq_lock, irq_flags);
 
-		if (irq_count || cb_count)
-			seq_printf(s, "idx:%d irq:%d cb:%d\n",
-					i, irq_count, cb_count);
+		if (irq_count || cb)
+			seq_printf(s, "idx:%d irq:%d cb:%ps\n", i, irq_count, cb);
 	}
 
 	return 0;
@@ -580,15 +541,8 @@  void dpu_core_irq_preinstall(struct msm_kms *kms)
 	dpu_disable_all_irqs(dpu_kms);
 	pm_runtime_put_sync(&dpu_kms->pdev->dev);
 
-	/* Create irq callbacks for all possible irq_idx */
-	dpu_kms->hw_intr->irq_cb_tbl = kcalloc(dpu_kms->hw_intr->total_irqs,
-			sizeof(struct list_head), GFP_KERNEL);
-	dpu_kms->hw_intr->irq_counts = kcalloc(dpu_kms->hw_intr->total_irqs,
-			sizeof(atomic_t), GFP_KERNEL);
-	for (i = 0; i < dpu_kms->hw_intr->total_irqs; i++) {
-		INIT_LIST_HEAD(&dpu_kms->hw_intr->irq_cb_tbl[i]);
-		atomic_set(&dpu_kms->hw_intr->irq_counts[i], 0);
-	}
+	for (i = 0; i < dpu_kms->hw_intr->total_irqs; i++)
+		atomic_set(&dpu_kms->hw_intr->irq_tbl[i].count, 0);
 }
 
 void dpu_core_irq_uninstall(struct msm_kms *kms)
@@ -598,7 +552,7 @@  void dpu_core_irq_uninstall(struct msm_kms *kms)
 
 	pm_runtime_get_sync(&dpu_kms->pdev->dev);
 	for (i = 0; i < dpu_kms->hw_intr->total_irqs; i++)
-		if (!list_empty(&dpu_kms->hw_intr->irq_cb_tbl[i]))
+		if (dpu_kms->hw_intr->irq_tbl[i].cb)
 			DPU_ERROR("irq_idx=%d still enabled/registered\n", i);
 
 	dpu_clear_irqs(dpu_kms);
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.h
index 1ab75cccd145..3136c1d260f8 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.h
@@ -43,19 +43,21 @@  enum dpu_hw_intr_reg {
  * @save_irq_status:  array of IRQ status reg storage created during init
  * @total_irqs: total number of irq_idx mapped in the hw_interrupts
  * @irq_lock:         spinlock for accessing IRQ resources
- * @irq_cb_tbl:       array of IRQ callbacks lists
- * @irq_counts:       array of IRQ counts
+ * @irq_cb_tbl:       array of IRQ callbacks
  */
 struct dpu_hw_intr {
 	struct dpu_hw_blk_reg_map hw;
-	u32 *cache_irq_mask;
+	u32 cache_irq_mask[MDP_INTR_MAX];
 	u32 *save_irq_status;
 	u32 total_irqs;
 	spinlock_t irq_lock;
 	unsigned long irq_mask;
 
-	struct list_head *irq_cb_tbl;
-	atomic_t *irq_counts;
+	struct {
+		void (*cb)(void *arg, int irq_idx);
+		void *arg;
+		atomic_t count;
+	} irq_tbl[];
 };
 
 /**
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h
index 2d385b4b7f5e..b6371f1d554c 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h
@@ -66,18 +66,6 @@ 
 
 #define DPU_NAME_SIZE  12
 
-/*
- * struct dpu_irq_callback - IRQ callback handlers
- * @list: list to callback
- * @func: intr handler
- * @arg: argument for the handler
- */
-struct dpu_irq_callback {
-	struct list_head list;
-	void (*func)(void *arg, int irq_idx);
-	void *arg;
-};
-
 struct dpu_kms {
 	struct msm_kms base;
 	struct drm_device *dev;
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_trace.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_trace.h
index 54d74341e690..91fa4d3fd63f 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_trace.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_trace.h
@@ -872,26 +872,26 @@  TRACE_EVENT(dpu_pp_connect_ext_te,
 );
 
 DECLARE_EVENT_CLASS(dpu_core_irq_callback_template,
-	TP_PROTO(int irq_idx, struct dpu_irq_callback *callback),
+	TP_PROTO(int irq_idx, void *callback),
 	TP_ARGS(irq_idx, callback),
 	TP_STRUCT__entry(
 		__field(	int,				irq_idx	)
-		__field(	struct dpu_irq_callback *,	callback)
+		__field(	void *,				callback)
 	),
 	TP_fast_assign(
 		__entry->irq_idx = irq_idx;
 		__entry->callback = callback;
 	),
-	TP_printk("irq_idx:%d callback:%pK", __entry->irq_idx,
+	TP_printk("irq_idx:%d callback:%ps", __entry->irq_idx,
 		  __entry->callback)
 );
 DEFINE_EVENT(dpu_core_irq_callback_template, dpu_core_irq_register_callback,
-	TP_PROTO(int irq_idx, struct dpu_irq_callback *callback),
+	TP_PROTO(int irq_idx, void *callback),
 	TP_ARGS(irq_idx, callback)
 );
 DEFINE_EVENT(dpu_core_irq_callback_template, dpu_core_irq_unregister_callback,
-	TP_PROTO(int irq_idx, struct dpu_irq_callback *callback),
-	TP_ARGS(irq_idx, callback)
+	TP_PROTO(int irq_idx),
+	TP_ARGS(irq_idx)
 );
 
 TRACE_EVENT(dpu_core_perf_update_clk,