1 /*
2  * Copyright (C) 2021-2022 Intel Corporation.
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  */
6 
7 #include <errno.h>
8 #include <asm/lib/bits.h>
9 #include <irq.h>
10 #include <common/softirq.h>
11 #include <asm/irq.h>
12 #include <asm/per_cpu.h>
13 
14 static spinlock_t irq_alloc_spinlock = { .head = 0U, .tail = 0U, };
15 
16 uint64_t irq_alloc_bitmap[IRQ_ALLOC_BITMAP_SIZE];
17 struct irq_desc irq_desc_array[NR_IRQS];
18 static uint64_t irq_rsvd_bitmap[IRQ_ALLOC_BITMAP_SIZE];
19 
20 /*
21  * alloc an free irq if req_irq is IRQ_INVALID, or else set assigned
22  * return: irq num on success, IRQ_INVALID on failure
23  */
alloc_irq_num(uint32_t req_irq,bool reserve)24 static uint32_t alloc_irq_num(uint32_t req_irq, bool reserve)
25 {
26 	uint32_t irq = req_irq;
27 	uint64_t rflags;
28 	uint32_t ret;
29 
30 	if ((irq >= NR_IRQS) && (irq != IRQ_INVALID)) {
31 		pr_err("[%s] invalid req_irq %u", __func__, req_irq);
32 	        ret = IRQ_INVALID;
33 	} else {
34 		spinlock_irqsave_obtain(&irq_alloc_spinlock, &rflags);
35 		if (irq == IRQ_INVALID) {
36 			/* if no valid irq num given, find a free one */
37 			irq = (uint32_t)ffz64_ex(irq_alloc_bitmap, NR_IRQS);
38 		}
39 
40 		if (irq >= NR_IRQS) {
41 			irq = IRQ_INVALID;
42 		} else {
43 			bitmap_set_nolock((uint16_t)(irq & 0x3FU),
44 					irq_alloc_bitmap + (irq >> 6U));
45 			if (reserve) {
46 				bitmap_set_nolock((uint16_t)(irq & 0x3FU),
47 						irq_rsvd_bitmap + (irq >> 6U));
48 			}
49 		}
50 		spinlock_irqrestore_release(&irq_alloc_spinlock, rflags);
51 		ret = irq;
52 	}
53 	return ret;
54 }
55 
reserve_irq_num(uint32_t irq)56 uint32_t reserve_irq_num(uint32_t irq)
57 {
58 	return alloc_irq_num(irq, true);
59 }
60 
61 /*
62  * @pre: irq is not in irq_static_mappings
63  * free irq num allocated via alloc_irq_num()
64  */
free_irq_num(uint32_t irq)65 static void free_irq_num(uint32_t irq)
66 {
67 	uint64_t rflags;
68 
69 	if (irq < NR_IRQS) {
70 		spinlock_irqsave_obtain(&irq_alloc_spinlock, &rflags);
71 
72 		if (bitmap_test((uint16_t)(irq & 0x3FU),
73 			irq_rsvd_bitmap + (irq >> 6U)) == false) {
74 			bitmap_clear_nolock((uint16_t)(irq & 0x3FU),
75 					irq_alloc_bitmap + (irq >> 6U));
76 		}
77 		spinlock_irqrestore_release(&irq_alloc_spinlock, rflags);
78 	}
79 }
80 
free_irq(uint32_t irq)81 void free_irq(uint32_t irq)
82 {
83 	uint64_t rflags;
84 	struct irq_desc *desc;
85 
86 	if (irq < NR_IRQS) {
87 		desc = &irq_desc_array[irq];
88 
89 		spinlock_irqsave_obtain(&desc->lock, &rflags);
90 		desc->action = NULL;
91 		desc->priv_data = NULL;
92 		desc->flags = IRQF_NONE;
93 		spinlock_irqrestore_release(&desc->lock, rflags);
94 
95 		free_irq_arch(irq);
96 		free_irq_num(irq);
97 	}
98 }
99 
100 /*
101  * There are four cases as to irq/vector allocation:
102  * case 1: req_irq = IRQ_INVALID
103  *      caller did not know which irq to use, and want system to
104  *      allocate available irq for it. These irq are in range:
105  *      nr_gsi ~ NR_IRQS
106  *      an irq will be allocated and a vector will be assigned to this
107  *      irq automatically.
108  * case 2: req_irq >= NR_LAGACY_IRQ and irq < nr_gsi
109  *      caller want to add device ISR handler into ioapic pins.
110  *      a vector will automatically assigned.
111  * case 3: req_irq >=0 and req_irq < NR_LEGACY_IRQ
112  *      caller want to add device ISR handler into ioapic pins, which
113  *      is a legacy irq, vector already reserved.
114  *      Nothing to do in this case.
115  * case 4: irq with speical type (not from IOAPIC/MSI)
116  *      These irq value are pre-defined for Timer, IPI, Spurious etc,
117  *      which is listed in irq_static_mappings[].
118  *	Nothing to do in this case.
119  *
120  * return value: valid irq (>=0) on success, otherwise errno (< 0).
121  */
request_irq(uint32_t req_irq,irq_action_t action_fn,void * priv_data,uint32_t flags)122 int32_t request_irq(uint32_t req_irq, irq_action_t action_fn, void *priv_data,
123 			uint32_t flags)
124 {
125 	struct irq_desc *desc;
126 	uint32_t irq;
127 	uint64_t rflags;
128 	int32_t ret;
129 
130 	irq = alloc_irq_num(req_irq, false);
131 	if (irq == IRQ_INVALID) {
132 		pr_err("[%s] invalid irq num", __func__);
133 		ret = -EINVAL;
134 	} else {
135 		if (!request_irq_arch(irq)) {
136 			pr_err("[%s] failed to alloc vector for irq %u",
137 				__func__, irq);
138 			free_irq_num(irq);
139 			ret = -EINVAL;
140 		} else {
141 			desc = &irq_desc_array[irq];
142 			if (desc->action == NULL) {
143 				spinlock_irqsave_obtain(&desc->lock, &rflags);
144 				desc->flags = flags;
145 				desc->priv_data = priv_data;
146 				desc->action = action_fn;
147 				spinlock_irqrestore_release(&desc->lock, rflags);
148 				ret = (int32_t)irq;
149 			} else {
150 				ret = -EBUSY;
151 				pr_err("%s: request irq(%u) failed, already requested",
152 				       __func__, irq);
153 			}
154 		}
155 	}
156 
157 	return ret;
158 }
159 
set_irq_trigger_mode(uint32_t irq,bool is_level_triggered)160 void set_irq_trigger_mode(uint32_t irq, bool is_level_triggered)
161 {
162 	uint64_t rflags;
163 	struct irq_desc *desc;
164 
165 	if (irq < NR_IRQS) {
166 		desc = &irq_desc_array[irq];
167 		spinlock_irqsave_obtain(&desc->lock, &rflags);
168 		if (is_level_triggered) {
169 			desc->flags |= IRQF_LEVEL;
170 		} else {
171 			desc->flags &= ~IRQF_LEVEL;
172 		}
173 		spinlock_irqrestore_release(&desc->lock, rflags);
174 	}
175 }
176 
handle_irq(const struct irq_desc * desc)177 static inline void handle_irq(const struct irq_desc *desc)
178 {
179 	irq_action_t action = desc->action;
180 
181 	pre_irq_arch(desc);
182 
183 	if (action != NULL) {
184 		action(desc->irq, desc->priv_data);
185 	}
186 
187 	post_irq_arch(desc);
188 }
189 
do_irq(const uint32_t irq)190 void do_irq(const uint32_t irq)
191 {
192 	struct irq_desc *desc;
193 
194 	if (irq < NR_IRQS) {
195 		desc = &irq_desc_array[irq];
196 		per_cpu(irq_count, get_pcpu_id())[irq]++;
197 
198 		/* XXX irq_alloc_bitmap is used lockless here */
199 		if (bitmap_test((uint16_t)(irq & 0x3FU), irq_alloc_bitmap + (irq >> 6U))) {
200 			handle_irq(desc);
201 		}
202 	}
203 
204 	do_softirq();
205 }
206 
init_irq_descs(void)207 static void init_irq_descs(void)
208 {
209 	uint32_t i;
210 
211 	for (i = 0U; i < NR_IRQS; i++) {
212 		struct irq_desc *desc = &irq_desc_array[i];
213 		desc->irq = i;
214 		spinlock_init(&desc->lock);
215 	}
216 
217 	init_irq_descs_arch(irq_desc_array);
218 }
219 
init_interrupt(uint16_t pcpu_id)220 void init_interrupt(uint16_t pcpu_id)
221 {
222 	init_interrupt_arch(pcpu_id);
223 
224 	if (pcpu_id == BSP_CPU_ID) {
225 		init_irq_descs();
226 		setup_irqs_arch();
227 		init_softirq();
228 	}
229 
230 	CPU_IRQ_ENABLE_ON_CONFIG();
231 }
232