aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2016-01-31 19:17:19 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2016-01-31 19:17:19 -0500
commitd517be5fcf1a7feb06ce3d5f28055ad1ce17030b (patch)
treeaa3974eaaa147425aa4cb96c865dc2683eaa3d3a
parentdc799d0179baa7f62d2e73a8217a273ca82adbdf (diff)
parent742563777e8da62197d6cb4b99f4027f59454735 (diff)
Merge branch 'x86-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull x86 fixes from Thomas Gleixner: "A bit on the largish side due to a series of fixes for a regression in the x86 vector management which was introduced in 4.3. This work was started in December already, but it took some time to fix all corner cases and a couple of older bugs in that area which were detected while at it Aside of that a few platform updates for intel-mid, quark and UV and two fixes for in the mm code: - Use proper types for pgprot values to avoid truncation - Prevent a size truncation in the pageattr code when setting page attributes for large mappings" * 'x86-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: (21 commits) x86/mm/pat: Avoid truncation when converting cpa->numpages to address x86/mm: Fix types used in pgprot cacheability flags translations x86/platform/quark: Print boundaries correctly x86/platform/UV: Remove EFI memmap quirk for UV2+ x86/platform/intel-mid: Join string and fix SoC name x86/platform/intel-mid: Enable 64-bit build x86/irq: Plug vector cleanup race x86/irq: Call irq_force_move_complete with irq descriptor x86/irq: Remove outgoing CPU from vector cleanup mask x86/irq: Remove the cpumask allocation from send_cleanup_vector() x86/irq: Clear move_in_progress before sending cleanup IPI x86/irq: Remove offline cpus from vector cleanup x86/irq: Get rid of code duplication x86/irq: Copy vectormask instead of an AND operation x86/irq: Check vector allocation early x86/irq: Reorganize the search in assign_irq_vector x86/irq: Reorganize the return path in assign_irq_vector x86/irq: Do not use apic_chip_data.old_domain as temporary buffer x86/irq: Validate that irq descriptor is still active x86/irq: Fix a race in x86_vector_free_irqs() ...
-rw-r--r--arch/x86/Kconfig3
-rw-r--r--arch/x86/include/asm/irq.h5
-rw-r--r--arch/x86/include/asm/pgtable_types.h6
-rw-r--r--arch/x86/kernel/apic/io_apic.c6
-rw-r--r--arch/x86/kernel/apic/vector.c221
-rw-r--r--arch/x86/kernel/apic/x2apic_uv_x.c5
-rw-r--r--arch/x86/kernel/head64.c8
-rw-r--r--arch/x86/kernel/irq.c11
-rw-r--r--arch/x86/mm/pageattr.c4
-rw-r--r--arch/x86/platform/efi/quirks.c17
-rw-r--r--arch/x86/platform/intel-mid/intel-mid.c8
-rw-r--r--arch/x86/platform/intel-quark/imr.c18
12 files changed, 209 insertions, 103 deletions
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index 330e738ccfc1..9af2e6338400 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -509,11 +509,10 @@ config X86_INTEL_CE
509 509
510config X86_INTEL_MID 510config X86_INTEL_MID
511 bool "Intel MID platform support" 511 bool "Intel MID platform support"
512 depends on X86_32
513 depends on X86_EXTENDED_PLATFORM 512 depends on X86_EXTENDED_PLATFORM
514 depends on X86_PLATFORM_DEVICES 513 depends on X86_PLATFORM_DEVICES
515 depends on PCI 514 depends on PCI
516 depends on PCI_GOANY 515 depends on X86_64 || (PCI_GOANY && X86_32)
517 depends on X86_IO_APIC 516 depends on X86_IO_APIC
518 select SFI 517 select SFI
519 select I2C 518 select I2C
diff --git a/arch/x86/include/asm/irq.h b/arch/x86/include/asm/irq.h
index 881b4768644a..e7de5c9a4fbd 100644
--- a/arch/x86/include/asm/irq.h
+++ b/arch/x86/include/asm/irq.h
@@ -23,11 +23,13 @@ extern void irq_ctx_init(int cpu);
23 23
24#define __ARCH_HAS_DO_SOFTIRQ 24#define __ARCH_HAS_DO_SOFTIRQ
25 25
26struct irq_desc;
27
26#ifdef CONFIG_HOTPLUG_CPU 28#ifdef CONFIG_HOTPLUG_CPU
27#include <linux/cpumask.h> 29#include <linux/cpumask.h>
28extern int check_irq_vectors_for_cpu_disable(void); 30extern int check_irq_vectors_for_cpu_disable(void);
29extern void fixup_irqs(void); 31extern void fixup_irqs(void);
30extern void irq_force_complete_move(int); 32extern void irq_force_complete_move(struct irq_desc *desc);
31#endif 33#endif
32 34
33#ifdef CONFIG_HAVE_KVM 35#ifdef CONFIG_HAVE_KVM
@@ -37,7 +39,6 @@ extern void kvm_set_posted_intr_wakeup_handler(void (*handler)(void));
37extern void (*x86_platform_ipi_callback)(void); 39extern void (*x86_platform_ipi_callback)(void);
38extern void native_init_IRQ(void); 40extern void native_init_IRQ(void);
39 41
40struct irq_desc;
41extern bool handle_irq(struct irq_desc *desc, struct pt_regs *regs); 42extern bool handle_irq(struct irq_desc *desc, struct pt_regs *regs);
42 43
43extern __visible unsigned int do_IRQ(struct pt_regs *regs); 44extern __visible unsigned int do_IRQ(struct pt_regs *regs);
diff --git a/arch/x86/include/asm/pgtable_types.h b/arch/x86/include/asm/pgtable_types.h
index 04c27a013165..4432ab7f407c 100644
--- a/arch/x86/include/asm/pgtable_types.h
+++ b/arch/x86/include/asm/pgtable_types.h
@@ -366,20 +366,18 @@ static inline enum page_cache_mode pgprot2cachemode(pgprot_t pgprot)
366} 366}
367static inline pgprot_t pgprot_4k_2_large(pgprot_t pgprot) 367static inline pgprot_t pgprot_4k_2_large(pgprot_t pgprot)
368{ 368{
369 pgprotval_t val = pgprot_val(pgprot);
369 pgprot_t new; 370 pgprot_t new;
370 unsigned long val;
371 371
372 val = pgprot_val(pgprot);
373 pgprot_val(new) = (val & ~(_PAGE_PAT | _PAGE_PAT_LARGE)) | 372 pgprot_val(new) = (val & ~(_PAGE_PAT | _PAGE_PAT_LARGE)) |
374 ((val & _PAGE_PAT) << (_PAGE_BIT_PAT_LARGE - _PAGE_BIT_PAT)); 373 ((val & _PAGE_PAT) << (_PAGE_BIT_PAT_LARGE - _PAGE_BIT_PAT));
375 return new; 374 return new;
376} 375}
377static inline pgprot_t pgprot_large_2_4k(pgprot_t pgprot) 376static inline pgprot_t pgprot_large_2_4k(pgprot_t pgprot)
378{ 377{
378 pgprotval_t val = pgprot_val(pgprot);
379 pgprot_t new; 379 pgprot_t new;
380 unsigned long val;
381 380
382 val = pgprot_val(pgprot);
383 pgprot_val(new) = (val & ~(_PAGE_PAT | _PAGE_PAT_LARGE)) | 381 pgprot_val(new) = (val & ~(_PAGE_PAT | _PAGE_PAT_LARGE)) |
384 ((val & _PAGE_PAT_LARGE) >> 382 ((val & _PAGE_PAT_LARGE) >>
385 (_PAGE_BIT_PAT_LARGE - _PAGE_BIT_PAT)); 383 (_PAGE_BIT_PAT_LARGE - _PAGE_BIT_PAT));
diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c
index f25321894ad2..fdb0fbfb1197 100644
--- a/arch/x86/kernel/apic/io_apic.c
+++ b/arch/x86/kernel/apic/io_apic.c
@@ -2521,6 +2521,7 @@ void __init setup_ioapic_dest(void)
2521{ 2521{
2522 int pin, ioapic, irq, irq_entry; 2522 int pin, ioapic, irq, irq_entry;
2523 const struct cpumask *mask; 2523 const struct cpumask *mask;
2524 struct irq_desc *desc;
2524 struct irq_data *idata; 2525 struct irq_data *idata;
2525 struct irq_chip *chip; 2526 struct irq_chip *chip;
2526 2527
@@ -2536,7 +2537,9 @@ void __init setup_ioapic_dest(void)
2536 if (irq < 0 || !mp_init_irq_at_boot(ioapic, irq)) 2537 if (irq < 0 || !mp_init_irq_at_boot(ioapic, irq))
2537 continue; 2538 continue;
2538 2539
2539 idata = irq_get_irq_data(irq); 2540 desc = irq_to_desc(irq);
2541 raw_spin_lock_irq(&desc->lock);
2542 idata = irq_desc_get_irq_data(desc);
2540 2543
2541 /* 2544 /*
2542 * Honour affinities which have been set in early boot 2545 * Honour affinities which have been set in early boot
@@ -2550,6 +2553,7 @@ void __init setup_ioapic_dest(void)
2550 /* Might be lapic_chip for irq 0 */ 2553 /* Might be lapic_chip for irq 0 */
2551 if (chip->irq_set_affinity) 2554 if (chip->irq_set_affinity)
2552 chip->irq_set_affinity(idata, mask, false); 2555 chip->irq_set_affinity(idata, mask, false);
2556 raw_spin_unlock_irq(&desc->lock);
2553 } 2557 }
2554} 2558}
2555#endif 2559#endif
diff --git a/arch/x86/kernel/apic/vector.c b/arch/x86/kernel/apic/vector.c
index 908cb37da171..3b670df4ba7b 100644
--- a/arch/x86/kernel/apic/vector.c
+++ b/arch/x86/kernel/apic/vector.c
@@ -31,7 +31,7 @@ struct apic_chip_data {
31struct irq_domain *x86_vector_domain; 31struct irq_domain *x86_vector_domain;
32EXPORT_SYMBOL_GPL(x86_vector_domain); 32EXPORT_SYMBOL_GPL(x86_vector_domain);
33static DEFINE_RAW_SPINLOCK(vector_lock); 33static DEFINE_RAW_SPINLOCK(vector_lock);
34static cpumask_var_t vector_cpumask; 34static cpumask_var_t vector_cpumask, vector_searchmask, searched_cpumask;
35static struct irq_chip lapic_controller; 35static struct irq_chip lapic_controller;
36#ifdef CONFIG_X86_IO_APIC 36#ifdef CONFIG_X86_IO_APIC
37static struct apic_chip_data *legacy_irq_data[NR_IRQS_LEGACY]; 37static struct apic_chip_data *legacy_irq_data[NR_IRQS_LEGACY];
@@ -118,35 +118,47 @@ static int __assign_irq_vector(int irq, struct apic_chip_data *d,
118 */ 118 */
119 static int current_vector = FIRST_EXTERNAL_VECTOR + VECTOR_OFFSET_START; 119 static int current_vector = FIRST_EXTERNAL_VECTOR + VECTOR_OFFSET_START;
120 static int current_offset = VECTOR_OFFSET_START % 16; 120 static int current_offset = VECTOR_OFFSET_START % 16;
121 int cpu, err; 121 int cpu, vector;
122 122
123 if (d->move_in_progress) 123 /*
124 * If there is still a move in progress or the previous move has not
125 * been cleaned up completely, tell the caller to come back later.
126 */
127 if (d->move_in_progress ||
128 cpumask_intersects(d->old_domain, cpu_online_mask))
124 return -EBUSY; 129 return -EBUSY;
125 130
126 /* Only try and allocate irqs on cpus that are present */ 131 /* Only try and allocate irqs on cpus that are present */
127 err = -ENOSPC;
128 cpumask_clear(d->old_domain); 132 cpumask_clear(d->old_domain);
133 cpumask_clear(searched_cpumask);
129 cpu = cpumask_first_and(mask, cpu_online_mask); 134 cpu = cpumask_first_and(mask, cpu_online_mask);
130 while (cpu < nr_cpu_ids) { 135 while (cpu < nr_cpu_ids) {
131 int new_cpu, vector, offset; 136 int new_cpu, offset;
132 137
138 /* Get the possible target cpus for @mask/@cpu from the apic */
133 apic->vector_allocation_domain(cpu, vector_cpumask, mask); 139 apic->vector_allocation_domain(cpu, vector_cpumask, mask);
134 140
141 /*
142 * Clear the offline cpus from @vector_cpumask for searching
143 * and verify whether the result overlaps with @mask. If true,
144 * then the call to apic->cpu_mask_to_apicid_and() will
145 * succeed as well. If not, no point in trying to find a
146 * vector in this mask.
147 */
148 cpumask_and(vector_searchmask, vector_cpumask, cpu_online_mask);
149 if (!cpumask_intersects(vector_searchmask, mask))
150 goto next_cpu;
151
135 if (cpumask_subset(vector_cpumask, d->domain)) { 152 if (cpumask_subset(vector_cpumask, d->domain)) {