Skip to content

Commit 2c044e0

Browse files
lyan3lijinxia
authored andcommitted
hv: pirq: refactor vector allocation/free
This commit refactors vector allocation/free codes, two functions are defined to help alloc/free vectors for an irq: - uint32_t alloc_irq_vector(uint32_t irq) - alloc a free vector (0x20 ~ 0xDF), and bind it to irq, for legacy irqs and static mapped irqs, vector has been allocated and bind, so just check the mapping correctness; - return: valid vector on success, VECTOR_INVALID on failure. - void free_irq_vector(uint32_t irq) - free vector allocated via alloc_irq_vector(), for legacy irqs and static mapped irqs, nothing need to do. Signed-off-by: Yan, Like <like.yan@intel.com> Acked-by: Anthony Xu <anthony.xu@intel.com>
1 parent 1bf2fc3 commit 2c044e0

File tree

4 files changed

+92
-145
lines changed

4 files changed

+92
-145
lines changed

hypervisor/arch/x86/ioapic.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -371,8 +371,8 @@ void setup_ioapic_irq(void)
371371
* for legacy irq, reserved vector and never free
372372
*/
373373
if (gsi < NR_LEGACY_IRQ) {
374-
vr = irq_desc_alloc_vector(gsi);
375-
if (vr > NR_MAX_VECTOR) {
374+
vr = alloc_irq_vector(gsi);
375+
if (vr == VECTOR_INVALID) {
376376
pr_err("failed to alloc VR");
377377
gsi++;
378378
continue;

hypervisor/arch/x86/irq.c

Lines changed: 87 additions & 138 deletions
Original file line numberDiff line numberDiff line change
@@ -46,22 +46,6 @@ static void init_irq_desc(void)
4646
}
4747
}
4848

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-
6549
/*
6650
* alloc an free irq if req_irq is IRQ_INVALID, or else set assigned
6751
* return: irq num on success, IRQ_INVALID on failure
@@ -119,54 +103,83 @@ void free_irq_num(uint32_t irq)
119103
}
120104
}
121105

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)
124113
{
114+
uint32_t vr;
125115
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+
}
126122

127123
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);
131139

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+
}
137152

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;
143154
}
144155

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)
147158
{
148159
struct irq_desc *desc;
149160
uint32_t vr;
150-
uint16_t pcpu_id;
161+
uint64_t rflags;
151162

152163
if (irq >= NR_IRQS) {
153164
return;
154165
}
155166

156167
desc = &irq_desc_array[irq];
157168

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);
158175
vr = desc->vector;
159-
desc->used = IRQ_NOT_ASSIGNED;
160176
desc->vector = VECTOR_INVALID;
161177

162178
vr &= NR_MAX_VECTOR;
163179
if (vector_to_irq[vr] == irq) {
164180
vector_to_irq[vr] = IRQ_INVALID;
165181
}
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);
170183
}
171184

172185
static void disable_pic_irq(void)
@@ -175,6 +188,28 @@ static void disable_pic_irq(void)
175188
pio_write8(0xffU, 0x21U);
176189
}
177190

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+
*/
178213
int32_t request_irq(uint32_t req_irq,
179214
irq_action_t action_fn,
180215
void *priv_data)
@@ -183,65 +218,32 @@ int32_t request_irq(uint32_t req_irq,
183218
uint32_t irq, vector;
184219
uint64_t rflags;
185220

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-
*/
213221
irq = alloc_irq_num(req_irq);
214222
if (irq == IRQ_INVALID) {
215223
pr_err("[%s] invalid irq num", __func__);
216224
return -EINVAL;
217225
}
218226

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+
219235
desc = &irq_desc_array[irq];
236+
spinlock_irqsave_obtain(&desc->lock, &rflags);
220237
if (desc->irq_handler == NULL) {
221238
desc->irq_handler = common_handler_edge;
222239
}
223240

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-
238241
if (desc->action == NULL) {
239-
spinlock_irqsave_obtain(&desc->lock, &rflags);
240242
desc->priv_data = priv_data;
241243
desc->action = action_fn;
242-
243244
spinlock_irqrestore_release(&desc->lock, rflags);
244245
} else {
246+
spinlock_irqrestore_release(&desc->lock, rflags);
245247
pr_err("%s: request irq(%u) vr(%u) failed,\
246248
already requested", __func__,
247249
irq, irq_to_vector(irq));
@@ -254,58 +256,6 @@ int32_t request_irq(uint32_t req_irq,
254256
return (int32_t)irq;
255257
}
256258

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-
309259
uint32_t irq_to_vector(uint32_t irq)
310260
{
311261
if (irq < NR_IRQS) {
@@ -527,14 +477,13 @@ void free_irq(uint32_t irq)
527477
dev_dbg(ACRN_DBG_IRQ, "[%s] irq%d vr:0x%x",
528478
__func__, irq, irq_to_vector(irq));
529479

530-
spinlock_irqsave_obtain(&desc->lock, &rflags);
480+
free_irq_vector(irq);
481+
free_irq_num(irq);
531482

483+
spinlock_irqsave_obtain(&desc->lock, &rflags);
532484
desc->action = NULL;
533485
desc->priv_data = NULL;
534-
535486
spinlock_irqrestore_release(&desc->lock, rflags);
536-
irq_desc_try_free_vector(desc->irq);
537-
free_irq_num(irq);
538487
}
539488

540489
#ifdef HV_DEBUG

hypervisor/include/arch/x86/irq.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,9 @@ typedef void (*spurious_handler_t)(uint32_t vector);
7575
extern spurious_handler_t spurious_handler;
7676

7777
uint32_t alloc_irq_num(uint32_t req_irq);
78+
uint32_t alloc_irq_vector(uint32_t irq);
79+
80+
uint32_t irq_to_vector(uint32_t irq);
7881

7982
/*
8083
* Some MSI message definitions

hypervisor/include/common/irq.h

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -34,11 +34,6 @@ struct irq_desc {
3434
spinlock_t lock;
3535
};
3636

37-
uint32_t irq_desc_alloc_vector(uint32_t irq);
38-
void irq_desc_try_free_vector(uint32_t irq);
39-
40-
uint32_t irq_to_vector(uint32_t irq);
41-
4237
int32_t request_irq(uint32_t irq,
4338
irq_action_t action_fn,
4439
void *priv_data);

0 commit comments

Comments
 (0)