diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/iommu/intel_intr_remapping.c | 54 | ||||
-rw-r--r-- | drivers/iommu/intr_remapping.c | 9 | ||||
-rw-r--r-- | drivers/iommu/intr_remapping.h | 6 |
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 | */ | ||
918 | static int | ||
919 | intel_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 | ||
905 | struct irq_remap_ops intel_irq_remap_ops = { | 958 | struct 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 | |||
114 | int 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 | ||
27 | struct IO_APIC_route_entry; | 27 | struct IO_APIC_route_entry; |
28 | struct io_apic_irq_attr; | 28 | struct io_apic_irq_attr; |
29 | struct irq_data; | ||
30 | struct cpumask; | ||
29 | 31 | ||
30 | extern int disable_intremap; | 32 | extern int disable_intremap; |
31 | extern int disable_sourceid_checking; | 33 | extern 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 | ||
59 | extern struct irq_remap_ops intel_irq_remap_ops; | 65 | extern struct irq_remap_ops intel_irq_remap_ops; |