@@ -46,22 +46,6 @@ static void init_irq_desc(void)
46
46
}
47
47
}
48
48
49
- /*
50
- * find available vector VECTOR_DYNAMIC_START ~ VECTOR_DYNAMIC_END
51
- */
52
- static uint32_t find_available_vector ()
53
- {
54
- uint32_t i ;
55
-
56
- /* TODO: vector lock required */
57
- for (i = VECTOR_DYNAMIC_START ; i <= VECTOR_DYNAMIC_END ; i ++ ) {
58
- if (vector_to_irq [i ] == IRQ_INVALID ) {
59
- return i ;
60
- }
61
- }
62
- return VECTOR_INVALID ;
63
- }
64
-
65
49
/*
66
50
* alloc an free irq if req_irq is IRQ_INVALID, or else set assigned
67
51
* return: irq num on success, IRQ_INVALID on failure
@@ -119,54 +103,83 @@ void free_irq_num(uint32_t irq)
119
103
}
120
104
}
121
105
122
- /* need lock protection before use */
123
- static void local_irq_desc_set_vector (uint32_t irq , uint32_t vr )
106
+ /*
107
+ * alloc an vectror and bind it to irq
108
+ * for legacy_irq (irq num < 16) and static mapped ones, do nothing
109
+ * if mapping is correct.
110
+ * retval: valid vector num on susccess, VECTOR_INVALID on failure.
111
+ */
112
+ uint32_t alloc_irq_vector (uint32_t irq )
124
113
{
114
+ uint32_t vr ;
125
115
struct irq_desc * desc ;
116
+ uint64_t rflags ;
117
+
118
+ if (irq >= NR_IRQS ) {
119
+ pr_err ("invalid irq[%u] to alloc vector" , irq );
120
+ return VECTOR_INVALID ;
121
+ }
126
122
127
123
desc = & irq_desc_array [irq ];
128
- vector_to_irq [vr ] = irq ;
129
- desc -> vector = vr ;
130
- }
124
+
125
+ if (desc -> vector != VECTOR_INVALID ) {
126
+ if (vector_to_irq [desc -> vector ] == irq ) {
127
+ /* statically binded */
128
+ vr = desc -> vector ;
129
+ } else {
130
+ pr_err ("[%s] irq[%u]:vector[%u] mismatch" ,
131
+ __func__ , irq , desc -> vector );
132
+ vr = VECTOR_INVALID ;
133
+ }
134
+ } else {
135
+ /* alloc a vector between:
136
+ * VECTOR_DYNAMIC_START ~ VECTOR_DYNAMC_END
137
+ */
138
+ spinlock_irqsave_obtain (& irq_alloc_spinlock , & rflags );
131
139
132
- /* lock version of set vector */
133
- static void irq_desc_set_vector (uint32_t irq , uint32_t vr )
134
- {
135
- uint64_t rflags ;
136
- struct irq_desc * desc ;
140
+ for (vr = VECTOR_DYNAMIC_START ;
141
+ vr <= VECTOR_DYNAMIC_END ; vr ++ ) {
142
+ if (vector_to_irq [vr ] == IRQ_INVALID ) {
143
+ desc -> vector = vr ;
144
+ vector_to_irq [vr ] = irq ;
145
+ break ;
146
+ }
147
+ }
148
+ vr = (vr > VECTOR_DYNAMIC_END ) ? VECTOR_INVALID : vr ;
149
+
150
+ spinlock_irqrestore_release (& irq_alloc_spinlock , rflags );
151
+ }
137
152
138
- desc = & irq_desc_array [irq ];
139
- spinlock_irqsave_obtain (& desc -> lock , & rflags );
140
- vector_to_irq [vr ] = irq ;
141
- desc -> vector = vr ;
142
- spinlock_irqrestore_release (& desc -> lock , rflags );
153
+ return vr ;
143
154
}
144
155
145
- /* used with holding lock outside */
146
- static void _irq_desc_free_vector (uint32_t irq )
156
+ /* free the vector allocated via alloc_irq_vector() */
157
+ void free_irq_vector (uint32_t irq )
147
158
{
148
159
struct irq_desc * desc ;
149
160
uint32_t vr ;
150
- uint16_t pcpu_id ;
161
+ uint64_t rflags ;
151
162
152
163
if (irq >= NR_IRQS ) {
153
164
return ;
154
165
}
155
166
156
167
desc = & irq_desc_array [irq ];
157
168
169
+ if ((irq < NR_LEGACY_IRQ ) || (desc -> vector >= VECTOR_FIXED_START )) {
170
+ /* do nothing for LEGACY_IRQ and static allocated ones */
171
+ return ;
172
+ }
173
+
174
+ spinlock_irqsave_obtain (& irq_alloc_spinlock , & rflags );
158
175
vr = desc -> vector ;
159
- desc -> used = IRQ_NOT_ASSIGNED ;
160
176
desc -> vector = VECTOR_INVALID ;
161
177
162
178
vr &= NR_MAX_VECTOR ;
163
179
if (vector_to_irq [vr ] == irq ) {
164
180
vector_to_irq [vr ] = IRQ_INVALID ;
165
181
}
166
-
167
- for (pcpu_id = 0U ; pcpu_id < phys_cpu_num ; pcpu_id ++ ) {
168
- per_cpu (irq_count , pcpu_id )[irq ] = 0UL ;
169
- }
182
+ spinlock_irqrestore_release (& irq_alloc_spinlock , rflags );
170
183
}
171
184
172
185
static void disable_pic_irq (void )
@@ -175,6 +188,28 @@ static void disable_pic_irq(void)
175
188
pio_write8 (0xffU , 0x21U );
176
189
}
177
190
191
+ /*
192
+ * There are four cases as to irq/vector allocation:
193
+ * case 1: req_irq = IRQ_INVALID
194
+ * caller did not know which irq to use, and want system to
195
+ * allocate available irq for it. These irq are in range:
196
+ * nr_gsi ~ NR_IRQS
197
+ * an irq will be allocated and a vector will be assigned to this
198
+ * irq automatically.
199
+ * case 2: req_irq >= NR_LAGACY_IRQ and irq < nr_gsi
200
+ * caller want to add device ISR handler into ioapic pins.
201
+ * a vector will automatically assigned.
202
+ * case 3: req_irq >=0 and req_irq < NR_LEGACY_IRQ
203
+ * caller want to add device ISR handler into ioapic pins, which
204
+ * is a legacy irq, vector already reserved.
205
+ * Nothing to do in this case.
206
+ * case 4: irq with speical type (not from IOAPIC/MSI)
207
+ * These irq value are pre-defined for Timer, IPI, Spurious etc,
208
+ * which is listed in irq_static_mappings[].
209
+ * Nothing to do in this case.
210
+ *
211
+ * return value: valid irq (>=0) on success, otherwise errno (< 0).
212
+ */
178
213
int32_t request_irq (uint32_t req_irq ,
179
214
irq_action_t action_fn ,
180
215
void * priv_data )
@@ -183,65 +218,32 @@ int32_t request_irq(uint32_t req_irq,
183
218
uint32_t irq , vector ;
184
219
uint64_t rflags ;
185
220
186
- /* ======================================================
187
- * This is low level ISR handler registering function
188
- * case: irq = IRQ_INVALID
189
- * caller did not know which irq to use, and want system to
190
- * allocate available irq for it. These irq are in range:
191
- * nr_gsi ~ NR_IRQS
192
- * a irq will be allocated and the vector will be assigned to this
193
- * irq automatically.
194
- *
195
- * case: irq >=0 and irq < nr_gsi
196
- * caller want to add device ISR handler into ioapic pins.
197
- * two kind of devices: legacy device and PCI device with INTx
198
- * a vector will automatically assigned.
199
- *
200
- * case: irq with speical type (not from IOAPIC/MSI)
201
- * These irq value are pre-defined for Timer, IPI, Spurious etc
202
- * vectors are pre-defined also
203
- *
204
- * return value: pinned irq and assigned vector for this irq.
205
- * caller can use this irq to enable/disable/mask/unmask interrupt
206
- * and if this irq is for:
207
- * GSI legacy: nothing to do for legacy irq, already initialized
208
- * GSI other: need to progam PCI INTx to match this irq pin
209
- * MSI: caller need program vector to PCI device
210
- *
211
- * =====================================================
212
- */
213
221
irq = alloc_irq_num (req_irq );
214
222
if (irq == IRQ_INVALID ) {
215
223
pr_err ("[%s] invalid irq num" , __func__ );
216
224
return - EINVAL ;
217
225
}
218
226
227
+ vector = alloc_irq_vector (irq );
228
+ if (vector == VECTOR_INVALID ) {
229
+ pr_err ("[%s] failed to alloc vector for irq %u" ,
230
+ __func__ , irq );
231
+ free_irq_num (irq );
232
+ return - EINVAL ;
233
+ }
234
+
219
235
desc = & irq_desc_array [irq ];
236
+ spinlock_irqsave_obtain (& desc -> lock , & rflags );
220
237
if (desc -> irq_handler == NULL ) {
221
238
desc -> irq_handler = common_handler_edge ;
222
239
}
223
240
224
- vector = desc -> vector ;
225
- if (vector >= VECTOR_FIXED_START &&
226
- vector <= VECTOR_FIXED_END ) {
227
- irq_desc_set_vector (irq , vector );
228
- } else if (vector > NR_MAX_VECTOR ) {
229
- irq_desc_alloc_vector (irq );
230
- }
231
-
232
- if (desc -> vector == VECTOR_INVALID ) {
233
- pr_err ("the input vector is not correct" );
234
- free_irq_num (irq );
235
- return - EINVAL ;
236
- }
237
-
238
241
if (desc -> action == NULL ) {
239
- spinlock_irqsave_obtain (& desc -> lock , & rflags );
240
242
desc -> priv_data = priv_data ;
241
243
desc -> action = action_fn ;
242
-
243
244
spinlock_irqrestore_release (& desc -> lock , rflags );
244
245
} else {
246
+ spinlock_irqrestore_release (& desc -> lock , rflags );
245
247
pr_err ("%s: request irq(%u) vr(%u) failed,\
246
248
already requested" , __func__ ,
247
249
irq , irq_to_vector (irq ));
@@ -254,58 +256,6 @@ int32_t request_irq(uint32_t req_irq,
254
256
return (int32_t )irq ;
255
257
}
256
258
257
- /* it is safe to call irq_desc_alloc_vector multiple times*/
258
- uint32_t irq_desc_alloc_vector (uint32_t irq )
259
- {
260
- uint32_t vr = VECTOR_INVALID ;
261
- uint64_t rflags ;
262
- struct irq_desc * desc ;
263
-
264
-
265
- /* irq should be always available at this time */
266
- if (irq >= NR_IRQS ) {
267
- return VECTOR_INVALID ;
268
- }
269
-
270
- desc = & irq_desc_array [irq ];
271
- spinlock_irqsave_obtain (& desc -> lock , & rflags );
272
- if (desc -> vector != VECTOR_INVALID ) {
273
- /* already allocated a vector */
274
- goto OUT ;
275
- }
276
-
277
- /* FLAT mode, a irq connected to every cpu's same vector */
278
- vr = find_available_vector ();
279
- if (vr > NR_MAX_VECTOR ) {
280
- pr_err ("no vector found for irq[%d]" , irq );
281
- goto OUT ;
282
- }
283
- local_irq_desc_set_vector (irq , vr );
284
- OUT :
285
- spinlock_irqrestore_release (& desc -> lock , rflags );
286
- return vr ;
287
- }
288
-
289
- void irq_desc_try_free_vector (uint32_t irq )
290
- {
291
- uint64_t rflags ;
292
- struct irq_desc * desc ;
293
-
294
- /* legacy irq's vector is reserved and should not be freed */
295
- if ((irq >= NR_IRQS ) || (irq < NR_LEGACY_IRQ )) {
296
- return ;
297
- }
298
-
299
- desc = & irq_desc_array [irq ];
300
- spinlock_irqsave_obtain (& desc -> lock , & rflags );
301
- if (desc -> action == NULL ) {
302
- _irq_desc_free_vector (irq );
303
- }
304
-
305
- spinlock_irqrestore_release (& desc -> lock , rflags );
306
-
307
- }
308
-
309
259
uint32_t irq_to_vector (uint32_t irq )
310
260
{
311
261
if (irq < NR_IRQS ) {
@@ -527,14 +477,13 @@ void free_irq(uint32_t irq)
527
477
dev_dbg (ACRN_DBG_IRQ , "[%s] irq%d vr:0x%x" ,
528
478
__func__ , irq , irq_to_vector (irq ));
529
479
530
- spinlock_irqsave_obtain (& desc -> lock , & rflags );
480
+ free_irq_vector (irq );
481
+ free_irq_num (irq );
531
482
483
+ spinlock_irqsave_obtain (& desc -> lock , & rflags );
532
484
desc -> action = NULL ;
533
485
desc -> priv_data = NULL ;
534
-
535
486
spinlock_irqrestore_release (& desc -> lock , rflags );
536
- irq_desc_try_free_vector (desc -> irq );
537
- free_irq_num (irq );
538
487
}
539
488
540
489
#ifdef HV_DEBUG
0 commit comments