hv: pirq: use a bitmap to maintain irq use status

This commit replaces the "used" field of irq_desc with a bitmap to maintain
the irq use status to save memory and LOC, and improve the efficiency as well.

Signed-off-by: Yan, Like <like.yan@intel.com>
Reviewed-by: Li, Fei1 <fei1.li@intel.com>
Acked-by: Anthony Xu <anthony.xu@intel.com>
This commit is contained in:
Yan, Like 2018-08-20 22:41:08 +08:00 committed by lijinxia
parent e0d40feaa8
commit 65e01a0cd2
3 changed files with 12 additions and 25 deletions

View File

@ -10,6 +10,8 @@
static spinlock_t exception_spinlock = { .head = 0U, .tail = 0U, };
static spinlock_t irq_alloc_spinlock = { .head = 0U, .tail = 0U, };
#define IRQ_ALLOC_BITMAP_SIZE INT_DIV_ROUNDUP(NR_IRQS, sizeof(uint64_t))
static uint64_t irq_alloc_bitmap[IRQ_ALLOC_BITMAP_SIZE];
static struct irq_desc irq_desc_array[NR_IRQS];
static uint32_t vector_to_irq[NR_MAX_VECTOR + 1];
@ -27,10 +29,8 @@ static uint32_t irq_static_mappings[NR_STATIC_MAPPINGS][2] = {
*/
uint32_t alloc_irq_num(uint32_t req_irq)
{
uint32_t i;
uint32_t irq = req_irq;
uint64_t rflags;
struct irq_desc *desc;
if ((irq >= NR_IRQS) && (irq != IRQ_INVALID)) {
pr_err("[%s] invalid req_irq %u", __func__, req_irq);
@ -40,18 +40,12 @@ uint32_t alloc_irq_num(uint32_t req_irq)
spinlock_irqsave_obtain(&irq_alloc_spinlock, &rflags);
if (irq == IRQ_INVALID) {
/* 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;
}
}
irq = ffz64_ex(irq_alloc_bitmap, NR_IRQS);
irq = (irq == NR_IRQS) ? IRQ_INVALID : irq;
}
if (irq != IRQ_INVALID) {
desc = &irq_desc_array[irq];
desc->used = IRQ_ASSIGNED;
bitmap_set_nolock(irq & 0x3FU, irq_alloc_bitmap + (irq >> 6U));
}
spinlock_irqrestore_release(&irq_alloc_spinlock, rflags);
return irq;
@ -73,7 +67,8 @@ void free_irq_num(uint32_t irq)
if ((irq_is_gsi(irq) == false)
&& (desc->vector <= VECTOR_DYNAMIC_END)) {
spinlock_irqsave_obtain(&irq_alloc_spinlock, &rflags);
desc->used = IRQ_NOT_ASSIGNED;
bitmap_test_and_clear_nolock(irq & 0x3FU,
irq_alloc_bitmap + (irq >> 6U));
spinlock_irqrestore_release(&irq_alloc_spinlock, rflags);
}
}
@ -338,7 +333,7 @@ void dispatch_interrupt(struct intr_excp_ctx *ctx)
goto ERR;
}
if (desc->used == IRQ_NOT_ASSIGNED) {
if (bitmap_test(irq & 0x3FU, irq_alloc_bitmap + (irq >> 6U)) == 0U) {
/* mask irq if possible */
goto ERR;
}
@ -396,7 +391,6 @@ void get_cpu_interrupt_info(char *str_arg, int str_max)
uint16_t pcpu_id;
uint32_t irq, vector;
int len, size = str_max;
struct irq_desc *desc;
len = snprintf(str, size, "\r\nIRQ\tVECTOR");
size -= len;
@ -408,10 +402,9 @@ void get_cpu_interrupt_info(char *str_arg, int str_max)
}
for (irq = 0U; irq < NR_IRQS; irq++) {
desc = &irq_desc_array[irq];
vector = irq_to_vector(irq);
if ((desc->used != IRQ_NOT_ASSIGNED) &&
(vector != VECTOR_INVALID)) {
if (bitmap_test(irq & 0x3FU, irq_alloc_bitmap + (irq >> 6U))
&& (vector != VECTOR_INVALID)) {
len = snprintf(str, size, "\r\n%d\t0x%X", irq, vector);
size -= len;
str += len;
@ -447,8 +440,8 @@ static void init_irq_descs(void)
uint32_t vr = irq_static_mappings[i][1];
irq_desc_array[irq].vector = vr;
irq_desc_array[irq].used = IRQ_ASSIGNED;
vector_to_irq[vr] = irq;
bitmap_set_nolock(irq & 0x3FU, irq_alloc_bitmap + (irq >> 6U));
}
}

View File

@ -24,7 +24,7 @@
#define NR_MAX_VECTOR 0xFFU
#define VECTOR_INVALID (NR_MAX_VECTOR + 1U)
#define NR_IRQS (256U + 16U)
#define NR_IRQS 256U
#define IRQ_INVALID 0xffffffffU
#define TIMER_IRQ (NR_IRQS - 1U)

View File

@ -17,17 +17,11 @@ enum irq_mode {
IRQ_DEASSERT,
};
enum irq_use_state {
IRQ_NOT_ASSIGNED = 0,
IRQ_ASSIGNED,
};
typedef int (*irq_action_t)(uint32_t irq, void *priv_data);
/* any field change in below required irq_lock protection with irqsave */
struct irq_desc {
uint32_t irq; /* index to irq_desc_base */
enum irq_use_state used; /* this irq have assigned to device */
uint32_t vector; /* assigned vector */
irq_action_t action; /* callback registered from component */