aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/iommu/intel_intr_remapping.c54
-rw-r--r--drivers/iommu/intr_remapping.c9
-rw-r--r--drivers/iommu/intr_remapping.h6
3 files changed, 69 insertions, 0 deletions
diff --git a/drivers/iommu/intel_intr_remapping.c b/drivers/iommu/intel_intr_remapping.c
index f495eba4b6ab..25372c1f3c8c 100644
--- a/drivers/iommu/intel_intr_remapping.c
+++ b/drivers/iommu/intel_intr_remapping.c
@@ -901,6 +901,59 @@ static int intel_setup_ioapic_entry(int irq,
901 return 0; 901 return 0;
902} 902}
903 903
904/*
905 * Migrate the IO-APIC irq in the presence of intr-remapping.
906 *
907 * For both level and edge triggered, irq migration is a simple atomic
908 * update(of vector and cpu destination) of IRTE and flush the hardware cache.
909 *
910 * For level triggered, we eliminate the io-apic RTE modification (with the
911 * updated vector information), by using a virtual vector (io-apic pin number).
912 * Real vector that is used for interrupting cpu will be coming from
913 * the interrupt-remapping table entry.
914 *
915 * As the migration is a simple atomic update of IRTE, the same mechanism
916 * is used to migrate MSI irq's in the presence of interrupt-remapping.
917 */
918static int
919intel_ioapic_set_affinity(struct irq_data *data, const struct cpumask *mask,
920 bool force)
921{
922 struct irq_cfg *cfg = data->chip_data;
923 unsigned int dest, irq = data->irq;
924 struct irte irte;
925
926 if (!cpumask_intersects(mask, cpu_online_mask))
927 return -EINVAL;
928
929 if (get_irte(irq, &irte))
930 return -EBUSY;
931
932 if (assign_irq_vector(irq, cfg, mask))
933 return -EBUSY;
934
935 dest = apic->cpu_mask_to_apicid_and(cfg->domain, mask);
936
937 irte.vector = cfg->vector;
938 irte.dest_id = IRTE_DEST(dest);
939
940 /*
941 * Atomically updates the IRTE with the new destination, vector
942 * and flushes the interrupt entry cache.
943 */
944 modify_irte(irq, &irte);
945
946 /*
947 * After this point, all the interrupts will start arriving
948 * at the new destination. So, time to cleanup the previous
949 * vector allocation.
950 */
951 if (cfg->move_in_progress)
952 send_cleanup_vector(cfg);
953
954 cpumask_copy(data->affinity, mask);
955 return 0;
956}
904 957
905struct irq_remap_ops intel_irq_remap_ops = { 958struct irq_remap_ops intel_irq_remap_ops = {
906 .supported = intel_intr_remapping_supported, 959 .supported = intel_intr_remapping_supported,
@@ -910,4 +963,5 @@ struct irq_remap_ops intel_irq_remap_ops = {
910 .hardware_reenable = reenable_intr_remapping, 963 .hardware_reenable = reenable_intr_remapping,
911 .enable_faulting = enable_drhd_fault_handling, 964 .enable_faulting = enable_drhd_fault_handling,
912 .setup_ioapic_entry = intel_setup_ioapic_entry, 965 .setup_ioapic_entry = intel_setup_ioapic_entry,
966 .set_affinity = intel_ioapic_set_affinity,
913}; 967};
diff --git a/drivers/iommu/intr_remapping.c b/drivers/iommu/intr_remapping.c
index 739148ab2538..2f4f27ffb861 100644
--- a/drivers/iommu/intr_remapping.c
+++ b/drivers/iommu/intr_remapping.c
@@ -110,3 +110,12 @@ int intr_setup_ioapic_entry(int irq,
110 return remap_ops->setup_ioapic_entry(irq, entry, destination, 110 return remap_ops->setup_ioapic_entry(irq, entry, destination,
111 vector, attr); 111 vector, attr);
112} 112}
113
114int intr_set_affinity(struct irq_data *data, const struct cpumask *mask,
115 bool force)
116{
117 if (!remap_ops || !remap_ops->set_affinity)
118 return 0;
119
120 return remap_ops->set_affinity(data, mask, force);
121}
diff --git a/drivers/iommu/intr_remapping.h b/drivers/iommu/intr_remapping.h
index e8994f2b3bbe..e0bc6e0ba1fb 100644
--- a/drivers/iommu/intr_remapping.h
+++ b/drivers/iommu/intr_remapping.h
@@ -26,6 +26,8 @@
26 26
27struct IO_APIC_route_entry; 27struct IO_APIC_route_entry;
28struct io_apic_irq_attr; 28struct io_apic_irq_attr;
29struct irq_data;
30struct cpumask;
29 31
30extern int disable_intremap; 32extern int disable_intremap;
31extern int disable_sourceid_checking; 33extern int disable_sourceid_checking;
@@ -54,6 +56,10 @@ struct irq_remap_ops {
54 int (*setup_ioapic_entry)(int irq, struct IO_APIC_route_entry *, 56 int (*setup_ioapic_entry)(int irq, struct IO_APIC_route_entry *,
55 unsigned int, int, 57 unsigned int, int,
56 struct io_apic_irq_attr *); 58 struct io_apic_irq_attr *);
59
60 /* Set the CPU affinity of a remapped interrupt */
61 int (*set_affinity)(struct irq_data *data, const struct cpumask *mask,
62 bool force);
57}; 63};
58 64
59extern struct irq_remap_ops intel_irq_remap_ops; 65extern struct irq_remap_ops intel_irq_remap_ops;