Skip to content

Commit

Permalink
iommu/vt-d: Convert IR set_affinity function to remap_ops
Browse files Browse the repository at this point in the history
The function to set interrupt affinity with interrupt
remapping enabled is Intel specific too. So move it to the
irq_remap_ops too.

Signed-off-by: Joerg Roedel <joerg.roedel@amd.com>
Acked-by: Yinghai Lu <yinghai@kernel.org>
Cc: David Woodhouse <dwmw2@infradead.org>
Cc: Alex Williamson <alex.williamson@redhat.com>
Signed-off-by: Suresh Siddha <suresh.b.siddha@intel.com>
Signed-off-by: Joerg Roedel <joerg.roedel@amd.com>
  • Loading branch information
Joerg Roedel committed May 7, 2012
1 parent 0c3f173 commit 4c1bad6
Show file tree
Hide file tree
Showing 5 changed files with 80 additions and 67 deletions.
9 changes: 9 additions & 0 deletions arch/x86/include/asm/intr_remapping.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,9 @@ extern int intr_setup_ioapic_entry(int irq,
struct IO_APIC_route_entry *entry,
unsigned int destination, int vector,
struct io_apic_irq_attr *attr);
extern int intr_set_affinity(struct irq_data *data,
const struct cpumask *mask,
bool force);

#else /* CONFIG_IRQ_REMAP */

Expand All @@ -59,6 +62,12 @@ static inline int intr_setup_ioapic_entry(int irq,
{
return -ENODEV;
}
static inline int intr_set_affinity(struct irq_data *data,
const struct cpumask *mask,
bool force)
{
return 0;
}
#endif /* CONFIG_IRQ_REMAP */

#endif /* __X86_INTR_REMAPPING_H */
69 changes: 2 additions & 67 deletions arch/x86/kernel/apic/io_apic.c
Original file line number Diff line number Diff line change
Expand Up @@ -2327,71 +2327,6 @@ ioapic_set_affinity(struct irq_data *data, const struct cpumask *mask,
return ret;
}

#ifdef CONFIG_IRQ_REMAP

/*
* Migrate the IO-APIC irq in the presence of intr-remapping.
*
* For both level and edge triggered, irq migration is a simple atomic
* update(of vector and cpu destination) of IRTE and flush the hardware cache.
*
* For level triggered, we eliminate the io-apic RTE modification (with the
* updated vector information), by using a virtual vector (io-apic pin number).
* Real vector that is used for interrupting cpu will be coming from
* the interrupt-remapping table entry.
*
* As the migration is a simple atomic update of IRTE, the same mechanism
* is used to migrate MSI irq's in the presence of interrupt-remapping.
*/
static int
ir_ioapic_set_affinity(struct irq_data *data, const struct cpumask *mask,
bool force)
{
struct irq_cfg *cfg = data->chip_data;
unsigned int dest, irq = data->irq;
struct irte irte;

if (!cpumask_intersects(mask, cpu_online_mask))
return -EINVAL;

if (get_irte(irq, &irte))
return -EBUSY;

if (assign_irq_vector(irq, cfg, mask))
return -EBUSY;

dest = apic->cpu_mask_to_apicid_and(cfg->domain, mask);

irte.vector = cfg->vector;
irte.dest_id = IRTE_DEST(dest);

/*
* Atomically updates the IRTE with the new destination, vector
* and flushes the interrupt entry cache.
*/
modify_irte(irq, &irte);

/*
* After this point, all the interrupts will start arriving
* at the new destination. So, time to cleanup the previous
* vector allocation.
*/
if (cfg->move_in_progress)
send_cleanup_vector(cfg);

cpumask_copy(data->affinity, mask);
return 0;
}

#else
static inline int
ir_ioapic_set_affinity(struct irq_data *data, const struct cpumask *mask,
bool force)
{
return 0;
}
#endif

asmlinkage void smp_irq_move_cleanup_interrupt(void)
{
unsigned vector, me;
Expand Down Expand Up @@ -2636,7 +2571,7 @@ static void irq_remap_modify_chip_defaults(struct irq_chip *chip)
chip->irq_eoi = ir_ack_apic_level;

#ifdef CONFIG_SMP
chip->irq_set_affinity = ir_ioapic_set_affinity;
chip->irq_set_affinity = intr_set_affinity;
#endif
}
#endif /* CONFIG_IRQ_REMAP */
Expand Down Expand Up @@ -3826,7 +3761,7 @@ void __init setup_ioapic_dest(void)
mask = apic->target_cpus();

if (intr_remapping_enabled)
ir_ioapic_set_affinity(idata, mask, false);
intr_set_affinity(idata, mask, false);
else
ioapic_set_affinity(idata, mask, false);
}
Expand Down
54 changes: 54 additions & 0 deletions drivers/iommu/intel_intr_remapping.c
Original file line number Diff line number Diff line change
Expand Up @@ -901,6 +901,59 @@ static int intel_setup_ioapic_entry(int irq,
return 0;
}

/*
* Migrate the IO-APIC irq in the presence of intr-remapping.
*
* For both level and edge triggered, irq migration is a simple atomic
* update(of vector and cpu destination) of IRTE and flush the hardware cache.
*
* For level triggered, we eliminate the io-apic RTE modification (with the
* updated vector information), by using a virtual vector (io-apic pin number).
* Real vector that is used for interrupting cpu will be coming from
* the interrupt-remapping table entry.
*
* As the migration is a simple atomic update of IRTE, the same mechanism
* is used to migrate MSI irq's in the presence of interrupt-remapping.
*/
static int
intel_ioapic_set_affinity(struct irq_data *data, const struct cpumask *mask,
bool force)
{
struct irq_cfg *cfg = data->chip_data;
unsigned int dest, irq = data->irq;
struct irte irte;

if (!cpumask_intersects(mask, cpu_online_mask))
return -EINVAL;

if (get_irte(irq, &irte))
return -EBUSY;

if (assign_irq_vector(irq, cfg, mask))
return -EBUSY;

dest = apic->cpu_mask_to_apicid_and(cfg->domain, mask);

irte.vector = cfg->vector;
irte.dest_id = IRTE_DEST(dest);

/*
* Atomically updates the IRTE with the new destination, vector
* and flushes the interrupt entry cache.
*/
modify_irte(irq, &irte);

/*
* After this point, all the interrupts will start arriving
* at the new destination. So, time to cleanup the previous
* vector allocation.
*/
if (cfg->move_in_progress)
send_cleanup_vector(cfg);

cpumask_copy(data->affinity, mask);
return 0;
}

struct irq_remap_ops intel_irq_remap_ops = {
.supported = intel_intr_remapping_supported,
Expand All @@ -910,4 +963,5 @@ struct irq_remap_ops intel_irq_remap_ops = {
.hardware_reenable = reenable_intr_remapping,
.enable_faulting = enable_drhd_fault_handling,
.setup_ioapic_entry = intel_setup_ioapic_entry,
.set_affinity = intel_ioapic_set_affinity,
};
9 changes: 9 additions & 0 deletions drivers/iommu/intr_remapping.c
Original file line number Diff line number Diff line change
Expand Up @@ -110,3 +110,12 @@ int intr_setup_ioapic_entry(int irq,
return remap_ops->setup_ioapic_entry(irq, entry, destination,
vector, attr);
}

int intr_set_affinity(struct irq_data *data, const struct cpumask *mask,
bool force)
{
if (!remap_ops || !remap_ops->set_affinity)
return 0;

return remap_ops->set_affinity(data, mask, force);
}
6 changes: 6 additions & 0 deletions drivers/iommu/intr_remapping.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@

struct IO_APIC_route_entry;
struct io_apic_irq_attr;
struct irq_data;
struct cpumask;

extern int disable_intremap;
extern int disable_sourceid_checking;
Expand Down Expand Up @@ -54,6 +56,10 @@ struct irq_remap_ops {
int (*setup_ioapic_entry)(int irq, struct IO_APIC_route_entry *,
unsigned int, int,
struct io_apic_irq_attr *);

/* Set the CPU affinity of a remapped interrupt */
int (*set_affinity)(struct irq_data *data, const struct cpumask *mask,
bool force);
};

extern struct irq_remap_ops intel_irq_remap_ops;
Expand Down

0 comments on commit 4c1bad6

Please sign in to comment.