Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 86886
b: refs/heads/master
c: a6cd632
h: refs/heads/master
v: v3
  • Loading branch information
Kenji Kaneshige authored and Tony Luck committed Mar 4, 2008
1 parent 58ce1fa commit 29a0fbf
Show file tree
Hide file tree
Showing 5 changed files with 121 additions and 34 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 86dffa4cd1a1d61fed68ab64c674d4094f2bdfe4
refs/heads/master: a6cd6322d594014240465210ccb290971469c6e8
4 changes: 3 additions & 1 deletion trunk/arch/ia64/kernel/iosapic.c
Original file line number Diff line number Diff line change
Expand Up @@ -345,7 +345,7 @@ iosapic_set_affinity (unsigned int irq, cpumask_t mask)
if (cpus_empty(mask))
return;

if (reassign_irq_vector(irq, first_cpu(mask)))
if (irq_prepare_move(irq, first_cpu(mask)))
return;

dest = cpu_physical_id(first_cpu(mask));
Expand Down Expand Up @@ -397,6 +397,7 @@ iosapic_end_level_irq (unsigned int irq)
struct iosapic_rte_info *rte;
int do_unmask_irq = 0;

irq_complete_move(irq);
if (unlikely(irq_desc[irq].status & IRQ_MOVE_PENDING)) {
do_unmask_irq = 1;
mask_irq(irq);
Expand Down Expand Up @@ -450,6 +451,7 @@ iosapic_ack_edge_irq (unsigned int irq)
{
irq_desc_t *idesc = irq_desc + irq;

irq_complete_move(irq);
move_native_irq(irq);
/*
* Once we have recorded IRQ_PENDING already, we can mask the
Expand Down
134 changes: 104 additions & 30 deletions trunk/arch/ia64/kernel/irq_ia64.c
Original file line number Diff line number Diff line change
Expand Up @@ -260,6 +260,8 @@ void __setup_vector_irq(int cpu)
}

#if defined(CONFIG_SMP) && (defined(CONFIG_IA64_GENERIC) || defined(CONFIG_IA64_DIG))
#define IA64_IRQ_MOVE_VECTOR IA64_DEF_FIRST_DEVICE_VECTOR

static enum vector_domain_type {
VECTOR_DOMAIN_NONE,
VECTOR_DOMAIN_PERCPU
Expand All @@ -272,6 +274,101 @@ static cpumask_t vector_allocation_domain(int cpu)
return CPU_MASK_ALL;
}

static int __irq_prepare_move(int irq, int cpu)
{
struct irq_cfg *cfg = &irq_cfg[irq];
int vector;
cpumask_t domain;

if (cfg->move_in_progress || cfg->move_cleanup_count)
return -EBUSY;
if (cfg->vector == IRQ_VECTOR_UNASSIGNED || !cpu_online(cpu))
return -EINVAL;
if (cpu_isset(cpu, cfg->domain))
return 0;
domain = vector_allocation_domain(cpu);
vector = find_unassigned_vector(domain);
if (vector < 0)
return -ENOSPC;
cfg->move_in_progress = 1;
cfg->old_domain = cfg->domain;
cfg->vector = IRQ_VECTOR_UNASSIGNED;
cfg->domain = CPU_MASK_NONE;
BUG_ON(__bind_irq_vector(irq, vector, domain));
return 0;
}

int irq_prepare_move(int irq, int cpu)
{
unsigned long flags;
int ret;

spin_lock_irqsave(&vector_lock, flags);
ret = __irq_prepare_move(irq, cpu);
spin_unlock_irqrestore(&vector_lock, flags);
return ret;
}

void irq_complete_move(unsigned irq)
{
struct irq_cfg *cfg = &irq_cfg[irq];
cpumask_t cleanup_mask;
int i;

if (likely(!cfg->move_in_progress))
return;

if (unlikely(cpu_isset(smp_processor_id(), cfg->old_domain)))
return;

cpus_and(cleanup_mask, cfg->old_domain, cpu_online_map);
cfg->move_cleanup_count = cpus_weight(cleanup_mask);
for_each_cpu_mask(i, cleanup_mask)
platform_send_ipi(i, IA64_IRQ_MOVE_VECTOR, IA64_IPI_DM_INT, 0);
cfg->move_in_progress = 0;
}

static irqreturn_t smp_irq_move_cleanup_interrupt(int irq, void *dev_id)
{
int me = smp_processor_id();
ia64_vector vector;
unsigned long flags;

for (vector = IA64_FIRST_DEVICE_VECTOR;
vector < IA64_LAST_DEVICE_VECTOR; vector++) {
int irq;
struct irq_desc *desc;
struct irq_cfg *cfg;
irq = __get_cpu_var(vector_irq)[vector];
if (irq < 0)
continue;

desc = irq_desc + irq;
cfg = irq_cfg + irq;
spin_lock(&desc->lock);
if (!cfg->move_cleanup_count)
goto unlock;

if (!cpu_isset(me, cfg->old_domain))
goto unlock;

spin_lock_irqsave(&vector_lock, flags);
__get_cpu_var(vector_irq)[vector] = -1;
cpu_clear(me, vector_table[vector]);
spin_unlock_irqrestore(&vector_lock, flags);
cfg->move_cleanup_count--;
unlock:
spin_unlock(&desc->lock);
}
return IRQ_HANDLED;
}

static struct irqaction irq_move_irqaction = {
.handler = smp_irq_move_cleanup_interrupt,
.flags = IRQF_DISABLED,
.name = "irq_move"
};

static int __init parse_vector_domain(char *arg)
{
if (!arg)
Expand Down Expand Up @@ -303,36 +400,6 @@ void destroy_and_reserve_irq(unsigned int irq)
spin_unlock_irqrestore(&vector_lock, flags);
}

static int __reassign_irq_vector(int irq, int cpu)
{
struct irq_cfg *cfg = &irq_cfg[irq];
int vector;
cpumask_t domain;

if (cfg->vector == IRQ_VECTOR_UNASSIGNED || !cpu_online(cpu))
return -EINVAL;
if (cpu_isset(cpu, cfg->domain))
return 0;
domain = vector_allocation_domain(cpu);
vector = find_unassigned_vector(domain);
if (vector < 0)
return -ENOSPC;
__clear_irq_vector(irq);
BUG_ON(__bind_irq_vector(irq, vector, domain));
return 0;
}

int reassign_irq_vector(int irq, int cpu)
{
unsigned long flags;
int ret;

spin_lock_irqsave(&vector_lock, flags);
ret = __reassign_irq_vector(irq, cpu);
spin_unlock_irqrestore(&vector_lock, flags);
return ret;
}

/*
* Dynamic irq allocate and deallocation for MSI
*/
Expand Down Expand Up @@ -578,6 +645,13 @@ init_IRQ (void)
register_percpu_irq(IA64_IPI_VECTOR, &ipi_irqaction);
register_percpu_irq(IA64_IPI_RESCHEDULE, &resched_irqaction);
register_percpu_irq(IA64_IPI_LOCAL_TLB_FLUSH, &tlb_irqaction);
#if defined(CONFIG_IA64_GENERIC) || defined(CONFIG_IA64_DIG)
if (vector_domain_type != VECTOR_DOMAIN_NONE) {
BUG_ON(IA64_FIRST_DEVICE_VECTOR != IA64_IRQ_MOVE_VECTOR);
IA64_FIRST_DEVICE_VECTOR++;
register_percpu_irq(IA64_IRQ_MOVE_VECTOR, &irq_move_irqaction);
}
#endif
#endif
#ifdef CONFIG_PERFMON
pfm_init_percpu();
Expand Down
3 changes: 2 additions & 1 deletion trunk/arch/ia64/kernel/msi_ia64.c
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ static void ia64_set_msi_irq_affinity(unsigned int irq, cpumask_t cpu_mask)
if (!cpu_online(cpu))
return;

if (reassign_irq_vector(irq, cpu))
if (irq_prepare_move(irq, cpu))
return;

read_msi_msg(irq, &msg);
Expand Down Expand Up @@ -119,6 +119,7 @@ void ia64_teardown_msi_irq(unsigned int irq)

static void ia64_ack_msi_irq(unsigned int irq)
{
irq_complete_move(irq);
move_native_irq(irq);
ia64_eoi();
}
Expand Down
12 changes: 11 additions & 1 deletion trunk/include/asm-ia64/hw_irq.h
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,9 @@ extern __u8 isa_irq_to_vector_map[16];
struct irq_cfg {
ia64_vector vector;
cpumask_t domain;
cpumask_t old_domain;
unsigned move_cleanup_count;
u8 move_in_progress : 1;
};
extern spinlock_t vector_lock;
extern struct irq_cfg irq_cfg[NR_IRQS];
Expand All @@ -106,12 +109,19 @@ extern int assign_irq_vector (int irq); /* allocate a free vector */
extern void free_irq_vector (int vector);
extern int reserve_irq_vector (int vector);
extern void __setup_vector_irq(int cpu);
extern int reassign_irq_vector(int irq, int cpu);
extern void ia64_send_ipi (int cpu, int vector, int delivery_mode, int redirect);
extern void register_percpu_irq (ia64_vector vec, struct irqaction *action);
extern int check_irq_used (int irq);
extern void destroy_and_reserve_irq (unsigned int irq);

#if defined(CONFIG_SMP) && (defined(CONFIG_IA64_GENERIC) || defined(CONFIG_IA64_DIG))
extern int irq_prepare_move(int irq, int cpu);
extern void irq_complete_move(unsigned int irq);
#else
static inline int irq_prepare_move(int irq, int cpu) { return 0; }
static inline void irq_complete_move(unsigned int irq) {}
#endif

static inline void ia64_resend_irq(unsigned int vector)
{
platform_send_ipi(smp_processor_id(), vector, IA64_IPI_DM_INT, 0);
Expand Down

0 comments on commit 29a0fbf

Please sign in to comment.