mirror of
https://github.com/projectacrn/acrn-hypervisor.git
synced 2025-07-19 18:02:06 +00:00
hv: pirq: refactor irq num alloc/free
This commit refactors the alloc/free irq num, two functions are defined: - uint32_t alloc_irq_num(uint32_t irq) - if irq is valid, mark the irq_desc as used; if it's IRQ_INVALID, alloc a free irq, or else do nothing; - return: irq num on success, or IRQ_INVALID on failure. - void free_irq_num(uint32_t irq) - free the irq num allocated via alloc_irq_num(); And a global spinlock to protect it from concurrent allocation/free. Signed-off-by: Yan, Like <like.yan@intel.com> Acked-by: Anthony Xu <anthony.xu@intel.com>
This commit is contained in:
parent
f77d885d7e
commit
1bf2fc342a
@ -361,7 +361,7 @@ void setup_ioapic_irq(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* pinned irq before use it */
|
/* pinned irq before use it */
|
||||||
if (irq_mark_used(gsi) >= NR_IRQS) {
|
if (alloc_irq_num(gsi) == IRQ_INVALID) {
|
||||||
pr_err("failed to alloc IRQ[%d]", gsi);
|
pr_err("failed to alloc IRQ[%d]", gsi);
|
||||||
gsi++;
|
gsi++;
|
||||||
continue;
|
continue;
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
#include <softirq.h>
|
#include <softirq.h>
|
||||||
|
|
||||||
static spinlock_t exception_spinlock = { .head = 0U, .tail = 0U, };
|
static spinlock_t exception_spinlock = { .head = 0U, .tail = 0U, };
|
||||||
|
static spinlock_t irq_alloc_spinlock = { .head = 0U, .tail = 0U, };
|
||||||
|
|
||||||
static struct irq_desc irq_desc_array[NR_IRQS];
|
static struct irq_desc irq_desc_array[NR_IRQS];
|
||||||
static uint32_t vector_to_irq[NR_MAX_VECTOR + 1];
|
static uint32_t vector_to_irq[NR_MAX_VECTOR + 1];
|
||||||
@ -62,49 +63,60 @@ static uint32_t find_available_vector()
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* check and set irq to be assigned
|
* alloc an free irq if req_irq is IRQ_INVALID, or else set assigned
|
||||||
* return: IRQ_INVALID if irq already assigned otherwise return irq
|
* return: irq num on success, IRQ_INVALID on failure
|
||||||
*/
|
*/
|
||||||
uint32_t irq_mark_used(uint32_t irq)
|
uint32_t alloc_irq_num(uint32_t req_irq)
|
||||||
{
|
{
|
||||||
|
uint32_t i;
|
||||||
|
uint32_t irq = req_irq;
|
||||||
uint64_t rflags;
|
uint64_t rflags;
|
||||||
struct irq_desc *desc;
|
struct irq_desc *desc;
|
||||||
|
|
||||||
if (irq >= NR_IRQS) {
|
if ((irq >= NR_IRQS) && (irq != IRQ_INVALID)) {
|
||||||
|
pr_err("[%s] invalid req_irq %u", __func__, req_irq);
|
||||||
return IRQ_INVALID;
|
return IRQ_INVALID;
|
||||||
}
|
}
|
||||||
|
|
||||||
desc = &irq_desc_array[irq];
|
spinlock_irqsave_obtain(&irq_alloc_spinlock, &rflags);
|
||||||
spinlock_irqsave_obtain(&desc->lock, &rflags);
|
if (irq == IRQ_INVALID) {
|
||||||
if (desc->used == IRQ_NOT_ASSIGNED) {
|
/* if no valid irq num given, find a free one */
|
||||||
|
for (i = irq_gsi_num(); i < NR_IRQS; i++) {
|
||||||
|
desc = &irq_desc_array[i];
|
||||||
|
if (desc->used == IRQ_NOT_ASSIGNED) {
|
||||||
|
irq = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (irq != IRQ_INVALID) {
|
||||||
|
desc = &irq_desc_array[irq];
|
||||||
desc->used = IRQ_ASSIGNED;
|
desc->used = IRQ_ASSIGNED;
|
||||||
}
|
}
|
||||||
spinlock_irqrestore_release(&desc->lock, rflags);
|
spinlock_irqrestore_release(&irq_alloc_spinlock, rflags);
|
||||||
return irq;
|
return irq;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* system find available irq and set assigned
|
* free irq num allocated via alloc_irq_num()
|
||||||
* return: irq, VECTOR_INVALID not found
|
|
||||||
*/
|
*/
|
||||||
static uint32_t alloc_irq(void)
|
void free_irq_num(uint32_t irq)
|
||||||
{
|
{
|
||||||
uint32_t i;
|
|
||||||
uint64_t rflags;
|
|
||||||
struct irq_desc *desc;
|
struct irq_desc *desc;
|
||||||
|
uint64_t rflags;
|
||||||
|
|
||||||
|
if (irq >= NR_IRQS) {
|
||||||
for (i = irq_gsi_num(); i < NR_IRQS; i++) {
|
return;
|
||||||
desc = &irq_desc_array[i];
|
}
|
||||||
spinlock_irqsave_obtain(&desc->lock, &rflags);
|
|
||||||
if (desc->used == IRQ_NOT_ASSIGNED) {
|
desc = &irq_desc_array[irq];
|
||||||
desc->used = IRQ_ASSIGNED;
|
if ((irq_is_gsi(irq) == false)
|
||||||
spinlock_irqrestore_release(&desc->lock, rflags);
|
&& (desc->vector <= VECTOR_DYNAMIC_END)) {
|
||||||
break;
|
spinlock_irqsave_obtain(&irq_alloc_spinlock, &rflags);
|
||||||
}
|
desc->used = IRQ_NOT_ASSIGNED;
|
||||||
spinlock_irqrestore_release(&desc->lock, rflags);
|
spinlock_irqrestore_release(&irq_alloc_spinlock, rflags);
|
||||||
}
|
}
|
||||||
return (i == NR_IRQS) ? IRQ_INVALID : i;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* need lock protection before use */
|
/* need lock protection before use */
|
||||||
@ -163,12 +175,12 @@ static void disable_pic_irq(void)
|
|||||||
pio_write8(0xffU, 0x21U);
|
pio_write8(0xffU, 0x21U);
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t request_irq(uint32_t irq_arg,
|
int32_t request_irq(uint32_t req_irq,
|
||||||
irq_action_t action_fn,
|
irq_action_t action_fn,
|
||||||
void *priv_data)
|
void *priv_data)
|
||||||
{
|
{
|
||||||
struct irq_desc *desc;
|
struct irq_desc *desc;
|
||||||
uint32_t irq = irq_arg, vector;
|
uint32_t irq, vector;
|
||||||
uint64_t rflags;
|
uint64_t rflags;
|
||||||
|
|
||||||
/* ======================================================
|
/* ======================================================
|
||||||
@ -198,18 +210,9 @@ int32_t request_irq(uint32_t irq_arg,
|
|||||||
*
|
*
|
||||||
* =====================================================
|
* =====================================================
|
||||||
*/
|
*/
|
||||||
|
irq = alloc_irq_num(req_irq);
|
||||||
/* HV select a irq for device if irq < 0
|
|
||||||
* this vector/irq match to APCI DSDT or PCI INTx/MSI
|
|
||||||
*/
|
|
||||||
if (irq == IRQ_INVALID) {
|
if (irq == IRQ_INVALID) {
|
||||||
irq = alloc_irq();
|
pr_err("[%s] invalid irq num", __func__);
|
||||||
} else {
|
|
||||||
irq = irq_mark_used(irq);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (irq >= NR_IRQS) {
|
|
||||||
pr_err("failed to assign IRQ");
|
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -228,7 +231,7 @@ int32_t request_irq(uint32_t irq_arg,
|
|||||||
|
|
||||||
if (desc->vector == VECTOR_INVALID) {
|
if (desc->vector == VECTOR_INVALID) {
|
||||||
pr_err("the input vector is not correct");
|
pr_err("the input vector is not correct");
|
||||||
/* FIXME: free allocated irq */
|
free_irq_num(irq);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -531,6 +534,7 @@ void free_irq(uint32_t irq)
|
|||||||
|
|
||||||
spinlock_irqrestore_release(&desc->lock, rflags);
|
spinlock_irqrestore_release(&desc->lock, rflags);
|
||||||
irq_desc_try_free_vector(desc->irq);
|
irq_desc_try_free_vector(desc->irq);
|
||||||
|
free_irq_num(irq);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef HV_DEBUG
|
#ifdef HV_DEBUG
|
||||||
|
@ -74,6 +74,8 @@ void setup_notification(void);
|
|||||||
typedef void (*spurious_handler_t)(uint32_t vector);
|
typedef void (*spurious_handler_t)(uint32_t vector);
|
||||||
extern spurious_handler_t spurious_handler;
|
extern spurious_handler_t spurious_handler;
|
||||||
|
|
||||||
|
uint32_t alloc_irq_num(uint32_t req_irq);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Some MSI message definitions
|
* Some MSI message definitions
|
||||||
*/
|
*/
|
||||||
|
@ -34,8 +34,6 @@ struct irq_desc {
|
|||||||
spinlock_t lock;
|
spinlock_t lock;
|
||||||
};
|
};
|
||||||
|
|
||||||
uint32_t irq_mark_used(uint32_t irq);
|
|
||||||
|
|
||||||
uint32_t irq_desc_alloc_vector(uint32_t irq);
|
uint32_t irq_desc_alloc_vector(uint32_t irq);
|
||||||
void irq_desc_try_free_vector(uint32_t irq);
|
void irq_desc_try_free_vector(uint32_t irq);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user