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) |
