8
8
#include <softirq.h>
9
9
10
10
static spinlock_t exception_spinlock = { .head = 0U , .tail = 0U , };
11
+ static spinlock_t irq_alloc_spinlock = { .head = 0U , .tail = 0U , };
11
12
12
13
static struct irq_desc irq_desc_array [NR_IRQS ];
13
14
static uint32_t vector_to_irq [NR_MAX_VECTOR + 1 ];
@@ -62,49 +63,60 @@ static uint32_t find_available_vector()
62
63
}
63
64
64
65
/*
65
- * check and set irq to be assigned
66
- * return: IRQ_INVALID if irq already assigned otherwise return irq
66
+ * alloc an free irq if req_irq is IRQ_INVALID, or else set assigned
67
+ * return: irq num on success, IRQ_INVALID on failure
67
68
*/
68
- uint32_t irq_mark_used (uint32_t irq )
69
+ uint32_t alloc_irq_num (uint32_t req_irq )
69
70
{
71
+ uint32_t i ;
72
+ uint32_t irq = req_irq ;
70
73
uint64_t rflags ;
71
74
struct irq_desc * desc ;
72
75
73
- if (irq >= NR_IRQS ) {
76
+ if ((irq >= NR_IRQS ) && (irq != IRQ_INVALID )) {
77
+ pr_err ("[%s] invalid req_irq %u" , __func__ , req_irq );
74
78
return IRQ_INVALID ;
75
79
}
76
80
77
- desc = & irq_desc_array [irq ];
78
- spinlock_irqsave_obtain (& desc -> lock , & rflags );
79
- if (desc -> used == IRQ_NOT_ASSIGNED ) {
81
+ spinlock_irqsave_obtain (& irq_alloc_spinlock , & rflags );
82
+ if (irq == IRQ_INVALID ) {
83
+ /* if no valid irq num given, find a free one */
84
+ for (i = irq_gsi_num (); i < NR_IRQS ; i ++ ) {
85
+ desc = & irq_desc_array [i ];
86
+ if (desc -> used == IRQ_NOT_ASSIGNED ) {
87
+ irq = i ;
88
+ break ;
89
+ }
90
+ }
91
+ }
92
+
93
+ if (irq != IRQ_INVALID ) {
94
+ desc = & irq_desc_array [irq ];
80
95
desc -> used = IRQ_ASSIGNED ;
81
96
}
82
- spinlock_irqrestore_release (& desc -> lock , rflags );
97
+ spinlock_irqrestore_release (& irq_alloc_spinlock , rflags );
83
98
return irq ;
84
99
}
85
100
86
101
/*
87
- * system find available irq and set assigned
88
- * return: irq, VECTOR_INVALID not found
102
+ * free irq num allocated via alloc_irq_num()
89
103
*/
90
- static uint32_t alloc_irq ( void )
104
+ void free_irq_num ( uint32_t irq )
91
105
{
92
- uint32_t i ;
93
- uint64_t rflags ;
94
106
struct irq_desc * desc ;
107
+ uint64_t rflags ;
95
108
109
+ if (irq >= NR_IRQS ) {
110
+ return ;
111
+ }
96
112
97
- for (i = irq_gsi_num (); i < NR_IRQS ; i ++ ) {
98
- desc = & irq_desc_array [i ];
99
- spinlock_irqsave_obtain (& desc -> lock , & rflags );
100
- if (desc -> used == IRQ_NOT_ASSIGNED ) {
101
- desc -> used = IRQ_ASSIGNED ;
102
- spinlock_irqrestore_release (& desc -> lock , rflags );
103
- break ;
104
- }
105
- spinlock_irqrestore_release (& desc -> lock , rflags );
113
+ desc = & irq_desc_array [irq ];
114
+ if ((irq_is_gsi (irq ) == false)
115
+ && (desc -> vector <= VECTOR_DYNAMIC_END )) {
116
+ spinlock_irqsave_obtain (& irq_alloc_spinlock , & rflags );
117
+ desc -> used = IRQ_NOT_ASSIGNED ;
118
+ spinlock_irqrestore_release (& irq_alloc_spinlock , rflags );
106
119
}
107
- return (i == NR_IRQS ) ? IRQ_INVALID : i ;
108
120
}
109
121
110
122
/* need lock protection before use */
@@ -163,12 +175,12 @@ static void disable_pic_irq(void)
163
175
pio_write8 (0xffU , 0x21U );
164
176
}
165
177
166
- int32_t request_irq (uint32_t irq_arg ,
178
+ int32_t request_irq (uint32_t req_irq ,
167
179
irq_action_t action_fn ,
168
180
void * priv_data )
169
181
{
170
182
struct irq_desc * desc ;
171
- uint32_t irq = irq_arg , vector ;
183
+ uint32_t irq , vector ;
172
184
uint64_t rflags ;
173
185
174
186
/* ======================================================
@@ -198,18 +210,9 @@ int32_t request_irq(uint32_t irq_arg,
198
210
*
199
211
* =====================================================
200
212
*/
201
-
202
- /* HV select a irq for device if irq < 0
203
- * this vector/irq match to APCI DSDT or PCI INTx/MSI
204
- */
213
+ irq = alloc_irq_num (req_irq );
205
214
if (irq == IRQ_INVALID ) {
206
- irq = alloc_irq ();
207
- } else {
208
- irq = irq_mark_used (irq );
209
- }
210
-
211
- if (irq >= NR_IRQS ) {
212
- pr_err ("failed to assign IRQ" );
215
+ pr_err ("[%s] invalid irq num" , __func__ );
213
216
return - EINVAL ;
214
217
}
215
218
@@ -228,7 +231,7 @@ int32_t request_irq(uint32_t irq_arg,
228
231
229
232
if (desc -> vector == VECTOR_INVALID ) {
230
233
pr_err ("the input vector is not correct" );
231
- /* FIXME: free allocated irq */
234
+ free_irq_num ( irq );
232
235
return - EINVAL ;
233
236
}
234
237
@@ -531,6 +534,7 @@ void free_irq(uint32_t irq)
531
534
532
535
spinlock_irqrestore_release (& desc -> lock , rflags );
533
536
irq_desc_try_free_vector (desc -> irq );
537
+ free_irq_num (irq );
534
538
}
535
539
536
540
#ifdef HV_DEBUG
0 commit comments