xref: /dpdk/drivers/bus/dpaa/base/qbman/dpaa_sys.c (revision d81734caccade4dc17d24d2ffd8b71244d35a69f)
1 /* SPDX-License-Identifier: (BSD-3-Clause OR GPL-2.0)
2  *
3  * Copyright 2013-2016 Freescale Semiconductor Inc.
4  * Copyright 2017 NXP
5  *
6  */
7 
8 #include <process.h>
9 #include "dpaa_sys.h"
10 
11 struct process_interrupt {
12 	int irq;
13 	irqreturn_t (*isr)(int irq, void *arg);
14 	unsigned long flags;
15 	const char *name;
16 	void *arg;
17 	struct list_head node;
18 };
19 
20 static COMPAT_LIST_HEAD(process_irq_list);
21 static pthread_mutex_t process_irq_lock = PTHREAD_MUTEX_INITIALIZER;
22 
process_interrupt_install(struct process_interrupt * irq)23 static void process_interrupt_install(struct process_interrupt *irq)
24 {
25 	int ret;
26 	/* Add the irq to the end of the list */
27 	ret = pthread_mutex_lock(&process_irq_lock);
28 	assert(!ret);
29 	list_add_tail(&irq->node, &process_irq_list);
30 	ret = pthread_mutex_unlock(&process_irq_lock);
31 	assert(!ret);
32 }
33 
process_interrupt_remove(struct process_interrupt * irq)34 static void process_interrupt_remove(struct process_interrupt *irq)
35 {
36 	int ret;
37 
38 	ret = pthread_mutex_lock(&process_irq_lock);
39 	assert(!ret);
40 	list_del(&irq->node);
41 	ret = pthread_mutex_unlock(&process_irq_lock);
42 	assert(!ret);
43 }
44 
process_interrupt_find(int irq_num)45 static struct process_interrupt *process_interrupt_find(int irq_num)
46 {
47 	int ret;
48 	struct process_interrupt *i = NULL;
49 
50 	ret = pthread_mutex_lock(&process_irq_lock);
51 	assert(!ret);
52 	list_for_each_entry(i, &process_irq_list, node) {
53 		if (i->irq == irq_num)
54 			goto done;
55 	}
56 done:
57 	ret = pthread_mutex_unlock(&process_irq_lock);
58 	assert(!ret);
59 	return i;
60 }
61 
62 /* This is the interface from the platform-agnostic driver code to (de)register
63  * interrupt handlers. We simply create/destroy corresponding structs.
64  */
qbman_request_irq(int irq,irqreturn_t (* isr)(int irq,void * arg),unsigned long flags,const char * name,void * arg __maybe_unused)65 int qbman_request_irq(int irq, irqreturn_t (*isr)(int irq, void *arg),
66 		      unsigned long flags, const char *name,
67 		      void *arg __maybe_unused)
68 {
69 	struct process_interrupt *irq_node =
70 		kmalloc(sizeof(*irq_node), GFP_KERNEL);
71 
72 	if (!irq_node)
73 		return -ENOMEM;
74 	irq_node->irq = irq;
75 	irq_node->isr = isr;
76 	irq_node->flags = flags;
77 	irq_node->name = name;
78 	irq_node->arg = arg;
79 	process_interrupt_install(irq_node);
80 	return 0;
81 }
82 
qbman_free_irq(int irq,__maybe_unused void * arg)83 int qbman_free_irq(int irq, __maybe_unused void *arg)
84 {
85 	struct process_interrupt *irq_node = process_interrupt_find(irq);
86 
87 	if (!irq_node)
88 		return -EINVAL;
89 	process_interrupt_remove(irq_node);
90 	kfree(irq_node);
91 	return 0;
92 }
93 
94 /* This is the interface from the platform-specific driver code to obtain
95  * interrupt handlers that have been registered.
96  */
qbman_invoke_irq(int irq)97 void qbman_invoke_irq(int irq)
98 {
99 	struct process_interrupt *irq_node = process_interrupt_find(irq);
100 
101 	if (irq_node)
102 		irq_node->isr(irq, irq_node->arg);
103 }
104