xref: /dpdk/drivers/bus/dpaa/base/qbman/dpaa_sys.c (revision d81734caccade4dc17d24d2ffd8b71244d35a69f)
1*d81734caSHemant Agrawal /* SPDX-License-Identifier: (BSD-3-Clause OR GPL-2.0)
290632b75SShreyansh Jain  *
390632b75SShreyansh Jain  * Copyright 2013-2016 Freescale Semiconductor Inc.
4*d81734caSHemant Agrawal  * Copyright 2017 NXP
590632b75SShreyansh Jain  *
690632b75SShreyansh Jain  */
790632b75SShreyansh Jain 
890632b75SShreyansh Jain #include <process.h>
990632b75SShreyansh Jain #include "dpaa_sys.h"
1090632b75SShreyansh Jain 
1190632b75SShreyansh Jain struct process_interrupt {
1290632b75SShreyansh Jain 	int irq;
1390632b75SShreyansh Jain 	irqreturn_t (*isr)(int irq, void *arg);
1490632b75SShreyansh Jain 	unsigned long flags;
1590632b75SShreyansh Jain 	const char *name;
1690632b75SShreyansh Jain 	void *arg;
1790632b75SShreyansh Jain 	struct list_head node;
1890632b75SShreyansh Jain };
1990632b75SShreyansh Jain 
2090632b75SShreyansh Jain static COMPAT_LIST_HEAD(process_irq_list);
2190632b75SShreyansh Jain static pthread_mutex_t process_irq_lock = PTHREAD_MUTEX_INITIALIZER;
2290632b75SShreyansh Jain 
process_interrupt_install(struct process_interrupt * irq)2390632b75SShreyansh Jain static void process_interrupt_install(struct process_interrupt *irq)
2490632b75SShreyansh Jain {
2590632b75SShreyansh Jain 	int ret;
2690632b75SShreyansh Jain 	/* Add the irq to the end of the list */
2790632b75SShreyansh Jain 	ret = pthread_mutex_lock(&process_irq_lock);
2890632b75SShreyansh Jain 	assert(!ret);
2990632b75SShreyansh Jain 	list_add_tail(&irq->node, &process_irq_list);
3090632b75SShreyansh Jain 	ret = pthread_mutex_unlock(&process_irq_lock);
3190632b75SShreyansh Jain 	assert(!ret);
3290632b75SShreyansh Jain }
3390632b75SShreyansh Jain 
process_interrupt_remove(struct process_interrupt * irq)3490632b75SShreyansh Jain static void process_interrupt_remove(struct process_interrupt *irq)
3590632b75SShreyansh Jain {
3690632b75SShreyansh Jain 	int ret;
3790632b75SShreyansh Jain 
3890632b75SShreyansh Jain 	ret = pthread_mutex_lock(&process_irq_lock);
3990632b75SShreyansh Jain 	assert(!ret);
4090632b75SShreyansh Jain 	list_del(&irq->node);
4190632b75SShreyansh Jain 	ret = pthread_mutex_unlock(&process_irq_lock);
4290632b75SShreyansh Jain 	assert(!ret);
4390632b75SShreyansh Jain }
4490632b75SShreyansh Jain 
process_interrupt_find(int irq_num)4590632b75SShreyansh Jain static struct process_interrupt *process_interrupt_find(int irq_num)
4690632b75SShreyansh Jain {
4790632b75SShreyansh Jain 	int ret;
4890632b75SShreyansh Jain 	struct process_interrupt *i = NULL;
4990632b75SShreyansh Jain 
5090632b75SShreyansh Jain 	ret = pthread_mutex_lock(&process_irq_lock);
5190632b75SShreyansh Jain 	assert(!ret);
5290632b75SShreyansh Jain 	list_for_each_entry(i, &process_irq_list, node) {
5390632b75SShreyansh Jain 		if (i->irq == irq_num)
5490632b75SShreyansh Jain 			goto done;
5590632b75SShreyansh Jain 	}
5690632b75SShreyansh Jain done:
5790632b75SShreyansh Jain 	ret = pthread_mutex_unlock(&process_irq_lock);
5890632b75SShreyansh Jain 	assert(!ret);
5990632b75SShreyansh Jain 	return i;
6090632b75SShreyansh Jain }
6190632b75SShreyansh Jain 
6290632b75SShreyansh Jain /* This is the interface from the platform-agnostic driver code to (de)register
6390632b75SShreyansh Jain  * interrupt handlers. We simply create/destroy corresponding structs.
6490632b75SShreyansh Jain  */
qbman_request_irq(int irq,irqreturn_t (* isr)(int irq,void * arg),unsigned long flags,const char * name,void * arg __maybe_unused)6590632b75SShreyansh Jain int qbman_request_irq(int irq, irqreturn_t (*isr)(int irq, void *arg),
6690632b75SShreyansh Jain 		      unsigned long flags, const char *name,
6790632b75SShreyansh Jain 		      void *arg __maybe_unused)
6890632b75SShreyansh Jain {
6990632b75SShreyansh Jain 	struct process_interrupt *irq_node =
7090632b75SShreyansh Jain 		kmalloc(sizeof(*irq_node), GFP_KERNEL);
7190632b75SShreyansh Jain 
7290632b75SShreyansh Jain 	if (!irq_node)
7390632b75SShreyansh Jain 		return -ENOMEM;
7490632b75SShreyansh Jain 	irq_node->irq = irq;
7590632b75SShreyansh Jain 	irq_node->isr = isr;
7690632b75SShreyansh Jain 	irq_node->flags = flags;
7790632b75SShreyansh Jain 	irq_node->name = name;
7890632b75SShreyansh Jain 	irq_node->arg = arg;
7990632b75SShreyansh Jain 	process_interrupt_install(irq_node);
8090632b75SShreyansh Jain 	return 0;
8190632b75SShreyansh Jain }
8290632b75SShreyansh Jain 
qbman_free_irq(int irq,__maybe_unused void * arg)8390632b75SShreyansh Jain int qbman_free_irq(int irq, __maybe_unused void *arg)
8490632b75SShreyansh Jain {
8590632b75SShreyansh Jain 	struct process_interrupt *irq_node = process_interrupt_find(irq);
8690632b75SShreyansh Jain 
8790632b75SShreyansh Jain 	if (!irq_node)
8890632b75SShreyansh Jain 		return -EINVAL;
8990632b75SShreyansh Jain 	process_interrupt_remove(irq_node);
9090632b75SShreyansh Jain 	kfree(irq_node);
9190632b75SShreyansh Jain 	return 0;
9290632b75SShreyansh Jain }
9390632b75SShreyansh Jain 
9490632b75SShreyansh Jain /* This is the interface from the platform-specific driver code to obtain
9590632b75SShreyansh Jain  * interrupt handlers that have been registered.
9690632b75SShreyansh Jain  */
qbman_invoke_irq(int irq)9790632b75SShreyansh Jain void qbman_invoke_irq(int irq)
9890632b75SShreyansh Jain {
9990632b75SShreyansh Jain 	struct process_interrupt *irq_node = process_interrupt_find(irq);
10090632b75SShreyansh Jain 
10190632b75SShreyansh Jain 	if (irq_node)
10290632b75SShreyansh Jain 		irq_node->isr(irq, irq_node->arg);
10390632b75SShreyansh Jain }
104