diff options
author | Joerg Roedel <joro@8bytes.org> | 2012-09-26 06:44:38 -0400 |
---|---|---|
committer | Joerg Roedel <joro@8bytes.org> | 2013-01-28 06:17:25 -0500 |
commit | 5afba62cc8a16716508605e02c1b02ee5f969184 (patch) | |
tree | ea92242734bb94960f215a352b1774938f578cc3 /arch | |
parent | 71054d8841b442bb3d8be60bde2bfac0483c19da (diff) |
x86, msi: Use IRQ remapping specific setup_msi_irqs routine
Use seperate routines to setup MSI IRQs for both
irq_remapping_enabled cases.
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>
Diffstat (limited to 'arch')
-rw-r--r-- | arch/x86/include/asm/irq_remapping.h | 12 | ||||
-rw-r--r-- | arch/x86/include/asm/pci.h | 3 | ||||
-rw-r--r-- | arch/x86/kernel/apic/io_apic.c | 104 |
3 files changed, 13 insertions, 106 deletions
diff --git a/arch/x86/include/asm/irq_remapping.h b/arch/x86/include/asm/irq_remapping.h index 5fb9bbbd2f14..0ee1e88bd17a 100644 --- a/arch/x86/include/asm/irq_remapping.h +++ b/arch/x86/include/asm/irq_remapping.h | |||
@@ -47,9 +47,6 @@ extern void free_remapped_irq(int irq); | |||
47 | extern void compose_remapped_msi_msg(struct pci_dev *pdev, | 47 | extern void compose_remapped_msi_msg(struct pci_dev *pdev, |
48 | unsigned int irq, unsigned int dest, | 48 | unsigned int irq, unsigned int dest, |
49 | struct msi_msg *msg, u8 hpet_id); | 49 | struct msi_msg *msg, u8 hpet_id); |
50 | extern int msi_alloc_remapped_irq(struct pci_dev *pdev, int irq, int nvec); | ||
51 | extern int msi_setup_remapped_irq(struct pci_dev *pdev, unsigned int irq, | ||
52 | int index, int sub_handle); | ||
53 | extern int setup_hpet_msi_remapped(unsigned int irq, unsigned int id); | 50 | extern int setup_hpet_msi_remapped(unsigned int irq, unsigned int id); |
54 | 51 | ||
55 | #else /* CONFIG_IRQ_REMAP */ | 52 | #else /* CONFIG_IRQ_REMAP */ |
@@ -83,15 +80,6 @@ static inline void compose_remapped_msi_msg(struct pci_dev *pdev, | |||
83 | struct msi_msg *msg, u8 hpet_id) | 80 | struct msi_msg *msg, u8 hpet_id) |
84 | { | 81 | { |
85 | } | 82 | } |
86 | static inline int msi_alloc_remapped_irq(struct pci_dev *pdev, int irq, int nvec) | ||
87 | { | ||
88 | return -ENODEV; | ||
89 | } | ||
90 | static inline int msi_setup_remapped_irq(struct pci_dev *pdev, unsigned int irq, | ||
91 | int index, int sub_handle) | ||
92 | { | ||
93 | return -ENODEV; | ||
94 | } | ||
95 | static inline int setup_hpet_msi_remapped(unsigned int irq, unsigned int id) | 83 | static inline int setup_hpet_msi_remapped(unsigned int irq, unsigned int id) |
96 | { | 84 | { |
97 | return -ENODEV; | 85 | return -ENODEV; |
diff --git a/arch/x86/include/asm/pci.h b/arch/x86/include/asm/pci.h index dba7805176bf..c28fd02f4bf7 100644 --- a/arch/x86/include/asm/pci.h +++ b/arch/x86/include/asm/pci.h | |||
@@ -121,9 +121,12 @@ static inline void x86_restore_msi_irqs(struct pci_dev *dev, int irq) | |||
121 | #define arch_teardown_msi_irq x86_teardown_msi_irq | 121 | #define arch_teardown_msi_irq x86_teardown_msi_irq |
122 | #define arch_restore_msi_irqs x86_restore_msi_irqs | 122 | #define arch_restore_msi_irqs x86_restore_msi_irqs |
123 | /* implemented in arch/x86/kernel/apic/io_apic. */ | 123 | /* implemented in arch/x86/kernel/apic/io_apic. */ |
124 | struct msi_desc; | ||
124 | int native_setup_msi_irqs(struct pci_dev *dev, int nvec, int type); | 125 | int native_setup_msi_irqs(struct pci_dev *dev, int nvec, int type); |
125 | void native_teardown_msi_irq(unsigned int irq); | 126 | void native_teardown_msi_irq(unsigned int irq); |
126 | void native_restore_msi_irqs(struct pci_dev *dev, int irq); | 127 | void native_restore_msi_irqs(struct pci_dev *dev, int irq); |
128 | int setup_msi_irq(struct pci_dev *dev, struct msi_desc *msidesc, | ||
129 | unsigned int irq_base, unsigned int irq_offset); | ||
127 | /* default to the implementation in drivers/lib/msi.c */ | 130 | /* default to the implementation in drivers/lib/msi.c */ |
128 | #define HAVE_DEFAULT_MSI_TEARDOWN_IRQS | 131 | #define HAVE_DEFAULT_MSI_TEARDOWN_IRQS |
129 | #define HAVE_DEFAULT_MSI_RESTORE_IRQS | 132 | #define HAVE_DEFAULT_MSI_RESTORE_IRQS |
diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c index e7b87630c13d..d4b045e018fb 100644 --- a/arch/x86/kernel/apic/io_apic.c +++ b/arch/x86/kernel/apic/io_apic.c | |||
@@ -3066,7 +3066,7 @@ void destroy_irq(unsigned int irq) | |||
3066 | free_irq_at(irq, cfg); | 3066 | free_irq_at(irq, cfg); |
3067 | } | 3067 | } |
3068 | 3068 | ||
3069 | static inline void destroy_irqs(unsigned int irq, unsigned int count) | 3069 | void destroy_irqs(unsigned int irq, unsigned int count) |
3070 | { | 3070 | { |
3071 | unsigned int i; | 3071 | unsigned int i; |
3072 | 3072 | ||
@@ -3165,8 +3165,8 @@ static struct irq_chip msi_chip = { | |||
3165 | .irq_retrigger = ioapic_retrigger_irq, | 3165 | .irq_retrigger = ioapic_retrigger_irq, |
3166 | }; | 3166 | }; |
3167 | 3167 | ||
3168 | static int setup_msi_irq(struct pci_dev *dev, struct msi_desc *msidesc, | 3168 | int setup_msi_irq(struct pci_dev *dev, struct msi_desc *msidesc, |
3169 | unsigned int irq_base, unsigned int irq_offset) | 3169 | unsigned int irq_base, unsigned int irq_offset) |
3170 | { | 3170 | { |
3171 | struct irq_chip *chip = &msi_chip; | 3171 | struct irq_chip *chip = &msi_chip; |
3172 | struct msi_msg msg; | 3172 | struct msi_msg msg; |
@@ -3198,44 +3198,28 @@ static int setup_msi_irq(struct pci_dev *dev, struct msi_desc *msidesc, | |||
3198 | return 0; | 3198 | return 0; |
3199 | } | 3199 | } |
3200 | 3200 | ||
3201 | int setup_msix_irqs(struct pci_dev *dev, int nvec) | 3201 | int native_setup_msi_irqs(struct pci_dev *dev, int nvec, int type) |
3202 | { | 3202 | { |
3203 | int node, ret, sub_handle, index = 0; | ||
3204 | unsigned int irq, irq_want; | 3203 | unsigned int irq, irq_want; |
3205 | struct msi_desc *msidesc; | 3204 | struct msi_desc *msidesc; |
3205 | int node, ret; | ||
3206 | |||
3207 | /* Multiple MSI vectors only supported with interrupt remapping */ | ||
3208 | if (type == PCI_CAP_ID_MSI && nvec > 1) | ||
3209 | return 1; | ||
3206 | 3210 | ||
3207 | node = dev_to_node(&dev->dev); | 3211 | node = dev_to_node(&dev->dev); |
3208 | irq_want = nr_irqs_gsi; | 3212 | irq_want = nr_irqs_gsi; |
3209 | sub_handle = 0; | ||
3210 | list_for_each_entry(msidesc, &dev->msi_list, list) { | 3213 | list_for_each_entry(msidesc, &dev->msi_list, list) { |
3211 | irq = create_irq_nr(irq_want, node); | 3214 | irq = create_irq_nr(irq_want, node); |
3212 | if (irq == 0) | 3215 | if (irq == 0) |
3213 | return -ENOSPC; | 3216 | return -ENOSPC; |
3217 | |||
3214 | irq_want = irq + 1; | 3218 | irq_want = irq + 1; |
3215 | if (!irq_remapping_enabled) | ||
3216 | goto no_ir; | ||
3217 | 3219 | ||
3218 | if (!sub_handle) { | ||
3219 | /* | ||
3220 | * allocate the consecutive block of IRTE's | ||
3221 | * for 'nvec' | ||
3222 | */ | ||
3223 | index = msi_alloc_remapped_irq(dev, irq, nvec); | ||
3224 | if (index < 0) { | ||
3225 | ret = index; | ||
3226 | goto error; | ||
3227 | } | ||
3228 | } else { | ||
3229 | ret = msi_setup_remapped_irq(dev, irq, index, | ||
3230 | sub_handle); | ||
3231 | if (ret < 0) | ||
3232 | goto error; | ||
3233 | } | ||
3234 | no_ir: | ||
3235 | ret = setup_msi_irq(dev, msidesc, irq, 0); | 3220 | ret = setup_msi_irq(dev, msidesc, irq, 0); |
3236 | if (ret < 0) | 3221 | if (ret < 0) |
3237 | goto error; | 3222 | goto error; |
3238 | sub_handle++; | ||
3239 | } | 3223 | } |
3240 | return 0; | 3224 | return 0; |
3241 | 3225 | ||
@@ -3244,74 +3228,6 @@ error: | |||
3244 | return ret; | 3228 | return ret; |
3245 | } | 3229 | } |
3246 | 3230 | ||
3247 | int setup_msi_irqs(struct pci_dev *dev, int nvec) | ||
3248 | { | ||
3249 | int node, ret, sub_handle, index = 0; | ||
3250 | unsigned int irq; | ||
3251 | struct msi_desc *msidesc; | ||
3252 | |||
3253 | if (nvec > 1 && !irq_remapping_enabled) | ||
3254 | return 1; | ||
3255 | |||
3256 | nvec = __roundup_pow_of_two(nvec); | ||
3257 | |||
3258 | WARN_ON(!list_is_singular(&dev->msi_list)); | ||
3259 | msidesc = list_entry(dev->msi_list.next, struct msi_desc, list); | ||
3260 | WARN_ON(msidesc->irq); | ||
3261 | WARN_ON(msidesc->msi_attrib.multiple); | ||
3262 | |||
3263 | node = dev_to_node(&dev->dev); | ||
3264 | irq = __create_irqs(nr_irqs_gsi, nvec, node); | ||
3265 | if (irq == 0) | ||
3266 | return -ENOSPC; | ||
3267 | |||
3268 | if (!irq_remapping_enabled) { | ||
3269 | ret = setup_msi_irq(dev, msidesc, irq, 0); | ||
3270 | if (ret < 0) | ||
3271 | goto error; | ||
3272 | return 0; | ||
3273 | } | ||
3274 | |||
3275 | msidesc->msi_attrib.multiple = ilog2(nvec); | ||
3276 | for (sub_handle = 0; sub_handle < nvec; sub_handle++) { | ||
3277 | if (!sub_handle) { | ||
3278 | index = msi_alloc_remapped_irq(dev, irq, nvec); | ||
3279 | if (index < 0) { | ||
3280 | ret = index; | ||
3281 | goto error; | ||
3282 | } | ||
3283 | } else { | ||
3284 | ret = msi_setup_remapped_irq(dev, irq + sub_handle, | ||
3285 | index, sub_handle); | ||
3286 | if (ret < 0) | ||
3287 | goto error; | ||
3288 | } | ||
3289 | ret = setup_msi_irq(dev, msidesc, irq, sub_handle); | ||
3290 | if (ret < 0) | ||
3291 | goto error; | ||
3292 | } | ||
3293 | return 0; | ||
3294 | |||
3295 | error: | ||
3296 | destroy_irqs(irq, nvec); | ||
3297 | |||
3298 | /* | ||
3299 | * Restore altered MSI descriptor fields and prevent just destroyed | ||
3300 | * IRQs from tearing down again in default_teardown_msi_irqs() | ||
3301 | */ | ||
3302 | msidesc->irq = 0; | ||
3303 | msidesc->msi_attrib.multiple = 0; | ||
3304 | |||
3305 | return ret; | ||
3306 | } | ||
3307 | |||
3308 | int native_setup_msi_irqs(struct pci_dev *dev, int nvec, int type) | ||
3309 | { | ||
3310 | if (type == PCI_CAP_ID_MSI) | ||
3311 | return setup_msi_irqs(dev, nvec); | ||
3312 | return setup_msix_irqs(dev, nvec); | ||
3313 | } | ||
3314 | |||
3315 | void native_teardown_msi_irq(unsigned int irq) | 3231 | void native_teardown_msi_irq(unsigned int irq) |
3316 | { | 3232 | { |
3317 | destroy_irq(irq); | 3233 | destroy_irq(irq); |