diff options
author | Joerg Roedel <joro@8bytes.org> | 2012-09-26 06:44:49 -0400 |
---|---|---|
committer | Joerg Roedel <joro@8bytes.org> | 2013-01-28 06:42:48 -0500 |
commit | 7601384f91be1a5ea60cb4ef6e28cad628e6cd1e (patch) | |
tree | c5dd95d5edb2d89aad2f7df7f70f6897c44beec8 | |
parent | 2976fd8417f5744de3bb9109e4f30f353a36b1c0 (diff) |
x86, msi: Introduce x86_msi.compose_msi_msg call-back
This call-back points to the right function for initializing
the msi_msg structure. The old code for msi_msg generation
was split up into the irq-remapped and the default case.
The irq-remapped case just calls into the specific Intel or
AMD implementation when the device is behind an IOMMU.
Otherwise the default function is called.
Signed-off-by: Joerg Roedel <joro@8bytes.org>
Acked-by: Sebastian Andrzej Siewior <sebastian@breakpoint.cc>
Reviewed-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
-rw-r--r-- | arch/x86/include/asm/io_apic.h | 4 | ||||
-rw-r--r-- | arch/x86/include/asm/x86_init.h | 4 | ||||
-rw-r--r-- | arch/x86/kernel/apic/io_apic.c | 57 | ||||
-rw-r--r-- | arch/x86/kernel/x86_init.c | 1 | ||||
-rw-r--r-- | drivers/iommu/irq_remapping.c | 9 |
5 files changed, 45 insertions, 30 deletions
diff --git a/arch/x86/include/asm/io_apic.h b/arch/x86/include/asm/io_apic.h index 36fb5abd3725..1838e884a5cc 100644 --- a/arch/x86/include/asm/io_apic.h +++ b/arch/x86/include/asm/io_apic.h | |||
@@ -158,6 +158,9 @@ extern int native_setup_ioapic_entry(int, struct IO_APIC_route_entry *, | |||
158 | struct io_apic_irq_attr *); | 158 | struct io_apic_irq_attr *); |
159 | extern void eoi_ioapic_irq(unsigned int irq, struct irq_cfg *cfg); | 159 | extern void eoi_ioapic_irq(unsigned int irq, struct irq_cfg *cfg); |
160 | 160 | ||
161 | extern void native_compose_msi_msg(struct pci_dev *pdev, | ||
162 | unsigned int irq, unsigned int dest, | ||
163 | struct msi_msg *msg, u8 hpet_id); | ||
161 | int io_apic_setup_irq_pin_once(unsigned int irq, int node, struct io_apic_irq_attr *attr); | 164 | int io_apic_setup_irq_pin_once(unsigned int irq, int node, struct io_apic_irq_attr *attr); |
162 | 165 | ||
163 | extern int save_ioapic_entries(void); | 166 | extern int save_ioapic_entries(void); |
@@ -242,6 +245,7 @@ static inline void disable_ioapic_support(void) { } | |||
242 | #define native_io_apic_print_entries NULL | 245 | #define native_io_apic_print_entries NULL |
243 | #define native_ioapic_set_affinity NULL | 246 | #define native_ioapic_set_affinity NULL |
244 | #define native_setup_ioapic_entry NULL | 247 | #define native_setup_ioapic_entry NULL |
248 | #define native_compose_msi_msg NULL | ||
245 | #endif | 249 | #endif |
246 | 250 | ||
247 | #endif /* _ASM_X86_IO_APIC_H */ | 251 | #endif /* _ASM_X86_IO_APIC_H */ |
diff --git a/arch/x86/include/asm/x86_init.h b/arch/x86/include/asm/x86_init.h index 17da29cf1a47..c9f87be84b0f 100644 --- a/arch/x86/include/asm/x86_init.h +++ b/arch/x86/include/asm/x86_init.h | |||
@@ -181,9 +181,13 @@ struct x86_platform_ops { | |||
181 | }; | 181 | }; |
182 | 182 | ||
183 | struct pci_dev; | 183 | struct pci_dev; |
184 | struct msi_msg; | ||
184 | 185 | ||
185 | struct x86_msi_ops { | 186 | struct x86_msi_ops { |
186 | int (*setup_msi_irqs)(struct pci_dev *dev, int nvec, int type); | 187 | int (*setup_msi_irqs)(struct pci_dev *dev, int nvec, int type); |
188 | void (*compose_msi_msg)(struct pci_dev *dev, unsigned int irq, | ||
189 | unsigned int dest, struct msi_msg *msg, | ||
190 | u8 hpet_id); | ||
187 | void (*teardown_msi_irq)(unsigned int irq); | 191 | void (*teardown_msi_irq)(unsigned int irq); |
188 | void (*teardown_msi_irqs)(struct pci_dev *dev); | 192 | void (*teardown_msi_irqs)(struct pci_dev *dev); |
189 | void (*restore_msi_irqs)(struct pci_dev *dev, int irq); | 193 | void (*restore_msi_irqs)(struct pci_dev *dev, int irq); |
diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c index 372512219a9b..b832810d28f0 100644 --- a/arch/x86/kernel/apic/io_apic.c +++ b/arch/x86/kernel/apic/io_apic.c | |||
@@ -3019,37 +3019,16 @@ void destroy_irqs(unsigned int irq, unsigned int count) | |||
3019 | /* | 3019 | /* |
3020 | * MSI message composition | 3020 | * MSI message composition |
3021 | */ | 3021 | */ |
3022 | #ifdef CONFIG_PCI_MSI | 3022 | void native_compose_msi_msg(struct pci_dev *pdev, |
3023 | static int msi_compose_msg(struct pci_dev *pdev, unsigned int irq, | 3023 | unsigned int irq, unsigned int dest, |
3024 | struct msi_msg *msg, u8 hpet_id) | 3024 | struct msi_msg *msg, u8 hpet_id) |
3025 | { | 3025 | { |
3026 | struct irq_cfg *cfg; | 3026 | struct irq_cfg *cfg = irq_cfg(irq); |
3027 | int err; | ||
3028 | unsigned dest; | ||
3029 | 3027 | ||
3030 | if (disable_apic) | 3028 | msg->address_hi = MSI_ADDR_BASE_HI; |
3031 | return -ENXIO; | ||
3032 | |||
3033 | cfg = irq_cfg(irq); | ||
3034 | err = assign_irq_vector(irq, cfg, apic->target_cpus()); | ||
3035 | if (err) | ||
3036 | return err; | ||
3037 | |||
3038 | err = apic->cpu_mask_to_apicid_and(cfg->domain, | ||
3039 | apic->target_cpus(), &dest); | ||
3040 | if (err) | ||
3041 | return err; | ||
3042 | |||
3043 | if (irq_remapped(cfg)) { | ||
3044 | compose_remapped_msi_msg(pdev, irq, dest, msg, hpet_id); | ||
3045 | return 0; | ||
3046 | } | ||
3047 | 3029 | ||
3048 | if (x2apic_enabled()) | 3030 | if (x2apic_enabled()) |
3049 | msg->address_hi = MSI_ADDR_BASE_HI | | 3031 | msg->address_hi |= MSI_ADDR_EXT_DEST_ID(dest); |
3050 | MSI_ADDR_EXT_DEST_ID(dest); | ||
3051 | else | ||
3052 | msg->address_hi = MSI_ADDR_BASE_HI; | ||
3053 | 3032 | ||
3054 | msg->address_lo = | 3033 | msg->address_lo = |
3055 | MSI_ADDR_BASE_LO | | 3034 | MSI_ADDR_BASE_LO | |
@@ -3068,6 +3047,30 @@ static int msi_compose_msg(struct pci_dev *pdev, unsigned int irq, | |||
3068 | MSI_DATA_DELIVERY_FIXED: | 3047 | MSI_DATA_DELIVERY_FIXED: |
3069 | MSI_DATA_DELIVERY_LOWPRI) | | 3048 | MSI_DATA_DELIVERY_LOWPRI) | |
3070 | MSI_DATA_VECTOR(cfg->vector); | 3049 | MSI_DATA_VECTOR(cfg->vector); |
3050 | } | ||
3051 | |||
3052 | #ifdef CONFIG_PCI_MSI | ||
3053 | static int msi_compose_msg(struct pci_dev *pdev, unsigned int irq, | ||
3054 | struct msi_msg *msg, u8 hpet_id) | ||
3055 | { | ||
3056 | struct irq_cfg *cfg; | ||
3057 | int err; | ||
3058 | unsigned dest; | ||
3059 | |||
3060 | if (disable_apic) | ||
3061 | return -ENXIO; | ||
3062 | |||
3063 | cfg = irq_cfg(irq); | ||
3064 | err = assign_irq_vector(irq, cfg, apic->target_cpus()); | ||
3065 | if (err) | ||
3066 | return err; | ||
3067 | |||
3068 | err = apic->cpu_mask_to_apicid_and(cfg->domain, | ||
3069 | apic->target_cpus(), &dest); | ||
3070 | if (err) | ||
3071 | return err; | ||
3072 | |||
3073 | x86_msi.compose_msi_msg(pdev, irq, dest, msg, hpet_id); | ||
3071 | 3074 | ||
3072 | return 0; | 3075 | return 0; |
3073 | } | 3076 | } |
diff --git a/arch/x86/kernel/x86_init.c b/arch/x86/kernel/x86_init.c index 06db44f4fbf5..ee4a17c22569 100644 --- a/arch/x86/kernel/x86_init.c +++ b/arch/x86/kernel/x86_init.c | |||
@@ -113,6 +113,7 @@ struct x86_platform_ops x86_platform = { | |||
113 | EXPORT_SYMBOL_GPL(x86_platform); | 113 | EXPORT_SYMBOL_GPL(x86_platform); |
114 | struct x86_msi_ops x86_msi = { | 114 | struct x86_msi_ops x86_msi = { |
115 | .setup_msi_irqs = native_setup_msi_irqs, | 115 | .setup_msi_irqs = native_setup_msi_irqs, |
116 | .compose_msi_msg = native_compose_msi_msg, | ||
116 | .teardown_msi_irq = native_teardown_msi_irq, | 117 | .teardown_msi_irq = native_teardown_msi_irq, |
117 | .teardown_msi_irqs = default_teardown_msi_irqs, | 118 | .teardown_msi_irqs = default_teardown_msi_irqs, |
118 | .restore_msi_irqs = default_restore_msi_irqs, | 119 | .restore_msi_irqs = default_restore_msi_irqs, |
diff --git a/drivers/iommu/irq_remapping.c b/drivers/iommu/irq_remapping.c index 339260c98cf9..158091b345cb 100644 --- a/drivers/iommu/irq_remapping.c +++ b/drivers/iommu/irq_remapping.c | |||
@@ -150,6 +150,7 @@ static void __init irq_remapping_modify_x86_ops(void) | |||
150 | x86_io_apic_ops.setup_entry = setup_ioapic_remapped_entry; | 150 | x86_io_apic_ops.setup_entry = setup_ioapic_remapped_entry; |
151 | x86_msi.setup_msi_irqs = irq_remapping_setup_msi_irqs; | 151 | x86_msi.setup_msi_irqs = irq_remapping_setup_msi_irqs; |
152 | x86_msi.setup_hpet_msi = setup_hpet_msi_remapped; | 152 | x86_msi.setup_hpet_msi = setup_hpet_msi_remapped; |
153 | x86_msi.compose_msi_msg = compose_remapped_msi_msg; | ||
153 | } | 154 | } |
154 | 155 | ||
155 | static __init int setup_nointremap(char *str) | 156 | static __init int setup_nointremap(char *str) |
@@ -295,10 +296,12 @@ void compose_remapped_msi_msg(struct pci_dev *pdev, | |||
295 | unsigned int irq, unsigned int dest, | 296 | unsigned int irq, unsigned int dest, |
296 | struct msi_msg *msg, u8 hpet_id) | 297 | struct msi_msg *msg, u8 hpet_id) |
297 | { | 298 | { |
298 | if (!remap_ops || !remap_ops->compose_msi_msg) | 299 | struct irq_cfg *cfg = irq_get_chip_data(irq); |
299 | return; | ||
300 | 300 | ||
301 | remap_ops->compose_msi_msg(pdev, irq, dest, msg, hpet_id); | 301 | if (!irq_remapped(cfg)) |
302 | native_compose_msi_msg(pdev, irq, dest, msg, hpet_id); | ||
303 | else if (remap_ops && remap_ops->compose_msi_msg) | ||
304 | remap_ops->compose_msi_msg(pdev, irq, dest, msg, hpet_id); | ||
302 | } | 305 | } |
303 | 306 | ||
304 | static int msi_alloc_remapped_irq(struct pci_dev *pdev, int irq, int nvec) | 307 | static int msi_alloc_remapped_irq(struct pci_dev *pdev, int irq, int nvec) |