diff options
author | 2016-12-05 09:03:15 -0500 | |
---|---|---|
committer | 2016-12-05 09:03:15 -0500 | |
commit | ddef146e89241cb6516bfa9a92b041b91912c20e (patch) | |
tree | e07eb7bd1f639d353b2a815d04918b93042ef85c | |
parent | grsecurity-3.1-4.8.11-201611271225 (diff) | |
download | hardened-patchset-ddef146e89241cb6516bfa9a92b041b91912c20e.tar.gz hardened-patchset-ddef146e89241cb6516bfa9a92b041b91912c20e.tar.bz2 hardened-patchset-ddef146e89241cb6516bfa9a92b041b91912c20e.zip |
grsecurity-3.1-4.8.12-20161203165820161203
-rw-r--r-- | 4.8.11/1008_linux-4.8.9.patch | 3120 | ||||
-rw-r--r-- | 4.8.11/1009_linux-4.8.10.patch | 4759 | ||||
-rw-r--r-- | 4.8.12/0000_README (renamed from 4.8.11/0000_README) | 14 | ||||
-rw-r--r-- | 4.8.12/1010_linux-4.8.11.patch (renamed from 4.8.11/1010_linux-4.8.11.patch) | 0 | ||||
-rw-r--r-- | 4.8.12/1011_linux-4.8.12.patch | 1563 | ||||
-rw-r--r-- | 4.8.12/4420_grsecurity-3.1-4.8.12-201612031658.patch (renamed from 4.8.11/4420_grsecurity-3.1-4.8.11-201611271225.patch) | 83 | ||||
-rw-r--r-- | 4.8.12/4425_grsec_remove_EI_PAX.patch (renamed from 4.8.11/4425_grsec_remove_EI_PAX.patch) | 0 | ||||
-rw-r--r-- | 4.8.12/4427_force_XATTR_PAX_tmpfs.patch (renamed from 4.8.11/4427_force_XATTR_PAX_tmpfs.patch) | 0 | ||||
-rw-r--r-- | 4.8.12/4430_grsec-remove-localversion-grsec.patch (renamed from 4.8.11/4430_grsec-remove-localversion-grsec.patch) | 0 | ||||
-rw-r--r-- | 4.8.12/4435_grsec-mute-warnings.patch (renamed from 4.8.11/4435_grsec-mute-warnings.patch) | 0 | ||||
-rw-r--r-- | 4.8.12/4440_grsec-remove-protected-paths.patch (renamed from 4.8.11/4440_grsec-remove-protected-paths.patch) | 0 | ||||
-rw-r--r-- | 4.8.12/4450_grsec-kconfig-default-gids.patch (renamed from 4.8.11/4450_grsec-kconfig-default-gids.patch) | 0 | ||||
-rw-r--r-- | 4.8.12/4465_selinux-avc_audit-log-curr_ip.patch (renamed from 4.8.11/4465_selinux-avc_audit-log-curr_ip.patch) | 0 | ||||
-rw-r--r-- | 4.8.12/4470_disable-compat_vdso.patch (renamed from 4.8.11/4470_disable-compat_vdso.patch) | 0 | ||||
-rw-r--r-- | 4.8.12/4475_emutramp_default_on.patch (renamed from 4.8.11/4475_emutramp_default_on.patch) | 0 |
15 files changed, 1594 insertions, 7945 deletions
diff --git a/4.8.11/1008_linux-4.8.9.patch b/4.8.11/1008_linux-4.8.9.patch deleted file mode 100644 index 2f909eb..0000000 --- a/4.8.11/1008_linux-4.8.9.patch +++ /dev/null @@ -1,3120 +0,0 @@ -diff --git a/Makefile b/Makefile -index 8f18daa..c1519ab 100644 ---- a/Makefile -+++ b/Makefile -@@ -1,6 +1,6 @@ - VERSION = 4 - PATCHLEVEL = 8 --SUBLEVEL = 8 -+SUBLEVEL = 9 - EXTRAVERSION = - NAME = Psychotic Stoned Sheep - -diff --git a/arch/arc/kernel/time.c b/arch/arc/kernel/time.c -index f927b8d..c10390d 100644 ---- a/arch/arc/kernel/time.c -+++ b/arch/arc/kernel/time.c -@@ -152,14 +152,17 @@ static cycle_t arc_read_rtc(struct clocksource *cs) - cycle_t full; - } stamp; - -- -- __asm__ __volatile( -- "1: \n" -- " lr %0, [AUX_RTC_LOW] \n" -- " lr %1, [AUX_RTC_HIGH] \n" -- " lr %2, [AUX_RTC_CTRL] \n" -- " bbit0.nt %2, 31, 1b \n" -- : "=r" (stamp.low), "=r" (stamp.high), "=r" (status)); -+ /* -+ * hardware has an internal state machine which tracks readout of -+ * low/high and updates the CTRL.status if -+ * - interrupt/exception taken between the two reads -+ * - high increments after low has been read -+ */ -+ do { -+ stamp.low = read_aux_reg(AUX_RTC_LOW); -+ stamp.high = read_aux_reg(AUX_RTC_HIGH); -+ status = read_aux_reg(AUX_RTC_CTRL); -+ } while (!(status & _BITUL(31))); - - return stamp.full; - } -diff --git a/arch/arc/mm/dma.c b/arch/arc/mm/dma.c -index 20afc65..9288851 100644 ---- a/arch/arc/mm/dma.c -+++ b/arch/arc/mm/dma.c -@@ -105,6 +105,31 @@ static void arc_dma_free(struct device *dev, size_t size, void *vaddr, - __free_pages(page, get_order(size)); - } - -+static int arc_dma_mmap(struct device *dev, struct vm_area_struct *vma, -+ void *cpu_addr, dma_addr_t dma_addr, size_t size, -+ unsigned long attrs) -+{ -+ unsigned long user_count = vma_pages(vma); -+ unsigned long count = PAGE_ALIGN(size) >> PAGE_SHIFT; -+ unsigned long pfn = __phys_to_pfn(plat_dma_to_phys(dev, dma_addr)); -+ unsigned long off = vma->vm_pgoff; -+ int ret = -ENXIO; -+ -+ vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); -+ -+ if (dma_mmap_from_coherent(dev, vma, cpu_addr, size, &ret)) -+ return ret; -+ -+ if (off < count && user_count <= (count - off)) { -+ ret = remap_pfn_range(vma, vma->vm_start, -+ pfn + off, -+ user_count << PAGE_SHIFT, -+ vma->vm_page_prot); -+ } -+ -+ return ret; -+} -+ - /* - * streaming DMA Mapping API... - * CPU accesses page via normal paddr, thus needs to explicitly made -@@ -193,6 +218,7 @@ static int arc_dma_supported(struct device *dev, u64 dma_mask) - struct dma_map_ops arc_dma_ops = { - .alloc = arc_dma_alloc, - .free = arc_dma_free, -+ .mmap = arc_dma_mmap, - .map_page = arc_dma_map_page, - .map_sg = arc_dma_map_sg, - .sync_single_for_device = arc_dma_sync_single_for_device, -diff --git a/arch/s390/hypfs/hypfs_diag.c b/arch/s390/hypfs/hypfs_diag.c -index 28f03ca..794bebb 100644 ---- a/arch/s390/hypfs/hypfs_diag.c -+++ b/arch/s390/hypfs/hypfs_diag.c -@@ -363,11 +363,11 @@ static void *diag204_store(void) - static int diag224_get_name_table(void) - { - /* memory must be below 2GB */ -- diag224_cpu_names = kmalloc(PAGE_SIZE, GFP_KERNEL | GFP_DMA); -+ diag224_cpu_names = (char *) __get_free_page(GFP_KERNEL | GFP_DMA); - if (!diag224_cpu_names) - return -ENOMEM; - if (diag224(diag224_cpu_names)) { -- kfree(diag224_cpu_names); -+ free_page((unsigned long) diag224_cpu_names); - return -EOPNOTSUPP; - } - EBCASC(diag224_cpu_names + 16, (*diag224_cpu_names + 1) * 16); -@@ -376,7 +376,7 @@ static int diag224_get_name_table(void) - - static void diag224_delete_name_table(void) - { -- kfree(diag224_cpu_names); -+ free_page((unsigned long) diag224_cpu_names); - } - - static int diag224_idx2name(int index, char *name) -diff --git a/arch/s390/include/asm/processor.h b/arch/s390/include/asm/processor.h -index 0332317..602af69 100644 ---- a/arch/s390/include/asm/processor.h -+++ b/arch/s390/include/asm/processor.h -@@ -192,7 +192,7 @@ struct task_struct; - struct mm_struct; - struct seq_file; - --typedef int (*dump_trace_func_t)(void *data, unsigned long address); -+typedef int (*dump_trace_func_t)(void *data, unsigned long address, int reliable); - void dump_trace(dump_trace_func_t func, void *data, - struct task_struct *task, unsigned long sp); - -diff --git a/arch/s390/kernel/dumpstack.c b/arch/s390/kernel/dumpstack.c -index 6693383..518f615 100644 ---- a/arch/s390/kernel/dumpstack.c -+++ b/arch/s390/kernel/dumpstack.c -@@ -38,10 +38,10 @@ __dump_trace(dump_trace_func_t func, void *data, unsigned long sp, - if (sp < low || sp > high - sizeof(*sf)) - return sp; - sf = (struct stack_frame *) sp; -+ if (func(data, sf->gprs[8], 0)) -+ return sp; - /* Follow the backchain. */ - while (1) { -- if (func(data, sf->gprs[8])) -- return sp; - low = sp; - sp = sf->back_chain; - if (!sp) -@@ -49,6 +49,8 @@ __dump_trace(dump_trace_func_t func, void *data, unsigned long sp, - if (sp <= low || sp > high - sizeof(*sf)) - return sp; - sf = (struct stack_frame *) sp; -+ if (func(data, sf->gprs[8], 1)) -+ return sp; - } - /* Zero backchain detected, check for interrupt frame. */ - sp = (unsigned long) (sf + 1); -@@ -56,7 +58,7 @@ __dump_trace(dump_trace_func_t func, void *data, unsigned long sp, - return sp; - regs = (struct pt_regs *) sp; - if (!user_mode(regs)) { -- if (func(data, regs->psw.addr)) -+ if (func(data, regs->psw.addr, 1)) - return sp; - } - low = sp; -@@ -90,7 +92,7 @@ struct return_address_data { - int depth; - }; - --static int __return_address(void *data, unsigned long address) -+static int __return_address(void *data, unsigned long address, int reliable) - { - struct return_address_data *rd = data; - -@@ -109,9 +111,12 @@ unsigned long return_address(int depth) - } - EXPORT_SYMBOL_GPL(return_address); - --static int show_address(void *data, unsigned long address) -+static int show_address(void *data, unsigned long address, int reliable) - { -- printk("([<%016lx>] %pSR)\n", address, (void *)address); -+ if (reliable) -+ printk(" [<%016lx>] %pSR \n", address, (void *)address); -+ else -+ printk("([<%016lx>] %pSR)\n", address, (void *)address); - return 0; - } - -diff --git a/arch/s390/kernel/perf_event.c b/arch/s390/kernel/perf_event.c -index 17431f6..955a7b6 100644 ---- a/arch/s390/kernel/perf_event.c -+++ b/arch/s390/kernel/perf_event.c -@@ -222,7 +222,7 @@ static int __init service_level_perf_register(void) - } - arch_initcall(service_level_perf_register); - --static int __perf_callchain_kernel(void *data, unsigned long address) -+static int __perf_callchain_kernel(void *data, unsigned long address, int reliable) - { - struct perf_callchain_entry_ctx *entry = data; - -diff --git a/arch/s390/kernel/stacktrace.c b/arch/s390/kernel/stacktrace.c -index 44f84b2..355db9d 100644 ---- a/arch/s390/kernel/stacktrace.c -+++ b/arch/s390/kernel/stacktrace.c -@@ -27,12 +27,12 @@ static int __save_address(void *data, unsigned long address, int nosched) - return 1; - } - --static int save_address(void *data, unsigned long address) -+static int save_address(void *data, unsigned long address, int reliable) - { - return __save_address(data, address, 0); - } - --static int save_address_nosched(void *data, unsigned long address) -+static int save_address_nosched(void *data, unsigned long address, int reliable) - { - return __save_address(data, address, 1); - } -diff --git a/arch/s390/oprofile/init.c b/arch/s390/oprofile/init.c -index 16f4c39..9a4de45 100644 ---- a/arch/s390/oprofile/init.c -+++ b/arch/s390/oprofile/init.c -@@ -13,7 +13,7 @@ - #include <linux/init.h> - #include <asm/processor.h> - --static int __s390_backtrace(void *data, unsigned long address) -+static int __s390_backtrace(void *data, unsigned long address, int reliable) - { - unsigned int *depth = data; - -diff --git a/arch/x86/entry/Makefile b/arch/x86/entry/Makefile -index 77f28ce..9976fce 100644 ---- a/arch/x86/entry/Makefile -+++ b/arch/x86/entry/Makefile -@@ -5,8 +5,8 @@ - OBJECT_FILES_NON_STANDARD_entry_$(BITS).o := y - OBJECT_FILES_NON_STANDARD_entry_64_compat.o := y - --CFLAGS_syscall_64.o += -Wno-override-init --CFLAGS_syscall_32.o += -Wno-override-init -+CFLAGS_syscall_64.o += $(call cc-option,-Wno-override-init,) -+CFLAGS_syscall_32.o += $(call cc-option,-Wno-override-init,) - obj-y := entry_$(BITS).o thunk_$(BITS).o syscall_$(BITS).o - obj-y += common.o - -diff --git a/arch/x86/kernel/acpi/boot.c b/arch/x86/kernel/acpi/boot.c -index fbd1944..d99ca57 100644 ---- a/arch/x86/kernel/acpi/boot.c -+++ b/arch/x86/kernel/acpi/boot.c -@@ -453,6 +453,7 @@ static void __init acpi_sci_ioapic_setup(u8 bus_irq, u16 polarity, u16 trigger, - polarity = acpi_sci_flags & ACPI_MADT_POLARITY_MASK; - - mp_override_legacy_irq(bus_irq, polarity, trigger, gsi); -+ acpi_penalize_sci_irq(bus_irq, trigger, polarity); - - /* - * stash over-ride to indicate we've been here -diff --git a/drivers/acpi/apei/ghes.c b/drivers/acpi/apei/ghes.c -index 60746ef..caea575 100644 ---- a/drivers/acpi/apei/ghes.c -+++ b/drivers/acpi/apei/ghes.c -@@ -662,7 +662,7 @@ static int ghes_proc(struct ghes *ghes) - ghes_do_proc(ghes, ghes->estatus); - out: - ghes_clear_estatus(ghes); -- return 0; -+ return rc; - } - - static void ghes_add_timer(struct ghes *ghes) -diff --git a/drivers/acpi/pci_link.c b/drivers/acpi/pci_link.c -index c983bf7..bc3d914 100644 ---- a/drivers/acpi/pci_link.c -+++ b/drivers/acpi/pci_link.c -@@ -87,6 +87,7 @@ struct acpi_pci_link { - - static LIST_HEAD(acpi_link_list); - static DEFINE_MUTEX(acpi_link_lock); -+static int sci_irq = -1, sci_penalty; - - /* -------------------------------------------------------------------------- - PCI Link Device Management -@@ -496,25 +497,13 @@ static int acpi_irq_get_penalty(int irq) - { - int penalty = 0; - -- /* -- * Penalize IRQ used by ACPI SCI. If ACPI SCI pin attributes conflict -- * with PCI IRQ attributes, mark ACPI SCI as ISA_ALWAYS so it won't be -- * use for PCI IRQs. -- */ -- if (irq == acpi_gbl_FADT.sci_interrupt) { -- u32 type = irq_get_trigger_type(irq) & IRQ_TYPE_SENSE_MASK; -- -- if (type != IRQ_TYPE_LEVEL_LOW) -- penalty += PIRQ_PENALTY_ISA_ALWAYS; -- else -- penalty += PIRQ_PENALTY_PCI_USING; -- } -+ if (irq == sci_irq) -+ penalty += sci_penalty; - - if (irq < ACPI_MAX_ISA_IRQS) - return penalty + acpi_isa_irq_penalty[irq]; - -- penalty += acpi_irq_pci_sharing_penalty(irq); -- return penalty; -+ return penalty + acpi_irq_pci_sharing_penalty(irq); - } - - int __init acpi_irq_penalty_init(void) -@@ -619,6 +608,10 @@ static int acpi_pci_link_allocate(struct acpi_pci_link *link) - acpi_device_bid(link->device)); - return -ENODEV; - } else { -+ if (link->irq.active < ACPI_MAX_ISA_IRQS) -+ acpi_isa_irq_penalty[link->irq.active] += -+ PIRQ_PENALTY_PCI_USING; -+ - printk(KERN_WARNING PREFIX "%s [%s] enabled at IRQ %d\n", - acpi_device_name(link->device), - acpi_device_bid(link->device), link->irq.active); -@@ -849,7 +842,7 @@ static int __init acpi_irq_penalty_update(char *str, int used) - continue; - - if (used) -- new_penalty = acpi_irq_get_penalty(irq) + -+ new_penalty = acpi_isa_irq_penalty[irq] + - PIRQ_PENALTY_ISA_USED; - else - new_penalty = 0; -@@ -871,7 +864,7 @@ static int __init acpi_irq_penalty_update(char *str, int used) - void acpi_penalize_isa_irq(int irq, int active) - { - if ((irq >= 0) && (irq < ARRAY_SIZE(acpi_isa_irq_penalty))) -- acpi_isa_irq_penalty[irq] = acpi_irq_get_penalty(irq) + -+ acpi_isa_irq_penalty[irq] += - (active ? PIRQ_PENALTY_ISA_USED : PIRQ_PENALTY_PCI_USING); - } - -@@ -881,6 +874,17 @@ bool acpi_isa_irq_available(int irq) - acpi_irq_get_penalty(irq) < PIRQ_PENALTY_ISA_ALWAYS); - } - -+void acpi_penalize_sci_irq(int irq, int trigger, int polarity) -+{ -+ sci_irq = irq; -+ -+ if (trigger == ACPI_MADT_TRIGGER_LEVEL && -+ polarity == ACPI_MADT_POLARITY_ACTIVE_LOW) -+ sci_penalty = PIRQ_PENALTY_PCI_USING; -+ else -+ sci_penalty = PIRQ_PENALTY_ISA_ALWAYS; -+} -+ - /* - * Over-ride default table to reserve additional IRQs for use by ISA - * e.g. acpi_irq_isa=5 -diff --git a/drivers/block/drbd/drbd_main.c b/drivers/block/drbd/drbd_main.c -index 100be55..8348272 100644 ---- a/drivers/block/drbd/drbd_main.c -+++ b/drivers/block/drbd/drbd_main.c -@@ -1871,7 +1871,7 @@ int drbd_send(struct drbd_connection *connection, struct socket *sock, - drbd_update_congested(connection); - } - do { -- rv = kernel_sendmsg(sock, &msg, &iov, 1, size); -+ rv = kernel_sendmsg(sock, &msg, &iov, 1, iov.iov_len); - if (rv == -EAGAIN) { - if (we_should_drop_the_connection(connection, sock)) - break; -diff --git a/drivers/char/agp/intel-gtt.c b/drivers/char/agp/intel-gtt.c -index 4431129..0f7d28a 100644 ---- a/drivers/char/agp/intel-gtt.c -+++ b/drivers/char/agp/intel-gtt.c -@@ -845,6 +845,8 @@ void intel_gtt_insert_page(dma_addr_t addr, - unsigned int flags) - { - intel_private.driver->write_entry(addr, pg, flags); -+ if (intel_private.driver->chipset_flush) -+ intel_private.driver->chipset_flush(); - } - EXPORT_SYMBOL(intel_gtt_insert_page); - -diff --git a/drivers/char/hw_random/core.c b/drivers/char/hw_random/core.c -index 9203f2d..340f96e 100644 ---- a/drivers/char/hw_random/core.c -+++ b/drivers/char/hw_random/core.c -@@ -84,14 +84,14 @@ static size_t rng_buffer_size(void) - - static void add_early_randomness(struct hwrng *rng) - { -- unsigned char bytes[16]; - int bytes_read; -+ size_t size = min_t(size_t, 16, rng_buffer_size()); - - mutex_lock(&reading_mutex); -- bytes_read = rng_get_data(rng, bytes, sizeof(bytes), 1); -+ bytes_read = rng_get_data(rng, rng_buffer, size, 1); - mutex_unlock(&reading_mutex); - if (bytes_read > 0) -- add_device_randomness(bytes, bytes_read); -+ add_device_randomness(rng_buffer, bytes_read); - } - - static inline void cleanup_rng(struct kref *kref) -diff --git a/drivers/clk/clk-qoriq.c b/drivers/clk/clk-qoriq.c -index 20b1055..80ae2a5 100644 ---- a/drivers/clk/clk-qoriq.c -+++ b/drivers/clk/clk-qoriq.c -@@ -700,6 +700,7 @@ static struct clk * __init create_mux_common(struct clockgen *cg, - struct mux_hwclock *hwc, - const struct clk_ops *ops, - unsigned long min_rate, -+ unsigned long max_rate, - unsigned long pct80_rate, - const char *fmt, int idx) - { -@@ -728,6 +729,8 @@ static struct clk * __init create_mux_common(struct clockgen *cg, - continue; - if (rate < min_rate) - continue; -+ if (rate > max_rate) -+ continue; - - parent_names[j] = div->name; - hwc->parent_to_clksel[j] = i; -@@ -759,7 +762,7 @@ static struct clk * __init create_one_cmux(struct clockgen *cg, int idx) - struct mux_hwclock *hwc; - const struct clockgen_pll_div *div; - unsigned long plat_rate, min_rate; -- u64 pct80_rate; -+ u64 max_rate, pct80_rate; - u32 clksel; - - hwc = kzalloc(sizeof(*hwc), GFP_KERNEL); -@@ -787,8 +790,8 @@ static struct clk * __init create_one_cmux(struct clockgen *cg, int idx) - return NULL; - } - -- pct80_rate = clk_get_rate(div->clk); -- pct80_rate *= 8; -+ max_rate = clk_get_rate(div->clk); -+ pct80_rate = max_rate * 8; - do_div(pct80_rate, 10); - - plat_rate = clk_get_rate(cg->pll[PLATFORM_PLL].div[PLL_DIV1].clk); -@@ -798,7 +801,7 @@ static struct clk * __init create_one_cmux(struct clockgen *cg, int idx) - else - min_rate = plat_rate / 2; - -- return create_mux_common(cg, hwc, &cmux_ops, min_rate, -+ return create_mux_common(cg, hwc, &cmux_ops, min_rate, max_rate, - pct80_rate, "cg-cmux%d", idx); - } - -@@ -813,7 +816,7 @@ static struct clk * __init create_one_hwaccel(struct clockgen *cg, int idx) - hwc->reg = cg->regs + 0x20 * idx + 0x10; - hwc->info = cg->info.hwaccel[idx]; - -- return create_mux_common(cg, hwc, &hwaccel_ops, 0, 0, -+ return create_mux_common(cg, hwc, &hwaccel_ops, 0, ULONG_MAX, 0, - "cg-hwaccel%d", idx); - } - -diff --git a/drivers/clk/samsung/clk-exynos-audss.c b/drivers/clk/samsung/clk-exynos-audss.c -index bdf8b97..0fa91f3 100644 ---- a/drivers/clk/samsung/clk-exynos-audss.c -+++ b/drivers/clk/samsung/clk-exynos-audss.c -@@ -82,6 +82,7 @@ static const struct of_device_id exynos_audss_clk_of_match[] = { - .data = (void *)TYPE_EXYNOS5420, }, - {}, - }; -+MODULE_DEVICE_TABLE(of, exynos_audss_clk_of_match); - - static void exynos_audss_clk_teardown(void) - { -diff --git a/drivers/clocksource/timer-sun5i.c b/drivers/clocksource/timer-sun5i.c -index c184eb8..4f87f3e 100644 ---- a/drivers/clocksource/timer-sun5i.c -+++ b/drivers/clocksource/timer-sun5i.c -@@ -152,6 +152,13 @@ static irqreturn_t sun5i_timer_interrupt(int irq, void *dev_id) - return IRQ_HANDLED; - } - -+static cycle_t sun5i_clksrc_read(struct clocksource *clksrc) -+{ -+ struct sun5i_timer_clksrc *cs = to_sun5i_timer_clksrc(clksrc); -+ -+ return ~readl(cs->timer.base + TIMER_CNTVAL_LO_REG(1)); -+} -+ - static int sun5i_rate_cb_clksrc(struct notifier_block *nb, - unsigned long event, void *data) - { -@@ -210,8 +217,13 @@ static int __init sun5i_setup_clocksource(struct device_node *node, - writel(TIMER_CTL_ENABLE | TIMER_CTL_RELOAD, - base + TIMER_CTL_REG(1)); - -- ret = clocksource_mmio_init(base + TIMER_CNTVAL_LO_REG(1), node->name, -- rate, 340, 32, clocksource_mmio_readl_down); -+ cs->clksrc.name = node->name; -+ cs->clksrc.rating = 340; -+ cs->clksrc.read = sun5i_clksrc_read; -+ cs->clksrc.mask = CLOCKSOURCE_MASK(32); -+ cs->clksrc.flags = CLOCK_SOURCE_IS_CONTINUOUS; -+ -+ ret = clocksource_register_hz(&cs->clksrc, rate); - if (ret) { - pr_err("Couldn't register clock source.\n"); - goto err_remove_notifier; -diff --git a/drivers/gpio/gpio-mvebu.c b/drivers/gpio/gpio-mvebu.c -index cd5dc27..1ed6132 100644 ---- a/drivers/gpio/gpio-mvebu.c -+++ b/drivers/gpio/gpio-mvebu.c -@@ -293,10 +293,10 @@ static void mvebu_gpio_irq_ack(struct irq_data *d) - { - struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d); - struct mvebu_gpio_chip *mvchip = gc->private; -- u32 mask = ~(1 << (d->irq - gc->irq_base)); -+ u32 mask = d->mask; - - irq_gc_lock(gc); -- writel_relaxed(mask, mvebu_gpioreg_edge_cause(mvchip)); -+ writel_relaxed(~mask, mvebu_gpioreg_edge_cause(mvchip)); - irq_gc_unlock(gc); - } - -@@ -305,7 +305,7 @@ static void mvebu_gpio_edge_irq_mask(struct irq_data *d) - struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d); - struct mvebu_gpio_chip *mvchip = gc->private; - struct irq_chip_type *ct = irq_data_get_chip_type(d); -- u32 mask = 1 << (d->irq - gc->irq_base); -+ u32 mask = d->mask; - - irq_gc_lock(gc); - ct->mask_cache_priv &= ~mask; -@@ -319,8 +319,7 @@ static void mvebu_gpio_edge_irq_unmask(struct irq_data *d) - struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d); - struct mvebu_gpio_chip *mvchip = gc->private; - struct irq_chip_type *ct = irq_data_get_chip_type(d); -- -- u32 mask = 1 << (d->irq - gc->irq_base); -+ u32 mask = d->mask; - - irq_gc_lock(gc); - ct->mask_cache_priv |= mask; -@@ -333,8 +332,7 @@ static void mvebu_gpio_level_irq_mask(struct irq_data *d) - struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d); - struct mvebu_gpio_chip *mvchip = gc->private; - struct irq_chip_type *ct = irq_data_get_chip_type(d); -- -- u32 mask = 1 << (d->irq - gc->irq_base); -+ u32 mask = d->mask; - - irq_gc_lock(gc); - ct->mask_cache_priv &= ~mask; -@@ -347,8 +345,7 @@ static void mvebu_gpio_level_irq_unmask(struct irq_data *d) - struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d); - struct mvebu_gpio_chip *mvchip = gc->private; - struct irq_chip_type *ct = irq_data_get_chip_type(d); -- -- u32 mask = 1 << (d->irq - gc->irq_base); -+ u32 mask = d->mask; - - irq_gc_lock(gc); - ct->mask_cache_priv |= mask; -@@ -462,7 +459,7 @@ static void mvebu_gpio_irq_handler(struct irq_desc *desc) - for (i = 0; i < mvchip->chip.ngpio; i++) { - int irq; - -- irq = mvchip->irqbase + i; -+ irq = irq_find_mapping(mvchip->domain, i); - - if (!(cause & (1 << i))) - continue; -@@ -655,6 +652,7 @@ static int mvebu_gpio_probe(struct platform_device *pdev) - struct irq_chip_type *ct; - struct clk *clk; - unsigned int ngpios; -+ bool have_irqs; - int soc_variant; - int i, cpu, id; - int err; -@@ -665,6 +663,9 @@ static int mvebu_gpio_probe(struct platform_device *pdev) - else - soc_variant = MVEBU_GPIO_SOC_VARIANT_ORION; - -+ /* Some gpio controllers do not provide irq support */ -+ have_irqs = of_irq_count(np) != 0; -+ - mvchip = devm_kzalloc(&pdev->dev, sizeof(struct mvebu_gpio_chip), - GFP_KERNEL); - if (!mvchip) -@@ -697,7 +698,8 @@ static int mvebu_gpio_probe(struct platform_device *pdev) - mvchip->chip.get = mvebu_gpio_get; - mvchip->chip.direction_output = mvebu_gpio_direction_output; - mvchip->chip.set = mvebu_gpio_set; -- mvchip->chip.to_irq = mvebu_gpio_to_irq; -+ if (have_irqs) -+ mvchip->chip.to_irq = mvebu_gpio_to_irq; - mvchip->chip.base = id * MVEBU_MAX_GPIO_PER_BANK; - mvchip->chip.ngpio = ngpios; - mvchip->chip.can_sleep = false; -@@ -758,34 +760,30 @@ static int mvebu_gpio_probe(struct platform_device *pdev) - devm_gpiochip_add_data(&pdev->dev, &mvchip->chip, mvchip); - - /* Some gpio controllers do not provide irq support */ -- if (!of_irq_count(np)) -+ if (!have_irqs) - return 0; - -- /* Setup the interrupt handlers. Each chip can have up to 4 -- * interrupt handlers, with each handler dealing with 8 GPIO -- * pins. */ -- for (i = 0; i < 4; i++) { -- int irq = platform_get_irq(pdev, i); -- -- if (irq < 0) -- continue; -- irq_set_chained_handler_and_data(irq, mvebu_gpio_irq_handler, -- mvchip); -- } -- -- mvchip->irqbase = irq_alloc_descs(-1, 0, ngpios, -1); -- if (mvchip->irqbase < 0) { -- dev_err(&pdev->dev, "no irqs\n"); -- return mvchip->irqbase; -+ mvchip->domain = -+ irq_domain_add_linear(np, ngpios, &irq_generic_chip_ops, NULL); -+ if (!mvchip->domain) { -+ dev_err(&pdev->dev, "couldn't allocate irq domain %s (DT).\n", -+ mvchip->chip.label); -+ return -ENODEV; - } - -- gc = irq_alloc_generic_chip("mvebu_gpio_irq", 2, mvchip->irqbase, -- mvchip->membase, handle_level_irq); -- if (!gc) { -- dev_err(&pdev->dev, "Cannot allocate generic irq_chip\n"); -- return -ENOMEM; -+ err = irq_alloc_domain_generic_chips( -+ mvchip->domain, ngpios, 2, np->name, handle_level_irq, -+ IRQ_NOREQUEST | IRQ_NOPROBE | IRQ_LEVEL, 0, 0); -+ if (err) { -+ dev_err(&pdev->dev, "couldn't allocate irq chips %s (DT).\n", -+ mvchip->chip.label); -+ goto err_domain; - } - -+ /* NOTE: The common accessors cannot be used because of the percpu -+ * access to the mask registers -+ */ -+ gc = irq_get_domain_generic_chip(mvchip->domain, 0); - gc->private = mvchip; - ct = &gc->chip_types[0]; - ct->type = IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW; -@@ -803,27 +801,23 @@ static int mvebu_gpio_probe(struct platform_device *pdev) - ct->handler = handle_edge_irq; - ct->chip.name = mvchip->chip.label; - -- irq_setup_generic_chip(gc, IRQ_MSK(ngpios), 0, -- IRQ_NOREQUEST, IRQ_LEVEL | IRQ_NOPROBE); -+ /* Setup the interrupt handlers. Each chip can have up to 4 -+ * interrupt handlers, with each handler dealing with 8 GPIO -+ * pins. -+ */ -+ for (i = 0; i < 4; i++) { -+ int irq = platform_get_irq(pdev, i); - -- /* Setup irq domain on top of the generic chip. */ -- mvchip->domain = irq_domain_add_simple(np, mvchip->chip.ngpio, -- mvchip->irqbase, -- &irq_domain_simple_ops, -- mvchip); -- if (!mvchip->domain) { -- dev_err(&pdev->dev, "couldn't allocate irq domain %s (DT).\n", -- mvchip->chip.label); -- err = -ENODEV; -- goto err_generic_chip; -+ if (irq < 0) -+ continue; -+ irq_set_chained_handler_and_data(irq, mvebu_gpio_irq_handler, -+ mvchip); - } - - return 0; - --err_generic_chip: -- irq_remove_generic_chip(gc, IRQ_MSK(ngpios), IRQ_NOREQUEST, -- IRQ_LEVEL | IRQ_NOPROBE); -- kfree(gc); -+err_domain: -+ irq_domain_remove(mvchip->domain); - - return err; - } -diff --git a/drivers/gpio/gpiolib-of.c b/drivers/gpio/gpiolib-of.c -index a28feb3..e3fc901 100644 ---- a/drivers/gpio/gpiolib-of.c -+++ b/drivers/gpio/gpiolib-of.c -@@ -26,14 +26,18 @@ - - #include "gpiolib.h" - --static int of_gpiochip_match_node(struct gpio_chip *chip, void *data) -+static int of_gpiochip_match_node_and_xlate(struct gpio_chip *chip, void *data) - { -- return chip->gpiodev->dev.of_node == data; -+ struct of_phandle_args *gpiospec = data; -+ -+ return chip->gpiodev->dev.of_node == gpiospec->np && -+ chip->of_xlate(chip, gpiospec, NULL) >= 0; - } - --static struct gpio_chip *of_find_gpiochip_by_node(struct device_node *np) -+static struct gpio_chip *of_find_gpiochip_by_xlate( -+ struct of_phandle_args *gpiospec) - { -- return gpiochip_find(np, of_gpiochip_match_node); -+ return gpiochip_find(gpiospec, of_gpiochip_match_node_and_xlate); - } - - static struct gpio_desc *of_xlate_and_get_gpiod_flags(struct gpio_chip *chip, -@@ -79,7 +83,7 @@ struct gpio_desc *of_get_named_gpiod_flags(struct device_node *np, - return ERR_PTR(ret); - } - -- chip = of_find_gpiochip_by_node(gpiospec.np); -+ chip = of_find_gpiochip_by_xlate(&gpiospec); - if (!chip) { - desc = ERR_PTR(-EPROBE_DEFER); - goto out; -diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_acp.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_acp.c -index 892d60f..2057683 100644 ---- a/drivers/gpu/drm/amd/amdgpu/amdgpu_acp.c -+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_acp.c -@@ -395,9 +395,12 @@ static int acp_hw_fini(void *handle) - { - int i, ret; - struct device *dev; -- - struct amdgpu_device *adev = (struct amdgpu_device *)handle; - -+ /* return early if no ACP */ -+ if (!adev->acp.acp_genpd) -+ return 0; -+ - for (i = 0; i < ACP_DEVS ; i++) { - dev = get_mfd_cell_dev(adev->acp.acp_cell[i].name, i); - ret = pm_genpd_remove_device(&adev->acp.acp_genpd->gpd, dev); -diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c -index 9aa533c..414a160 100644 ---- a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c -+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c -@@ -605,6 +605,7 @@ static int __init amdgpu_init(void) - { - amdgpu_sync_init(); - amdgpu_fence_slab_init(); -+ amd_sched_fence_slab_init(); - if (vgacon_text_force()) { - DRM_ERROR("VGACON disables amdgpu kernel modesetting.\n"); - return -EINVAL; -@@ -624,6 +625,7 @@ static void __exit amdgpu_exit(void) - drm_pci_exit(driver, pdriver); - amdgpu_unregister_atpx_handler(); - amdgpu_sync_fini(); -+ amd_sched_fence_slab_fini(); - amdgpu_fence_slab_fini(); - } - -diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_fence.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_fence.c -index 0b109ae..c82b95b8 100644 ---- a/drivers/gpu/drm/amd/amdgpu/amdgpu_fence.c -+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_fence.c -@@ -68,6 +68,7 @@ int amdgpu_fence_slab_init(void) - - void amdgpu_fence_slab_fini(void) - { -+ rcu_barrier(); - kmem_cache_destroy(amdgpu_fence_slab); - } - /* -diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c -index e24a8af..1ed64ae 100644 ---- a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c -+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c -@@ -99,6 +99,8 @@ int amdgpu_driver_load_kms(struct drm_device *dev, unsigned long flags) - - if ((amdgpu_runtime_pm != 0) && - amdgpu_has_atpx() && -+ (amdgpu_is_atpx_hybrid() || -+ amdgpu_has_atpx_dgpu_power_cntl()) && - ((flags & AMD_IS_APU) == 0)) - flags |= AMD_IS_PX; - -diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c -index 80120fa..e86ca39 100644 ---- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c -+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c -@@ -1654,5 +1654,6 @@ void amdgpu_vm_manager_fini(struct amdgpu_device *adev) - fence_put(adev->vm_manager.ids[i].first); - amdgpu_sync_free(&adev->vm_manager.ids[i].active); - fence_put(id->flushed_updates); -+ fence_put(id->last_flush); - } - } -diff --git a/drivers/gpu/drm/amd/scheduler/gpu_scheduler.c b/drivers/gpu/drm/amd/scheduler/gpu_scheduler.c -index 963a24d..ffe1f85 100644 ---- a/drivers/gpu/drm/amd/scheduler/gpu_scheduler.c -+++ b/drivers/gpu/drm/amd/scheduler/gpu_scheduler.c -@@ -34,9 +34,6 @@ static bool amd_sched_entity_is_ready(struct amd_sched_entity *entity); - static void amd_sched_wakeup(struct amd_gpu_scheduler *sched); - static void amd_sched_process_job(struct fence *f, struct fence_cb *cb); - --struct kmem_cache *sched_fence_slab; --atomic_t sched_fence_slab_ref = ATOMIC_INIT(0); -- - /* Initialize a given run queue struct */ - static void amd_sched_rq_init(struct amd_sched_rq *rq) - { -@@ -618,13 +615,6 @@ int amd_sched_init(struct amd_gpu_scheduler *sched, - INIT_LIST_HEAD(&sched->ring_mirror_list); - spin_lock_init(&sched->job_list_lock); - atomic_set(&sched->hw_rq_count, 0); -- if (atomic_inc_return(&sched_fence_slab_ref) == 1) { -- sched_fence_slab = kmem_cache_create( -- "amd_sched_fence", sizeof(struct amd_sched_fence), 0, -- SLAB_HWCACHE_ALIGN, NULL); -- if (!sched_fence_slab) -- return -ENOMEM; -- } - - /* Each scheduler will run on a seperate kernel thread */ - sched->thread = kthread_run(amd_sched_main, sched, sched->name); -@@ -645,6 +635,4 @@ void amd_sched_fini(struct amd_gpu_scheduler *sched) - { - if (sched->thread) - kthread_stop(sched->thread); -- if (atomic_dec_and_test(&sched_fence_slab_ref)) -- kmem_cache_destroy(sched_fence_slab); - } -diff --git a/drivers/gpu/drm/amd/scheduler/gpu_scheduler.h b/drivers/gpu/drm/amd/scheduler/gpu_scheduler.h -index 7cbbbfb..51068e6 100644 ---- a/drivers/gpu/drm/amd/scheduler/gpu_scheduler.h -+++ b/drivers/gpu/drm/amd/scheduler/gpu_scheduler.h -@@ -30,9 +30,6 @@ - struct amd_gpu_scheduler; - struct amd_sched_rq; - --extern struct kmem_cache *sched_fence_slab; --extern atomic_t sched_fence_slab_ref; -- - /** - * A scheduler entity is a wrapper around a job queue or a group - * of other entities. Entities take turns emitting jobs from their -@@ -145,6 +142,9 @@ void amd_sched_entity_fini(struct amd_gpu_scheduler *sched, - struct amd_sched_entity *entity); - void amd_sched_entity_push_job(struct amd_sched_job *sched_job); - -+int amd_sched_fence_slab_init(void); -+void amd_sched_fence_slab_fini(void); -+ - struct amd_sched_fence *amd_sched_fence_create( - struct amd_sched_entity *s_entity, void *owner); - void amd_sched_fence_scheduled(struct amd_sched_fence *fence); -diff --git a/drivers/gpu/drm/amd/scheduler/sched_fence.c b/drivers/gpu/drm/amd/scheduler/sched_fence.c -index 6b63bea..93ad2e1 100644 ---- a/drivers/gpu/drm/amd/scheduler/sched_fence.c -+++ b/drivers/gpu/drm/amd/scheduler/sched_fence.c -@@ -27,6 +27,25 @@ - #include <drm/drmP.h> - #include "gpu_scheduler.h" - -+static struct kmem_cache *sched_fence_slab; -+ -+int amd_sched_fence_slab_init(void) -+{ -+ sched_fence_slab = kmem_cache_create( -+ "amd_sched_fence", sizeof(struct amd_sched_fence), 0, -+ SLAB_HWCACHE_ALIGN, NULL); -+ if (!sched_fence_slab) -+ return -ENOMEM; -+ -+ return 0; -+} -+ -+void amd_sched_fence_slab_fini(void) -+{ -+ rcu_barrier(); -+ kmem_cache_destroy(sched_fence_slab); -+} -+ - struct amd_sched_fence *amd_sched_fence_create(struct amd_sched_entity *entity, - void *owner) - { -diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c -index 5de36d8..d46fa22 100644 ---- a/drivers/gpu/drm/i915/i915_drv.c -+++ b/drivers/gpu/drm/i915/i915_drv.c -@@ -1490,8 +1490,6 @@ static int i915_drm_suspend(struct drm_device *dev) - - dev_priv->suspend_count++; - -- intel_display_set_init_power(dev_priv, false); -- - intel_csr_ucode_suspend(dev_priv); - - out: -@@ -1508,6 +1506,8 @@ static int i915_drm_suspend_late(struct drm_device *drm_dev, bool hibernation) - - disable_rpm_wakeref_asserts(dev_priv); - -+ intel_display_set_init_power(dev_priv, false); -+ - fw_csr = !IS_BROXTON(dev_priv) && - suspend_to_idle(dev_priv) && dev_priv->csr.dmc_payload; - /* -diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c -index 63462f2..e26f889 100644 ---- a/drivers/gpu/drm/i915/intel_display.c -+++ b/drivers/gpu/drm/i915/intel_display.c -@@ -9737,6 +9737,29 @@ static void bxt_modeset_commit_cdclk(struct drm_atomic_state *old_state) - bxt_set_cdclk(to_i915(dev), req_cdclk); - } - -+static int bdw_adjust_min_pipe_pixel_rate(struct intel_crtc_state *crtc_state, -+ int pixel_rate) -+{ -+ struct drm_i915_private *dev_priv = to_i915(crtc_state->base.crtc->dev); -+ -+ /* pixel rate mustn't exceed 95% of cdclk with IPS on BDW */ -+ if (IS_BROADWELL(dev_priv) && crtc_state->ips_enabled) -+ pixel_rate = DIV_ROUND_UP(pixel_rate * 100, 95); -+ -+ /* BSpec says "Do not use DisplayPort with CDCLK less than -+ * 432 MHz, audio enabled, port width x4, and link rate -+ * HBR2 (5.4 GHz), or else there may be audio corruption or -+ * screen corruption." -+ */ -+ if (intel_crtc_has_dp_encoder(crtc_state) && -+ crtc_state->has_audio && -+ crtc_state->port_clock >= 540000 && -+ crtc_state->lane_count == 4) -+ pixel_rate = max(432000, pixel_rate); -+ -+ return pixel_rate; -+} -+ - /* compute the max rate for new configuration */ - static int ilk_max_pixel_rate(struct drm_atomic_state *state) - { -@@ -9762,9 +9785,9 @@ static int ilk_max_pixel_rate(struct drm_atomic_state *state) - - pixel_rate = ilk_pipe_pixel_rate(crtc_state); - -- /* pixel rate mustn't exceed 95% of cdclk with IPS on BDW */ -- if (IS_BROADWELL(dev_priv) && crtc_state->ips_enabled) -- pixel_rate = DIV_ROUND_UP(pixel_rate * 100, 95); -+ if (IS_BROADWELL(dev_priv) || IS_GEN9(dev_priv)) -+ pixel_rate = bdw_adjust_min_pipe_pixel_rate(crtc_state, -+ pixel_rate); - - intel_state->min_pixclk[i] = pixel_rate; - } -diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c -index c3aa9e6..1421270 100644 ---- a/drivers/gpu/drm/i915/intel_hdmi.c -+++ b/drivers/gpu/drm/i915/intel_hdmi.c -@@ -1759,6 +1759,50 @@ intel_hdmi_add_properties(struct intel_hdmi *intel_hdmi, struct drm_connector *c - intel_hdmi->aspect_ratio = HDMI_PICTURE_ASPECT_NONE; - } - -+static u8 intel_hdmi_ddc_pin(struct drm_i915_private *dev_priv, -+ enum port port) -+{ -+ const struct ddi_vbt_port_info *info = -+ &dev_priv->vbt.ddi_port_info[port]; -+ u8 ddc_pin; -+ -+ if (info->alternate_ddc_pin) { -+ DRM_DEBUG_KMS("Using DDC pin 0x%x for port %c (VBT)\n", -+ info->alternate_ddc_pin, port_name(port)); -+ return info->alternate_ddc_pin; -+ } -+ -+ switch (port) { -+ case PORT_B: -+ if (IS_BROXTON(dev_priv)) -+ ddc_pin = GMBUS_PIN_1_BXT; -+ else -+ ddc_pin = GMBUS_PIN_DPB; -+ break; -+ case PORT_C: -+ if (IS_BROXTON(dev_priv)) -+ ddc_pin = GMBUS_PIN_2_BXT; -+ else -+ ddc_pin = GMBUS_PIN_DPC; -+ break; -+ case PORT_D: -+ if (IS_CHERRYVIEW(dev_priv)) -+ ddc_pin = GMBUS_PIN_DPD_CHV; -+ else -+ ddc_pin = GMBUS_PIN_DPD; -+ break; -+ default: -+ MISSING_CASE(port); -+ ddc_pin = GMBUS_PIN_DPB; -+ break; -+ } -+ -+ DRM_DEBUG_KMS("Using DDC pin 0x%x for port %c (platform default)\n", -+ ddc_pin, port_name(port)); -+ -+ return ddc_pin; -+} -+ - void intel_hdmi_init_connector(struct intel_digital_port *intel_dig_port, - struct intel_connector *intel_connector) - { -@@ -1768,7 +1812,6 @@ void intel_hdmi_init_connector(struct intel_digital_port *intel_dig_port, - struct drm_device *dev = intel_encoder->base.dev; - struct drm_i915_private *dev_priv = to_i915(dev); - enum port port = intel_dig_port->port; -- uint8_t alternate_ddc_pin; - - DRM_DEBUG_KMS("Adding HDMI connector on port %c\n", - port_name(port)); -@@ -1786,12 +1829,10 @@ void intel_hdmi_init_connector(struct intel_digital_port *intel_dig_port, - connector->doublescan_allowed = 0; - connector->stereo_allowed = 1; - -+ intel_hdmi->ddc_bus = intel_hdmi_ddc_pin(dev_priv, port); -+ - switch (port) { - case PORT_B: -- if (IS_BROXTON(dev_priv)) -- intel_hdmi->ddc_bus = GMBUS_PIN_1_BXT; -- else -- intel_hdmi->ddc_bus = GMBUS_PIN_DPB; - /* - * On BXT A0/A1, sw needs to activate DDIA HPD logic and - * interrupts to check the external panel connection. -@@ -1802,46 +1843,17 @@ void intel_hdmi_init_connector(struct intel_digital_port *intel_dig_port, - intel_encoder->hpd_pin = HPD_PORT_B; - break; - case PORT_C: -- if (IS_BROXTON(dev_priv)) -- intel_hdmi->ddc_bus = GMBUS_PIN_2_BXT; -- else -- intel_hdmi->ddc_bus = GMBUS_PIN_DPC; - intel_encoder->hpd_pin = HPD_PORT_C; - break; - case PORT_D: -- if (WARN_ON(IS_BROXTON(dev_priv))) -- intel_hdmi->ddc_bus = GMBUS_PIN_DISABLED; -- else if (IS_CHERRYVIEW(dev_priv)) -- intel_hdmi->ddc_bus = GMBUS_PIN_DPD_CHV; -- else -- intel_hdmi->ddc_bus = GMBUS_PIN_DPD; - intel_encoder->hpd_pin = HPD_PORT_D; - break; - case PORT_E: -- /* On SKL PORT E doesn't have seperate GMBUS pin -- * We rely on VBT to set a proper alternate GMBUS pin. */ -- alternate_ddc_pin = -- dev_priv->vbt.ddi_port_info[PORT_E].alternate_ddc_pin; -- switch (alternate_ddc_pin) { -- case DDC_PIN_B: -- intel_hdmi->ddc_bus = GMBUS_PIN_DPB; -- break; -- case DDC_PIN_C: -- intel_hdmi->ddc_bus = GMBUS_PIN_DPC; -- break; -- case DDC_PIN_D: -- intel_hdmi->ddc_bus = GMBUS_PIN_DPD; -- break; -- default: -- MISSING_CASE(alternate_ddc_pin); -- } - intel_encoder->hpd_pin = HPD_PORT_E; - break; -- case PORT_A: -- intel_encoder->hpd_pin = HPD_PORT_A; -- /* Internal port only for eDP. */ - default: -- BUG(); -+ MISSING_CASE(port); -+ return; - } - - if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) { -diff --git a/drivers/gpu/drm/radeon/radeon_device.c b/drivers/gpu/drm/radeon/radeon_device.c -index 554ca71..edd2d03 100644 ---- a/drivers/gpu/drm/radeon/radeon_device.c -+++ b/drivers/gpu/drm/radeon/radeon_device.c -@@ -104,6 +104,14 @@ static const char radeon_family_name[][16] = { - "LAST", - }; - -+#if defined(CONFIG_VGA_SWITCHEROO) -+bool radeon_has_atpx_dgpu_power_cntl(void); -+bool radeon_is_atpx_hybrid(void); -+#else -+static inline bool radeon_has_atpx_dgpu_power_cntl(void) { return false; } -+static inline bool radeon_is_atpx_hybrid(void) { return false; } -+#endif -+ - #define RADEON_PX_QUIRK_DISABLE_PX (1 << 0) - #define RADEON_PX_QUIRK_LONG_WAKEUP (1 << 1) - -@@ -160,6 +168,11 @@ static void radeon_device_handle_px_quirks(struct radeon_device *rdev) - - if (rdev->px_quirk_flags & RADEON_PX_QUIRK_DISABLE_PX) - rdev->flags &= ~RADEON_IS_PX; -+ -+ /* disable PX is the system doesn't support dGPU power control or hybrid gfx */ -+ if (!radeon_is_atpx_hybrid() && -+ !radeon_has_atpx_dgpu_power_cntl()) -+ rdev->flags &= ~RADEON_IS_PX; - } - - /** -diff --git a/drivers/iio/accel/st_accel_core.c b/drivers/iio/accel/st_accel_core.c -index da3fb06..ce69048 100644 ---- a/drivers/iio/accel/st_accel_core.c -+++ b/drivers/iio/accel/st_accel_core.c -@@ -743,8 +743,8 @@ static int st_accel_read_raw(struct iio_dev *indio_dev, - - return IIO_VAL_INT; - case IIO_CHAN_INFO_SCALE: -- *val = 0; -- *val2 = adata->current_fullscale->gain; -+ *val = adata->current_fullscale->gain / 1000000; -+ *val2 = adata->current_fullscale->gain % 1000000; - return IIO_VAL_INT_PLUS_MICRO; - case IIO_CHAN_INFO_SAMP_FREQ: - *val = adata->odr; -@@ -763,9 +763,13 @@ static int st_accel_write_raw(struct iio_dev *indio_dev, - int err; - - switch (mask) { -- case IIO_CHAN_INFO_SCALE: -- err = st_sensors_set_fullscale_by_gain(indio_dev, val2); -+ case IIO_CHAN_INFO_SCALE: { -+ int gain; -+ -+ gain = val * 1000000 + val2; -+ err = st_sensors_set_fullscale_by_gain(indio_dev, gain); - break; -+ } - case IIO_CHAN_INFO_SAMP_FREQ: - if (val2) - return -EINVAL; -diff --git a/drivers/iio/common/hid-sensors/hid-sensor-attributes.c b/drivers/iio/common/hid-sensors/hid-sensor-attributes.c -index dc33c1d..b5beea53 100644 ---- a/drivers/iio/common/hid-sensors/hid-sensor-attributes.c -+++ b/drivers/iio/common/hid-sensors/hid-sensor-attributes.c -@@ -30,26 +30,26 @@ static struct { - u32 usage_id; - int unit; /* 0 for default others from HID sensor spec */ - int scale_val0; /* scale, whole number */ -- int scale_val1; /* scale, fraction in micros */ -+ int scale_val1; /* scale, fraction in nanos */ - } unit_conversion[] = { -- {HID_USAGE_SENSOR_ACCEL_3D, 0, 9, 806650}, -+ {HID_USAGE_SENSOR_ACCEL_3D, 0, 9, 806650000}, - {HID_USAGE_SENSOR_ACCEL_3D, - HID_USAGE_SENSOR_UNITS_METERS_PER_SEC_SQRD, 1, 0}, - {HID_USAGE_SENSOR_ACCEL_3D, -- HID_USAGE_SENSOR_UNITS_G, 9, 806650}, -+ HID_USAGE_SENSOR_UNITS_G, 9, 806650000}, - -- {HID_USAGE_SENSOR_GYRO_3D, 0, 0, 17453}, -+ {HID_USAGE_SENSOR_GYRO_3D, 0, 0, 17453293}, - {HID_USAGE_SENSOR_GYRO_3D, - HID_USAGE_SENSOR_UNITS_RADIANS_PER_SECOND, 1, 0}, - {HID_USAGE_SENSOR_GYRO_3D, -- HID_USAGE_SENSOR_UNITS_DEGREES_PER_SECOND, 0, 17453}, -+ HID_USAGE_SENSOR_UNITS_DEGREES_PER_SECOND, 0, 17453293}, - -- {HID_USAGE_SENSOR_COMPASS_3D, 0, 0, 1000}, -+ {HID_USAGE_SENSOR_COMPASS_3D, 0, 0, 1000000}, - {HID_USAGE_SENSOR_COMPASS_3D, HID_USAGE_SENSOR_UNITS_GAUSS, 1, 0}, - -- {HID_USAGE_SENSOR_INCLINOMETER_3D, 0, 0, 17453}, -+ {HID_USAGE_SENSOR_INCLINOMETER_3D, 0, 0, 17453293}, - {HID_USAGE_SENSOR_INCLINOMETER_3D, -- HID_USAGE_SENSOR_UNITS_DEGREES, 0, 17453}, -+ HID_USAGE_SENSOR_UNITS_DEGREES, 0, 17453293}, - {HID_USAGE_SENSOR_INCLINOMETER_3D, - HID_USAGE_SENSOR_UNITS_RADIANS, 1, 0}, - -@@ -57,7 +57,7 @@ static struct { - {HID_USAGE_SENSOR_ALS, HID_USAGE_SENSOR_UNITS_LUX, 1, 0}, - - {HID_USAGE_SENSOR_PRESSURE, 0, 100, 0}, -- {HID_USAGE_SENSOR_PRESSURE, HID_USAGE_SENSOR_UNITS_PASCAL, 0, 1000}, -+ {HID_USAGE_SENSOR_PRESSURE, HID_USAGE_SENSOR_UNITS_PASCAL, 0, 1000000}, - }; - - static int pow_10(unsigned power) -@@ -266,15 +266,15 @@ EXPORT_SYMBOL(hid_sensor_write_raw_hyst_value); - /* - * This fuction applies the unit exponent to the scale. - * For example: -- * 9.806650 ->exp:2-> val0[980]val1[665000] -- * 9.000806 ->exp:2-> val0[900]val1[80600] -- * 0.174535 ->exp:2-> val0[17]val1[453500] -- * 1.001745 ->exp:0-> val0[1]val1[1745] -- * 1.001745 ->exp:2-> val0[100]val1[174500] -- * 1.001745 ->exp:4-> val0[10017]val1[450000] -- * 9.806650 ->exp:-2-> val0[0]val1[98066] -+ * 9.806650000 ->exp:2-> val0[980]val1[665000000] -+ * 9.000806000 ->exp:2-> val0[900]val1[80600000] -+ * 0.174535293 ->exp:2-> val0[17]val1[453529300] -+ * 1.001745329 ->exp:0-> val0[1]val1[1745329] -+ * 1.001745329 ->exp:2-> val0[100]val1[174532900] -+ * 1.001745329 ->exp:4-> val0[10017]val1[453290000] -+ * 9.806650000 ->exp:-2-> val0[0]val1[98066500] - */ --static void adjust_exponent_micro(int *val0, int *val1, int scale0, -+static void adjust_exponent_nano(int *val0, int *val1, int scale0, - int scale1, int exp) - { - int i; -@@ -285,32 +285,32 @@ static void adjust_exponent_micro(int *val0, int *val1, int scale0, - if (exp > 0) { - *val0 = scale0 * pow_10(exp); - res = 0; -- if (exp > 6) { -+ if (exp > 9) { - *val1 = 0; - return; - } - for (i = 0; i < exp; ++i) { -- x = scale1 / pow_10(5 - i); -+ x = scale1 / pow_10(8 - i); - res += (pow_10(exp - 1 - i) * x); -- scale1 = scale1 % pow_10(5 - i); -+ scale1 = scale1 % pow_10(8 - i); - } - *val0 += res; - *val1 = scale1 * pow_10(exp); - } else if (exp < 0) { - exp = abs(exp); -- if (exp > 6) { -+ if (exp > 9) { - *val0 = *val1 = 0; - return; - } - *val0 = scale0 / pow_10(exp); - rem = scale0 % pow_10(exp); - res = 0; -- for (i = 0; i < (6 - exp); ++i) { -- x = scale1 / pow_10(5 - i); -- res += (pow_10(5 - exp - i) * x); -- scale1 = scale1 % pow_10(5 - i); -+ for (i = 0; i < (9 - exp); ++i) { -+ x = scale1 / pow_10(8 - i); -+ res += (pow_10(8 - exp - i) * x); -+ scale1 = scale1 % pow_10(8 - i); - } -- *val1 = rem * pow_10(6 - exp) + res; -+ *val1 = rem * pow_10(9 - exp) + res; - } else { - *val0 = scale0; - *val1 = scale1; -@@ -332,14 +332,14 @@ int hid_sensor_format_scale(u32 usage_id, - unit_conversion[i].unit == attr_info->units) { - exp = hid_sensor_convert_exponent( - attr_info->unit_expo); -- adjust_exponent_micro(val0, val1, -+ adjust_exponent_nano(val0, val1, - unit_conversion[i].scale_val0, - unit_conversion[i].scale_val1, exp); - break; - } - } - -- return IIO_VAL_INT_PLUS_MICRO; -+ return IIO_VAL_INT_PLUS_NANO; - } - EXPORT_SYMBOL(hid_sensor_format_scale); - -diff --git a/drivers/iio/common/st_sensors/st_sensors_core.c b/drivers/iio/common/st_sensors/st_sensors_core.c -index 2d5282e..32a5946 100644 ---- a/drivers/iio/common/st_sensors/st_sensors_core.c -+++ b/drivers/iio/common/st_sensors/st_sensors_core.c -@@ -619,7 +619,7 @@ EXPORT_SYMBOL(st_sensors_sysfs_sampling_frequency_avail); - ssize_t st_sensors_sysfs_scale_avail(struct device *dev, - struct device_attribute *attr, char *buf) - { -- int i, len = 0; -+ int i, len = 0, q, r; - struct iio_dev *indio_dev = dev_get_drvdata(dev); - struct st_sensor_data *sdata = iio_priv(indio_dev); - -@@ -628,8 +628,10 @@ ssize_t st_sensors_sysfs_scale_avail(struct device *dev, - if (sdata->sensor_settings->fs.fs_avl[i].num == 0) - break; - -- len += scnprintf(buf + len, PAGE_SIZE - len, "0.%06u ", -- sdata->sensor_settings->fs.fs_avl[i].gain); -+ q = sdata->sensor_settings->fs.fs_avl[i].gain / 1000000; -+ r = sdata->sensor_settings->fs.fs_avl[i].gain % 1000000; -+ -+ len += scnprintf(buf + len, PAGE_SIZE - len, "%u.%06u ", q, r); - } - mutex_unlock(&indio_dev->mlock); - buf[len - 1] = '\n'; -diff --git a/drivers/iio/orientation/hid-sensor-rotation.c b/drivers/iio/orientation/hid-sensor-rotation.c -index b98b9d9..a97e802c 100644 ---- a/drivers/iio/orientation/hid-sensor-rotation.c -+++ b/drivers/iio/orientation/hid-sensor-rotation.c -@@ -335,6 +335,7 @@ static struct platform_driver hid_dev_rot_platform_driver = { - .id_table = hid_dev_rot_ids, - .driver = { - .name = KBUILD_MODNAME, -+ .pm = &hid_sensor_pm_ops, - }, - .probe = hid_dev_rot_probe, - .remove = hid_dev_rot_remove, -diff --git a/drivers/input/rmi4/rmi_i2c.c b/drivers/input/rmi4/rmi_i2c.c -index 6f2e0e4..1ebc2c1 100644 ---- a/drivers/input/rmi4/rmi_i2c.c -+++ b/drivers/input/rmi4/rmi_i2c.c -@@ -221,6 +221,21 @@ static const struct of_device_id rmi_i2c_of_match[] = { - MODULE_DEVICE_TABLE(of, rmi_i2c_of_match); - #endif - -+static void rmi_i2c_regulator_bulk_disable(void *data) -+{ -+ struct rmi_i2c_xport *rmi_i2c = data; -+ -+ regulator_bulk_disable(ARRAY_SIZE(rmi_i2c->supplies), -+ rmi_i2c->supplies); -+} -+ -+static void rmi_i2c_unregister_transport(void *data) -+{ -+ struct rmi_i2c_xport *rmi_i2c = data; -+ -+ rmi_unregister_transport_device(&rmi_i2c->xport); -+} -+ - static int rmi_i2c_probe(struct i2c_client *client, - const struct i2c_device_id *id) - { -@@ -264,6 +279,12 @@ static int rmi_i2c_probe(struct i2c_client *client, - if (retval < 0) - return retval; - -+ retval = devm_add_action_or_reset(&client->dev, -+ rmi_i2c_regulator_bulk_disable, -+ rmi_i2c); -+ if (retval) -+ return retval; -+ - of_property_read_u32(client->dev.of_node, "syna,startup-delay-ms", - &rmi_i2c->startup_delay); - -@@ -294,6 +315,11 @@ static int rmi_i2c_probe(struct i2c_client *client, - client->addr); - return retval; - } -+ retval = devm_add_action_or_reset(&client->dev, -+ rmi_i2c_unregister_transport, -+ rmi_i2c); -+ if (retval) -+ return retval; - - retval = rmi_i2c_init_irq(client); - if (retval < 0) -@@ -304,17 +330,6 @@ static int rmi_i2c_probe(struct i2c_client *client, - return 0; - } - --static int rmi_i2c_remove(struct i2c_client *client) --{ -- struct rmi_i2c_xport *rmi_i2c = i2c_get_clientdata(client); -- -- rmi_unregister_transport_device(&rmi_i2c->xport); -- regulator_bulk_disable(ARRAY_SIZE(rmi_i2c->supplies), -- rmi_i2c->supplies); -- -- return 0; --} -- - #ifdef CONFIG_PM_SLEEP - static int rmi_i2c_suspend(struct device *dev) - { -@@ -431,7 +446,6 @@ static struct i2c_driver rmi_i2c_driver = { - }, - .id_table = rmi_id, - .probe = rmi_i2c_probe, -- .remove = rmi_i2c_remove, - }; - - module_i2c_driver(rmi_i2c_driver); -diff --git a/drivers/input/rmi4/rmi_spi.c b/drivers/input/rmi4/rmi_spi.c -index 55bd1b3..4ebef60 100644 ---- a/drivers/input/rmi4/rmi_spi.c -+++ b/drivers/input/rmi4/rmi_spi.c -@@ -396,6 +396,13 @@ static inline int rmi_spi_of_probe(struct spi_device *spi, - } - #endif - -+static void rmi_spi_unregister_transport(void *data) -+{ -+ struct rmi_spi_xport *rmi_spi = data; -+ -+ rmi_unregister_transport_device(&rmi_spi->xport); -+} -+ - static int rmi_spi_probe(struct spi_device *spi) - { - struct rmi_spi_xport *rmi_spi; -@@ -464,6 +471,11 @@ static int rmi_spi_probe(struct spi_device *spi) - dev_err(&spi->dev, "failed to register transport.\n"); - return retval; - } -+ retval = devm_add_action_or_reset(&spi->dev, -+ rmi_spi_unregister_transport, -+ rmi_spi); -+ if (retval) -+ return retval; - - retval = rmi_spi_init_irq(spi); - if (retval < 0) -@@ -473,15 +485,6 @@ static int rmi_spi_probe(struct spi_device *spi) - return 0; - } - --static int rmi_spi_remove(struct spi_device *spi) --{ -- struct rmi_spi_xport *rmi_spi = spi_get_drvdata(spi); -- -- rmi_unregister_transport_device(&rmi_spi->xport); -- -- return 0; --} -- - #ifdef CONFIG_PM_SLEEP - static int rmi_spi_suspend(struct device *dev) - { -@@ -577,7 +580,6 @@ static struct spi_driver rmi_spi_driver = { - }, - .id_table = rmi_id, - .probe = rmi_spi_probe, -- .remove = rmi_spi_remove, - }; - - module_spi_driver(rmi_spi_driver); -diff --git a/drivers/iommu/amd_iommu.c b/drivers/iommu/amd_iommu.c -index 96de97a..822fc4a 100644 ---- a/drivers/iommu/amd_iommu.c -+++ b/drivers/iommu/amd_iommu.c -@@ -1654,6 +1654,9 @@ static void dma_ops_domain_free(struct dma_ops_domain *dom) - - free_pagetable(&dom->domain); - -+ if (dom->domain.id) -+ domain_id_free(dom->domain.id); -+ - kfree(dom); - } - -diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c -index ebb5bf3..1257b0b 100644 ---- a/drivers/iommu/intel-iommu.c -+++ b/drivers/iommu/intel-iommu.c -@@ -1711,6 +1711,7 @@ static void disable_dmar_iommu(struct intel_iommu *iommu) - if (!iommu->domains || !iommu->domain_ids) - return; - -+again: - spin_lock_irqsave(&device_domain_lock, flags); - list_for_each_entry_safe(info, tmp, &device_domain_list, global) { - struct dmar_domain *domain; -@@ -1723,10 +1724,19 @@ static void disable_dmar_iommu(struct intel_iommu *iommu) - - domain = info->domain; - -- dmar_remove_one_dev_info(domain, info->dev); -+ __dmar_remove_one_dev_info(info); - -- if (!domain_type_is_vm_or_si(domain)) -+ if (!domain_type_is_vm_or_si(domain)) { -+ /* -+ * The domain_exit() function can't be called under -+ * device_domain_lock, as it takes this lock itself. -+ * So release the lock here and re-run the loop -+ * afterwards. -+ */ -+ spin_unlock_irqrestore(&device_domain_lock, flags); - domain_exit(domain); -+ goto again; -+ } - } - spin_unlock_irqrestore(&device_domain_lock, flags); - -diff --git a/drivers/iommu/io-pgtable-arm-v7s.c b/drivers/iommu/io-pgtable-arm-v7s.c -index def8ca1..f50e51c 100644 ---- a/drivers/iommu/io-pgtable-arm-v7s.c -+++ b/drivers/iommu/io-pgtable-arm-v7s.c -@@ -633,6 +633,10 @@ static struct io_pgtable *arm_v7s_alloc_pgtable(struct io_pgtable_cfg *cfg, - { - struct arm_v7s_io_pgtable *data; - -+#ifdef PHYS_OFFSET -+ if (upper_32_bits(PHYS_OFFSET)) -+ return NULL; -+#endif - if (cfg->ias > ARM_V7S_ADDR_BITS || cfg->oas > ARM_V7S_ADDR_BITS) - return NULL; - -diff --git a/drivers/media/usb/dvb-usb/dib0700_core.c b/drivers/media/usb/dvb-usb/dib0700_core.c -index bf890c3..f73e108 100644 ---- a/drivers/media/usb/dvb-usb/dib0700_core.c -+++ b/drivers/media/usb/dvb-usb/dib0700_core.c -@@ -677,7 +677,7 @@ static void dib0700_rc_urb_completion(struct urb *purb) - struct dvb_usb_device *d = purb->context; - struct dib0700_rc_response *poll_reply; - enum rc_type protocol; -- u32 uninitialized_var(keycode); -+ u32 keycode; - u8 toggle; - - deb_info("%s()\n", __func__); -@@ -719,7 +719,8 @@ static void dib0700_rc_urb_completion(struct urb *purb) - poll_reply->nec.data == 0x00 && - poll_reply->nec.not_data == 0xff) { - poll_reply->data_state = 2; -- break; -+ rc_repeat(d->rc_dev); -+ goto resubmit; - } - - if ((poll_reply->nec.data ^ poll_reply->nec.not_data) != 0xff) { -diff --git a/drivers/misc/mei/bus-fixup.c b/drivers/misc/mei/bus-fixup.c -index e9e6ea3..75b9d4a 100644 ---- a/drivers/misc/mei/bus-fixup.c -+++ b/drivers/misc/mei/bus-fixup.c -@@ -178,7 +178,7 @@ static int mei_nfc_if_version(struct mei_cl *cl, - - ret = 0; - bytes_recv = __mei_cl_recv(cl, (u8 *)reply, if_version_length); -- if (bytes_recv < 0 || bytes_recv < sizeof(struct mei_nfc_reply)) { -+ if (bytes_recv < if_version_length) { - dev_err(bus->dev, "Could not read IF version\n"); - ret = -EIO; - goto err; -diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c -index c57eb32..6ef1e3c 100644 ---- a/drivers/mmc/core/mmc.c -+++ b/drivers/mmc/core/mmc.c -@@ -26,6 +26,8 @@ - #include "mmc_ops.h" - #include "sd_ops.h" - -+#define DEFAULT_CMD6_TIMEOUT_MS 500 -+ - static const unsigned int tran_exp[] = { - 10000, 100000, 1000000, 10000000, - 0, 0, 0, 0 -@@ -571,6 +573,7 @@ static int mmc_decode_ext_csd(struct mmc_card *card, u8 *ext_csd) - card->erased_byte = 0x0; - - /* eMMC v4.5 or later */ -+ card->ext_csd.generic_cmd6_time = DEFAULT_CMD6_TIMEOUT_MS; - if (card->ext_csd.rev >= 6) { - card->ext_csd.feature_support |= MMC_DISCARD_FEATURE; - -diff --git a/drivers/mmc/host/mxs-mmc.c b/drivers/mmc/host/mxs-mmc.c -index d839147..44ecebd 100644 ---- a/drivers/mmc/host/mxs-mmc.c -+++ b/drivers/mmc/host/mxs-mmc.c -@@ -661,13 +661,13 @@ static int mxs_mmc_probe(struct platform_device *pdev) - - platform_set_drvdata(pdev, mmc); - -+ spin_lock_init(&host->lock); -+ - ret = devm_request_irq(&pdev->dev, irq_err, mxs_mmc_irq_handler, 0, - dev_name(&pdev->dev), host); - if (ret) - goto out_free_dma; - -- spin_lock_init(&host->lock); -- - ret = mmc_add_host(mmc); - if (ret) - goto out_free_dma; -diff --git a/drivers/mmc/host/sdhci-msm.c b/drivers/mmc/host/sdhci-msm.c -index 8ef44a2a..90ed2e1 100644 ---- a/drivers/mmc/host/sdhci-msm.c -+++ b/drivers/mmc/host/sdhci-msm.c -@@ -647,6 +647,7 @@ static int sdhci_msm_probe(struct platform_device *pdev) - if (msm_host->pwr_irq < 0) { - dev_err(&pdev->dev, "Get pwr_irq failed (%d)\n", - msm_host->pwr_irq); -+ ret = msm_host->pwr_irq; - goto clk_disable; - } - -diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c -index a8a022a..6eb8f07 100644 ---- a/drivers/mmc/host/sdhci.c -+++ b/drivers/mmc/host/sdhci.c -@@ -2269,10 +2269,8 @@ static bool sdhci_request_done(struct sdhci_host *host) - - for (i = 0; i < SDHCI_MAX_MRQS; i++) { - mrq = host->mrqs_done[i]; -- if (mrq) { -- host->mrqs_done[i] = NULL; -+ if (mrq) - break; -- } - } - - if (!mrq) { -@@ -2303,6 +2301,17 @@ static bool sdhci_request_done(struct sdhci_host *host) - * upon error conditions. - */ - if (sdhci_needs_reset(host, mrq)) { -+ /* -+ * Do not finish until command and data lines are available for -+ * reset. Note there can only be one other mrq, so it cannot -+ * also be in mrqs_done, otherwise host->cmd and host->data_cmd -+ * would both be null. -+ */ -+ if (host->cmd || host->data_cmd) { -+ spin_unlock_irqrestore(&host->lock, flags); -+ return true; -+ } -+ - /* Some controllers need this kick or reset won't work here */ - if (host->quirks & SDHCI_QUIRK_CLOCK_BEFORE_RESET) - /* This is to force an update */ -@@ -2310,10 +2319,8 @@ static bool sdhci_request_done(struct sdhci_host *host) - - /* Spec says we should do both at the same time, but Ricoh - controllers do not like that. */ -- if (!host->cmd) -- sdhci_do_reset(host, SDHCI_RESET_CMD); -- if (!host->data_cmd) -- sdhci_do_reset(host, SDHCI_RESET_DATA); -+ sdhci_do_reset(host, SDHCI_RESET_CMD); -+ sdhci_do_reset(host, SDHCI_RESET_DATA); - - host->pending_reset = false; - } -@@ -2321,6 +2328,8 @@ static bool sdhci_request_done(struct sdhci_host *host) - if (!sdhci_has_requests(host)) - sdhci_led_deactivate(host); - -+ host->mrqs_done[i] = NULL; -+ - mmiowb(); - spin_unlock_irqrestore(&host->lock, flags); - -@@ -2500,9 +2509,6 @@ static void sdhci_data_irq(struct sdhci_host *host, u32 intmask) - if (!host->data) { - struct mmc_command *data_cmd = host->data_cmd; - -- if (data_cmd) -- host->data_cmd = NULL; -- - /* - * The "data complete" interrupt is also used to - * indicate that a busy state has ended. See comment -@@ -2510,11 +2516,13 @@ static void sdhci_data_irq(struct sdhci_host *host, u32 intmask) - */ - if (data_cmd && (data_cmd->flags & MMC_RSP_BUSY)) { - if (intmask & SDHCI_INT_DATA_TIMEOUT) { -+ host->data_cmd = NULL; - data_cmd->error = -ETIMEDOUT; - sdhci_finish_mrq(host, data_cmd->mrq); - return; - } - if (intmask & SDHCI_INT_DATA_END) { -+ host->data_cmd = NULL; - /* - * Some cards handle busy-end interrupt - * before the command completed, so make -diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c -index c74d164..6b46a37 100644 ---- a/drivers/net/ethernet/intel/i40e/i40e_main.c -+++ b/drivers/net/ethernet/intel/i40e/i40e_main.c -@@ -9001,7 +9001,7 @@ static int i40e_ndo_bridge_getlink(struct sk_buff *skb, u32 pid, u32 seq, - return 0; - - return ndo_dflt_bridge_getlink(skb, pid, seq, dev, veb->bridge_mode, -- nlflags, 0, 0, filter_mask, NULL); -+ 0, 0, nlflags, filter_mask, NULL); - } - - /* Hardware supports L4 tunnel length of 128B (=2^7) which includes -diff --git a/drivers/nfc/mei_phy.c b/drivers/nfc/mei_phy.c -index 83deda4..6f9563a 100644 ---- a/drivers/nfc/mei_phy.c -+++ b/drivers/nfc/mei_phy.c -@@ -133,7 +133,7 @@ static int mei_nfc_if_version(struct nfc_mei_phy *phy) - return -ENOMEM; - - bytes_recv = mei_cldev_recv(phy->cldev, (u8 *)reply, if_version_length); -- if (bytes_recv < 0 || bytes_recv < sizeof(struct mei_nfc_reply)) { -+ if (bytes_recv < 0 || bytes_recv < if_version_length) { - pr_err("Could not read IF version\n"); - r = -EIO; - goto err; -diff --git a/drivers/nvme/host/pci.c b/drivers/nvme/host/pci.c -index 60f7eab..da134a0 100644 ---- a/drivers/nvme/host/pci.c -+++ b/drivers/nvme/host/pci.c -@@ -1531,9 +1531,9 @@ static int nvme_delete_queue(struct nvme_queue *nvmeq, u8 opcode) - return 0; - } - --static void nvme_disable_io_queues(struct nvme_dev *dev) -+static void nvme_disable_io_queues(struct nvme_dev *dev, int queues) - { -- int pass, queues = dev->online_queues - 1; -+ int pass; - unsigned long timeout; - u8 opcode = nvme_admin_delete_sq; - -@@ -1678,7 +1678,7 @@ static void nvme_pci_disable(struct nvme_dev *dev) - - static void nvme_dev_disable(struct nvme_dev *dev, bool shutdown) - { -- int i; -+ int i, queues; - u32 csts = -1; - - del_timer_sync(&dev->watchdog_timer); -@@ -1689,6 +1689,7 @@ static void nvme_dev_disable(struct nvme_dev *dev, bool shutdown) - csts = readl(dev->bar + NVME_REG_CSTS); - } - -+ queues = dev->online_queues - 1; - for (i = dev->queue_count - 1; i > 0; i--) - nvme_suspend_queue(dev->queues[i]); - -@@ -1700,7 +1701,7 @@ static void nvme_dev_disable(struct nvme_dev *dev, bool shutdown) - if (dev->queue_count) - nvme_suspend_queue(dev->queues[0]); - } else { -- nvme_disable_io_queues(dev); -+ nvme_disable_io_queues(dev, queues); - nvme_disable_admin_queue(dev, shutdown); - } - nvme_pci_disable(dev); -diff --git a/drivers/pci/setup-res.c b/drivers/pci/setup-res.c -index 66c4d8f..9526e34 100644 ---- a/drivers/pci/setup-res.c -+++ b/drivers/pci/setup-res.c -@@ -121,6 +121,14 @@ int pci_claim_resource(struct pci_dev *dev, int resource) - return -EINVAL; - } - -+ /* -+ * If we have a shadow copy in RAM, the PCI device doesn't respond -+ * to the shadow range, so we don't need to claim it, and upstream -+ * bridges don't need to route the range to the device. -+ */ -+ if (res->flags & IORESOURCE_ROM_SHADOW) -+ return 0; -+ - root = pci_find_parent_resource(dev, res); - if (!root) { - dev_info(&dev->dev, "can't claim BAR %d %pR: no compatible bridge window\n", -diff --git a/drivers/pinctrl/bcm/pinctrl-iproc-gpio.c b/drivers/pinctrl/bcm/pinctrl-iproc-gpio.c -index 7f77007..5d1e505c3 100644 ---- a/drivers/pinctrl/bcm/pinctrl-iproc-gpio.c -+++ b/drivers/pinctrl/bcm/pinctrl-iproc-gpio.c -@@ -844,6 +844,6 @@ static struct platform_driver iproc_gpio_driver = { - - static int __init iproc_gpio_init(void) - { -- return platform_driver_probe(&iproc_gpio_driver, iproc_gpio_probe); -+ return platform_driver_register(&iproc_gpio_driver); - } - arch_initcall_sync(iproc_gpio_init); -diff --git a/drivers/pinctrl/bcm/pinctrl-nsp-gpio.c b/drivers/pinctrl/bcm/pinctrl-nsp-gpio.c -index 35783db..c8deb8b 100644 ---- a/drivers/pinctrl/bcm/pinctrl-nsp-gpio.c -+++ b/drivers/pinctrl/bcm/pinctrl-nsp-gpio.c -@@ -741,6 +741,6 @@ static struct platform_driver nsp_gpio_driver = { - - static int __init nsp_gpio_init(void) - { -- return platform_driver_probe(&nsp_gpio_driver, nsp_gpio_probe); -+ return platform_driver_register(&nsp_gpio_driver); - } - arch_initcall_sync(nsp_gpio_init); -diff --git a/drivers/pinctrl/intel/pinctrl-cherryview.c b/drivers/pinctrl/intel/pinctrl-cherryview.c -index 0fe8fad..bc31504 100644 ---- a/drivers/pinctrl/intel/pinctrl-cherryview.c -+++ b/drivers/pinctrl/intel/pinctrl-cherryview.c -@@ -1634,12 +1634,15 @@ static int chv_pinctrl_remove(struct platform_device *pdev) - } - - #ifdef CONFIG_PM_SLEEP --static int chv_pinctrl_suspend(struct device *dev) -+static int chv_pinctrl_suspend_noirq(struct device *dev) - { - struct platform_device *pdev = to_platform_device(dev); - struct chv_pinctrl *pctrl = platform_get_drvdata(pdev); -+ unsigned long flags; - int i; - -+ raw_spin_lock_irqsave(&chv_lock, flags); -+ - pctrl->saved_intmask = readl(pctrl->regs + CHV_INTMASK); - - for (i = 0; i < pctrl->community->npins; i++) { -@@ -1660,15 +1663,20 @@ static int chv_pinctrl_suspend(struct device *dev) - ctx->padctrl1 = readl(reg); - } - -+ raw_spin_unlock_irqrestore(&chv_lock, flags); -+ - return 0; - } - --static int chv_pinctrl_resume(struct device *dev) -+static int chv_pinctrl_resume_noirq(struct device *dev) - { - struct platform_device *pdev = to_platform_device(dev); - struct chv_pinctrl *pctrl = platform_get_drvdata(pdev); -+ unsigned long flags; - int i; - -+ raw_spin_lock_irqsave(&chv_lock, flags); -+ - /* - * Mask all interrupts before restoring per-pin configuration - * registers because we don't know in which state BIOS left them -@@ -1713,12 +1721,15 @@ static int chv_pinctrl_resume(struct device *dev) - chv_writel(0xffff, pctrl->regs + CHV_INTSTAT); - chv_writel(pctrl->saved_intmask, pctrl->regs + CHV_INTMASK); - -+ raw_spin_unlock_irqrestore(&chv_lock, flags); -+ - return 0; - } - #endif - - static const struct dev_pm_ops chv_pinctrl_pm_ops = { -- SET_LATE_SYSTEM_SLEEP_PM_OPS(chv_pinctrl_suspend, chv_pinctrl_resume) -+ SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(chv_pinctrl_suspend_noirq, -+ chv_pinctrl_resume_noirq) - }; - - static const struct acpi_device_id chv_pinctrl_acpi_match[] = { -diff --git a/drivers/platform/x86/toshiba-wmi.c b/drivers/platform/x86/toshiba-wmi.c -index feac457..2df07ee 100644 ---- a/drivers/platform/x86/toshiba-wmi.c -+++ b/drivers/platform/x86/toshiba-wmi.c -@@ -24,14 +24,15 @@ - #include <linux/acpi.h> - #include <linux/input.h> - #include <linux/input/sparse-keymap.h> -+#include <linux/dmi.h> - - MODULE_AUTHOR("Azael Avalos"); - MODULE_DESCRIPTION("Toshiba WMI Hotkey Driver"); - MODULE_LICENSE("GPL"); - --#define TOSHIBA_WMI_EVENT_GUID "59142400-C6A3-40FA-BADB-8A2652834100" -+#define WMI_EVENT_GUID "59142400-C6A3-40FA-BADB-8A2652834100" - --MODULE_ALIAS("wmi:"TOSHIBA_WMI_EVENT_GUID); -+MODULE_ALIAS("wmi:"WMI_EVENT_GUID); - - static struct input_dev *toshiba_wmi_input_dev; - -@@ -63,6 +64,16 @@ static void toshiba_wmi_notify(u32 value, void *context) - kfree(response.pointer); - } - -+static struct dmi_system_id toshiba_wmi_dmi_table[] __initdata = { -+ { -+ .ident = "Toshiba laptop", -+ .matches = { -+ DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), -+ }, -+ }, -+ {} -+}; -+ - static int __init toshiba_wmi_input_setup(void) - { - acpi_status status; -@@ -81,7 +92,7 @@ static int __init toshiba_wmi_input_setup(void) - if (err) - goto err_free_dev; - -- status = wmi_install_notify_handler(TOSHIBA_WMI_EVENT_GUID, -+ status = wmi_install_notify_handler(WMI_EVENT_GUID, - toshiba_wmi_notify, NULL); - if (ACPI_FAILURE(status)) { - err = -EIO; -@@ -95,7 +106,7 @@ static int __init toshiba_wmi_input_setup(void) - return 0; - - err_remove_notifier: -- wmi_remove_notify_handler(TOSHIBA_WMI_EVENT_GUID); -+ wmi_remove_notify_handler(WMI_EVENT_GUID); - err_free_keymap: - sparse_keymap_free(toshiba_wmi_input_dev); - err_free_dev: -@@ -105,7 +116,7 @@ static int __init toshiba_wmi_input_setup(void) - - static void toshiba_wmi_input_destroy(void) - { -- wmi_remove_notify_handler(TOSHIBA_WMI_EVENT_GUID); -+ wmi_remove_notify_handler(WMI_EVENT_GUID); - sparse_keymap_free(toshiba_wmi_input_dev); - input_unregister_device(toshiba_wmi_input_dev); - } -@@ -114,7 +125,8 @@ static int __init toshiba_wmi_init(void) - { - int ret; - -- if (!wmi_has_guid(TOSHIBA_WMI_EVENT_GUID)) -+ if (!wmi_has_guid(WMI_EVENT_GUID) || -+ !dmi_check_system(toshiba_wmi_dmi_table)) - return -ENODEV; - - ret = toshiba_wmi_input_setup(); -@@ -130,7 +142,7 @@ static int __init toshiba_wmi_init(void) - - static void __exit toshiba_wmi_exit(void) - { -- if (wmi_has_guid(TOSHIBA_WMI_EVENT_GUID)) -+ if (wmi_has_guid(WMI_EVENT_GUID)) - toshiba_wmi_input_destroy(); - } - -diff --git a/drivers/rtc/rtc-pcf2123.c b/drivers/rtc/rtc-pcf2123.c -index b4478cc..8895f77 100644 ---- a/drivers/rtc/rtc-pcf2123.c -+++ b/drivers/rtc/rtc-pcf2123.c -@@ -182,7 +182,8 @@ static ssize_t pcf2123_show(struct device *dev, struct device_attribute *attr, - } - - static ssize_t pcf2123_store(struct device *dev, struct device_attribute *attr, -- const char *buffer, size_t count) { -+ const char *buffer, size_t count) -+{ - struct pcf2123_sysfs_reg *r; - unsigned long reg; - unsigned long val; -@@ -199,7 +200,7 @@ static ssize_t pcf2123_store(struct device *dev, struct device_attribute *attr, - if (ret) - return ret; - -- pcf2123_write_reg(dev, reg, val); -+ ret = pcf2123_write_reg(dev, reg, val); - if (ret < 0) - return -EIO; - return count; -diff --git a/drivers/scsi/device_handler/scsi_dh_alua.c b/drivers/scsi/device_handler/scsi_dh_alua.c -index 752b5c9..920c421 100644 ---- a/drivers/scsi/device_handler/scsi_dh_alua.c -+++ b/drivers/scsi/device_handler/scsi_dh_alua.c -@@ -792,6 +792,7 @@ static void alua_rtpg_work(struct work_struct *work) - WARN_ON(pg->flags & ALUA_PG_RUN_RTPG); - WARN_ON(pg->flags & ALUA_PG_RUN_STPG); - spin_unlock_irqrestore(&pg->lock, flags); -+ kref_put(&pg->kref, release_port_group); - return; - } - if (pg->flags & ALUA_SYNC_STPG) -@@ -889,6 +890,7 @@ static void alua_rtpg_queue(struct alua_port_group *pg, - /* Do not queue if the worker is already running */ - if (!(pg->flags & ALUA_PG_RUNNING)) { - kref_get(&pg->kref); -+ sdev = NULL; - start_queue = 1; - } - } -@@ -900,7 +902,8 @@ static void alua_rtpg_queue(struct alua_port_group *pg, - if (start_queue && - !queue_delayed_work(alua_wq, &pg->rtpg_work, - msecs_to_jiffies(ALUA_RTPG_DELAY_MSECS))) { -- scsi_device_put(sdev); -+ if (sdev) -+ scsi_device_put(sdev); - kref_put(&pg->kref, release_port_group); - } - } -diff --git a/drivers/scsi/mpt3sas/mpt3sas_scsih.c b/drivers/scsi/mpt3sas/mpt3sas_scsih.c -index 4cb7990..46c0f5e 100644 ---- a/drivers/scsi/mpt3sas/mpt3sas_scsih.c -+++ b/drivers/scsi/mpt3sas/mpt3sas_scsih.c -@@ -1273,9 +1273,9 @@ scsih_target_alloc(struct scsi_target *starget) - sas_target_priv_data->handle = raid_device->handle; - sas_target_priv_data->sas_address = raid_device->wwid; - sas_target_priv_data->flags |= MPT_TARGET_FLAGS_VOLUME; -- sas_target_priv_data->raid_device = raid_device; - if (ioc->is_warpdrive) -- raid_device->starget = starget; -+ sas_target_priv_data->raid_device = raid_device; -+ raid_device->starget = starget; - } - spin_unlock_irqrestore(&ioc->raid_device_lock, flags); - return 0; -diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c -index 2674f4c..e46e2c5 100644 ---- a/drivers/scsi/qla2xxx/qla_os.c -+++ b/drivers/scsi/qla2xxx/qla_os.c -@@ -2341,6 +2341,8 @@ qla2xxx_scan_finished(struct Scsi_Host *shost, unsigned long time) - { - scsi_qla_host_t *vha = shost_priv(shost); - -+ if (test_bit(UNLOADING, &vha->dpc_flags)) -+ return 1; - if (!vha->host) - return 1; - if (time > vha->hw->loop_reset_delay * HZ) -diff --git a/drivers/staging/comedi/drivers/ni_tio.c b/drivers/staging/comedi/drivers/ni_tio.c -index 7043eb0..5ab49a7 100644 ---- a/drivers/staging/comedi/drivers/ni_tio.c -+++ b/drivers/staging/comedi/drivers/ni_tio.c -@@ -207,7 +207,8 @@ static int ni_tio_clock_period_ps(const struct ni_gpct *counter, - * clock period is specified by user with prescaling - * already taken into account. - */ -- return counter->clock_period_ps; -+ *period_ps = counter->clock_period_ps; -+ return 0; - } - - switch (generic_clock_source & NI_GPCT_PRESCALE_MODE_CLOCK_SRC_MASK) { -diff --git a/drivers/staging/iio/impedance-analyzer/ad5933.c b/drivers/staging/iio/impedance-analyzer/ad5933.c -index 24c348d..98d9473 100644 ---- a/drivers/staging/iio/impedance-analyzer/ad5933.c -+++ b/drivers/staging/iio/impedance-analyzer/ad5933.c -@@ -655,6 +655,7 @@ static void ad5933_work(struct work_struct *work) - __be16 buf[2]; - int val[2]; - unsigned char status; -+ int ret; - - mutex_lock(&indio_dev->mlock); - if (st->state == AD5933_CTRL_INIT_START_FREQ) { -@@ -662,19 +663,22 @@ static void ad5933_work(struct work_struct *work) - ad5933_cmd(st, AD5933_CTRL_START_SWEEP); - st->state = AD5933_CTRL_START_SWEEP; - schedule_delayed_work(&st->work, st->poll_time_jiffies); -- mutex_unlock(&indio_dev->mlock); -- return; -+ goto out; - } - -- ad5933_i2c_read(st->client, AD5933_REG_STATUS, 1, &status); -+ ret = ad5933_i2c_read(st->client, AD5933_REG_STATUS, 1, &status); -+ if (ret) -+ goto out; - - if (status & AD5933_STAT_DATA_VALID) { - int scan_count = bitmap_weight(indio_dev->active_scan_mask, - indio_dev->masklength); -- ad5933_i2c_read(st->client, -+ ret = ad5933_i2c_read(st->client, - test_bit(1, indio_dev->active_scan_mask) ? - AD5933_REG_REAL_DATA : AD5933_REG_IMAG_DATA, - scan_count * 2, (u8 *)buf); -+ if (ret) -+ goto out; - - if (scan_count == 2) { - val[0] = be16_to_cpu(buf[0]); -@@ -686,8 +690,7 @@ static void ad5933_work(struct work_struct *work) - } else { - /* no data available - try again later */ - schedule_delayed_work(&st->work, st->poll_time_jiffies); -- mutex_unlock(&indio_dev->mlock); -- return; -+ goto out; - } - - if (status & AD5933_STAT_SWEEP_DONE) { -@@ -700,7 +703,7 @@ static void ad5933_work(struct work_struct *work) - ad5933_cmd(st, AD5933_CTRL_INC_FREQ); - schedule_delayed_work(&st->work, st->poll_time_jiffies); - } -- -+out: - mutex_unlock(&indio_dev->mlock); - } - -diff --git a/drivers/staging/nvec/nvec_ps2.c b/drivers/staging/nvec/nvec_ps2.c -index a324322..499952c 100644 ---- a/drivers/staging/nvec/nvec_ps2.c -+++ b/drivers/staging/nvec/nvec_ps2.c -@@ -106,13 +106,12 @@ static int nvec_mouse_probe(struct platform_device *pdev) - { - struct nvec_chip *nvec = dev_get_drvdata(pdev->dev.parent); - struct serio *ser_dev; -- char mouse_reset[] = { NVEC_PS2, SEND_COMMAND, PSMOUSE_RST, 3 }; - -- ser_dev = devm_kzalloc(&pdev->dev, sizeof(struct serio), GFP_KERNEL); -+ ser_dev = kzalloc(sizeof(struct serio), GFP_KERNEL); - if (!ser_dev) - return -ENOMEM; - -- ser_dev->id.type = SERIO_PS_PSTHRU; -+ ser_dev->id.type = SERIO_8042; - ser_dev->write = ps2_sendcommand; - ser_dev->start = ps2_startstreaming; - ser_dev->stop = ps2_stopstreaming; -@@ -127,9 +126,6 @@ static int nvec_mouse_probe(struct platform_device *pdev) - - serio_register_port(ser_dev); - -- /* mouse reset */ -- nvec_write_async(nvec, mouse_reset, sizeof(mouse_reset)); -- - return 0; - } - -diff --git a/drivers/staging/sm750fb/ddk750_reg.h b/drivers/staging/sm750fb/ddk750_reg.h -index 9552479..4ed6d8d 100644 ---- a/drivers/staging/sm750fb/ddk750_reg.h -+++ b/drivers/staging/sm750fb/ddk750_reg.h -@@ -601,13 +601,13 @@ - - #define PANEL_PLANE_TL 0x08001C - #define PANEL_PLANE_TL_TOP_SHIFT 16 --#define PANEL_PLANE_TL_TOP_MASK (0xeff << 16) --#define PANEL_PLANE_TL_LEFT_MASK 0xeff -+#define PANEL_PLANE_TL_TOP_MASK (0x7ff << 16) -+#define PANEL_PLANE_TL_LEFT_MASK 0x7ff - - #define PANEL_PLANE_BR 0x080020 - #define PANEL_PLANE_BR_BOTTOM_SHIFT 16 --#define PANEL_PLANE_BR_BOTTOM_MASK (0xeff << 16) --#define PANEL_PLANE_BR_RIGHT_MASK 0xeff -+#define PANEL_PLANE_BR_BOTTOM_MASK (0x7ff << 16) -+#define PANEL_PLANE_BR_RIGHT_MASK 0x7ff - - #define PANEL_HORIZONTAL_TOTAL 0x080024 - #define PANEL_HORIZONTAL_TOTAL_TOTAL_SHIFT 16 -diff --git a/drivers/tty/serial/atmel_serial.c b/drivers/tty/serial/atmel_serial.c -index 8bbde52..21aeac5 100644 ---- a/drivers/tty/serial/atmel_serial.c -+++ b/drivers/tty/serial/atmel_serial.c -@@ -2026,6 +2026,7 @@ static void atmel_serial_pm(struct uart_port *port, unsigned int state, - static void atmel_set_termios(struct uart_port *port, struct ktermios *termios, - struct ktermios *old) - { -+ struct atmel_uart_port *atmel_port = to_atmel_uart_port(port); - unsigned long flags; - unsigned int old_mode, mode, imr, quot, baud; - -@@ -2129,11 +2130,29 @@ static void atmel_set_termios(struct uart_port *port, struct ktermios *termios, - mode |= ATMEL_US_USMODE_RS485; - } else if (termios->c_cflag & CRTSCTS) { - /* RS232 with hardware handshake (RTS/CTS) */ -- if (atmel_use_dma_rx(port) && !atmel_use_fifo(port)) { -- dev_info(port->dev, "not enabling hardware flow control because DMA is used"); -- termios->c_cflag &= ~CRTSCTS; -- } else { -+ if (atmel_use_fifo(port) && -+ !mctrl_gpio_to_gpiod(atmel_port->gpios, UART_GPIO_CTS)) { -+ /* -+ * with ATMEL_US_USMODE_HWHS set, the controller will -+ * be able to drive the RTS pin high/low when the RX -+ * FIFO is above RXFTHRES/below RXFTHRES2. -+ * It will also disable the transmitter when the CTS -+ * pin is high. -+ * This mode is not activated if CTS pin is a GPIO -+ * because in this case, the transmitter is always -+ * disabled (there must be an internal pull-up -+ * responsible for this behaviour). -+ * If the RTS pin is a GPIO, the controller won't be -+ * able to drive it according to the FIFO thresholds, -+ * but it will be handled by the driver. -+ */ - mode |= ATMEL_US_USMODE_HWHS; -+ } else { -+ /* -+ * For platforms without FIFO, the flow control is -+ * handled by the driver. -+ */ -+ mode |= ATMEL_US_USMODE_NORMAL; - } - } else { - /* RS232 without hadware handshake */ -diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c -index 0f3f62e..3ca9fdb 100644 ---- a/drivers/usb/class/cdc-acm.c -+++ b/drivers/usb/class/cdc-acm.c -@@ -946,8 +946,6 @@ static int wait_serial_change(struct acm *acm, unsigned long arg) - DECLARE_WAITQUEUE(wait, current); - struct async_icount old, new; - -- if (arg & (TIOCM_DSR | TIOCM_RI | TIOCM_CD)) -- return -EINVAL; - do { - spin_lock_irq(&acm->read_lock); - old = acm->oldcount; -@@ -1175,6 +1173,8 @@ static int acm_probe(struct usb_interface *intf, - if (quirks == IGNORE_DEVICE) - return -ENODEV; - -+ memset(&h, 0x00, sizeof(struct usb_cdc_parsed_header)); -+ - num_rx_buf = (quirks == SINGLE_RX_URB) ? 1 : ACM_NR; - - /* handle quirks deadly to normal probing*/ -diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c -index 35d0924..2d47010 100644 ---- a/drivers/usb/dwc3/core.c -+++ b/drivers/usb/dwc3/core.c -@@ -669,15 +669,14 @@ static int dwc3_core_init(struct dwc3 *dwc) - return 0; - - err4: -- phy_power_off(dwc->usb2_generic_phy); -+ phy_power_off(dwc->usb3_generic_phy); - - err3: -- phy_power_off(dwc->usb3_generic_phy); -+ phy_power_off(dwc->usb2_generic_phy); - - err2: - usb_phy_set_suspend(dwc->usb2_phy, 1); - usb_phy_set_suspend(dwc->usb3_phy, 1); -- dwc3_core_exit(dwc); - - err1: - usb_phy_shutdown(dwc->usb2_phy); -diff --git a/drivers/usb/gadget/function/u_ether.c b/drivers/usb/gadget/function/u_ether.c -index 9b9e71f..f590ada 100644 ---- a/drivers/usb/gadget/function/u_ether.c -+++ b/drivers/usb/gadget/function/u_ether.c -@@ -585,14 +585,6 @@ static netdev_tx_t eth_start_xmit(struct sk_buff *skb, - - req->length = length; - -- /* throttle high/super speed IRQ rate back slightly */ -- if (gadget_is_dualspeed(dev->gadget)) -- req->no_interrupt = (((dev->gadget->speed == USB_SPEED_HIGH || -- dev->gadget->speed == USB_SPEED_SUPER)) && -- !list_empty(&dev->tx_reqs)) -- ? ((atomic_read(&dev->tx_qlen) % dev->qmult) != 0) -- : 0; -- - retval = usb_ep_queue(in, req, GFP_ATOMIC); - switch (retval) { - default: -diff --git a/drivers/watchdog/watchdog_core.c b/drivers/watchdog/watchdog_core.c -index 6abb83c..74265b2 100644 ---- a/drivers/watchdog/watchdog_core.c -+++ b/drivers/watchdog/watchdog_core.c -@@ -349,7 +349,7 @@ int devm_watchdog_register_device(struct device *dev, - struct watchdog_device **rcwdd; - int ret; - -- rcwdd = devres_alloc(devm_watchdog_unregister_device, sizeof(*wdd), -+ rcwdd = devres_alloc(devm_watchdog_unregister_device, sizeof(*rcwdd), - GFP_KERNEL); - if (!rcwdd) - return -ENOMEM; -diff --git a/fs/coredump.c b/fs/coredump.c -index 281b768..eb9c92c 100644 ---- a/fs/coredump.c -+++ b/fs/coredump.c -@@ -1,6 +1,7 @@ - #include <linux/slab.h> - #include <linux/file.h> - #include <linux/fdtable.h> -+#include <linux/freezer.h> - #include <linux/mm.h> - #include <linux/stat.h> - #include <linux/fcntl.h> -@@ -423,7 +424,9 @@ static int coredump_wait(int exit_code, struct core_state *core_state) - if (core_waiters > 0) { - struct core_thread *ptr; - -+ freezer_do_not_count(); - wait_for_completion(&core_state->startup); -+ freezer_count(); - /* - * Wait for all the threads to become inactive, so that - * all the thread context (extended register state, like -diff --git a/fs/nfs/nfs4session.c b/fs/nfs/nfs4session.c -index b629730..150c5a1 100644 ---- a/fs/nfs/nfs4session.c -+++ b/fs/nfs/nfs4session.c -@@ -178,12 +178,14 @@ static int nfs4_slot_get_seqid(struct nfs4_slot_table *tbl, u32 slotid, - __must_hold(&tbl->slot_tbl_lock) - { - struct nfs4_slot *slot; -+ int ret; - - slot = nfs4_lookup_slot(tbl, slotid); -- if (IS_ERR(slot)) -- return PTR_ERR(slot); -- *seq_nr = slot->seq_nr; -- return 0; -+ ret = PTR_ERR_OR_ZERO(slot); -+ if (!ret) -+ *seq_nr = slot->seq_nr; -+ -+ return ret; - } - - /* -diff --git a/include/linux/acpi.h b/include/linux/acpi.h -index c5eaf2f..67d1d3e 100644 ---- a/include/linux/acpi.h -+++ b/include/linux/acpi.h -@@ -318,6 +318,7 @@ struct pci_dev; - int acpi_pci_irq_enable (struct pci_dev *dev); - void acpi_penalize_isa_irq(int irq, int active); - bool acpi_isa_irq_available(int irq); -+void acpi_penalize_sci_irq(int irq, int trigger, int polarity); - void acpi_pci_irq_disable (struct pci_dev *dev); - - extern int ec_read(u8 addr, u8 *val); -diff --git a/include/linux/frontswap.h b/include/linux/frontswap.h -index c46d2aa..1d18af0 100644 ---- a/include/linux/frontswap.h -+++ b/include/linux/frontswap.h -@@ -106,8 +106,9 @@ static inline void frontswap_invalidate_area(unsigned type) - - static inline void frontswap_init(unsigned type, unsigned long *map) - { -- if (frontswap_enabled()) -- __frontswap_init(type, map); -+#ifdef CONFIG_FRONTSWAP -+ __frontswap_init(type, map); -+#endif - } - - #endif /* _LINUX_FRONTSWAP_H */ -diff --git a/include/linux/sunrpc/svc_rdma.h b/include/linux/sunrpc/svc_rdma.h -index d6917b8..3584bc8 100644 ---- a/include/linux/sunrpc/svc_rdma.h -+++ b/include/linux/sunrpc/svc_rdma.h -@@ -86,6 +86,7 @@ struct svc_rdma_op_ctxt { - unsigned long flags; - enum dma_data_direction direction; - int count; -+ unsigned int mapped_sges; - struct ib_sge sge[RPCSVC_MAXPAGES]; - struct page *pages[RPCSVC_MAXPAGES]; - }; -@@ -193,6 +194,14 @@ struct svcxprt_rdma { - - #define RPCSVC_MAXPAYLOAD_RDMA RPCSVC_MAXPAYLOAD - -+/* Track DMA maps for this transport and context */ -+static inline void svc_rdma_count_mappings(struct svcxprt_rdma *rdma, -+ struct svc_rdma_op_ctxt *ctxt) -+{ -+ ctxt->mapped_sges++; -+ atomic_inc(&rdma->sc_dma_used); -+} -+ - /* svc_rdma_backchannel.c */ - extern int svc_rdma_handle_bc_reply(struct rpc_xprt *xprt, - struct rpcrdma_msg *rmsgp, -diff --git a/lib/genalloc.c b/lib/genalloc.c -index 0a11396..144fe6b 100644 ---- a/lib/genalloc.c -+++ b/lib/genalloc.c -@@ -292,7 +292,7 @@ unsigned long gen_pool_alloc_algo(struct gen_pool *pool, size_t size, - struct gen_pool_chunk *chunk; - unsigned long addr = 0; - int order = pool->min_alloc_order; -- int nbits, start_bit = 0, end_bit, remain; -+ int nbits, start_bit, end_bit, remain; - - #ifndef CONFIG_ARCH_HAVE_NMI_SAFE_CMPXCHG - BUG_ON(in_nmi()); -@@ -307,6 +307,7 @@ unsigned long gen_pool_alloc_algo(struct gen_pool *pool, size_t size, - if (size > atomic_read(&chunk->avail)) - continue; - -+ start_bit = 0; - end_bit = chunk_size(chunk) >> order; - retry: - start_bit = algo(chunk->bits, end_bit, start_bit, -diff --git a/mm/hugetlb.c b/mm/hugetlb.c -index 770d83e..0ddce6a 100644 ---- a/mm/hugetlb.c -+++ b/mm/hugetlb.c -@@ -1826,11 +1826,17 @@ static void return_unused_surplus_pages(struct hstate *h, - * is not the case is if a reserve map was changed between calls. It - * is the responsibility of the caller to notice the difference and - * take appropriate action. -+ * -+ * vma_add_reservation is used in error paths where a reservation must -+ * be restored when a newly allocated huge page must be freed. It is -+ * to be called after calling vma_needs_reservation to determine if a -+ * reservation exists. - */ - enum vma_resv_mode { - VMA_NEEDS_RESV, - VMA_COMMIT_RESV, - VMA_END_RESV, -+ VMA_ADD_RESV, - }; - static long __vma_reservation_common(struct hstate *h, - struct vm_area_struct *vma, unsigned long addr, -@@ -1856,6 +1862,14 @@ static long __vma_reservation_common(struct hstate *h, - region_abort(resv, idx, idx + 1); - ret = 0; - break; -+ case VMA_ADD_RESV: -+ if (vma->vm_flags & VM_MAYSHARE) -+ ret = region_add(resv, idx, idx + 1); -+ else { -+ region_abort(resv, idx, idx + 1); -+ ret = region_del(resv, idx, idx + 1); -+ } -+ break; - default: - BUG(); - } -@@ -1903,6 +1917,56 @@ static void vma_end_reservation(struct hstate *h, - (void)__vma_reservation_common(h, vma, addr, VMA_END_RESV); - } - -+static long vma_add_reservation(struct hstate *h, -+ struct vm_area_struct *vma, unsigned long addr) -+{ -+ return __vma_reservation_common(h, vma, addr, VMA_ADD_RESV); -+} -+ -+/* -+ * This routine is called to restore a reservation on error paths. In the -+ * specific error paths, a huge page was allocated (via alloc_huge_page) -+ * and is about to be freed. If a reservation for the page existed, -+ * alloc_huge_page would have consumed the reservation and set PagePrivate -+ * in the newly allocated page. When the page is freed via free_huge_page, -+ * the global reservation count will be incremented if PagePrivate is set. -+ * However, free_huge_page can not adjust the reserve map. Adjust the -+ * reserve map here to be consistent with global reserve count adjustments -+ * to be made by free_huge_page. -+ */ -+static void restore_reserve_on_error(struct hstate *h, -+ struct vm_area_struct *vma, unsigned long address, -+ struct page *page) -+{ -+ if (unlikely(PagePrivate(page))) { -+ long rc = vma_needs_reservation(h, vma, address); -+ -+ if (unlikely(rc < 0)) { -+ /* -+ * Rare out of memory condition in reserve map -+ * manipulation. Clear PagePrivate so that -+ * global reserve count will not be incremented -+ * by free_huge_page. This will make it appear -+ * as though the reservation for this page was -+ * consumed. This may prevent the task from -+ * faulting in the page at a later time. This -+ * is better than inconsistent global huge page -+ * accounting of reserve counts. -+ */ -+ ClearPagePrivate(page); -+ } else if (rc) { -+ rc = vma_add_reservation(h, vma, address); -+ if (unlikely(rc < 0)) -+ /* -+ * See above comment about rare out of -+ * memory condition. -+ */ -+ ClearPagePrivate(page); -+ } else -+ vma_end_reservation(h, vma, address); -+ } -+} -+ - struct page *alloc_huge_page(struct vm_area_struct *vma, - unsigned long addr, int avoid_reserve) - { -@@ -3498,6 +3562,7 @@ static int hugetlb_cow(struct mm_struct *mm, struct vm_area_struct *vma, - spin_unlock(ptl); - mmu_notifier_invalidate_range_end(mm, mmun_start, mmun_end); - out_release_all: -+ restore_reserve_on_error(h, vma, address, new_page); - put_page(new_page); - out_release_old: - put_page(old_page); -@@ -3680,6 +3745,7 @@ static int hugetlb_no_page(struct mm_struct *mm, struct vm_area_struct *vma, - spin_unlock(ptl); - backout_unlocked: - unlock_page(page); -+ restore_reserve_on_error(h, vma, address, page); - put_page(page); - goto out; - } -diff --git a/mm/memory-failure.c b/mm/memory-failure.c -index de88f33..19e796d 100644 ---- a/mm/memory-failure.c -+++ b/mm/memory-failure.c -@@ -1112,10 +1112,10 @@ int memory_failure(unsigned long pfn, int trapno, int flags) - } - - if (!PageHuge(p) && PageTransHuge(hpage)) { -- lock_page(hpage); -- if (!PageAnon(hpage) || unlikely(split_huge_page(hpage))) { -- unlock_page(hpage); -- if (!PageAnon(hpage)) -+ lock_page(p); -+ if (!PageAnon(p) || unlikely(split_huge_page(p))) { -+ unlock_page(p); -+ if (!PageAnon(p)) - pr_err("Memory failure: %#lx: non anonymous thp\n", - pfn); - else -@@ -1126,9 +1126,7 @@ int memory_failure(unsigned long pfn, int trapno, int flags) - put_hwpoison_page(p); - return -EBUSY; - } -- unlock_page(hpage); -- get_hwpoison_page(p); -- put_hwpoison_page(hpage); -+ unlock_page(p); - VM_BUG_ON_PAGE(!page_count(p), p); - hpage = compound_head(p); - } -diff --git a/mm/shmem.c b/mm/shmem.c -index 971fc83..38aa5e0 100644 ---- a/mm/shmem.c -+++ b/mm/shmem.c -@@ -1483,6 +1483,8 @@ static int shmem_replace_page(struct page **pagep, gfp_t gfp, - copy_highpage(newpage, oldpage); - flush_dcache_page(newpage); - -+ __SetPageLocked(newpage); -+ __SetPageSwapBacked(newpage); - SetPageUptodate(newpage); - set_page_private(newpage, swap_index); - SetPageSwapCache(newpage); -diff --git a/mm/slab_common.c b/mm/slab_common.c -index 71f0b28..329b038 100644 ---- a/mm/slab_common.c -+++ b/mm/slab_common.c -@@ -533,8 +533,8 @@ void memcg_create_kmem_cache(struct mem_cgroup *memcg, - - s = create_cache(cache_name, root_cache->object_size, - root_cache->size, root_cache->align, -- root_cache->flags, root_cache->ctor, -- memcg, root_cache); -+ root_cache->flags & CACHE_CREATE_MASK, -+ root_cache->ctor, memcg, root_cache); - /* - * If we could not create a memcg cache, do not complain, because - * that's not critical at all as we can always proceed with the root -diff --git a/mm/swapfile.c b/mm/swapfile.c -index 2657acc..bf262e4 100644 ---- a/mm/swapfile.c -+++ b/mm/swapfile.c -@@ -2218,6 +2218,8 @@ static unsigned long read_swap_header(struct swap_info_struct *p, - swab32s(&swap_header->info.version); - swab32s(&swap_header->info.last_page); - swab32s(&swap_header->info.nr_badpages); -+ if (swap_header->info.nr_badpages > MAX_SWAP_BADPAGES) -+ return 0; - for (i = 0; i < swap_header->info.nr_badpages; i++) - swab32s(&swap_header->info.badpages[i]); - } -diff --git a/net/batman-adv/originator.c b/net/batman-adv/originator.c -index 3940b5d..3e9667e 100644 ---- a/net/batman-adv/originator.c -+++ b/net/batman-adv/originator.c -@@ -537,7 +537,7 @@ batadv_hardif_neigh_create(struct batadv_hard_iface *hard_iface, - if (bat_priv->algo_ops->neigh.hardif_init) - bat_priv->algo_ops->neigh.hardif_init(hardif_neigh); - -- hlist_add_head(&hardif_neigh->list, &hard_iface->neigh_list); -+ hlist_add_head_rcu(&hardif_neigh->list, &hard_iface->neigh_list); - - out: - spin_unlock_bh(&hard_iface->neigh_list_lock); -diff --git a/net/ceph/ceph_fs.c b/net/ceph/ceph_fs.c -index 7d54e94..dcbe67f 100644 ---- a/net/ceph/ceph_fs.c -+++ b/net/ceph/ceph_fs.c -@@ -34,7 +34,8 @@ void ceph_file_layout_from_legacy(struct ceph_file_layout *fl, - fl->stripe_count = le32_to_cpu(legacy->fl_stripe_count); - fl->object_size = le32_to_cpu(legacy->fl_object_size); - fl->pool_id = le32_to_cpu(legacy->fl_pg_pool); -- if (fl->pool_id == 0) -+ if (fl->pool_id == 0 && fl->stripe_unit == 0 && -+ fl->stripe_count == 0 && fl->object_size == 0) - fl->pool_id = -1; - } - EXPORT_SYMBOL(ceph_file_layout_from_legacy); -diff --git a/net/netfilter/nf_log.c b/net/netfilter/nf_log.c -index aa5847a..1df2c8d 100644 ---- a/net/netfilter/nf_log.c -+++ b/net/netfilter/nf_log.c -@@ -420,7 +420,7 @@ static int nf_log_proc_dostring(struct ctl_table *table, int write, - char buf[NFLOGGER_NAME_LEN]; - int r = 0; - int tindex = (unsigned long)table->extra1; -- struct net *net = current->nsproxy->net_ns; -+ struct net *net = table->extra2; - - if (write) { - struct ctl_table tmp = *table; -@@ -474,7 +474,6 @@ static int netfilter_log_sysctl_init(struct net *net) - 3, "%d", i); - nf_log_sysctl_table[i].procname = - nf_log_sysctl_fnames[i]; -- nf_log_sysctl_table[i].data = NULL; - nf_log_sysctl_table[i].maxlen = NFLOGGER_NAME_LEN; - nf_log_sysctl_table[i].mode = 0644; - nf_log_sysctl_table[i].proc_handler = -@@ -484,6 +483,9 @@ static int netfilter_log_sysctl_init(struct net *net) - } - } - -+ for (i = NFPROTO_UNSPEC; i < NFPROTO_NUMPROTO; i++) -+ table[i].extra2 = net; -+ - net->nf.nf_log_dir_header = register_net_sysctl(net, - "net/netfilter/nf_log", - table); -diff --git a/net/sunrpc/xprtrdma/frwr_ops.c b/net/sunrpc/xprtrdma/frwr_ops.c -index 892b5e1..2761377 100644 ---- a/net/sunrpc/xprtrdma/frwr_ops.c -+++ b/net/sunrpc/xprtrdma/frwr_ops.c -@@ -44,18 +44,20 @@ - * being done. - * - * When the underlying transport disconnects, MRs are left in one of -- * three states: -+ * four states: - * - * INVALID: The MR was not in use before the QP entered ERROR state. -- * (Or, the LOCAL_INV WR has not completed or flushed yet). -- * -- * STALE: The MR was being registered or unregistered when the QP -- * entered ERROR state, and the pending WR was flushed. - * - * VALID: The MR was registered before the QP entered ERROR state. - * -- * When frwr_op_map encounters STALE and VALID MRs, they are recovered -- * with ib_dereg_mr and then are re-initialized. Beause MR recovery -+ * FLUSHED_FR: The MR was being registered when the QP entered ERROR -+ * state, and the pending WR was flushed. -+ * -+ * FLUSHED_LI: The MR was being invalidated when the QP entered ERROR -+ * state, and the pending WR was flushed. -+ * -+ * When frwr_op_map encounters FLUSHED and VALID MRs, they are recovered -+ * with ib_dereg_mr and then are re-initialized. Because MR recovery - * allocates fresh resources, it is deferred to a workqueue, and the - * recovered MRs are placed back on the rb_mws list when recovery is - * complete. frwr_op_map allocates another MR for the current RPC while -@@ -175,12 +177,15 @@ __frwr_reset_mr(struct rpcrdma_ia *ia, struct rpcrdma_mw *r) - static void - frwr_op_recover_mr(struct rpcrdma_mw *mw) - { -+ enum rpcrdma_frmr_state state = mw->frmr.fr_state; - struct rpcrdma_xprt *r_xprt = mw->mw_xprt; - struct rpcrdma_ia *ia = &r_xprt->rx_ia; - int rc; - - rc = __frwr_reset_mr(ia, mw); -- ib_dma_unmap_sg(ia->ri_device, mw->mw_sg, mw->mw_nents, mw->mw_dir); -+ if (state != FRMR_FLUSHED_LI) -+ ib_dma_unmap_sg(ia->ri_device, -+ mw->mw_sg, mw->mw_nents, mw->mw_dir); - if (rc) - goto out_release; - -@@ -261,10 +266,8 @@ frwr_op_maxpages(struct rpcrdma_xprt *r_xprt) - } - - static void --__frwr_sendcompletion_flush(struct ib_wc *wc, struct rpcrdma_frmr *frmr, -- const char *wr) -+__frwr_sendcompletion_flush(struct ib_wc *wc, const char *wr) - { -- frmr->fr_state = FRMR_IS_STALE; - if (wc->status != IB_WC_WR_FLUSH_ERR) - pr_err("rpcrdma: %s: %s (%u/0x%x)\n", - wr, ib_wc_status_msg(wc->status), -@@ -287,7 +290,8 @@ frwr_wc_fastreg(struct ib_cq *cq, struct ib_wc *wc) - if (wc->status != IB_WC_SUCCESS) { - cqe = wc->wr_cqe; - frmr = container_of(cqe, struct rpcrdma_frmr, fr_cqe); -- __frwr_sendcompletion_flush(wc, frmr, "fastreg"); -+ frmr->fr_state = FRMR_FLUSHED_FR; -+ __frwr_sendcompletion_flush(wc, "fastreg"); - } - } - -@@ -307,7 +311,8 @@ frwr_wc_localinv(struct ib_cq *cq, struct ib_wc *wc) - if (wc->status != IB_WC_SUCCESS) { - cqe = wc->wr_cqe; - frmr = container_of(cqe, struct rpcrdma_frmr, fr_cqe); -- __frwr_sendcompletion_flush(wc, frmr, "localinv"); -+ frmr->fr_state = FRMR_FLUSHED_LI; -+ __frwr_sendcompletion_flush(wc, "localinv"); - } - } - -@@ -327,9 +332,11 @@ frwr_wc_localinv_wake(struct ib_cq *cq, struct ib_wc *wc) - /* WARNING: Only wr_cqe and status are reliable at this point */ - cqe = wc->wr_cqe; - frmr = container_of(cqe, struct rpcrdma_frmr, fr_cqe); -- if (wc->status != IB_WC_SUCCESS) -- __frwr_sendcompletion_flush(wc, frmr, "localinv"); -- complete_all(&frmr->fr_linv_done); -+ if (wc->status != IB_WC_SUCCESS) { -+ frmr->fr_state = FRMR_FLUSHED_LI; -+ __frwr_sendcompletion_flush(wc, "localinv"); -+ } -+ complete(&frmr->fr_linv_done); - } - - /* Post a REG_MR Work Request to register a memory region -diff --git a/net/sunrpc/xprtrdma/svc_rdma_backchannel.c b/net/sunrpc/xprtrdma/svc_rdma_backchannel.c -index a2a7519..cd0c558 100644 ---- a/net/sunrpc/xprtrdma/svc_rdma_backchannel.c -+++ b/net/sunrpc/xprtrdma/svc_rdma_backchannel.c -@@ -129,7 +129,7 @@ static int svc_rdma_bc_sendto(struct svcxprt_rdma *rdma, - ret = -EIO; - goto out_unmap; - } -- atomic_inc(&rdma->sc_dma_used); -+ svc_rdma_count_mappings(rdma, ctxt); - - memset(&send_wr, 0, sizeof(send_wr)); - ctxt->cqe.done = svc_rdma_wc_send; -diff --git a/net/sunrpc/xprtrdma/svc_rdma_recvfrom.c b/net/sunrpc/xprtrdma/svc_rdma_recvfrom.c -index 2c25606..ad1df97 100644 ---- a/net/sunrpc/xprtrdma/svc_rdma_recvfrom.c -+++ b/net/sunrpc/xprtrdma/svc_rdma_recvfrom.c -@@ -159,7 +159,7 @@ int rdma_read_chunk_lcl(struct svcxprt_rdma *xprt, - ctxt->sge[pno].addr); - if (ret) - goto err; -- atomic_inc(&xprt->sc_dma_used); -+ svc_rdma_count_mappings(xprt, ctxt); - - ctxt->sge[pno].lkey = xprt->sc_pd->local_dma_lkey; - ctxt->sge[pno].length = len; -diff --git a/net/sunrpc/xprtrdma/svc_rdma_sendto.c b/net/sunrpc/xprtrdma/svc_rdma_sendto.c -index 54d53330..3b95b19 100644 ---- a/net/sunrpc/xprtrdma/svc_rdma_sendto.c -+++ b/net/sunrpc/xprtrdma/svc_rdma_sendto.c -@@ -280,7 +280,7 @@ static int send_write(struct svcxprt_rdma *xprt, struct svc_rqst *rqstp, - if (ib_dma_mapping_error(xprt->sc_cm_id->device, - sge[sge_no].addr)) - goto err; -- atomic_inc(&xprt->sc_dma_used); -+ svc_rdma_count_mappings(xprt, ctxt); - sge[sge_no].lkey = xprt->sc_pd->local_dma_lkey; - ctxt->count++; - sge_off = 0; -@@ -489,7 +489,7 @@ static int send_reply(struct svcxprt_rdma *rdma, - ctxt->sge[0].length, DMA_TO_DEVICE); - if (ib_dma_mapping_error(rdma->sc_cm_id->device, ctxt->sge[0].addr)) - goto err; -- atomic_inc(&rdma->sc_dma_used); -+ svc_rdma_count_mappings(rdma, ctxt); - - ctxt->direction = DMA_TO_DEVICE; - -@@ -505,7 +505,7 @@ static int send_reply(struct svcxprt_rdma *rdma, - if (ib_dma_mapping_error(rdma->sc_cm_id->device, - ctxt->sge[sge_no].addr)) - goto err; -- atomic_inc(&rdma->sc_dma_used); -+ svc_rdma_count_mappings(rdma, ctxt); - ctxt->sge[sge_no].lkey = rdma->sc_pd->local_dma_lkey; - ctxt->sge[sge_no].length = sge_bytes; - } -@@ -523,23 +523,9 @@ static int send_reply(struct svcxprt_rdma *rdma, - ctxt->pages[page_no+1] = rqstp->rq_respages[page_no]; - ctxt->count++; - rqstp->rq_respages[page_no] = NULL; -- /* -- * If there are more pages than SGE, terminate SGE -- * list so that svc_rdma_unmap_dma doesn't attempt to -- * unmap garbage. -- */ -- if (page_no+1 >= sge_no) -- ctxt->sge[page_no+1].length = 0; - } - rqstp->rq_next_page = rqstp->rq_respages + 1; - -- /* The loop above bumps sc_dma_used for each sge. The -- * xdr_buf.tail gets a separate sge, but resides in the -- * same page as xdr_buf.head. Don't count it twice. -- */ -- if (sge_no > ctxt->count) -- atomic_dec(&rdma->sc_dma_used); -- - if (sge_no > rdma->sc_max_sge) { - pr_err("svcrdma: Too many sges (%d)\n", sge_no); - goto err; -@@ -635,7 +621,7 @@ int svc_rdma_sendto(struct svc_rqst *rqstp) - ret = send_reply(rdma, rqstp, res_page, rdma_resp, vec, - inline_bytes); - if (ret < 0) -- goto err1; -+ goto err0; - - svc_rdma_put_req_map(rdma, vec); - dprintk("svcrdma: send_reply returns %d\n", ret); -@@ -692,7 +678,7 @@ void svc_rdma_send_error(struct svcxprt_rdma *xprt, struct rpcrdma_msg *rmsgp, - svc_rdma_put_context(ctxt, 1); - return; - } -- atomic_inc(&xprt->sc_dma_used); -+ svc_rdma_count_mappings(xprt, ctxt); - - /* Prepare SEND WR */ - memset(&err_wr, 0, sizeof(err_wr)); -diff --git a/net/sunrpc/xprtrdma/svc_rdma_transport.c b/net/sunrpc/xprtrdma/svc_rdma_transport.c -index dd94401..924271c 100644 ---- a/net/sunrpc/xprtrdma/svc_rdma_transport.c -+++ b/net/sunrpc/xprtrdma/svc_rdma_transport.c -@@ -198,6 +198,7 @@ struct svc_rdma_op_ctxt *svc_rdma_get_context(struct svcxprt_rdma *xprt) - - out: - ctxt->count = 0; -+ ctxt->mapped_sges = 0; - ctxt->frmr = NULL; - return ctxt; - -@@ -221,22 +222,27 @@ struct svc_rdma_op_ctxt *svc_rdma_get_context(struct svcxprt_rdma *xprt) - void svc_rdma_unmap_dma(struct svc_rdma_op_ctxt *ctxt) - { - struct svcxprt_rdma *xprt = ctxt->xprt; -- int i; -- for (i = 0; i < ctxt->count && ctxt->sge[i].length; i++) { -+ struct ib_device *device = xprt->sc_cm_id->device; -+ u32 lkey = xprt->sc_pd->local_dma_lkey; -+ unsigned int i, count; -+ -+ for (count = 0, i = 0; i < ctxt->mapped_sges; i++) { - /* - * Unmap the DMA addr in the SGE if the lkey matches - * the local_dma_lkey, otherwise, ignore it since it is - * an FRMR lkey and will be unmapped later when the - * last WR that uses it completes. - */ -- if (ctxt->sge[i].lkey == xprt->sc_pd->local_dma_lkey) { -- atomic_dec(&xprt->sc_dma_used); -- ib_dma_unmap_page(xprt->sc_cm_id->device, -+ if (ctxt->sge[i].lkey == lkey) { -+ count++; -+ ib_dma_unmap_page(device, - ctxt->sge[i].addr, - ctxt->sge[i].length, - ctxt->direction); - } - } -+ ctxt->mapped_sges = 0; -+ atomic_sub(count, &xprt->sc_dma_used); - } - - void svc_rdma_put_context(struct svc_rdma_op_ctxt *ctxt, int free_pages) -@@ -600,7 +606,7 @@ int svc_rdma_post_recv(struct svcxprt_rdma *xprt, gfp_t flags) - DMA_FROM_DEVICE); - if (ib_dma_mapping_error(xprt->sc_cm_id->device, pa)) - goto err_put_ctxt; -- atomic_inc(&xprt->sc_dma_used); -+ svc_rdma_count_mappings(xprt, ctxt); - ctxt->sge[sge_no].addr = pa; - ctxt->sge[sge_no].length = PAGE_SIZE; - ctxt->sge[sge_no].lkey = xprt->sc_pd->local_dma_lkey; -diff --git a/net/sunrpc/xprtrdma/xprt_rdma.h b/net/sunrpc/xprtrdma/xprt_rdma.h -index a71b0f5..edc0344 100644 ---- a/net/sunrpc/xprtrdma/xprt_rdma.h -+++ b/net/sunrpc/xprtrdma/xprt_rdma.h -@@ -207,7 +207,8 @@ struct rpcrdma_rep { - enum rpcrdma_frmr_state { - FRMR_IS_INVALID, /* ready to be used */ - FRMR_IS_VALID, /* in use */ -- FRMR_IS_STALE, /* failed completion */ -+ FRMR_FLUSHED_FR, /* flushed FASTREG WR */ -+ FRMR_FLUSHED_LI, /* flushed LOCALINV WR */ - }; - - struct rpcrdma_frmr { -diff --git a/sound/core/info.c b/sound/core/info.c -index 895362a..8ab72e0 100644 ---- a/sound/core/info.c -+++ b/sound/core/info.c -@@ -325,10 +325,15 @@ static ssize_t snd_info_text_entry_write(struct file *file, - size_t next; - int err = 0; - -+ if (!entry->c.text.write) -+ return -EIO; - pos = *offset; - if (!valid_pos(pos, count)) - return -EIO; - next = pos + count; -+ /* don't handle too large text inputs */ -+ if (next > 16 * 1024) -+ return -EIO; - mutex_lock(&entry->access); - buf = data->wbuffer; - if (!buf) { -@@ -366,7 +371,9 @@ static int snd_info_seq_show(struct seq_file *seq, void *p) - struct snd_info_private_data *data = seq->private; - struct snd_info_entry *entry = data->entry; - -- if (entry->c.text.read) { -+ if (!entry->c.text.read) { -+ return -EIO; -+ } else { - data->rbuffer->buffer = (char *)seq; /* XXX hack! */ - entry->c.text.read(entry, data->rbuffer); - } -diff --git a/sound/soc/codecs/cs4270.c b/sound/soc/codecs/cs4270.c -index e07807d..3670086b 100644 ---- a/sound/soc/codecs/cs4270.c -+++ b/sound/soc/codecs/cs4270.c -@@ -148,11 +148,11 @@ SND_SOC_DAPM_OUTPUT("AOUTR"), - }; - - static const struct snd_soc_dapm_route cs4270_dapm_routes[] = { -- { "Capture", NULL, "AINA" }, -- { "Capture", NULL, "AINB" }, -+ { "Capture", NULL, "AINL" }, -+ { "Capture", NULL, "AINR" }, - -- { "AOUTA", NULL, "Playback" }, -- { "AOUTB", NULL, "Playback" }, -+ { "AOUTL", NULL, "Playback" }, -+ { "AOUTR", NULL, "Playback" }, - }; - - /** -diff --git a/sound/soc/intel/skylake/skl.c b/sound/soc/intel/skylake/skl.c -index e3e7641..7b7a380 100644 ---- a/sound/soc/intel/skylake/skl.c -+++ b/sound/soc/intel/skylake/skl.c -@@ -785,8 +785,7 @@ static void skl_remove(struct pci_dev *pci) - - release_firmware(skl->tplg); - -- if (pci_dev_run_wake(pci)) -- pm_runtime_get_noresume(&pci->dev); -+ pm_runtime_get_noresume(&pci->dev); - - /* codec removal, invoke bus_device_remove */ - snd_hdac_ext_bus_device_remove(ebus); -diff --git a/sound/soc/sunxi/sun4i-codec.c b/sound/soc/sunxi/sun4i-codec.c -index 44f170c..03c18db 100644 ---- a/sound/soc/sunxi/sun4i-codec.c -+++ b/sound/soc/sunxi/sun4i-codec.c -@@ -738,11 +738,11 @@ static struct snd_soc_card *sun4i_codec_create_card(struct device *dev) - - card = devm_kzalloc(dev, sizeof(*card), GFP_KERNEL); - if (!card) -- return NULL; -+ return ERR_PTR(-ENOMEM); - - card->dai_link = sun4i_codec_create_link(dev, &card->num_links); - if (!card->dai_link) -- return NULL; -+ return ERR_PTR(-ENOMEM); - - card->dev = dev; - card->name = "sun4i-codec"; -@@ -842,7 +842,8 @@ static int sun4i_codec_probe(struct platform_device *pdev) - } - - card = sun4i_codec_create_card(&pdev->dev); -- if (!card) { -+ if (IS_ERR(card)) { -+ ret = PTR_ERR(card); - dev_err(&pdev->dev, "Failed to create our card\n"); - goto err_unregister_codec; - } -diff --git a/tools/perf/ui/browsers/hists.c b/tools/perf/ui/browsers/hists.c -index 7aee954..4ad1eac 100644 ---- a/tools/perf/ui/browsers/hists.c -+++ b/tools/perf/ui/browsers/hists.c -@@ -595,7 +595,8 @@ int hist_browser__run(struct hist_browser *browser, const char *help) - u64 nr_entries; - hbt->timer(hbt->arg); - -- if (hist_browser__has_filter(browser)) -+ if (hist_browser__has_filter(browser) || -+ symbol_conf.report_hierarchy) - hist_browser__update_nr_entries(browser); - - nr_entries = hist_browser__nr_entries(browser); -diff --git a/tools/power/cpupower/utils/cpufreq-set.c b/tools/power/cpupower/utils/cpufreq-set.c -index b4bf769..1eef0ae 100644 ---- a/tools/power/cpupower/utils/cpufreq-set.c -+++ b/tools/power/cpupower/utils/cpufreq-set.c -@@ -296,7 +296,7 @@ int cmd_freq_set(int argc, char **argv) - struct cpufreq_affected_cpus *cpus; - - if (!bitmask_isbitset(cpus_chosen, cpu) || -- cpupower_is_cpu_online(cpu)) -+ cpupower_is_cpu_online(cpu) != 1) - continue; - - cpus = cpufreq_get_related_cpus(cpu); -@@ -316,10 +316,7 @@ int cmd_freq_set(int argc, char **argv) - cpu <= bitmask_last(cpus_chosen); cpu++) { - - if (!bitmask_isbitset(cpus_chosen, cpu) || -- cpupower_is_cpu_online(cpu)) -- continue; -- -- if (cpupower_is_cpu_online(cpu) != 1) -+ cpupower_is_cpu_online(cpu) != 1) - continue; - - printf(_("Setting cpu: %d\n"), cpu); -diff --git a/virt/kvm/arm/vgic/vgic-mmio.c b/virt/kvm/arm/vgic/vgic-mmio.c -index 3bad3c5..d1b080c 100644 ---- a/virt/kvm/arm/vgic/vgic-mmio.c -+++ b/virt/kvm/arm/vgic/vgic-mmio.c -@@ -453,17 +453,33 @@ struct vgic_io_device *kvm_to_vgic_iodev(const struct kvm_io_device *dev) - return container_of(dev, struct vgic_io_device, dev); - } - --static bool check_region(const struct vgic_register_region *region, -+static bool check_region(const struct kvm *kvm, -+ const struct vgic_register_region *region, - gpa_t addr, int len) - { -- if ((region->access_flags & VGIC_ACCESS_8bit) && len == 1) -- return true; -- if ((region->access_flags & VGIC_ACCESS_32bit) && -- len == sizeof(u32) && !(addr & 3)) -- return true; -- if ((region->access_flags & VGIC_ACCESS_64bit) && -- len == sizeof(u64) && !(addr & 7)) -- return true; -+ int flags, nr_irqs = kvm->arch.vgic.nr_spis + VGIC_NR_PRIVATE_IRQS; -+ -+ switch (len) { -+ case sizeof(u8): -+ flags = VGIC_ACCESS_8bit; -+ break; -+ case sizeof(u32): -+ flags = VGIC_ACCESS_32bit; -+ break; -+ case sizeof(u64): -+ flags = VGIC_ACCESS_64bit; -+ break; -+ default: -+ return false; -+ } -+ -+ if ((region->access_flags & flags) && IS_ALIGNED(addr, len)) { -+ if (!region->bits_per_irq) -+ return true; -+ -+ /* Do we access a non-allocated IRQ? */ -+ return VGIC_ADDR_TO_INTID(addr, region->bits_per_irq) < nr_irqs; -+ } - - return false; - } -@@ -477,7 +493,7 @@ static int dispatch_mmio_read(struct kvm_vcpu *vcpu, struct kvm_io_device *dev, - - region = vgic_find_mmio_region(iodev->regions, iodev->nr_regions, - addr - iodev->base_addr); -- if (!region || !check_region(region, addr, len)) { -+ if (!region || !check_region(vcpu->kvm, region, addr, len)) { - memset(val, 0, len); - return 0; - } -@@ -510,10 +526,7 @@ static int dispatch_mmio_write(struct kvm_vcpu *vcpu, struct kvm_io_device *dev, - - region = vgic_find_mmio_region(iodev->regions, iodev->nr_regions, - addr - iodev->base_addr); -- if (!region) -- return 0; -- -- if (!check_region(region, addr, len)) -+ if (!region || !check_region(vcpu->kvm, region, addr, len)) - return 0; - - switch (iodev->iodev_type) { -diff --git a/virt/kvm/arm/vgic/vgic-mmio.h b/virt/kvm/arm/vgic/vgic-mmio.h -index 0b3ecf9..ba63d91 100644 ---- a/virt/kvm/arm/vgic/vgic-mmio.h -+++ b/virt/kvm/arm/vgic/vgic-mmio.h -@@ -50,15 +50,15 @@ extern struct kvm_io_device_ops kvm_io_gic_ops; - #define VGIC_ADDR_IRQ_MASK(bits) (((bits) * 1024 / 8) - 1) - - /* -- * (addr & mask) gives us the byte offset for the INT ID, so we want to -- * divide this with 'bytes per irq' to get the INT ID, which is given -- * by '(bits) / 8'. But we do this with fixed-point-arithmetic and -- * take advantage of the fact that division by a fraction equals -- * multiplication with the inverted fraction, and scale up both the -- * numerator and denominator with 8 to support at most 64 bits per IRQ: -+ * (addr & mask) gives us the _byte_ offset for the INT ID. -+ * We multiply this by 8 the get the _bit_ offset, then divide this by -+ * the number of bits to learn the actual INT ID. -+ * But instead of a division (which requires a "long long div" implementation), -+ * we shift by the binary logarithm of <bits>. -+ * This assumes that <bits> is a power of two. - */ - #define VGIC_ADDR_TO_INTID(addr, bits) (((addr) & VGIC_ADDR_IRQ_MASK(bits)) * \ -- 64 / (bits) / 8) -+ 8 >> ilog2(bits)) - - /* - * Some VGIC registers store per-IRQ information, with a different number diff --git a/4.8.11/1009_linux-4.8.10.patch b/4.8.11/1009_linux-4.8.10.patch deleted file mode 100644 index 1e751e5..0000000 --- a/4.8.11/1009_linux-4.8.10.patch +++ /dev/null @@ -1,4759 +0,0 @@ -diff --git a/Makefile b/Makefile -index c1519ab..7cf2b49 100644 ---- a/Makefile -+++ b/Makefile -@@ -1,6 +1,6 @@ - VERSION = 4 - PATCHLEVEL = 8 --SUBLEVEL = 9 -+SUBLEVEL = 10 - EXTRAVERSION = - NAME = Psychotic Stoned Sheep - -diff --git a/arch/sparc/include/asm/uaccess_64.h b/arch/sparc/include/asm/uaccess_64.h -index 37a315d..a6847fc 100644 ---- a/arch/sparc/include/asm/uaccess_64.h -+++ b/arch/sparc/include/asm/uaccess_64.h -@@ -98,7 +98,6 @@ struct exception_table_entry { - unsigned int insn, fixup; - }; - --void __ret_efault(void); - void __retl_efault(void); - - /* Uh, these should become the main single-value transfer routines.. -@@ -205,55 +204,34 @@ int __get_user_bad(void); - unsigned long __must_check ___copy_from_user(void *to, - const void __user *from, - unsigned long size); --unsigned long copy_from_user_fixup(void *to, const void __user *from, -- unsigned long size); - static inline unsigned long __must_check - copy_from_user(void *to, const void __user *from, unsigned long size) - { -- unsigned long ret; -- - check_object_size(to, size, false); - -- ret = ___copy_from_user(to, from, size); -- if (unlikely(ret)) -- ret = copy_from_user_fixup(to, from, size); -- -- return ret; -+ return ___copy_from_user(to, from, size); - } - #define __copy_from_user copy_from_user - - unsigned long __must_check ___copy_to_user(void __user *to, - const void *from, - unsigned long size); --unsigned long copy_to_user_fixup(void __user *to, const void *from, -- unsigned long size); - static inline unsigned long __must_check - copy_to_user(void __user *to, const void *from, unsigned long size) - { -- unsigned long ret; -- - check_object_size(from, size, true); - -- ret = ___copy_to_user(to, from, size); -- if (unlikely(ret)) -- ret = copy_to_user_fixup(to, from, size); -- return ret; -+ return ___copy_to_user(to, from, size); - } - #define __copy_to_user copy_to_user - - unsigned long __must_check ___copy_in_user(void __user *to, - const void __user *from, - unsigned long size); --unsigned long copy_in_user_fixup(void __user *to, void __user *from, -- unsigned long size); - static inline unsigned long __must_check - copy_in_user(void __user *to, void __user *from, unsigned long size) - { -- unsigned long ret = ___copy_in_user(to, from, size); -- -- if (unlikely(ret)) -- ret = copy_in_user_fixup(to, from, size); -- return ret; -+ return ___copy_in_user(to, from, size); - } - #define __copy_in_user copy_in_user - -diff --git a/arch/sparc/kernel/head_64.S b/arch/sparc/kernel/head_64.S -index a076b42..5f1f3ae 100644 ---- a/arch/sparc/kernel/head_64.S -+++ b/arch/sparc/kernel/head_64.S -@@ -922,47 +922,11 @@ prom_tba: .xword 0 - tlb_type: .word 0 /* Must NOT end up in BSS */ - .section ".fixup",#alloc,#execinstr - -- .globl __ret_efault, __retl_efault, __ret_one, __retl_one --ENTRY(__ret_efault) -- ret -- restore %g0, -EFAULT, %o0 --ENDPROC(__ret_efault) -- - ENTRY(__retl_efault) - retl - mov -EFAULT, %o0 - ENDPROC(__retl_efault) - --ENTRY(__retl_one) -- retl -- mov 1, %o0 --ENDPROC(__retl_one) -- --ENTRY(__retl_one_fp) -- VISExitHalf -- retl -- mov 1, %o0 --ENDPROC(__retl_one_fp) -- --ENTRY(__ret_one_asi) -- wr %g0, ASI_AIUS, %asi -- ret -- restore %g0, 1, %o0 --ENDPROC(__ret_one_asi) -- --ENTRY(__retl_one_asi) -- wr %g0, ASI_AIUS, %asi -- retl -- mov 1, %o0 --ENDPROC(__retl_one_asi) -- --ENTRY(__retl_one_asi_fp) -- wr %g0, ASI_AIUS, %asi -- VISExitHalf -- retl -- mov 1, %o0 --ENDPROC(__retl_one_asi_fp) -- - ENTRY(__retl_o1) - retl - mov %o1, %o0 -diff --git a/arch/sparc/kernel/jump_label.c b/arch/sparc/kernel/jump_label.c -index 59bbeff..07933b9 100644 ---- a/arch/sparc/kernel/jump_label.c -+++ b/arch/sparc/kernel/jump_label.c -@@ -13,19 +13,30 @@ - void arch_jump_label_transform(struct jump_entry *entry, - enum jump_label_type type) - { -- u32 val; - u32 *insn = (u32 *) (unsigned long) entry->code; -+ u32 val; - - if (type == JUMP_LABEL_JMP) { - s32 off = (s32)entry->target - (s32)entry->code; -+ bool use_v9_branch = false; -+ -+ BUG_ON(off & 3); - - #ifdef CONFIG_SPARC64 -- /* ba,pt %xcc, . + (off << 2) */ -- val = 0x10680000 | ((u32) off >> 2); --#else -- /* ba . + (off << 2) */ -- val = 0x10800000 | ((u32) off >> 2); -+ if (off <= 0xfffff && off >= -0x100000) -+ use_v9_branch = true; - #endif -+ if (use_v9_branch) { -+ /* WDISP19 - target is . + immed << 2 */ -+ /* ba,pt %xcc, . + off */ -+ val = 0x10680000 | (((u32) off >> 2) & 0x7ffff); -+ } else { -+ /* WDISP22 - target is . + immed << 2 */ -+ BUG_ON(off > 0x7fffff); -+ BUG_ON(off < -0x800000); -+ /* ba . + off */ -+ val = 0x10800000 | (((u32) off >> 2) & 0x3fffff); -+ } - } else { - val = 0x01000000; - } -diff --git a/arch/sparc/kernel/sparc_ksyms_64.c b/arch/sparc/kernel/sparc_ksyms_64.c -index 9e034f2..20ffb05 100644 ---- a/arch/sparc/kernel/sparc_ksyms_64.c -+++ b/arch/sparc/kernel/sparc_ksyms_64.c -@@ -27,7 +27,6 @@ EXPORT_SYMBOL(__flushw_user); - EXPORT_SYMBOL_GPL(real_hard_smp_processor_id); - - /* from head_64.S */ --EXPORT_SYMBOL(__ret_efault); - EXPORT_SYMBOL(tlb_type); - EXPORT_SYMBOL(sun4v_chip_type); - EXPORT_SYMBOL(prom_root_node); -diff --git a/arch/sparc/lib/GENcopy_from_user.S b/arch/sparc/lib/GENcopy_from_user.S -index b7d0bd6..69a439f 100644 ---- a/arch/sparc/lib/GENcopy_from_user.S -+++ b/arch/sparc/lib/GENcopy_from_user.S -@@ -3,11 +3,11 @@ - * Copyright (C) 2007 David S. Miller (davem@davemloft.net) - */ - --#define EX_LD(x) \ -+#define EX_LD(x,y) \ - 98: x; \ - .section __ex_table,"a";\ - .align 4; \ -- .word 98b, __retl_one; \ -+ .word 98b, y; \ - .text; \ - .align 4; - -diff --git a/arch/sparc/lib/GENcopy_to_user.S b/arch/sparc/lib/GENcopy_to_user.S -index 780550e..9947427 100644 ---- a/arch/sparc/lib/GENcopy_to_user.S -+++ b/arch/sparc/lib/GENcopy_to_user.S -@@ -3,11 +3,11 @@ - * Copyright (C) 2007 David S. Miller (davem@davemloft.net) - */ - --#define EX_ST(x) \ -+#define EX_ST(x,y) \ - 98: x; \ - .section __ex_table,"a";\ - .align 4; \ -- .word 98b, __retl_one; \ -+ .word 98b, y; \ - .text; \ - .align 4; - -diff --git a/arch/sparc/lib/GENmemcpy.S b/arch/sparc/lib/GENmemcpy.S -index 89358ee..059ea24 100644 ---- a/arch/sparc/lib/GENmemcpy.S -+++ b/arch/sparc/lib/GENmemcpy.S -@@ -4,21 +4,18 @@ - */ - - #ifdef __KERNEL__ -+#include <linux/linkage.h> - #define GLOBAL_SPARE %g7 - #else - #define GLOBAL_SPARE %g5 - #endif - - #ifndef EX_LD --#define EX_LD(x) x -+#define EX_LD(x,y) x - #endif - - #ifndef EX_ST --#define EX_ST(x) x --#endif -- --#ifndef EX_RETVAL --#define EX_RETVAL(x) x -+#define EX_ST(x,y) x - #endif - - #ifndef LOAD -@@ -45,6 +42,29 @@ - .register %g3,#scratch - - .text -+ -+#ifndef EX_RETVAL -+#define EX_RETVAL(x) x -+ENTRY(GEN_retl_o4_1) -+ add %o4, %o2, %o4 -+ retl -+ add %o4, 1, %o0 -+ENDPROC(GEN_retl_o4_1) -+ENTRY(GEN_retl_g1_8) -+ add %g1, %o2, %g1 -+ retl -+ add %g1, 8, %o0 -+ENDPROC(GEN_retl_g1_8) -+ENTRY(GEN_retl_o2_4) -+ retl -+ add %o2, 4, %o0 -+ENDPROC(GEN_retl_o2_4) -+ENTRY(GEN_retl_o2_1) -+ retl -+ add %o2, 1, %o0 -+ENDPROC(GEN_retl_o2_1) -+#endif -+ - .align 64 - - .globl FUNC_NAME -@@ -73,8 +93,8 @@ FUNC_NAME: /* %o0=dst, %o1=src, %o2=len */ - sub %g0, %o4, %o4 - sub %o2, %o4, %o2 - 1: subcc %o4, 1, %o4 -- EX_LD(LOAD(ldub, %o1, %g1)) -- EX_ST(STORE(stb, %g1, %o0)) -+ EX_LD(LOAD(ldub, %o1, %g1),GEN_retl_o4_1) -+ EX_ST(STORE(stb, %g1, %o0),GEN_retl_o4_1) - add %o1, 1, %o1 - bne,pt %XCC, 1b - add %o0, 1, %o0 -@@ -82,8 +102,8 @@ FUNC_NAME: /* %o0=dst, %o1=src, %o2=len */ - andn %o2, 0x7, %g1 - sub %o2, %g1, %o2 - 1: subcc %g1, 0x8, %g1 -- EX_LD(LOAD(ldx, %o1, %g2)) -- EX_ST(STORE(stx, %g2, %o0)) -+ EX_LD(LOAD(ldx, %o1, %g2),GEN_retl_g1_8) -+ EX_ST(STORE(stx, %g2, %o0),GEN_retl_g1_8) - add %o1, 0x8, %o1 - bne,pt %XCC, 1b - add %o0, 0x8, %o0 -@@ -100,8 +120,8 @@ FUNC_NAME: /* %o0=dst, %o1=src, %o2=len */ - - 1: - subcc %o2, 4, %o2 -- EX_LD(LOAD(lduw, %o1, %g1)) -- EX_ST(STORE(stw, %g1, %o1 + %o3)) -+ EX_LD(LOAD(lduw, %o1, %g1),GEN_retl_o2_4) -+ EX_ST(STORE(stw, %g1, %o1 + %o3),GEN_retl_o2_4) - bgu,pt %XCC, 1b - add %o1, 4, %o1 - -@@ -111,8 +131,8 @@ FUNC_NAME: /* %o0=dst, %o1=src, %o2=len */ - .align 32 - 90: - subcc %o2, 1, %o2 -- EX_LD(LOAD(ldub, %o1, %g1)) -- EX_ST(STORE(stb, %g1, %o1 + %o3)) -+ EX_LD(LOAD(ldub, %o1, %g1),GEN_retl_o2_1) -+ EX_ST(STORE(stb, %g1, %o1 + %o3),GEN_retl_o2_1) - bgu,pt %XCC, 90b - add %o1, 1, %o1 - retl -diff --git a/arch/sparc/lib/Makefile b/arch/sparc/lib/Makefile -index 3269b02..4f2384a 100644 ---- a/arch/sparc/lib/Makefile -+++ b/arch/sparc/lib/Makefile -@@ -38,7 +38,7 @@ lib-$(CONFIG_SPARC64) += NG4patch.o NG4copy_page.o NG4clear_page.o NG4memset.o - lib-$(CONFIG_SPARC64) += GENmemcpy.o GENcopy_from_user.o GENcopy_to_user.o - lib-$(CONFIG_SPARC64) += GENpatch.o GENpage.o GENbzero.o - --lib-$(CONFIG_SPARC64) += copy_in_user.o user_fixup.o memmove.o -+lib-$(CONFIG_SPARC64) += copy_in_user.o memmove.o - lib-$(CONFIG_SPARC64) += mcount.o ipcsum.o xor.o hweight.o ffs.o - - obj-$(CONFIG_SPARC64) += iomap.o -diff --git a/arch/sparc/lib/NG2copy_from_user.S b/arch/sparc/lib/NG2copy_from_user.S -index d5242b8..b79a699 100644 ---- a/arch/sparc/lib/NG2copy_from_user.S -+++ b/arch/sparc/lib/NG2copy_from_user.S -@@ -3,19 +3,19 @@ - * Copyright (C) 2007 David S. Miller (davem@davemloft.net) - */ - --#define EX_LD(x) \ -+#define EX_LD(x,y) \ - 98: x; \ - .section __ex_table,"a";\ - .align 4; \ -- .word 98b, __retl_one_asi;\ -+ .word 98b, y; \ - .text; \ - .align 4; - --#define EX_LD_FP(x) \ -+#define EX_LD_FP(x,y) \ - 98: x; \ - .section __ex_table,"a";\ - .align 4; \ -- .word 98b, __retl_one_asi_fp;\ -+ .word 98b, y##_fp; \ - .text; \ - .align 4; - -diff --git a/arch/sparc/lib/NG2copy_to_user.S b/arch/sparc/lib/NG2copy_to_user.S -index 4e962d9..dcec55f 100644 ---- a/arch/sparc/lib/NG2copy_to_user.S -+++ b/arch/sparc/lib/NG2copy_to_user.S -@@ -3,19 +3,19 @@ - * Copyright (C) 2007 David S. Miller (davem@davemloft.net) - */ - --#define EX_ST(x) \ -+#define EX_ST(x,y) \ - 98: x; \ - .section __ex_table,"a";\ - .align 4; \ -- .word 98b, __retl_one_asi;\ -+ .word 98b, y; \ - .text; \ - .align 4; - --#define EX_ST_FP(x) \ -+#define EX_ST_FP(x,y) \ - 98: x; \ - .section __ex_table,"a";\ - .align 4; \ -- .word 98b, __retl_one_asi_fp;\ -+ .word 98b, y##_fp; \ - .text; \ - .align 4; - -diff --git a/arch/sparc/lib/NG2memcpy.S b/arch/sparc/lib/NG2memcpy.S -index d5f585d..c629dbd 100644 ---- a/arch/sparc/lib/NG2memcpy.S -+++ b/arch/sparc/lib/NG2memcpy.S -@@ -4,6 +4,7 @@ - */ - - #ifdef __KERNEL__ -+#include <linux/linkage.h> - #include <asm/visasm.h> - #include <asm/asi.h> - #define GLOBAL_SPARE %g7 -@@ -32,21 +33,17 @@ - #endif - - #ifndef EX_LD --#define EX_LD(x) x -+#define EX_LD(x,y) x - #endif - #ifndef EX_LD_FP --#define EX_LD_FP(x) x -+#define EX_LD_FP(x,y) x - #endif - - #ifndef EX_ST --#define EX_ST(x) x -+#define EX_ST(x,y) x - #endif - #ifndef EX_ST_FP --#define EX_ST_FP(x) x --#endif -- --#ifndef EX_RETVAL --#define EX_RETVAL(x) x -+#define EX_ST_FP(x,y) x - #endif - - #ifndef LOAD -@@ -140,45 +137,110 @@ - fsrc2 %x6, %f12; \ - fsrc2 %x7, %f14; - #define FREG_LOAD_1(base, x0) \ -- EX_LD_FP(LOAD(ldd, base + 0x00, %x0)) -+ EX_LD_FP(LOAD(ldd, base + 0x00, %x0), NG2_retl_o2_plus_g1) - #define FREG_LOAD_2(base, x0, x1) \ -- EX_LD_FP(LOAD(ldd, base + 0x00, %x0)); \ -- EX_LD_FP(LOAD(ldd, base + 0x08, %x1)); -+ EX_LD_FP(LOAD(ldd, base + 0x00, %x0), NG2_retl_o2_plus_g1); \ -+ EX_LD_FP(LOAD(ldd, base + 0x08, %x1), NG2_retl_o2_plus_g1); - #define FREG_LOAD_3(base, x0, x1, x2) \ -- EX_LD_FP(LOAD(ldd, base + 0x00, %x0)); \ -- EX_LD_FP(LOAD(ldd, base + 0x08, %x1)); \ -- EX_LD_FP(LOAD(ldd, base + 0x10, %x2)); -+ EX_LD_FP(LOAD(ldd, base + 0x00, %x0), NG2_retl_o2_plus_g1); \ -+ EX_LD_FP(LOAD(ldd, base + 0x08, %x1), NG2_retl_o2_plus_g1); \ -+ EX_LD_FP(LOAD(ldd, base + 0x10, %x2), NG2_retl_o2_plus_g1); - #define FREG_LOAD_4(base, x0, x1, x2, x3) \ -- EX_LD_FP(LOAD(ldd, base + 0x00, %x0)); \ -- EX_LD_FP(LOAD(ldd, base + 0x08, %x1)); \ -- EX_LD_FP(LOAD(ldd, base + 0x10, %x2)); \ -- EX_LD_FP(LOAD(ldd, base + 0x18, %x3)); -+ EX_LD_FP(LOAD(ldd, base + 0x00, %x0), NG2_retl_o2_plus_g1); \ -+ EX_LD_FP(LOAD(ldd, base + 0x08, %x1), NG2_retl_o2_plus_g1); \ -+ EX_LD_FP(LOAD(ldd, base + 0x10, %x2), NG2_retl_o2_plus_g1); \ -+ EX_LD_FP(LOAD(ldd, base + 0x18, %x3), NG2_retl_o2_plus_g1); - #define FREG_LOAD_5(base, x0, x1, x2, x3, x4) \ -- EX_LD_FP(LOAD(ldd, base + 0x00, %x0)); \ -- EX_LD_FP(LOAD(ldd, base + 0x08, %x1)); \ -- EX_LD_FP(LOAD(ldd, base + 0x10, %x2)); \ -- EX_LD_FP(LOAD(ldd, base + 0x18, %x3)); \ -- EX_LD_FP(LOAD(ldd, base + 0x20, %x4)); -+ EX_LD_FP(LOAD(ldd, base + 0x00, %x0), NG2_retl_o2_plus_g1); \ -+ EX_LD_FP(LOAD(ldd, base + 0x08, %x1), NG2_retl_o2_plus_g1); \ -+ EX_LD_FP(LOAD(ldd, base + 0x10, %x2), NG2_retl_o2_plus_g1); \ -+ EX_LD_FP(LOAD(ldd, base + 0x18, %x3), NG2_retl_o2_plus_g1); \ -+ EX_LD_FP(LOAD(ldd, base + 0x20, %x4), NG2_retl_o2_plus_g1); - #define FREG_LOAD_6(base, x0, x1, x2, x3, x4, x5) \ -- EX_LD_FP(LOAD(ldd, base + 0x00, %x0)); \ -- EX_LD_FP(LOAD(ldd, base + 0x08, %x1)); \ -- EX_LD_FP(LOAD(ldd, base + 0x10, %x2)); \ -- EX_LD_FP(LOAD(ldd, base + 0x18, %x3)); \ -- EX_LD_FP(LOAD(ldd, base + 0x20, %x4)); \ -- EX_LD_FP(LOAD(ldd, base + 0x28, %x5)); -+ EX_LD_FP(LOAD(ldd, base + 0x00, %x0), NG2_retl_o2_plus_g1); \ -+ EX_LD_FP(LOAD(ldd, base + 0x08, %x1), NG2_retl_o2_plus_g1); \ -+ EX_LD_FP(LOAD(ldd, base + 0x10, %x2), NG2_retl_o2_plus_g1); \ -+ EX_LD_FP(LOAD(ldd, base + 0x18, %x3), NG2_retl_o2_plus_g1); \ -+ EX_LD_FP(LOAD(ldd, base + 0x20, %x4), NG2_retl_o2_plus_g1); \ -+ EX_LD_FP(LOAD(ldd, base + 0x28, %x5), NG2_retl_o2_plus_g1); - #define FREG_LOAD_7(base, x0, x1, x2, x3, x4, x5, x6) \ -- EX_LD_FP(LOAD(ldd, base + 0x00, %x0)); \ -- EX_LD_FP(LOAD(ldd, base + 0x08, %x1)); \ -- EX_LD_FP(LOAD(ldd, base + 0x10, %x2)); \ -- EX_LD_FP(LOAD(ldd, base + 0x18, %x3)); \ -- EX_LD_FP(LOAD(ldd, base + 0x20, %x4)); \ -- EX_LD_FP(LOAD(ldd, base + 0x28, %x5)); \ -- EX_LD_FP(LOAD(ldd, base + 0x30, %x6)); -+ EX_LD_FP(LOAD(ldd, base + 0x00, %x0), NG2_retl_o2_plus_g1); \ -+ EX_LD_FP(LOAD(ldd, base + 0x08, %x1), NG2_retl_o2_plus_g1); \ -+ EX_LD_FP(LOAD(ldd, base + 0x10, %x2), NG2_retl_o2_plus_g1); \ -+ EX_LD_FP(LOAD(ldd, base + 0x18, %x3), NG2_retl_o2_plus_g1); \ -+ EX_LD_FP(LOAD(ldd, base + 0x20, %x4), NG2_retl_o2_plus_g1); \ -+ EX_LD_FP(LOAD(ldd, base + 0x28, %x5), NG2_retl_o2_plus_g1); \ -+ EX_LD_FP(LOAD(ldd, base + 0x30, %x6), NG2_retl_o2_plus_g1); - - .register %g2,#scratch - .register %g3,#scratch - - .text -+#ifndef EX_RETVAL -+#define EX_RETVAL(x) x -+__restore_fp: -+ VISExitHalf -+__restore_asi: -+ retl -+ wr %g0, ASI_AIUS, %asi -+ENTRY(NG2_retl_o2) -+ ba,pt %xcc, __restore_asi -+ mov %o2, %o0 -+ENDPROC(NG2_retl_o2) -+ENTRY(NG2_retl_o2_plus_1) -+ ba,pt %xcc, __restore_asi -+ add %o2, 1, %o0 -+ENDPROC(NG2_retl_o2_plus_1) -+ENTRY(NG2_retl_o2_plus_4) -+ ba,pt %xcc, __restore_asi -+ add %o2, 4, %o0 -+ENDPROC(NG2_retl_o2_plus_4) -+ENTRY(NG2_retl_o2_plus_8) -+ ba,pt %xcc, __restore_asi -+ add %o2, 8, %o0 -+ENDPROC(NG2_retl_o2_plus_8) -+ENTRY(NG2_retl_o2_plus_o4_plus_1) -+ add %o4, 1, %o4 -+ ba,pt %xcc, __restore_asi -+ add %o2, %o4, %o0 -+ENDPROC(NG2_retl_o2_plus_o4_plus_1) -+ENTRY(NG2_retl_o2_plus_o4_plus_8) -+ add %o4, 8, %o4 -+ ba,pt %xcc, __restore_asi -+ add %o2, %o4, %o0 -+ENDPROC(NG2_retl_o2_plus_o4_plus_8) -+ENTRY(NG2_retl_o2_plus_o4_plus_16) -+ add %o4, 16, %o4 -+ ba,pt %xcc, __restore_asi -+ add %o2, %o4, %o0 -+ENDPROC(NG2_retl_o2_plus_o4_plus_16) -+ENTRY(NG2_retl_o2_plus_g1_fp) -+ ba,pt %xcc, __restore_fp -+ add %o2, %g1, %o0 -+ENDPROC(NG2_retl_o2_plus_g1_fp) -+ENTRY(NG2_retl_o2_plus_g1_plus_64_fp) -+ add %g1, 64, %g1 -+ ba,pt %xcc, __restore_fp -+ add %o2, %g1, %o0 -+ENDPROC(NG2_retl_o2_plus_g1_plus_64_fp) -+ENTRY(NG2_retl_o2_plus_g1_plus_1) -+ add %g1, 1, %g1 -+ ba,pt %xcc, __restore_asi -+ add %o2, %g1, %o0 -+ENDPROC(NG2_retl_o2_plus_g1_plus_1) -+ENTRY(NG2_retl_o2_and_7_plus_o4) -+ and %o2, 7, %o2 -+ ba,pt %xcc, __restore_asi -+ add %o2, %o4, %o0 -+ENDPROC(NG2_retl_o2_and_7_plus_o4) -+ENTRY(NG2_retl_o2_and_7_plus_o4_plus_8) -+ and %o2, 7, %o2 -+ add %o4, 8, %o4 -+ ba,pt %xcc, __restore_asi -+ add %o2, %o4, %o0 -+ENDPROC(NG2_retl_o2_and_7_plus_o4_plus_8) -+#endif -+ - .align 64 - - .globl FUNC_NAME -@@ -230,8 +292,8 @@ FUNC_NAME: /* %o0=dst, %o1=src, %o2=len */ - sub %g0, %o4, %o4 ! bytes to align dst - sub %o2, %o4, %o2 - 1: subcc %o4, 1, %o4 -- EX_LD(LOAD(ldub, %o1, %g1)) -- EX_ST(STORE(stb, %g1, %o0)) -+ EX_LD(LOAD(ldub, %o1, %g1), NG2_retl_o2_plus_o4_plus_1) -+ EX_ST(STORE(stb, %g1, %o0), NG2_retl_o2_plus_o4_plus_1) - add %o1, 1, %o1 - bne,pt %XCC, 1b - add %o0, 1, %o0 -@@ -281,11 +343,11 @@ FUNC_NAME: /* %o0=dst, %o1=src, %o2=len */ - nop - /* fall through for 0 < low bits < 8 */ - 110: sub %o4, 64, %g2 -- EX_LD_FP(LOAD_BLK(%g2, %f0)) --1: EX_ST_FP(STORE_INIT(%g0, %o4 + %g3)) -- EX_LD_FP(LOAD_BLK(%o4, %f16)) -+ EX_LD_FP(LOAD_BLK(%g2, %f0), NG2_retl_o2_plus_g1) -+1: EX_ST_FP(STORE_INIT(%g0, %o4 + %g3), NG2_retl_o2_plus_g1) -+ EX_LD_FP(LOAD_BLK(%o4, %f16), NG2_retl_o2_plus_g1) - FREG_FROB(f0, f2, f4, f6, f8, f10, f12, f14, f16) -- EX_ST_FP(STORE_BLK(%f0, %o4 + %g3)) -+ EX_ST_FP(STORE_BLK(%f0, %o4 + %g3), NG2_retl_o2_plus_g1) - FREG_MOVE_8(f16, f18, f20, f22, f24, f26, f28, f30) - subcc %g1, 64, %g1 - add %o4, 64, %o4 -@@ -296,10 +358,10 @@ FUNC_NAME: /* %o0=dst, %o1=src, %o2=len */ - - 120: sub %o4, 56, %g2 - FREG_LOAD_7(%g2, f0, f2, f4, f6, f8, f10, f12) --1: EX_ST_FP(STORE_INIT(%g0, %o4 + %g3)) -- EX_LD_FP(LOAD_BLK(%o4, %f16)) -+1: EX_ST_FP(STORE_INIT(%g0, %o4 + %g3), NG2_retl_o2_plus_g1) -+ EX_LD_FP(LOAD_BLK(%o4, %f16), NG2_retl_o2_plus_g1) - FREG_FROB(f0, f2, f4, f6, f8, f10, f12, f16, f18) -- EX_ST_FP(STORE_BLK(%f0, %o4 + %g3)) -+ EX_ST_FP(STORE_BLK(%f0, %o4 + %g3), NG2_retl_o2_plus_g1) - FREG_MOVE_7(f18, f20, f22, f24, f26, f28, f30) - subcc %g1, 64, %g1 - add %o4, 64, %o4 -@@ -310,10 +372,10 @@ FUNC_NAME: /* %o0=dst, %o1=src, %o2=len */ - - 130: sub %o4, 48, %g2 - FREG_LOAD_6(%g2, f0, f2, f4, f6, f8, f10) --1: EX_ST_FP(STORE_INIT(%g0, %o4 + %g3)) -- EX_LD_FP(LOAD_BLK(%o4, %f16)) -+1: EX_ST_FP(STORE_INIT(%g0, %o4 + %g3), NG2_retl_o2_plus_g1) -+ EX_LD_FP(LOAD_BLK(%o4, %f16), NG2_retl_o2_plus_g1) - FREG_FROB(f0, f2, f4, f6, f8, f10, f16, f18, f20) -- EX_ST_FP(STORE_BLK(%f0, %o4 + %g3)) -+ EX_ST_FP(STORE_BLK(%f0, %o4 + %g3), NG2_retl_o2_plus_g1) - FREG_MOVE_6(f20, f22, f24, f26, f28, f30) - subcc %g1, 64, %g1 - add %o4, 64, %o4 -@@ -324,10 +386,10 @@ FUNC_NAME: /* %o0=dst, %o1=src, %o2=len */ - - 140: sub %o4, 40, %g2 - FREG_LOAD_5(%g2, f0, f2, f4, f6, f8) --1: EX_ST_FP(STORE_INIT(%g0, %o4 + %g3)) -- EX_LD_FP(LOAD_BLK(%o4, %f16)) -+1: EX_ST_FP(STORE_INIT(%g0, %o4 + %g3), NG2_retl_o2_plus_g1) -+ EX_LD_FP(LOAD_BLK(%o4, %f16), NG2_retl_o2_plus_g1) - FREG_FROB(f0, f2, f4, f6, f8, f16, f18, f20, f22) -- EX_ST_FP(STORE_BLK(%f0, %o4 + %g3)) -+ EX_ST_FP(STORE_BLK(%f0, %o4 + %g3), NG2_retl_o2_plus_g1) - FREG_MOVE_5(f22, f24, f26, f28, f30) - subcc %g1, 64, %g1 - add %o4, 64, %o4 -@@ -338,10 +400,10 @@ FUNC_NAME: /* %o0=dst, %o1=src, %o2=len */ - - 150: sub %o4, 32, %g2 - FREG_LOAD_4(%g2, f0, f2, f4, f6) --1: EX_ST_FP(STORE_INIT(%g0, %o4 + %g3)) -- EX_LD_FP(LOAD_BLK(%o4, %f16)) -+1: EX_ST_FP(STORE_INIT(%g0, %o4 + %g3), NG2_retl_o2_plus_g1) -+ EX_LD_FP(LOAD_BLK(%o4, %f16), NG2_retl_o2_plus_g1) - FREG_FROB(f0, f2, f4, f6, f16, f18, f20, f22, f24) -- EX_ST_FP(STORE_BLK(%f0, %o4 + %g3)) -+ EX_ST_FP(STORE_BLK(%f0, %o4 + %g3), NG2_retl_o2_plus_g1) - FREG_MOVE_4(f24, f26, f28, f30) - subcc %g1, 64, %g1 - add %o4, 64, %o4 -@@ -352,10 +414,10 @@ FUNC_NAME: /* %o0=dst, %o1=src, %o2=len */ - - 160: sub %o4, 24, %g2 - FREG_LOAD_3(%g2, f0, f2, f4) --1: EX_ST_FP(STORE_INIT(%g0, %o4 + %g3)) -- EX_LD_FP(LOAD_BLK(%o4, %f16)) -+1: EX_ST_FP(STORE_INIT(%g0, %o4 + %g3), NG2_retl_o2_plus_g1) -+ EX_LD_FP(LOAD_BLK(%o4, %f16), NG2_retl_o2_plus_g1) - FREG_FROB(f0, f2, f4, f16, f18, f20, f22, f24, f26) -- EX_ST_FP(STORE_BLK(%f0, %o4 + %g3)) -+ EX_ST_FP(STORE_BLK(%f0, %o4 + %g3), NG2_retl_o2_plus_g1) - FREG_MOVE_3(f26, f28, f30) - subcc %g1, 64, %g1 - add %o4, 64, %o4 -@@ -366,10 +428,10 @@ FUNC_NAME: /* %o0=dst, %o1=src, %o2=len */ - - 170: sub %o4, 16, %g2 - FREG_LOAD_2(%g2, f0, f2) --1: EX_ST_FP(STORE_INIT(%g0, %o4 + %g3)) -- EX_LD_FP(LOAD_BLK(%o4, %f16)) -+1: EX_ST_FP(STORE_INIT(%g0, %o4 + %g3), NG2_retl_o2_plus_g1) -+ EX_LD_FP(LOAD_BLK(%o4, %f16), NG2_retl_o2_plus_g1) - FREG_FROB(f0, f2, f16, f18, f20, f22, f24, f26, f28) -- EX_ST_FP(STORE_BLK(%f0, %o4 + %g3)) -+ EX_ST_FP(STORE_BLK(%f0, %o4 + %g3), NG2_retl_o2_plus_g1) - FREG_MOVE_2(f28, f30) - subcc %g1, 64, %g1 - add %o4, 64, %o4 -@@ -380,10 +442,10 @@ FUNC_NAME: /* %o0=dst, %o1=src, %o2=len */ - - 180: sub %o4, 8, %g2 - FREG_LOAD_1(%g2, f0) --1: EX_ST_FP(STORE_INIT(%g0, %o4 + %g3)) -- EX_LD_FP(LOAD_BLK(%o4, %f16)) -+1: EX_ST_FP(STORE_INIT(%g0, %o4 + %g3), NG2_retl_o2_plus_g1) -+ EX_LD_FP(LOAD_BLK(%o4, %f16), NG2_retl_o2_plus_g1) - FREG_FROB(f0, f16, f18, f20, f22, f24, f26, f28, f30) -- EX_ST_FP(STORE_BLK(%f0, %o4 + %g3)) -+ EX_ST_FP(STORE_BLK(%f0, %o4 + %g3), NG2_retl_o2_plus_g1) - FREG_MOVE_1(f30) - subcc %g1, 64, %g1 - add %o4, 64, %o4 -@@ -393,10 +455,10 @@ FUNC_NAME: /* %o0=dst, %o1=src, %o2=len */ - nop - - 190: --1: EX_ST_FP(STORE_INIT(%g0, %o4 + %g3)) -+1: EX_ST_FP(STORE_INIT(%g0, %o4 + %g3), NG2_retl_o2_plus_g1) - subcc %g1, 64, %g1 -- EX_LD_FP(LOAD_BLK(%o4, %f0)) -- EX_ST_FP(STORE_BLK(%f0, %o4 + %g3)) -+ EX_LD_FP(LOAD_BLK(%o4, %f0), NG2_retl_o2_plus_g1_plus_64) -+ EX_ST_FP(STORE_BLK(%f0, %o4 + %g3), NG2_retl_o2_plus_g1_plus_64) - add %o4, 64, %o4 - bne,pt %xcc, 1b - LOAD(prefetch, %o4 + 64, #one_read) -@@ -423,28 +485,28 @@ FUNC_NAME: /* %o0=dst, %o1=src, %o2=len */ - andn %o2, 0xf, %o4 - and %o2, 0xf, %o2 - 1: subcc %o4, 0x10, %o4 -- EX_LD(LOAD(ldx, %o1, %o5)) -+ EX_LD(LOAD(ldx, %o1, %o5), NG2_retl_o2_plus_o4_plus_16) - add %o1, 0x08, %o1 -- EX_LD(LOAD(ldx, %o1, %g1)) -+ EX_LD(LOAD(ldx, %o1, %g1), NG2_retl_o2_plus_o4_plus_16) - sub %o1, 0x08, %o1 -- EX_ST(STORE(stx, %o5, %o1 + GLOBAL_SPARE)) -+ EX_ST(STORE(stx, %o5, %o1 + GLOBAL_SPARE), NG2_retl_o2_plus_o4_plus_16) - add %o1, 0x8, %o1 -- EX_ST(STORE(stx, %g1, %o1 + GLOBAL_SPARE)) -+ EX_ST(STORE(stx, %g1, %o1 + GLOBAL_SPARE), NG2_retl_o2_plus_o4_plus_8) - bgu,pt %XCC, 1b - add %o1, 0x8, %o1 - 73: andcc %o2, 0x8, %g0 - be,pt %XCC, 1f - nop - sub %o2, 0x8, %o2 -- EX_LD(LOAD(ldx, %o1, %o5)) -- EX_ST(STORE(stx, %o5, %o1 + GLOBAL_SPARE)) -+ EX_LD(LOAD(ldx, %o1, %o5), NG2_retl_o2_plus_8) -+ EX_ST(STORE(stx, %o5, %o1 + GLOBAL_SPARE), NG2_retl_o2_plus_8) - add %o1, 0x8, %o1 - 1: andcc %o2, 0x4, %g0 - be,pt %XCC, 1f - nop - sub %o2, 0x4, %o2 -- EX_LD(LOAD(lduw, %o1, %o5)) -- EX_ST(STORE(stw, %o5, %o1 + GLOBAL_SPARE)) -+ EX_LD(LOAD(lduw, %o1, %o5), NG2_retl_o2_plus_4) -+ EX_ST(STORE(stw, %o5, %o1 + GLOBAL_SPARE), NG2_retl_o2_plus_4) - add %o1, 0x4, %o1 - 1: cmp %o2, 0 - be,pt %XCC, 85f -@@ -460,8 +522,8 @@ FUNC_NAME: /* %o0=dst, %o1=src, %o2=len */ - sub %o2, %g1, %o2 - - 1: subcc %g1, 1, %g1 -- EX_LD(LOAD(ldub, %o1, %o5)) -- EX_ST(STORE(stb, %o5, %o1 + GLOBAL_SPARE)) -+ EX_LD(LOAD(ldub, %o1, %o5), NG2_retl_o2_plus_g1_plus_1) -+ EX_ST(STORE(stb, %o5, %o1 + GLOBAL_SPARE), NG2_retl_o2_plus_g1_plus_1) - bgu,pt %icc, 1b - add %o1, 1, %o1 - -@@ -477,16 +539,16 @@ FUNC_NAME: /* %o0=dst, %o1=src, %o2=len */ - - 8: mov 64, GLOBAL_SPARE - andn %o1, 0x7, %o1 -- EX_LD(LOAD(ldx, %o1, %g2)) -+ EX_LD(LOAD(ldx, %o1, %g2), NG2_retl_o2) - sub GLOBAL_SPARE, %g1, GLOBAL_SPARE - andn %o2, 0x7, %o4 - sllx %g2, %g1, %g2 - 1: add %o1, 0x8, %o1 -- EX_LD(LOAD(ldx, %o1, %g3)) -+ EX_LD(LOAD(ldx, %o1, %g3), NG2_retl_o2_and_7_plus_o4) - subcc %o4, 0x8, %o4 - srlx %g3, GLOBAL_SPARE, %o5 - or %o5, %g2, %o5 -- EX_ST(STORE(stx, %o5, %o0)) -+ EX_ST(STORE(stx, %o5, %o0), NG2_retl_o2_and_7_plus_o4_plus_8) - add %o0, 0x8, %o0 - bgu,pt %icc, 1b - sllx %g3, %g1, %g2 -@@ -506,8 +568,8 @@ FUNC_NAME: /* %o0=dst, %o1=src, %o2=len */ - - 1: - subcc %o2, 4, %o2 -- EX_LD(LOAD(lduw, %o1, %g1)) -- EX_ST(STORE(stw, %g1, %o1 + GLOBAL_SPARE)) -+ EX_LD(LOAD(lduw, %o1, %g1), NG2_retl_o2_plus_4) -+ EX_ST(STORE(stw, %g1, %o1 + GLOBAL_SPARE), NG2_retl_o2_plus_4) - bgu,pt %XCC, 1b - add %o1, 4, %o1 - -@@ -517,8 +579,8 @@ FUNC_NAME: /* %o0=dst, %o1=src, %o2=len */ - .align 32 - 90: - subcc %o2, 1, %o2 -- EX_LD(LOAD(ldub, %o1, %g1)) -- EX_ST(STORE(stb, %g1, %o1 + GLOBAL_SPARE)) -+ EX_LD(LOAD(ldub, %o1, %g1), NG2_retl_o2_plus_1) -+ EX_ST(STORE(stb, %g1, %o1 + GLOBAL_SPARE), NG2_retl_o2_plus_1) - bgu,pt %XCC, 90b - add %o1, 1, %o1 - retl -diff --git a/arch/sparc/lib/NG4copy_from_user.S b/arch/sparc/lib/NG4copy_from_user.S -index 2e8ee7a..16a286c 100644 ---- a/arch/sparc/lib/NG4copy_from_user.S -+++ b/arch/sparc/lib/NG4copy_from_user.S -@@ -3,19 +3,19 @@ - * Copyright (C) 2012 David S. Miller (davem@davemloft.net) - */ - --#define EX_LD(x) \ -+#define EX_LD(x, y) \ - 98: x; \ - .section __ex_table,"a";\ - .align 4; \ -- .word 98b, __retl_one_asi;\ -+ .word 98b, y; \ - .text; \ - .align 4; - --#define EX_LD_FP(x) \ -+#define EX_LD_FP(x,y) \ - 98: x; \ - .section __ex_table,"a";\ - .align 4; \ -- .word 98b, __retl_one_asi_fp;\ -+ .word 98b, y##_fp; \ - .text; \ - .align 4; - -diff --git a/arch/sparc/lib/NG4copy_to_user.S b/arch/sparc/lib/NG4copy_to_user.S -index be0bf45..6b0276f 100644 ---- a/arch/sparc/lib/NG4copy_to_user.S -+++ b/arch/sparc/lib/NG4copy_to_user.S -@@ -3,19 +3,19 @@ - * Copyright (C) 2012 David S. Miller (davem@davemloft.net) - */ - --#define EX_ST(x) \ -+#define EX_ST(x,y) \ - 98: x; \ - .section __ex_table,"a";\ - .align 4; \ -- .word 98b, __retl_one_asi;\ -+ .word 98b, y; \ - .text; \ - .align 4; - --#define EX_ST_FP(x) \ -+#define EX_ST_FP(x,y) \ - 98: x; \ - .section __ex_table,"a";\ - .align 4; \ -- .word 98b, __retl_one_asi_fp;\ -+ .word 98b, y##_fp; \ - .text; \ - .align 4; - -diff --git a/arch/sparc/lib/NG4memcpy.S b/arch/sparc/lib/NG4memcpy.S -index 8e13ee1..75bb93b 100644 ---- a/arch/sparc/lib/NG4memcpy.S -+++ b/arch/sparc/lib/NG4memcpy.S -@@ -4,6 +4,7 @@ - */ - - #ifdef __KERNEL__ -+#include <linux/linkage.h> - #include <asm/visasm.h> - #include <asm/asi.h> - #define GLOBAL_SPARE %g7 -@@ -46,22 +47,19 @@ - #endif - - #ifndef EX_LD --#define EX_LD(x) x -+#define EX_LD(x,y) x - #endif - #ifndef EX_LD_FP --#define EX_LD_FP(x) x -+#define EX_LD_FP(x,y) x - #endif - - #ifndef EX_ST --#define EX_ST(x) x -+#define EX_ST(x,y) x - #endif - #ifndef EX_ST_FP --#define EX_ST_FP(x) x -+#define EX_ST_FP(x,y) x - #endif - --#ifndef EX_RETVAL --#define EX_RETVAL(x) x --#endif - - #ifndef LOAD - #define LOAD(type,addr,dest) type [addr], dest -@@ -94,6 +92,158 @@ - .register %g3,#scratch - - .text -+#ifndef EX_RETVAL -+#define EX_RETVAL(x) x -+__restore_asi_fp: -+ VISExitHalf -+__restore_asi: -+ retl -+ wr %g0, ASI_AIUS, %asi -+ -+ENTRY(NG4_retl_o2) -+ ba,pt %xcc, __restore_asi -+ mov %o2, %o0 -+ENDPROC(NG4_retl_o2) -+ENTRY(NG4_retl_o2_plus_1) -+ ba,pt %xcc, __restore_asi -+ add %o2, 1, %o0 -+ENDPROC(NG4_retl_o2_plus_1) -+ENTRY(NG4_retl_o2_plus_4) -+ ba,pt %xcc, __restore_asi -+ add %o2, 4, %o0 -+ENDPROC(NG4_retl_o2_plus_4) -+ENTRY(NG4_retl_o2_plus_o5) -+ ba,pt %xcc, __restore_asi -+ add %o2, %o5, %o0 -+ENDPROC(NG4_retl_o2_plus_o5) -+ENTRY(NG4_retl_o2_plus_o5_plus_4) -+ add %o5, 4, %o5 -+ ba,pt %xcc, __restore_asi -+ add %o2, %o5, %o0 -+ENDPROC(NG4_retl_o2_plus_o5_plus_4) -+ENTRY(NG4_retl_o2_plus_o5_plus_8) -+ add %o5, 8, %o5 -+ ba,pt %xcc, __restore_asi -+ add %o2, %o5, %o0 -+ENDPROC(NG4_retl_o2_plus_o5_plus_8) -+ENTRY(NG4_retl_o2_plus_o5_plus_16) -+ add %o5, 16, %o5 -+ ba,pt %xcc, __restore_asi -+ add %o2, %o5, %o0 -+ENDPROC(NG4_retl_o2_plus_o5_plus_16) -+ENTRY(NG4_retl_o2_plus_o5_plus_24) -+ add %o5, 24, %o5 -+ ba,pt %xcc, __restore_asi -+ add %o2, %o5, %o0 -+ENDPROC(NG4_retl_o2_plus_o5_plus_24) -+ENTRY(NG4_retl_o2_plus_o5_plus_32) -+ add %o5, 32, %o5 -+ ba,pt %xcc, __restore_asi -+ add %o2, %o5, %o0 -+ENDPROC(NG4_retl_o2_plus_o5_plus_32) -+ENTRY(NG4_retl_o2_plus_g1) -+ ba,pt %xcc, __restore_asi -+ add %o2, %g1, %o0 -+ENDPROC(NG4_retl_o2_plus_g1) -+ENTRY(NG4_retl_o2_plus_g1_plus_1) -+ add %g1, 1, %g1 -+ ba,pt %xcc, __restore_asi -+ add %o2, %g1, %o0 -+ENDPROC(NG4_retl_o2_plus_g1_plus_1) -+ENTRY(NG4_retl_o2_plus_g1_plus_8) -+ add %g1, 8, %g1 -+ ba,pt %xcc, __restore_asi -+ add %o2, %g1, %o0 -+ENDPROC(NG4_retl_o2_plus_g1_plus_8) -+ENTRY(NG4_retl_o2_plus_o4) -+ ba,pt %xcc, __restore_asi -+ add %o2, %o4, %o0 -+ENDPROC(NG4_retl_o2_plus_o4) -+ENTRY(NG4_retl_o2_plus_o4_plus_8) -+ add %o4, 8, %o4 -+ ba,pt %xcc, __restore_asi -+ add %o2, %o4, %o0 -+ENDPROC(NG4_retl_o2_plus_o4_plus_8) -+ENTRY(NG4_retl_o2_plus_o4_plus_16) -+ add %o4, 16, %o4 -+ ba,pt %xcc, __restore_asi -+ add %o2, %o4, %o0 -+ENDPROC(NG4_retl_o2_plus_o4_plus_16) -+ENTRY(NG4_retl_o2_plus_o4_plus_24) -+ add %o4, 24, %o4 -+ ba,pt %xcc, __restore_asi -+ add %o2, %o4, %o0 -+ENDPROC(NG4_retl_o2_plus_o4_plus_24) -+ENTRY(NG4_retl_o2_plus_o4_plus_32) -+ add %o4, 32, %o4 -+ ba,pt %xcc, __restore_asi -+ add %o2, %o4, %o0 -+ENDPROC(NG4_retl_o2_plus_o4_plus_32) -+ENTRY(NG4_retl_o2_plus_o4_plus_40) -+ add %o4, 40, %o4 -+ ba,pt %xcc, __restore_asi -+ add %o2, %o4, %o0 -+ENDPROC(NG4_retl_o2_plus_o4_plus_40) -+ENTRY(NG4_retl_o2_plus_o4_plus_48) -+ add %o4, 48, %o4 -+ ba,pt %xcc, __restore_asi -+ add %o2, %o4, %o0 -+ENDPROC(NG4_retl_o2_plus_o4_plus_48) -+ENTRY(NG4_retl_o2_plus_o4_plus_56) -+ add %o4, 56, %o4 -+ ba,pt %xcc, __restore_asi -+ add %o2, %o4, %o0 -+ENDPROC(NG4_retl_o2_plus_o4_plus_56) -+ENTRY(NG4_retl_o2_plus_o4_plus_64) -+ add %o4, 64, %o4 -+ ba,pt %xcc, __restore_asi -+ add %o2, %o4, %o0 -+ENDPROC(NG4_retl_o2_plus_o4_plus_64) -+ENTRY(NG4_retl_o2_plus_o4_fp) -+ ba,pt %xcc, __restore_asi_fp -+ add %o2, %o4, %o0 -+ENDPROC(NG4_retl_o2_plus_o4_fp) -+ENTRY(NG4_retl_o2_plus_o4_plus_8_fp) -+ add %o4, 8, %o4 -+ ba,pt %xcc, __restore_asi_fp -+ add %o2, %o4, %o0 -+ENDPROC(NG4_retl_o2_plus_o4_plus_8_fp) -+ENTRY(NG4_retl_o2_plus_o4_plus_16_fp) -+ add %o4, 16, %o4 -+ ba,pt %xcc, __restore_asi_fp -+ add %o2, %o4, %o0 -+ENDPROC(NG4_retl_o2_plus_o4_plus_16_fp) -+ENTRY(NG4_retl_o2_plus_o4_plus_24_fp) -+ add %o4, 24, %o4 -+ ba,pt %xcc, __restore_asi_fp -+ add %o2, %o4, %o0 -+ENDPROC(NG4_retl_o2_plus_o4_plus_24_fp) -+ENTRY(NG4_retl_o2_plus_o4_plus_32_fp) -+ add %o4, 32, %o4 -+ ba,pt %xcc, __restore_asi_fp -+ add %o2, %o4, %o0 -+ENDPROC(NG4_retl_o2_plus_o4_plus_32_fp) -+ENTRY(NG4_retl_o2_plus_o4_plus_40_fp) -+ add %o4, 40, %o4 -+ ba,pt %xcc, __restore_asi_fp -+ add %o2, %o4, %o0 -+ENDPROC(NG4_retl_o2_plus_o4_plus_40_fp) -+ENTRY(NG4_retl_o2_plus_o4_plus_48_fp) -+ add %o4, 48, %o4 -+ ba,pt %xcc, __restore_asi_fp -+ add %o2, %o4, %o0 -+ENDPROC(NG4_retl_o2_plus_o4_plus_48_fp) -+ENTRY(NG4_retl_o2_plus_o4_plus_56_fp) -+ add %o4, 56, %o4 -+ ba,pt %xcc, __restore_asi_fp -+ add %o2, %o4, %o0 -+ENDPROC(NG4_retl_o2_plus_o4_plus_56_fp) -+ENTRY(NG4_retl_o2_plus_o4_plus_64_fp) -+ add %o4, 64, %o4 -+ ba,pt %xcc, __restore_asi_fp -+ add %o2, %o4, %o0 -+ENDPROC(NG4_retl_o2_plus_o4_plus_64_fp) -+#endif - .align 64 - - .globl FUNC_NAME -@@ -124,12 +274,13 @@ FUNC_NAME: /* %o0=dst, %o1=src, %o2=len */ - brz,pt %g1, 51f - sub %o2, %g1, %o2 - --1: EX_LD(LOAD(ldub, %o1 + 0x00, %g2)) -+ -+1: EX_LD(LOAD(ldub, %o1 + 0x00, %g2), NG4_retl_o2_plus_g1) - add %o1, 1, %o1 - subcc %g1, 1, %g1 - add %o0, 1, %o0 - bne,pt %icc, 1b -- EX_ST(STORE(stb, %g2, %o0 - 0x01)) -+ EX_ST(STORE(stb, %g2, %o0 - 0x01), NG4_retl_o2_plus_g1_plus_1) - - 51: LOAD(prefetch, %o1 + 0x040, #n_reads_strong) - LOAD(prefetch, %o1 + 0x080, #n_reads_strong) -@@ -154,43 +305,43 @@ FUNC_NAME: /* %o0=dst, %o1=src, %o2=len */ - brz,pt %g1, .Llarge_aligned - sub %o2, %g1, %o2 - --1: EX_LD(LOAD(ldx, %o1 + 0x00, %g2)) -+1: EX_LD(LOAD(ldx, %o1 + 0x00, %g2), NG4_retl_o2_plus_g1) - add %o1, 8, %o1 - subcc %g1, 8, %g1 - add %o0, 8, %o0 - bne,pt %icc, 1b -- EX_ST(STORE(stx, %g2, %o0 - 0x08)) -+ EX_ST(STORE(stx, %g2, %o0 - 0x08), NG4_retl_o2_plus_g1_plus_8) - - .Llarge_aligned: - /* len >= 0x80 && src 8-byte aligned && dest 8-byte aligned */ - andn %o2, 0x3f, %o4 - sub %o2, %o4, %o2 - --1: EX_LD(LOAD(ldx, %o1 + 0x00, %g1)) -+1: EX_LD(LOAD(ldx, %o1 + 0x00, %g1), NG4_retl_o2_plus_o4) - add %o1, 0x40, %o1 -- EX_LD(LOAD(ldx, %o1 - 0x38, %g2)) -+ EX_LD(LOAD(ldx, %o1 - 0x38, %g2), NG4_retl_o2_plus_o4) - subcc %o4, 0x40, %o4 -- EX_LD(LOAD(ldx, %o1 - 0x30, %g3)) -- EX_LD(LOAD(ldx, %o1 - 0x28, GLOBAL_SPARE)) -- EX_LD(LOAD(ldx, %o1 - 0x20, %o5)) -- EX_ST(STORE_INIT(%g1, %o0)) -+ EX_LD(LOAD(ldx, %o1 - 0x30, %g3), NG4_retl_o2_plus_o4_plus_64) -+ EX_LD(LOAD(ldx, %o1 - 0x28, GLOBAL_SPARE), NG4_retl_o2_plus_o4_plus_64) -+ EX_LD(LOAD(ldx, %o1 - 0x20, %o5), NG4_retl_o2_plus_o4_plus_64) -+ EX_ST(STORE_INIT(%g1, %o0), NG4_retl_o2_plus_o4_plus_64) - add %o0, 0x08, %o0 -- EX_ST(STORE_INIT(%g2, %o0)) -+ EX_ST(STORE_INIT(%g2, %o0), NG4_retl_o2_plus_o4_plus_56) - add %o0, 0x08, %o0 -- EX_LD(LOAD(ldx, %o1 - 0x18, %g2)) -- EX_ST(STORE_INIT(%g3, %o0)) -+ EX_LD(LOAD(ldx, %o1 - 0x18, %g2), NG4_retl_o2_plus_o4_plus_48) -+ EX_ST(STORE_INIT(%g3, %o0), NG4_retl_o2_plus_o4_plus_48) - add %o0, 0x08, %o0 -- EX_LD(LOAD(ldx, %o1 - 0x10, %g3)) -- EX_ST(STORE_INIT(GLOBAL_SPARE, %o0)) -+ EX_LD(LOAD(ldx, %o1 - 0x10, %g3), NG4_retl_o2_plus_o4_plus_40) -+ EX_ST(STORE_INIT(GLOBAL_SPARE, %o0), NG4_retl_o2_plus_o4_plus_40) - add %o0, 0x08, %o0 -- EX_LD(LOAD(ldx, %o1 - 0x08, GLOBAL_SPARE)) -- EX_ST(STORE_INIT(%o5, %o0)) -+ EX_LD(LOAD(ldx, %o1 - 0x08, GLOBAL_SPARE), NG4_retl_o2_plus_o4_plus_32) -+ EX_ST(STORE_INIT(%o5, %o0), NG4_retl_o2_plus_o4_plus_32) - add %o0, 0x08, %o0 -- EX_ST(STORE_INIT(%g2, %o0)) -+ EX_ST(STORE_INIT(%g2, %o0), NG4_retl_o2_plus_o4_plus_24) - add %o0, 0x08, %o0 -- EX_ST(STORE_INIT(%g3, %o0)) -+ EX_ST(STORE_INIT(%g3, %o0), NG4_retl_o2_plus_o4_plus_16) - add %o0, 0x08, %o0 -- EX_ST(STORE_INIT(GLOBAL_SPARE, %o0)) -+ EX_ST(STORE_INIT(GLOBAL_SPARE, %o0), NG4_retl_o2_plus_o4_plus_8) - add %o0, 0x08, %o0 - bne,pt %icc, 1b - LOAD(prefetch, %o1 + 0x200, #n_reads_strong) -@@ -216,17 +367,17 @@ FUNC_NAME: /* %o0=dst, %o1=src, %o2=len */ - sub %o2, %o4, %o2 - alignaddr %o1, %g0, %g1 - add %o1, %o4, %o1 -- EX_LD_FP(LOAD(ldd, %g1 + 0x00, %f0)) --1: EX_LD_FP(LOAD(ldd, %g1 + 0x08, %f2)) -+ EX_LD_FP(LOAD(ldd, %g1 + 0x00, %f0), NG4_retl_o2_plus_o4) -+1: EX_LD_FP(LOAD(ldd, %g1 + 0x08, %f2), NG4_retl_o2_plus_o4) - subcc %o4, 0x40, %o4 -- EX_LD_FP(LOAD(ldd, %g1 + 0x10, %f4)) -- EX_LD_FP(LOAD(ldd, %g1 + 0x18, %f6)) -- EX_LD_FP(LOAD(ldd, %g1 + 0x20, %f8)) -- EX_LD_FP(LOAD(ldd, %g1 + 0x28, %f10)) -- EX_LD_FP(LOAD(ldd, %g1 + 0x30, %f12)) -- EX_LD_FP(LOAD(ldd, %g1 + 0x38, %f14)) -+ EX_LD_FP(LOAD(ldd, %g1 + 0x10, %f4), NG4_retl_o2_plus_o4_plus_64) -+ EX_LD_FP(LOAD(ldd, %g1 + 0x18, %f6), NG4_retl_o2_plus_o4_plus_64) -+ EX_LD_FP(LOAD(ldd, %g1 + 0x20, %f8), NG4_retl_o2_plus_o4_plus_64) -+ EX_LD_FP(LOAD(ldd, %g1 + 0x28, %f10), NG4_retl_o2_plus_o4_plus_64) -+ EX_LD_FP(LOAD(ldd, %g1 + 0x30, %f12), NG4_retl_o2_plus_o4_plus_64) -+ EX_LD_FP(LOAD(ldd, %g1 + 0x38, %f14), NG4_retl_o2_plus_o4_plus_64) - faligndata %f0, %f2, %f16 -- EX_LD_FP(LOAD(ldd, %g1 + 0x40, %f0)) -+ EX_LD_FP(LOAD(ldd, %g1 + 0x40, %f0), NG4_retl_o2_plus_o4_plus_64) - faligndata %f2, %f4, %f18 - add %g1, 0x40, %g1 - faligndata %f4, %f6, %f20 -@@ -235,14 +386,14 @@ FUNC_NAME: /* %o0=dst, %o1=src, %o2=len */ - faligndata %f10, %f12, %f26 - faligndata %f12, %f14, %f28 - faligndata %f14, %f0, %f30 -- EX_ST_FP(STORE(std, %f16, %o0 + 0x00)) -- EX_ST_FP(STORE(std, %f18, %o0 + 0x08)) -- EX_ST_FP(STORE(std, %f20, %o0 + 0x10)) -- EX_ST_FP(STORE(std, %f22, %o0 + 0x18)) -- EX_ST_FP(STORE(std, %f24, %o0 + 0x20)) -- EX_ST_FP(STORE(std, %f26, %o0 + 0x28)) -- EX_ST_FP(STORE(std, %f28, %o0 + 0x30)) -- EX_ST_FP(STORE(std, %f30, %o0 + 0x38)) -+ EX_ST_FP(STORE(std, %f16, %o0 + 0x00), NG4_retl_o2_plus_o4_plus_64) -+ EX_ST_FP(STORE(std, %f18, %o0 + 0x08), NG4_retl_o2_plus_o4_plus_56) -+ EX_ST_FP(STORE(std, %f20, %o0 + 0x10), NG4_retl_o2_plus_o4_plus_48) -+ EX_ST_FP(STORE(std, %f22, %o0 + 0x18), NG4_retl_o2_plus_o4_plus_40) -+ EX_ST_FP(STORE(std, %f24, %o0 + 0x20), NG4_retl_o2_plus_o4_plus_32) -+ EX_ST_FP(STORE(std, %f26, %o0 + 0x28), NG4_retl_o2_plus_o4_plus_24) -+ EX_ST_FP(STORE(std, %f28, %o0 + 0x30), NG4_retl_o2_plus_o4_plus_16) -+ EX_ST_FP(STORE(std, %f30, %o0 + 0x38), NG4_retl_o2_plus_o4_plus_8) - add %o0, 0x40, %o0 - bne,pt %icc, 1b - LOAD(prefetch, %g1 + 0x200, #n_reads_strong) -@@ -270,37 +421,38 @@ FUNC_NAME: /* %o0=dst, %o1=src, %o2=len */ - andncc %o2, 0x20 - 1, %o5 - be,pn %icc, 2f - sub %o2, %o5, %o2 --1: EX_LD(LOAD(ldx, %o1 + 0x00, %g1)) -- EX_LD(LOAD(ldx, %o1 + 0x08, %g2)) -- EX_LD(LOAD(ldx, %o1 + 0x10, GLOBAL_SPARE)) -- EX_LD(LOAD(ldx, %o1 + 0x18, %o4)) -+1: EX_LD(LOAD(ldx, %o1 + 0x00, %g1), NG4_retl_o2_plus_o5) -+ EX_LD(LOAD(ldx, %o1 + 0x08, %g2), NG4_retl_o2_plus_o5) -+ EX_LD(LOAD(ldx, %o1 + 0x10, GLOBAL_SPARE), NG4_retl_o2_plus_o5) -+ EX_LD(LOAD(ldx, %o1 + 0x18, %o4), NG4_retl_o2_plus_o5) - add %o1, 0x20, %o1 - subcc %o5, 0x20, %o5 -- EX_ST(STORE(stx, %g1, %o0 + 0x00)) -- EX_ST(STORE(stx, %g2, %o0 + 0x08)) -- EX_ST(STORE(stx, GLOBAL_SPARE, %o0 + 0x10)) -- EX_ST(STORE(stx, %o4, %o0 + 0x18)) -+ EX_ST(STORE(stx, %g1, %o0 + 0x00), NG4_retl_o2_plus_o5_plus_32) -+ EX_ST(STORE(stx, %g2, %o0 + 0x08), NG4_retl_o2_plus_o5_plus_24) -+ EX_ST(STORE(stx, GLOBAL_SPARE, %o0 + 0x10), NG4_retl_o2_plus_o5_plus_24) -+ EX_ST(STORE(stx, %o4, %o0 + 0x18), NG4_retl_o2_plus_o5_plus_8) - bne,pt %icc, 1b - add %o0, 0x20, %o0 - 2: andcc %o2, 0x18, %o5 - be,pt %icc, 3f - sub %o2, %o5, %o2 --1: EX_LD(LOAD(ldx, %o1 + 0x00, %g1)) -+ -+1: EX_LD(LOAD(ldx, %o1 + 0x00, %g1), NG4_retl_o2_plus_o5) - add %o1, 0x08, %o1 - add %o0, 0x08, %o0 - subcc %o5, 0x08, %o5 - bne,pt %icc, 1b -- EX_ST(STORE(stx, %g1, %o0 - 0x08)) -+ EX_ST(STORE(stx, %g1, %o0 - 0x08), NG4_retl_o2_plus_o5_plus_8) - 3: brz,pt %o2, .Lexit - cmp %o2, 0x04 - bl,pn %icc, .Ltiny - nop -- EX_LD(LOAD(lduw, %o1 + 0x00, %g1)) -+ EX_LD(LOAD(lduw, %o1 + 0x00, %g1), NG4_retl_o2) - add %o1, 0x04, %o1 - add %o0, 0x04, %o0 - subcc %o2, 0x04, %o2 - bne,pn %icc, .Ltiny -- EX_ST(STORE(stw, %g1, %o0 - 0x04)) -+ EX_ST(STORE(stw, %g1, %o0 - 0x04), NG4_retl_o2_plus_4) - ba,a,pt %icc, .Lexit - .Lmedium_unaligned: - /* First get dest 8 byte aligned. */ -@@ -309,12 +461,12 @@ FUNC_NAME: /* %o0=dst, %o1=src, %o2=len */ - brz,pt %g1, 2f - sub %o2, %g1, %o2 - --1: EX_LD(LOAD(ldub, %o1 + 0x00, %g2)) -+1: EX_LD(LOAD(ldub, %o1 + 0x00, %g2), NG4_retl_o2_plus_g1) - add %o1, 1, %o1 - subcc %g1, 1, %g1 - add %o0, 1, %o0 - bne,pt %icc, 1b -- EX_ST(STORE(stb, %g2, %o0 - 0x01)) -+ EX_ST(STORE(stb, %g2, %o0 - 0x01), NG4_retl_o2_plus_g1_plus_1) - 2: - and %o1, 0x7, %g1 - brz,pn %g1, .Lmedium_noprefetch -@@ -322,16 +474,16 @@ FUNC_NAME: /* %o0=dst, %o1=src, %o2=len */ - mov 64, %g2 - sub %g2, %g1, %g2 - andn %o1, 0x7, %o1 -- EX_LD(LOAD(ldx, %o1 + 0x00, %o4)) -+ EX_LD(LOAD(ldx, %o1 + 0x00, %o4), NG4_retl_o2) - sllx %o4, %g1, %o4 - andn %o2, 0x08 - 1, %o5 - sub %o2, %o5, %o2 --1: EX_LD(LOAD(ldx, %o1 + 0x08, %g3)) -+1: EX_LD(LOAD(ldx, %o1 + 0x08, %g3), NG4_retl_o2_plus_o5) - add %o1, 0x08, %o1 - subcc %o5, 0x08, %o5 - srlx %g3, %g2, GLOBAL_SPARE - or GLOBAL_SPARE, %o4, GLOBAL_SPARE -- EX_ST(STORE(stx, GLOBAL_SPARE, %o0 + 0x00)) -+ EX_ST(STORE(stx, GLOBAL_SPARE, %o0 + 0x00), NG4_retl_o2_plus_o5_plus_8) - add %o0, 0x08, %o0 - bne,pt %icc, 1b - sllx %g3, %g1, %o4 -@@ -342,17 +494,17 @@ FUNC_NAME: /* %o0=dst, %o1=src, %o2=len */ - ba,pt %icc, .Lsmall_unaligned - - .Ltiny: -- EX_LD(LOAD(ldub, %o1 + 0x00, %g1)) -+ EX_LD(LOAD(ldub, %o1 + 0x00, %g1), NG4_retl_o2) - subcc %o2, 1, %o2 - be,pn %icc, .Lexit -- EX_ST(STORE(stb, %g1, %o0 + 0x00)) -- EX_LD(LOAD(ldub, %o1 + 0x01, %g1)) -+ EX_ST(STORE(stb, %g1, %o0 + 0x00), NG4_retl_o2_plus_1) -+ EX_LD(LOAD(ldub, %o1 + 0x01, %g1), NG4_retl_o2) - subcc %o2, 1, %o2 - be,pn %icc, .Lexit -- EX_ST(STORE(stb, %g1, %o0 + 0x01)) -- EX_LD(LOAD(ldub, %o1 + 0x02, %g1)) -+ EX_ST(STORE(stb, %g1, %o0 + 0x01), NG4_retl_o2_plus_1) -+ EX_LD(LOAD(ldub, %o1 + 0x02, %g1), NG4_retl_o2) - ba,pt %icc, .Lexit -- EX_ST(STORE(stb, %g1, %o0 + 0x02)) -+ EX_ST(STORE(stb, %g1, %o0 + 0x02), NG4_retl_o2) - - .Lsmall: - andcc %g2, 0x3, %g0 -@@ -360,22 +512,22 @@ FUNC_NAME: /* %o0=dst, %o1=src, %o2=len */ - andn %o2, 0x4 - 1, %o5 - sub %o2, %o5, %o2 - 1: -- EX_LD(LOAD(lduw, %o1 + 0x00, %g1)) -+ EX_LD(LOAD(lduw, %o1 + 0x00, %g1), NG4_retl_o2_plus_o5) - add %o1, 0x04, %o1 - subcc %o5, 0x04, %o5 - add %o0, 0x04, %o0 - bne,pt %icc, 1b -- EX_ST(STORE(stw, %g1, %o0 - 0x04)) -+ EX_ST(STORE(stw, %g1, %o0 - 0x04), NG4_retl_o2_plus_o5_plus_4) - brz,pt %o2, .Lexit - nop - ba,a,pt %icc, .Ltiny - - .Lsmall_unaligned: --1: EX_LD(LOAD(ldub, %o1 + 0x00, %g1)) -+1: EX_LD(LOAD(ldub, %o1 + 0x00, %g1), NG4_retl_o2) - add %o1, 1, %o1 - add %o0, 1, %o0 - subcc %o2, 1, %o2 - bne,pt %icc, 1b -- EX_ST(STORE(stb, %g1, %o0 - 0x01)) -+ EX_ST(STORE(stb, %g1, %o0 - 0x01), NG4_retl_o2_plus_1) - ba,a,pt %icc, .Lexit - .size FUNC_NAME, .-FUNC_NAME -diff --git a/arch/sparc/lib/NGcopy_from_user.S b/arch/sparc/lib/NGcopy_from_user.S -index 5d1e4d1..9cd42fc 100644 ---- a/arch/sparc/lib/NGcopy_from_user.S -+++ b/arch/sparc/lib/NGcopy_from_user.S -@@ -3,11 +3,11 @@ - * Copyright (C) 2006, 2007 David S. Miller (davem@davemloft.net) - */ - --#define EX_LD(x) \ -+#define EX_LD(x,y) \ - 98: x; \ - .section __ex_table,"a";\ - .align 4; \ -- .word 98b, __ret_one_asi;\ -+ .word 98b, y; \ - .text; \ - .align 4; - -diff --git a/arch/sparc/lib/NGcopy_to_user.S b/arch/sparc/lib/NGcopy_to_user.S -index ff630dc..5c358af 100644 ---- a/arch/sparc/lib/NGcopy_to_user.S -+++ b/arch/sparc/lib/NGcopy_to_user.S -@@ -3,11 +3,11 @@ - * Copyright (C) 2006, 2007 David S. Miller (davem@davemloft.net) - */ - --#define EX_ST(x) \ -+#define EX_ST(x,y) \ - 98: x; \ - .section __ex_table,"a";\ - .align 4; \ -- .word 98b, __ret_one_asi;\ -+ .word 98b, y; \ - .text; \ - .align 4; - -diff --git a/arch/sparc/lib/NGmemcpy.S b/arch/sparc/lib/NGmemcpy.S -index 96a14ca..d88c4ed 100644 ---- a/arch/sparc/lib/NGmemcpy.S -+++ b/arch/sparc/lib/NGmemcpy.S -@@ -4,6 +4,7 @@ - */ - - #ifdef __KERNEL__ -+#include <linux/linkage.h> - #include <asm/asi.h> - #include <asm/thread_info.h> - #define GLOBAL_SPARE %g7 -@@ -27,15 +28,11 @@ - #endif - - #ifndef EX_LD --#define EX_LD(x) x -+#define EX_LD(x,y) x - #endif - - #ifndef EX_ST --#define EX_ST(x) x --#endif -- --#ifndef EX_RETVAL --#define EX_RETVAL(x) x -+#define EX_ST(x,y) x - #endif - - #ifndef LOAD -@@ -79,6 +76,92 @@ - .register %g3,#scratch - - .text -+#ifndef EX_RETVAL -+#define EX_RETVAL(x) x -+__restore_asi: -+ ret -+ wr %g0, ASI_AIUS, %asi -+ restore -+ENTRY(NG_ret_i2_plus_i4_plus_1) -+ ba,pt %xcc, __restore_asi -+ add %i2, %i5, %i0 -+ENDPROC(NG_ret_i2_plus_i4_plus_1) -+ENTRY(NG_ret_i2_plus_g1) -+ ba,pt %xcc, __restore_asi -+ add %i2, %g1, %i0 -+ENDPROC(NG_ret_i2_plus_g1) -+ENTRY(NG_ret_i2_plus_g1_minus_8) -+ sub %g1, 8, %g1 -+ ba,pt %xcc, __restore_asi -+ add %i2, %g1, %i0 -+ENDPROC(NG_ret_i2_plus_g1_minus_8) -+ENTRY(NG_ret_i2_plus_g1_minus_16) -+ sub %g1, 16, %g1 -+ ba,pt %xcc, __restore_asi -+ add %i2, %g1, %i0 -+ENDPROC(NG_ret_i2_plus_g1_minus_16) -+ENTRY(NG_ret_i2_plus_g1_minus_24) -+ sub %g1, 24, %g1 -+ ba,pt %xcc, __restore_asi -+ add %i2, %g1, %i0 -+ENDPROC(NG_ret_i2_plus_g1_minus_24) -+ENTRY(NG_ret_i2_plus_g1_minus_32) -+ sub %g1, 32, %g1 -+ ba,pt %xcc, __restore_asi -+ add %i2, %g1, %i0 -+ENDPROC(NG_ret_i2_plus_g1_minus_32) -+ENTRY(NG_ret_i2_plus_g1_minus_40) -+ sub %g1, 40, %g1 -+ ba,pt %xcc, __restore_asi -+ add %i2, %g1, %i0 -+ENDPROC(NG_ret_i2_plus_g1_minus_40) -+ENTRY(NG_ret_i2_plus_g1_minus_48) -+ sub %g1, 48, %g1 -+ ba,pt %xcc, __restore_asi -+ add %i2, %g1, %i0 -+ENDPROC(NG_ret_i2_plus_g1_minus_48) -+ENTRY(NG_ret_i2_plus_g1_minus_56) -+ sub %g1, 56, %g1 -+ ba,pt %xcc, __restore_asi -+ add %i2, %g1, %i0 -+ENDPROC(NG_ret_i2_plus_g1_minus_56) -+ENTRY(NG_ret_i2_plus_i4) -+ ba,pt %xcc, __restore_asi -+ add %i2, %i4, %i0 -+ENDPROC(NG_ret_i2_plus_i4) -+ENTRY(NG_ret_i2_plus_i4_minus_8) -+ sub %i4, 8, %i4 -+ ba,pt %xcc, __restore_asi -+ add %i2, %i4, %i0 -+ENDPROC(NG_ret_i2_plus_i4_minus_8) -+ENTRY(NG_ret_i2_plus_8) -+ ba,pt %xcc, __restore_asi -+ add %i2, 8, %i0 -+ENDPROC(NG_ret_i2_plus_8) -+ENTRY(NG_ret_i2_plus_4) -+ ba,pt %xcc, __restore_asi -+ add %i2, 4, %i0 -+ENDPROC(NG_ret_i2_plus_4) -+ENTRY(NG_ret_i2_plus_1) -+ ba,pt %xcc, __restore_asi -+ add %i2, 1, %i0 -+ENDPROC(NG_ret_i2_plus_1) -+ENTRY(NG_ret_i2_plus_g1_plus_1) -+ add %g1, 1, %g1 -+ ba,pt %xcc, __restore_asi -+ add %i2, %g1, %i0 -+ENDPROC(NG_ret_i2_plus_g1_plus_1) -+ENTRY(NG_ret_i2) -+ ba,pt %xcc, __restore_asi -+ mov %i2, %i0 -+ENDPROC(NG_ret_i2) -+ENTRY(NG_ret_i2_and_7_plus_i4) -+ and %i2, 7, %i2 -+ ba,pt %xcc, __restore_asi -+ add %i2, %i4, %i0 -+ENDPROC(NG_ret_i2_and_7_plus_i4) -+#endif -+ - .align 64 - - .globl FUNC_NAME -@@ -126,8 +209,8 @@ FUNC_NAME: /* %i0=dst, %i1=src, %i2=len */ - sub %g0, %i4, %i4 ! bytes to align dst - sub %i2, %i4, %i2 - 1: subcc %i4, 1, %i4 -- EX_LD(LOAD(ldub, %i1, %g1)) -- EX_ST(STORE(stb, %g1, %o0)) -+ EX_LD(LOAD(ldub, %i1, %g1), NG_ret_i2_plus_i4_plus_1) -+ EX_ST(STORE(stb, %g1, %o0), NG_ret_i2_plus_i4_plus_1) - add %i1, 1, %i1 - bne,pt %XCC, 1b - add %o0, 1, %o0 -@@ -160,7 +243,7 @@ FUNC_NAME: /* %i0=dst, %i1=src, %i2=len */ - and %i4, 0x7, GLOBAL_SPARE - sll GLOBAL_SPARE, 3, GLOBAL_SPARE - mov 64, %i5 -- EX_LD(LOAD_TWIN(%i1, %g2, %g3)) -+ EX_LD(LOAD_TWIN(%i1, %g2, %g3), NG_ret_i2_plus_g1) - sub %i5, GLOBAL_SPARE, %i5 - mov 16, %o4 - mov 32, %o5 -@@ -178,31 +261,31 @@ FUNC_NAME: /* %i0=dst, %i1=src, %i2=len */ - srlx WORD3, PRE_SHIFT, TMP; \ - or WORD2, TMP, WORD2; - --8: EX_LD(LOAD_TWIN(%i1 + %o4, %o2, %o3)) -+8: EX_LD(LOAD_TWIN(%i1 + %o4, %o2, %o3), NG_ret_i2_plus_g1) - MIX_THREE_WORDS(%g2, %g3, %o2, %i5, GLOBAL_SPARE, %o1) - LOAD(prefetch, %i1 + %i3, #one_read) - -- EX_ST(STORE_INIT(%g2, %o0 + 0x00)) -- EX_ST(STORE_INIT(%g3, %o0 + 0x08)) -+ EX_ST(STORE_INIT(%g2, %o0 + 0x00), NG_ret_i2_plus_g1) -+ EX_ST(STORE_INIT(%g3, %o0 + 0x08), NG_ret_i2_plus_g1_minus_8) - -- EX_LD(LOAD_TWIN(%i1 + %o5, %g2, %g3)) -+ EX_LD(LOAD_TWIN(%i1 + %o5, %g2, %g3), NG_ret_i2_plus_g1_minus_16) - MIX_THREE_WORDS(%o2, %o3, %g2, %i5, GLOBAL_SPARE, %o1) - -- EX_ST(STORE_INIT(%o2, %o0 + 0x10)) -- EX_ST(STORE_INIT(%o3, %o0 + 0x18)) -+ EX_ST(STORE_INIT(%o2, %o0 + 0x10), NG_ret_i2_plus_g1_minus_16) -+ EX_ST(STORE_INIT(%o3, %o0 + 0x18), NG_ret_i2_plus_g1_minus_24) - -- EX_LD(LOAD_TWIN(%i1 + %o7, %o2, %o3)) -+ EX_LD(LOAD_TWIN(%i1 + %o7, %o2, %o3), NG_ret_i2_plus_g1_minus_32) - MIX_THREE_WORDS(%g2, %g3, %o2, %i5, GLOBAL_SPARE, %o1) - -- EX_ST(STORE_INIT(%g2, %o0 + 0x20)) -- EX_ST(STORE_INIT(%g3, %o0 + 0x28)) -+ EX_ST(STORE_INIT(%g2, %o0 + 0x20), NG_ret_i2_plus_g1_minus_32) -+ EX_ST(STORE_INIT(%g3, %o0 + 0x28), NG_ret_i2_plus_g1_minus_40) - -- EX_LD(LOAD_TWIN(%i1 + %i3, %g2, %g3)) -+ EX_LD(LOAD_TWIN(%i1 + %i3, %g2, %g3), NG_ret_i2_plus_g1_minus_48) - add %i1, 64, %i1 - MIX_THREE_WORDS(%o2, %o3, %g2, %i5, GLOBAL_SPARE, %o1) - -- EX_ST(STORE_INIT(%o2, %o0 + 0x30)) -- EX_ST(STORE_INIT(%o3, %o0 + 0x38)) -+ EX_ST(STORE_INIT(%o2, %o0 + 0x30), NG_ret_i2_plus_g1_minus_48) -+ EX_ST(STORE_INIT(%o3, %o0 + 0x38), NG_ret_i2_plus_g1_minus_56) - - subcc %g1, 64, %g1 - bne,pt %XCC, 8b -@@ -211,31 +294,31 @@ FUNC_NAME: /* %i0=dst, %i1=src, %i2=len */ - ba,pt %XCC, 60f - add %i1, %i4, %i1 - --9: EX_LD(LOAD_TWIN(%i1 + %o4, %o2, %o3)) -+9: EX_LD(LOAD_TWIN(%i1 + %o4, %o2, %o3), NG_ret_i2_plus_g1) - MIX_THREE_WORDS(%g3, %o2, %o3, %i5, GLOBAL_SPARE, %o1) - LOAD(prefetch, %i1 + %i3, #one_read) - -- EX_ST(STORE_INIT(%g3, %o0 + 0x00)) -- EX_ST(STORE_INIT(%o2, %o0 + 0x08)) -+ EX_ST(STORE_INIT(%g3, %o0 + 0x00), NG_ret_i2_plus_g1) -+ EX_ST(STORE_INIT(%o2, %o0 + 0x08), NG_ret_i2_plus_g1_minus_8) - -- EX_LD(LOAD_TWIN(%i1 + %o5, %g2, %g3)) -+ EX_LD(LOAD_TWIN(%i1 + %o5, %g2, %g3), NG_ret_i2_plus_g1_minus_16) - MIX_THREE_WORDS(%o3, %g2, %g3, %i5, GLOBAL_SPARE, %o1) - -- EX_ST(STORE_INIT(%o3, %o0 + 0x10)) -- EX_ST(STORE_INIT(%g2, %o0 + 0x18)) -+ EX_ST(STORE_INIT(%o3, %o0 + 0x10), NG_ret_i2_plus_g1_minus_16) -+ EX_ST(STORE_INIT(%g2, %o0 + 0x18), NG_ret_i2_plus_g1_minus_24) - -- EX_LD(LOAD_TWIN(%i1 + %o7, %o2, %o3)) -+ EX_LD(LOAD_TWIN(%i1 + %o7, %o2, %o3), NG_ret_i2_plus_g1_minus_32) - MIX_THREE_WORDS(%g3, %o2, %o3, %i5, GLOBAL_SPARE, %o1) - -- EX_ST(STORE_INIT(%g3, %o0 + 0x20)) -- EX_ST(STORE_INIT(%o2, %o0 + 0x28)) -+ EX_ST(STORE_INIT(%g3, %o0 + 0x20), NG_ret_i2_plus_g1_minus_32) -+ EX_ST(STORE_INIT(%o2, %o0 + 0x28), NG_ret_i2_plus_g1_minus_40) - -- EX_LD(LOAD_TWIN(%i1 + %i3, %g2, %g3)) -+ EX_LD(LOAD_TWIN(%i1 + %i3, %g2, %g3), NG_ret_i2_plus_g1_minus_48) - add %i1, 64, %i1 - MIX_THREE_WORDS(%o3, %g2, %g3, %i5, GLOBAL_SPARE, %o1) - -- EX_ST(STORE_INIT(%o3, %o0 + 0x30)) -- EX_ST(STORE_INIT(%g2, %o0 + 0x38)) -+ EX_ST(STORE_INIT(%o3, %o0 + 0x30), NG_ret_i2_plus_g1_minus_48) -+ EX_ST(STORE_INIT(%g2, %o0 + 0x38), NG_ret_i2_plus_g1_minus_56) - - subcc %g1, 64, %g1 - bne,pt %XCC, 9b -@@ -249,25 +332,25 @@ FUNC_NAME: /* %i0=dst, %i1=src, %i2=len */ - * one twin load ahead, then add 8 back into source when - * we finish the loop. - */ -- EX_LD(LOAD_TWIN(%i1, %o4, %o5)) -+ EX_LD(LOAD_TWIN(%i1, %o4, %o5), NG_ret_i2_plus_g1) - mov 16, %o7 - mov 32, %g2 - mov 48, %g3 - mov 64, %o1 --1: EX_LD(LOAD_TWIN(%i1 + %o7, %o2, %o3)) -+1: EX_LD(LOAD_TWIN(%i1 + %o7, %o2, %o3), NG_ret_i2_plus_g1) - LOAD(prefetch, %i1 + %o1, #one_read) -- EX_ST(STORE_INIT(%o5, %o0 + 0x00)) ! initializes cache line -- EX_ST(STORE_INIT(%o2, %o0 + 0x08)) -- EX_LD(LOAD_TWIN(%i1 + %g2, %o4, %o5)) -- EX_ST(STORE_INIT(%o3, %o0 + 0x10)) -- EX_ST(STORE_INIT(%o4, %o0 + 0x18)) -- EX_LD(LOAD_TWIN(%i1 + %g3, %o2, %o3)) -- EX_ST(STORE_INIT(%o5, %o0 + 0x20)) -- EX_ST(STORE_INIT(%o2, %o0 + 0x28)) -- EX_LD(LOAD_TWIN(%i1 + %o1, %o4, %o5)) -+ EX_ST(STORE_INIT(%o5, %o0 + 0x00), NG_ret_i2_plus_g1) ! initializes cache line -+ EX_ST(STORE_INIT(%o2, %o0 + 0x08), NG_ret_i2_plus_g1_minus_8) -+ EX_LD(LOAD_TWIN(%i1 + %g2, %o4, %o5), NG_ret_i2_plus_g1_minus_16) -+ EX_ST(STORE_INIT(%o3, %o0 + 0x10), NG_ret_i2_plus_g1_minus_16) -+ EX_ST(STORE_INIT(%o4, %o0 + 0x18), NG_ret_i2_plus_g1_minus_24) -+ EX_LD(LOAD_TWIN(%i1 + %g3, %o2, %o3), NG_ret_i2_plus_g1_minus_32) -+ EX_ST(STORE_INIT(%o5, %o0 + 0x20), NG_ret_i2_plus_g1_minus_32) -+ EX_ST(STORE_INIT(%o2, %o0 + 0x28), NG_ret_i2_plus_g1_minus_40) -+ EX_LD(LOAD_TWIN(%i1 + %o1, %o4, %o5), NG_ret_i2_plus_g1_minus_48) - add %i1, 64, %i1 -- EX_ST(STORE_INIT(%o3, %o0 + 0x30)) -- EX_ST(STORE_INIT(%o4, %o0 + 0x38)) -+ EX_ST(STORE_INIT(%o3, %o0 + 0x30), NG_ret_i2_plus_g1_minus_48) -+ EX_ST(STORE_INIT(%o4, %o0 + 0x38), NG_ret_i2_plus_g1_minus_56) - subcc %g1, 64, %g1 - bne,pt %XCC, 1b - add %o0, 64, %o0 -@@ -282,20 +365,20 @@ FUNC_NAME: /* %i0=dst, %i1=src, %i2=len */ - mov 32, %g2 - mov 48, %g3 - mov 64, %o1 --1: EX_LD(LOAD_TWIN(%i1 + %g0, %o4, %o5)) -- EX_LD(LOAD_TWIN(%i1 + %o7, %o2, %o3)) -+1: EX_LD(LOAD_TWIN(%i1 + %g0, %o4, %o5), NG_ret_i2_plus_g1) -+ EX_LD(LOAD_TWIN(%i1 + %o7, %o2, %o3), NG_ret_i2_plus_g1) - LOAD(prefetch, %i1 + %o1, #one_read) -- EX_ST(STORE_INIT(%o4, %o0 + 0x00)) ! initializes cache line -- EX_ST(STORE_INIT(%o5, %o0 + 0x08)) -- EX_LD(LOAD_TWIN(%i1 + %g2, %o4, %o5)) -- EX_ST(STORE_INIT(%o2, %o0 + 0x10)) -- EX_ST(STORE_INIT(%o3, %o0 + 0x18)) -- EX_LD(LOAD_TWIN(%i1 + %g3, %o2, %o3)) -+ EX_ST(STORE_INIT(%o4, %o0 + 0x00), NG_ret_i2_plus_g1) ! initializes cache line -+ EX_ST(STORE_INIT(%o5, %o0 + 0x08), NG_ret_i2_plus_g1_minus_8) -+ EX_LD(LOAD_TWIN(%i1 + %g2, %o4, %o5), NG_ret_i2_plus_g1_minus_16) -+ EX_ST(STORE_INIT(%o2, %o0 + 0x10), NG_ret_i2_plus_g1_minus_16) -+ EX_ST(STORE_INIT(%o3, %o0 + 0x18), NG_ret_i2_plus_g1_minus_24) -+ EX_LD(LOAD_TWIN(%i1 + %g3, %o2, %o3), NG_ret_i2_plus_g1_minus_32) - add %i1, 64, %i1 -- EX_ST(STORE_INIT(%o4, %o0 + 0x20)) -- EX_ST(STORE_INIT(%o5, %o0 + 0x28)) -- EX_ST(STORE_INIT(%o2, %o0 + 0x30)) -- EX_ST(STORE_INIT(%o3, %o0 + 0x38)) -+ EX_ST(STORE_INIT(%o4, %o0 + 0x20), NG_ret_i2_plus_g1_minus_32) -+ EX_ST(STORE_INIT(%o5, %o0 + 0x28), NG_ret_i2_plus_g1_minus_40) -+ EX_ST(STORE_INIT(%o2, %o0 + 0x30), NG_ret_i2_plus_g1_minus_48) -+ EX_ST(STORE_INIT(%o3, %o0 + 0x38), NG_ret_i2_plus_g1_minus_56) - subcc %g1, 64, %g1 - bne,pt %XCC, 1b - add %o0, 64, %o0 -@@ -321,28 +404,28 @@ FUNC_NAME: /* %i0=dst, %i1=src, %i2=len */ - andn %i2, 0xf, %i4 - and %i2, 0xf, %i2 - 1: subcc %i4, 0x10, %i4 -- EX_LD(LOAD(ldx, %i1, %o4)) -+ EX_LD(LOAD(ldx, %i1, %o4), NG_ret_i2_plus_i4) - add %i1, 0x08, %i1 -- EX_LD(LOAD(ldx, %i1, %g1)) -+ EX_LD(LOAD(ldx, %i1, %g1), NG_ret_i2_plus_i4) - sub %i1, 0x08, %i1 -- EX_ST(STORE(stx, %o4, %i1 + %i3)) -+ EX_ST(STORE(stx, %o4, %i1 + %i3), NG_ret_i2_plus_i4) - add %i1, 0x8, %i1 -- EX_ST(STORE(stx, %g1, %i1 + %i3)) -+ EX_ST(STORE(stx, %g1, %i1 + %i3), NG_ret_i2_plus_i4_minus_8) - bgu,pt %XCC, 1b - add %i1, 0x8, %i1 - 73: andcc %i2, 0x8, %g0 - be,pt %XCC, 1f - nop - sub %i2, 0x8, %i2 -- EX_LD(LOAD(ldx, %i1, %o4)) -- EX_ST(STORE(stx, %o4, %i1 + %i3)) -+ EX_LD(LOAD(ldx, %i1, %o4), NG_ret_i2_plus_8) -+ EX_ST(STORE(stx, %o4, %i1 + %i3), NG_ret_i2_plus_8) - add %i1, 0x8, %i1 - 1: andcc %i2, 0x4, %g0 - be,pt %XCC, 1f - nop - sub %i2, 0x4, %i2 -- EX_LD(LOAD(lduw, %i1, %i5)) -- EX_ST(STORE(stw, %i5, %i1 + %i3)) -+ EX_LD(LOAD(lduw, %i1, %i5), NG_ret_i2_plus_4) -+ EX_ST(STORE(stw, %i5, %i1 + %i3), NG_ret_i2_plus_4) - add %i1, 0x4, %i1 - 1: cmp %i2, 0 - be,pt %XCC, 85f -@@ -358,8 +441,8 @@ FUNC_NAME: /* %i0=dst, %i1=src, %i2=len */ - sub %i2, %g1, %i2 - - 1: subcc %g1, 1, %g1 -- EX_LD(LOAD(ldub, %i1, %i5)) -- EX_ST(STORE(stb, %i5, %i1 + %i3)) -+ EX_LD(LOAD(ldub, %i1, %i5), NG_ret_i2_plus_g1_plus_1) -+ EX_ST(STORE(stb, %i5, %i1 + %i3), NG_ret_i2_plus_g1_plus_1) - bgu,pt %icc, 1b - add %i1, 1, %i1 - -@@ -375,16 +458,16 @@ FUNC_NAME: /* %i0=dst, %i1=src, %i2=len */ - - 8: mov 64, %i3 - andn %i1, 0x7, %i1 -- EX_LD(LOAD(ldx, %i1, %g2)) -+ EX_LD(LOAD(ldx, %i1, %g2), NG_ret_i2) - sub %i3, %g1, %i3 - andn %i2, 0x7, %i4 - sllx %g2, %g1, %g2 - 1: add %i1, 0x8, %i1 -- EX_LD(LOAD(ldx, %i1, %g3)) -+ EX_LD(LOAD(ldx, %i1, %g3), NG_ret_i2_and_7_plus_i4) - subcc %i4, 0x8, %i4 - srlx %g3, %i3, %i5 - or %i5, %g2, %i5 -- EX_ST(STORE(stx, %i5, %o0)) -+ EX_ST(STORE(stx, %i5, %o0), NG_ret_i2_and_7_plus_i4) - add %o0, 0x8, %o0 - bgu,pt %icc, 1b - sllx %g3, %g1, %g2 -@@ -404,8 +487,8 @@ FUNC_NAME: /* %i0=dst, %i1=src, %i2=len */ - - 1: - subcc %i2, 4, %i2 -- EX_LD(LOAD(lduw, %i1, %g1)) -- EX_ST(STORE(stw, %g1, %i1 + %i3)) -+ EX_LD(LOAD(lduw, %i1, %g1), NG_ret_i2_plus_4) -+ EX_ST(STORE(stw, %g1, %i1 + %i3), NG_ret_i2_plus_4) - bgu,pt %XCC, 1b - add %i1, 4, %i1 - -@@ -415,8 +498,8 @@ FUNC_NAME: /* %i0=dst, %i1=src, %i2=len */ - .align 32 - 90: - subcc %i2, 1, %i2 -- EX_LD(LOAD(ldub, %i1, %g1)) -- EX_ST(STORE(stb, %g1, %i1 + %i3)) -+ EX_LD(LOAD(ldub, %i1, %g1), NG_ret_i2_plus_1) -+ EX_ST(STORE(stb, %g1, %i1 + %i3), NG_ret_i2_plus_1) - bgu,pt %XCC, 90b - add %i1, 1, %i1 - ret -diff --git a/arch/sparc/lib/U1copy_from_user.S b/arch/sparc/lib/U1copy_from_user.S -index ecc5692..bb6ff73 100644 ---- a/arch/sparc/lib/U1copy_from_user.S -+++ b/arch/sparc/lib/U1copy_from_user.S -@@ -3,19 +3,19 @@ - * Copyright (C) 1999, 2000, 2004 David S. Miller (davem@redhat.com) - */ - --#define EX_LD(x) \ -+#define EX_LD(x,y) \ - 98: x; \ - .section __ex_table,"a";\ - .align 4; \ -- .word 98b, __retl_one; \ -+ .word 98b, y; \ - .text; \ - .align 4; - --#define EX_LD_FP(x) \ -+#define EX_LD_FP(x,y) \ - 98: x; \ - .section __ex_table,"a";\ - .align 4; \ -- .word 98b, __retl_one_fp;\ -+ .word 98b, y; \ - .text; \ - .align 4; - -diff --git a/arch/sparc/lib/U1copy_to_user.S b/arch/sparc/lib/U1copy_to_user.S -index 9eea392..ed92ce73 100644 ---- a/arch/sparc/lib/U1copy_to_user.S -+++ b/arch/sparc/lib/U1copy_to_user.S -@@ -3,19 +3,19 @@ - * Copyright (C) 1999, 2000, 2004 David S. Miller (davem@redhat.com) - */ - --#define EX_ST(x) \ -+#define EX_ST(x,y) \ - 98: x; \ - .section __ex_table,"a";\ - .align 4; \ -- .word 98b, __retl_one; \ -+ .word 98b, y; \ - .text; \ - .align 4; - --#define EX_ST_FP(x) \ -+#define EX_ST_FP(x,y) \ - 98: x; \ - .section __ex_table,"a";\ - .align 4; \ -- .word 98b, __retl_one_fp;\ -+ .word 98b, y; \ - .text; \ - .align 4; - -diff --git a/arch/sparc/lib/U1memcpy.S b/arch/sparc/lib/U1memcpy.S -index 3e6209e..f30d2ab 100644 ---- a/arch/sparc/lib/U1memcpy.S -+++ b/arch/sparc/lib/U1memcpy.S -@@ -5,6 +5,7 @@ - */ - - #ifdef __KERNEL__ -+#include <linux/linkage.h> - #include <asm/visasm.h> - #include <asm/asi.h> - #define GLOBAL_SPARE g7 -@@ -23,21 +24,17 @@ - #endif - - #ifndef EX_LD --#define EX_LD(x) x -+#define EX_LD(x,y) x - #endif - #ifndef EX_LD_FP --#define EX_LD_FP(x) x -+#define EX_LD_FP(x,y) x - #endif - - #ifndef EX_ST --#define EX_ST(x) x -+#define EX_ST(x,y) x - #endif - #ifndef EX_ST_FP --#define EX_ST_FP(x) x --#endif -- --#ifndef EX_RETVAL --#define EX_RETVAL(x) x -+#define EX_ST_FP(x,y) x - #endif - - #ifndef LOAD -@@ -78,53 +75,169 @@ - faligndata %f7, %f8, %f60; \ - faligndata %f8, %f9, %f62; - --#define MAIN_LOOP_CHUNK(src, dest, fdest, fsrc, len, jmptgt) \ -- EX_LD_FP(LOAD_BLK(%src, %fdest)); \ -- EX_ST_FP(STORE_BLK(%fsrc, %dest)); \ -- add %src, 0x40, %src; \ -- subcc %len, 0x40, %len; \ -- be,pn %xcc, jmptgt; \ -- add %dest, 0x40, %dest; \ -- --#define LOOP_CHUNK1(src, dest, len, branch_dest) \ -- MAIN_LOOP_CHUNK(src, dest, f0, f48, len, branch_dest) --#define LOOP_CHUNK2(src, dest, len, branch_dest) \ -- MAIN_LOOP_CHUNK(src, dest, f16, f48, len, branch_dest) --#define LOOP_CHUNK3(src, dest, len, branch_dest) \ -- MAIN_LOOP_CHUNK(src, dest, f32, f48, len, branch_dest) -+#define MAIN_LOOP_CHUNK(src, dest, fdest, fsrc, jmptgt) \ -+ EX_LD_FP(LOAD_BLK(%src, %fdest), U1_gs_80_fp); \ -+ EX_ST_FP(STORE_BLK(%fsrc, %dest), U1_gs_80_fp); \ -+ add %src, 0x40, %src; \ -+ subcc %GLOBAL_SPARE, 0x40, %GLOBAL_SPARE; \ -+ be,pn %xcc, jmptgt; \ -+ add %dest, 0x40, %dest; \ -+ -+#define LOOP_CHUNK1(src, dest, branch_dest) \ -+ MAIN_LOOP_CHUNK(src, dest, f0, f48, branch_dest) -+#define LOOP_CHUNK2(src, dest, branch_dest) \ -+ MAIN_LOOP_CHUNK(src, dest, f16, f48, branch_dest) -+#define LOOP_CHUNK3(src, dest, branch_dest) \ -+ MAIN_LOOP_CHUNK(src, dest, f32, f48, branch_dest) - - #define DO_SYNC membar #Sync; - #define STORE_SYNC(dest, fsrc) \ -- EX_ST_FP(STORE_BLK(%fsrc, %dest)); \ -+ EX_ST_FP(STORE_BLK(%fsrc, %dest), U1_gs_80_fp); \ - add %dest, 0x40, %dest; \ - DO_SYNC - - #define STORE_JUMP(dest, fsrc, target) \ -- EX_ST_FP(STORE_BLK(%fsrc, %dest)); \ -+ EX_ST_FP(STORE_BLK(%fsrc, %dest), U1_gs_40_fp); \ - add %dest, 0x40, %dest; \ - ba,pt %xcc, target; \ - nop; - --#define FINISH_VISCHUNK(dest, f0, f1, left) \ -- subcc %left, 8, %left;\ -- bl,pn %xcc, 95f; \ -- faligndata %f0, %f1, %f48; \ -- EX_ST_FP(STORE(std, %f48, %dest)); \ -+#define FINISH_VISCHUNK(dest, f0, f1) \ -+ subcc %g3, 8, %g3; \ -+ bl,pn %xcc, 95f; \ -+ faligndata %f0, %f1, %f48; \ -+ EX_ST_FP(STORE(std, %f48, %dest), U1_g3_8_fp); \ - add %dest, 8, %dest; - --#define UNEVEN_VISCHUNK_LAST(dest, f0, f1, left) \ -- subcc %left, 8, %left; \ -- bl,pn %xcc, 95f; \ -+#define UNEVEN_VISCHUNK_LAST(dest, f0, f1) \ -+ subcc %g3, 8, %g3; \ -+ bl,pn %xcc, 95f; \ - fsrc2 %f0, %f1; - --#define UNEVEN_VISCHUNK(dest, f0, f1, left) \ -- UNEVEN_VISCHUNK_LAST(dest, f0, f1, left) \ -+#define UNEVEN_VISCHUNK(dest, f0, f1) \ -+ UNEVEN_VISCHUNK_LAST(dest, f0, f1) \ - ba,a,pt %xcc, 93f; - - .register %g2,#scratch - .register %g3,#scratch - - .text -+#ifndef EX_RETVAL -+#define EX_RETVAL(x) x -+ENTRY(U1_g1_1_fp) -+ VISExitHalf -+ add %g1, 1, %g1 -+ add %g1, %g2, %g1 -+ retl -+ add %g1, %o2, %o0 -+ENDPROC(U1_g1_1_fp) -+ENTRY(U1_g2_0_fp) -+ VISExitHalf -+ retl -+ add %g2, %o2, %o0 -+ENDPROC(U1_g2_0_fp) -+ENTRY(U1_g2_8_fp) -+ VISExitHalf -+ add %g2, 8, %g2 -+ retl -+ add %g2, %o2, %o0 -+ENDPROC(U1_g2_8_fp) -+ENTRY(U1_gs_0_fp) -+ VISExitHalf -+ add %GLOBAL_SPARE, %g3, %o0 -+ retl -+ add %o0, %o2, %o0 -+ENDPROC(U1_gs_0_fp) -+ENTRY(U1_gs_80_fp) -+ VISExitHalf -+ add %GLOBAL_SPARE, 0x80, %GLOBAL_SPARE -+ add %GLOBAL_SPARE, %g3, %o0 -+ retl -+ add %o0, %o2, %o0 -+ENDPROC(U1_gs_80_fp) -+ENTRY(U1_gs_40_fp) -+ VISExitHalf -+ add %GLOBAL_SPARE, 0x40, %GLOBAL_SPARE -+ add %GLOBAL_SPARE, %g3, %o0 -+ retl -+ add %o0, %o2, %o0 -+ENDPROC(U1_gs_40_fp) -+ENTRY(U1_g3_0_fp) -+ VISExitHalf -+ retl -+ add %g3, %o2, %o0 -+ENDPROC(U1_g3_0_fp) -+ENTRY(U1_g3_8_fp) -+ VISExitHalf -+ add %g3, 8, %g3 -+ retl -+ add %g3, %o2, %o0 -+ENDPROC(U1_g3_8_fp) -+ENTRY(U1_o2_0_fp) -+ VISExitHalf -+ retl -+ mov %o2, %o0 -+ENDPROC(U1_o2_0_fp) -+ENTRY(U1_o2_1_fp) -+ VISExitHalf -+ retl -+ add %o2, 1, %o0 -+ENDPROC(U1_o2_1_fp) -+ENTRY(U1_gs_0) -+ VISExitHalf -+ retl -+ add %GLOBAL_SPARE, %o2, %o0 -+ENDPROC(U1_gs_0) -+ENTRY(U1_gs_8) -+ VISExitHalf -+ add %GLOBAL_SPARE, %o2, %GLOBAL_SPARE -+ retl -+ add %GLOBAL_SPARE, 0x8, %o0 -+ENDPROC(U1_gs_8) -+ENTRY(U1_gs_10) -+ VISExitHalf -+ add %GLOBAL_SPARE, %o2, %GLOBAL_SPARE -+ retl -+ add %GLOBAL_SPARE, 0x10, %o0 -+ENDPROC(U1_gs_10) -+ENTRY(U1_o2_0) -+ retl -+ mov %o2, %o0 -+ENDPROC(U1_o2_0) -+ENTRY(U1_o2_8) -+ retl -+ add %o2, 8, %o0 -+ENDPROC(U1_o2_8) -+ENTRY(U1_o2_4) -+ retl -+ add %o2, 4, %o0 -+ENDPROC(U1_o2_4) -+ENTRY(U1_o2_1) -+ retl -+ add %o2, 1, %o0 -+ENDPROC(U1_o2_1) -+ENTRY(U1_g1_0) -+ retl -+ add %g1, %o2, %o0 -+ENDPROC(U1_g1_0) -+ENTRY(U1_g1_1) -+ add %g1, 1, %g1 -+ retl -+ add %g1, %o2, %o0 -+ENDPROC(U1_g1_1) -+ENTRY(U1_gs_0_o2_adj) -+ and %o2, 7, %o2 -+ retl -+ add %GLOBAL_SPARE, %o2, %o0 -+ENDPROC(U1_gs_0_o2_adj) -+ENTRY(U1_gs_8_o2_adj) -+ and %o2, 7, %o2 -+ add %GLOBAL_SPARE, 8, %GLOBAL_SPARE -+ retl -+ add %GLOBAL_SPARE, %o2, %o0 -+ENDPROC(U1_gs_8_o2_adj) -+#endif -+ - .align 64 - - .globl FUNC_NAME -@@ -166,8 +279,8 @@ FUNC_NAME: /* %o0=dst, %o1=src, %o2=len */ - and %g2, 0x38, %g2 - - 1: subcc %g1, 0x1, %g1 -- EX_LD_FP(LOAD(ldub, %o1 + 0x00, %o3)) -- EX_ST_FP(STORE(stb, %o3, %o1 + %GLOBAL_SPARE)) -+ EX_LD_FP(LOAD(ldub, %o1 + 0x00, %o3), U1_g1_1_fp) -+ EX_ST_FP(STORE(stb, %o3, %o1 + %GLOBAL_SPARE), U1_g1_1_fp) - bgu,pt %XCC, 1b - add %o1, 0x1, %o1 - -@@ -178,20 +291,20 @@ FUNC_NAME: /* %o0=dst, %o1=src, %o2=len */ - be,pt %icc, 3f - alignaddr %o1, %g0, %o1 - -- EX_LD_FP(LOAD(ldd, %o1, %f4)) --1: EX_LD_FP(LOAD(ldd, %o1 + 0x8, %f6)) -+ EX_LD_FP(LOAD(ldd, %o1, %f4), U1_g2_0_fp) -+1: EX_LD_FP(LOAD(ldd, %o1 + 0x8, %f6), U1_g2_0_fp) - add %o1, 0x8, %o1 - subcc %g2, 0x8, %g2 - faligndata %f4, %f6, %f0 -- EX_ST_FP(STORE(std, %f0, %o0)) -+ EX_ST_FP(STORE(std, %f0, %o0), U1_g2_8_fp) - be,pn %icc, 3f - add %o0, 0x8, %o0 - -- EX_LD_FP(LOAD(ldd, %o1 + 0x8, %f4)) -+ EX_LD_FP(LOAD(ldd, %o1 + 0x8, %f4), U1_g2_0_fp) - add %o1, 0x8, %o1 - subcc %g2, 0x8, %g2 - faligndata %f6, %f4, %f0 -- EX_ST_FP(STORE(std, %f0, %o0)) -+ EX_ST_FP(STORE(std, %f0, %o0), U1_g2_8_fp) - bne,pt %icc, 1b - add %o0, 0x8, %o0 - -@@ -214,13 +327,13 @@ FUNC_NAME: /* %o0=dst, %o1=src, %o2=len */ - add %g1, %GLOBAL_SPARE, %g1 - subcc %o2, %g3, %o2 - -- EX_LD_FP(LOAD_BLK(%o1, %f0)) -+ EX_LD_FP(LOAD_BLK(%o1, %f0), U1_gs_0_fp) - add %o1, 0x40, %o1 - add %g1, %g3, %g1 -- EX_LD_FP(LOAD_BLK(%o1, %f16)) -+ EX_LD_FP(LOAD_BLK(%o1, %f16), U1_gs_0_fp) - add %o1, 0x40, %o1 - sub %GLOBAL_SPARE, 0x80, %GLOBAL_SPARE -- EX_LD_FP(LOAD_BLK(%o1, %f32)) -+ EX_LD_FP(LOAD_BLK(%o1, %f32), U1_gs_80_fp) - add %o1, 0x40, %o1 - - /* There are 8 instances of the unrolled loop, -@@ -240,11 +353,11 @@ FUNC_NAME: /* %o0=dst, %o1=src, %o2=len */ - - .align 64 - 1: FREG_FROB(f0, f2, f4, f6, f8, f10,f12,f14,f16) -- LOOP_CHUNK1(o1, o0, GLOBAL_SPARE, 1f) -+ LOOP_CHUNK1(o1, o0, 1f) - FREG_FROB(f16,f18,f20,f22,f24,f26,f28,f30,f32) -- LOOP_CHUNK2(o1, o0, GLOBAL_SPARE, 2f) -+ LOOP_CHUNK2(o1, o0, 2f) - FREG_FROB(f32,f34,f36,f38,f40,f42,f44,f46,f0) -- LOOP_CHUNK3(o1, o0, GLOBAL_SPARE, 3f) -+ LOOP_CHUNK3(o1, o0, 3f) - ba,pt %xcc, 1b+4 - faligndata %f0, %f2, %f48 - 1: FREG_FROB(f16,f18,f20,f22,f24,f26,f28,f30,f32) -@@ -261,11 +374,11 @@ FUNC_NAME: /* %o0=dst, %o1=src, %o2=len */ - STORE_JUMP(o0, f48, 56f) - - 1: FREG_FROB(f2, f4, f6, f8, f10,f12,f14,f16,f18) -- LOOP_CHUNK1(o1, o0, GLOBAL_SPARE, 1f) -+ LOOP_CHUNK1(o1, o0, 1f) - FREG_FROB(f18,f20,f22,f24,f26,f28,f30,f32,f34) -- LOOP_CHUNK2(o1, o0, GLOBAL_SPARE, 2f) -+ LOOP_CHUNK2(o1, o0, 2f) - FREG_FROB(f34,f36,f38,f40,f42,f44,f46,f0, f2) -- LOOP_CHUNK3(o1, o0, GLOBAL_SPARE, 3f) -+ LOOP_CHUNK3(o1, o0, 3f) - ba,pt %xcc, 1b+4 - faligndata %f2, %f4, %f48 - 1: FREG_FROB(f18,f20,f22,f24,f26,f28,f30,f32,f34) -@@ -282,11 +395,11 @@ FUNC_NAME: /* %o0=dst, %o1=src, %o2=len */ - STORE_JUMP(o0, f48, 57f) - - 1: FREG_FROB(f4, f6, f8, f10,f12,f14,f16,f18,f20) -- LOOP_CHUNK1(o1, o0, GLOBAL_SPARE, 1f) -+ LOOP_CHUNK1(o1, o0, 1f) - FREG_FROB(f20,f22,f24,f26,f28,f30,f32,f34,f36) -- LOOP_CHUNK2(o1, o0, GLOBAL_SPARE, 2f) -+ LOOP_CHUNK2(o1, o0, 2f) - FREG_FROB(f36,f38,f40,f42,f44,f46,f0, f2, f4) -- LOOP_CHUNK3(o1, o0, GLOBAL_SPARE, 3f) -+ LOOP_CHUNK3(o1, o0, 3f) - ba,pt %xcc, 1b+4 - faligndata %f4, %f6, %f48 - 1: FREG_FROB(f20,f22,f24,f26,f28,f30,f32,f34,f36) -@@ -303,11 +416,11 @@ FUNC_NAME: /* %o0=dst, %o1=src, %o2=len */ - STORE_JUMP(o0, f48, 58f) - - 1: FREG_FROB(f6, f8, f10,f12,f14,f16,f18,f20,f22) -- LOOP_CHUNK1(o1, o0, GLOBAL_SPARE, 1f) -+ LOOP_CHUNK1(o1, o0, 1f) - FREG_FROB(f22,f24,f26,f28,f30,f32,f34,f36,f38) -- LOOP_CHUNK2(o1, o0, GLOBAL_SPARE, 2f) -+ LOOP_CHUNK2(o1, o0, 2f) - FREG_FROB(f38,f40,f42,f44,f46,f0, f2, f4, f6) -- LOOP_CHUNK3(o1, o0, GLOBAL_SPARE, 3f) -+ LOOP_CHUNK3(o1, o0, 3f) - ba,pt %xcc, 1b+4 - faligndata %f6, %f8, %f48 - 1: FREG_FROB(f22,f24,f26,f28,f30,f32,f34,f36,f38) -@@ -324,11 +437,11 @@ FUNC_NAME: /* %o0=dst, %o1=src, %o2=len */ - STORE_JUMP(o0, f48, 59f) - - 1: FREG_FROB(f8, f10,f12,f14,f16,f18,f20,f22,f24) -- LOOP_CHUNK1(o1, o0, GLOBAL_SPARE, 1f) -+ LOOP_CHUNK1(o1, o0, 1f) - FREG_FROB(f24,f26,f28,f30,f32,f34,f36,f38,f40) -- LOOP_CHUNK2(o1, o0, GLOBAL_SPARE, 2f) -+ LOOP_CHUNK2(o1, o0, 2f) - FREG_FROB(f40,f42,f44,f46,f0, f2, f4, f6, f8) -- LOOP_CHUNK3(o1, o0, GLOBAL_SPARE, 3f) -+ LOOP_CHUNK3(o1, o0, 3f) - ba,pt %xcc, 1b+4 - faligndata %f8, %f10, %f48 - 1: FREG_FROB(f24,f26,f28,f30,f32,f34,f36,f38,f40) -@@ -345,11 +458,11 @@ FUNC_NAME: /* %o0=dst, %o1=src, %o2=len */ - STORE_JUMP(o0, f48, 60f) - - 1: FREG_FROB(f10,f12,f14,f16,f18,f20,f22,f24,f26) -- LOOP_CHUNK1(o1, o0, GLOBAL_SPARE, 1f) -+ LOOP_CHUNK1(o1, o0, 1f) - FREG_FROB(f26,f28,f30,f32,f34,f36,f38,f40,f42) -- LOOP_CHUNK2(o1, o0, GLOBAL_SPARE, 2f) -+ LOOP_CHUNK2(o1, o0, 2f) - FREG_FROB(f42,f44,f46,f0, f2, f4, f6, f8, f10) -- LOOP_CHUNK3(o1, o0, GLOBAL_SPARE, 3f) -+ LOOP_CHUNK3(o1, o0, 3f) - ba,pt %xcc, 1b+4 - faligndata %f10, %f12, %f48 - 1: FREG_FROB(f26,f28,f30,f32,f34,f36,f38,f40,f42) -@@ -366,11 +479,11 @@ FUNC_NAME: /* %o0=dst, %o1=src, %o2=len */ - STORE_JUMP(o0, f48, 61f) - - 1: FREG_FROB(f12,f14,f16,f18,f20,f22,f24,f26,f28) -- LOOP_CHUNK1(o1, o0, GLOBAL_SPARE, 1f) -+ LOOP_CHUNK1(o1, o0, 1f) - FREG_FROB(f28,f30,f32,f34,f36,f38,f40,f42,f44) -- LOOP_CHUNK2(o1, o0, GLOBAL_SPARE, 2f) -+ LOOP_CHUNK2(o1, o0, 2f) - FREG_FROB(f44,f46,f0, f2, f4, f6, f8, f10,f12) -- LOOP_CHUNK3(o1, o0, GLOBAL_SPARE, 3f) -+ LOOP_CHUNK3(o1, o0, 3f) - ba,pt %xcc, 1b+4 - faligndata %f12, %f14, %f48 - 1: FREG_FROB(f28,f30,f32,f34,f36,f38,f40,f42,f44) -@@ -387,11 +500,11 @@ FUNC_NAME: /* %o0=dst, %o1=src, %o2=len */ - STORE_JUMP(o0, f48, 62f) - - 1: FREG_FROB(f14,f16,f18,f20,f22,f24,f26,f28,f30) -- LOOP_CHUNK1(o1, o0, GLOBAL_SPARE, 1f) -+ LOOP_CHUNK1(o1, o0, 1f) - FREG_FROB(f30,f32,f34,f36,f38,f40,f42,f44,f46) -- LOOP_CHUNK2(o1, o0, GLOBAL_SPARE, 2f) -+ LOOP_CHUNK2(o1, o0, 2f) - FREG_FROB(f46,f0, f2, f4, f6, f8, f10,f12,f14) -- LOOP_CHUNK3(o1, o0, GLOBAL_SPARE, 3f) -+ LOOP_CHUNK3(o1, o0, 3f) - ba,pt %xcc, 1b+4 - faligndata %f14, %f16, %f48 - 1: FREG_FROB(f30,f32,f34,f36,f38,f40,f42,f44,f46) -@@ -407,53 +520,53 @@ FUNC_NAME: /* %o0=dst, %o1=src, %o2=len */ - FREG_FROB(f30,f32,f34,f36,f38,f40,f42,f44,f46) - STORE_JUMP(o0, f48, 63f) - --40: FINISH_VISCHUNK(o0, f0, f2, g3) --41: FINISH_VISCHUNK(o0, f2, f4, g3) --42: FINISH_VISCHUNK(o0, f4, f6, g3) --43: FINISH_VISCHUNK(o0, f6, f8, g3) --44: FINISH_VISCHUNK(o0, f8, f10, g3) --45: FINISH_VISCHUNK(o0, f10, f12, g3) --46: FINISH_VISCHUNK(o0, f12, f14, g3) --47: UNEVEN_VISCHUNK(o0, f14, f0, g3) --48: FINISH_VISCHUNK(o0, f16, f18, g3) --49: FINISH_VISCHUNK(o0, f18, f20, g3) --50: FINISH_VISCHUNK(o0, f20, f22, g3) --51: FINISH_VISCHUNK(o0, f22, f24, g3) --52: FINISH_VISCHUNK(o0, f24, f26, g3) --53: FINISH_VISCHUNK(o0, f26, f28, g3) --54: FINISH_VISCHUNK(o0, f28, f30, g3) --55: UNEVEN_VISCHUNK(o0, f30, f0, g3) --56: FINISH_VISCHUNK(o0, f32, f34, g3) --57: FINISH_VISCHUNK(o0, f34, f36, g3) --58: FINISH_VISCHUNK(o0, f36, f38, g3) --59: FINISH_VISCHUNK(o0, f38, f40, g3) --60: FINISH_VISCHUNK(o0, f40, f42, g3) --61: FINISH_VISCHUNK(o0, f42, f44, g3) --62: FINISH_VISCHUNK(o0, f44, f46, g3) --63: UNEVEN_VISCHUNK_LAST(o0, f46, f0, g3) -- --93: EX_LD_FP(LOAD(ldd, %o1, %f2)) -+40: FINISH_VISCHUNK(o0, f0, f2) -+41: FINISH_VISCHUNK(o0, f2, f4) -+42: FINISH_VISCHUNK(o0, f4, f6) -+43: FINISH_VISCHUNK(o0, f6, f8) -+44: FINISH_VISCHUNK(o0, f8, f10) -+45: FINISH_VISCHUNK(o0, f10, f12) -+46: FINISH_VISCHUNK(o0, f12, f14) -+47: UNEVEN_VISCHUNK(o0, f14, f0) -+48: FINISH_VISCHUNK(o0, f16, f18) -+49: FINISH_VISCHUNK(o0, f18, f20) -+50: FINISH_VISCHUNK(o0, f20, f22) -+51: FINISH_VISCHUNK(o0, f22, f24) -+52: FINISH_VISCHUNK(o0, f24, f26) -+53: FINISH_VISCHUNK(o0, f26, f28) -+54: FINISH_VISCHUNK(o0, f28, f30) -+55: UNEVEN_VISCHUNK(o0, f30, f0) -+56: FINISH_VISCHUNK(o0, f32, f34) -+57: FINISH_VISCHUNK(o0, f34, f36) -+58: FINISH_VISCHUNK(o0, f36, f38) -+59: FINISH_VISCHUNK(o0, f38, f40) -+60: FINISH_VISCHUNK(o0, f40, f42) -+61: FINISH_VISCHUNK(o0, f42, f44) -+62: FINISH_VISCHUNK(o0, f44, f46) -+63: UNEVEN_VISCHUNK_LAST(o0, f46, f0) -+ -+93: EX_LD_FP(LOAD(ldd, %o1, %f2), U1_g3_0_fp) - add %o1, 8, %o1 - subcc %g3, 8, %g3 - faligndata %f0, %f2, %f8 -- EX_ST_FP(STORE(std, %f8, %o0)) -+ EX_ST_FP(STORE(std, %f8, %o0), U1_g3_8_fp) - bl,pn %xcc, 95f - add %o0, 8, %o0 -- EX_LD_FP(LOAD(ldd, %o1, %f0)) -+ EX_LD_FP(LOAD(ldd, %o1, %f0), U1_g3_0_fp) - add %o1, 8, %o1 - subcc %g3, 8, %g3 - faligndata %f2, %f0, %f8 -- EX_ST_FP(STORE(std, %f8, %o0)) -+ EX_ST_FP(STORE(std, %f8, %o0), U1_g3_8_fp) - bge,pt %xcc, 93b - add %o0, 8, %o0 - - 95: brz,pt %o2, 2f - mov %g1, %o1 - --1: EX_LD_FP(LOAD(ldub, %o1, %o3)) -+1: EX_LD_FP(LOAD(ldub, %o1, %o3), U1_o2_0_fp) - add %o1, 1, %o1 - subcc %o2, 1, %o2 -- EX_ST_FP(STORE(stb, %o3, %o0)) -+ EX_ST_FP(STORE(stb, %o3, %o0), U1_o2_1_fp) - bne,pt %xcc, 1b - add %o0, 1, %o0 - -@@ -469,27 +582,27 @@ FUNC_NAME: /* %o0=dst, %o1=src, %o2=len */ - - 72: andn %o2, 0xf, %GLOBAL_SPARE - and %o2, 0xf, %o2 --1: EX_LD(LOAD(ldx, %o1 + 0x00, %o5)) -- EX_LD(LOAD(ldx, %o1 + 0x08, %g1)) -+1: EX_LD(LOAD(ldx, %o1 + 0x00, %o5), U1_gs_0) -+ EX_LD(LOAD(ldx, %o1 + 0x08, %g1), U1_gs_0) - subcc %GLOBAL_SPARE, 0x10, %GLOBAL_SPARE -- EX_ST(STORE(stx, %o5, %o1 + %o3)) -+ EX_ST(STORE(stx, %o5, %o1 + %o3), U1_gs_10) - add %o1, 0x8, %o1 -- EX_ST(STORE(stx, %g1, %o1 + %o3)) -+ EX_ST(STORE(stx, %g1, %o1 + %o3), U1_gs_8) - bgu,pt %XCC, 1b - add %o1, 0x8, %o1 - 73: andcc %o2, 0x8, %g0 - be,pt %XCC, 1f - nop -- EX_LD(LOAD(ldx, %o1, %o5)) -+ EX_LD(LOAD(ldx, %o1, %o5), U1_o2_0) - sub %o2, 0x8, %o2 -- EX_ST(STORE(stx, %o5, %o1 + %o3)) -+ EX_ST(STORE(stx, %o5, %o1 + %o3), U1_o2_8) - add %o1, 0x8, %o1 - 1: andcc %o2, 0x4, %g0 - be,pt %XCC, 1f - nop -- EX_LD(LOAD(lduw, %o1, %o5)) -+ EX_LD(LOAD(lduw, %o1, %o5), U1_o2_0) - sub %o2, 0x4, %o2 -- EX_ST(STORE(stw, %o5, %o1 + %o3)) -+ EX_ST(STORE(stw, %o5, %o1 + %o3), U1_o2_4) - add %o1, 0x4, %o1 - 1: cmp %o2, 0 - be,pt %XCC, 85f -@@ -503,9 +616,9 @@ FUNC_NAME: /* %o0=dst, %o1=src, %o2=len */ - sub %g0, %g1, %g1 - sub %o2, %g1, %o2 - --1: EX_LD(LOAD(ldub, %o1, %o5)) -+1: EX_LD(LOAD(ldub, %o1, %o5), U1_g1_0) - subcc %g1, 1, %g1 -- EX_ST(STORE(stb, %o5, %o1 + %o3)) -+ EX_ST(STORE(stb, %o5, %o1 + %o3), U1_g1_1) - bgu,pt %icc, 1b - add %o1, 1, %o1 - -@@ -521,16 +634,16 @@ FUNC_NAME: /* %o0=dst, %o1=src, %o2=len */ - - 8: mov 64, %o3 - andn %o1, 0x7, %o1 -- EX_LD(LOAD(ldx, %o1, %g2)) -+ EX_LD(LOAD(ldx, %o1, %g2), U1_o2_0) - sub %o3, %g1, %o3 - andn %o2, 0x7, %GLOBAL_SPARE - sllx %g2, %g1, %g2 --1: EX_LD(LOAD(ldx, %o1 + 0x8, %g3)) -+1: EX_LD(LOAD(ldx, %o1 + 0x8, %g3), U1_gs_0_o2_adj) - subcc %GLOBAL_SPARE, 0x8, %GLOBAL_SPARE - add %o1, 0x8, %o1 - srlx %g3, %o3, %o5 - or %o5, %g2, %o5 -- EX_ST(STORE(stx, %o5, %o0)) -+ EX_ST(STORE(stx, %o5, %o0), U1_gs_8_o2_adj) - add %o0, 0x8, %o0 - bgu,pt %icc, 1b - sllx %g3, %g1, %g2 -@@ -548,9 +661,9 @@ FUNC_NAME: /* %o0=dst, %o1=src, %o2=len */ - bne,pn %XCC, 90f - sub %o0, %o1, %o3 - --1: EX_LD(LOAD(lduw, %o1, %g1)) -+1: EX_LD(LOAD(lduw, %o1, %g1), U1_o2_0) - subcc %o2, 4, %o2 -- EX_ST(STORE(stw, %g1, %o1 + %o3)) -+ EX_ST(STORE(stw, %g1, %o1 + %o3), U1_o2_4) - bgu,pt %XCC, 1b - add %o1, 4, %o1 - -@@ -558,9 +671,9 @@ FUNC_NAME: /* %o0=dst, %o1=src, %o2=len */ - mov EX_RETVAL(%o4), %o0 - - .align 32 --90: EX_LD(LOAD(ldub, %o1, %g1)) -+90: EX_LD(LOAD(ldub, %o1, %g1), U1_o2_0) - subcc %o2, 1, %o2 -- EX_ST(STORE(stb, %g1, %o1 + %o3)) -+ EX_ST(STORE(stb, %g1, %o1 + %o3), U1_o2_1) - bgu,pt %XCC, 90b - add %o1, 1, %o1 - retl -diff --git a/arch/sparc/lib/U3copy_from_user.S b/arch/sparc/lib/U3copy_from_user.S -index 88ad73d..db73010 100644 ---- a/arch/sparc/lib/U3copy_from_user.S -+++ b/arch/sparc/lib/U3copy_from_user.S -@@ -3,19 +3,19 @@ - * Copyright (C) 1999, 2000, 2004 David S. Miller (davem@redhat.com) - */ - --#define EX_LD(x) \ -+#define EX_LD(x,y) \ - 98: x; \ - .section __ex_table,"a";\ - .align 4; \ -- .word 98b, __retl_one; \ -+ .word 98b, y; \ - .text; \ - .align 4; - --#define EX_LD_FP(x) \ -+#define EX_LD_FP(x,y) \ - 98: x; \ - .section __ex_table,"a";\ - .align 4; \ -- .word 98b, __retl_one_fp;\ -+ .word 98b, y##_fp; \ - .text; \ - .align 4; - -diff --git a/arch/sparc/lib/U3copy_to_user.S b/arch/sparc/lib/U3copy_to_user.S -index 845139d..c4ee858 100644 ---- a/arch/sparc/lib/U3copy_to_user.S -+++ b/arch/sparc/lib/U3copy_to_user.S -@@ -3,19 +3,19 @@ - * Copyright (C) 1999, 2000, 2004 David S. Miller (davem@redhat.com) - */ - --#define EX_ST(x) \ -+#define EX_ST(x,y) \ - 98: x; \ - .section __ex_table,"a";\ - .align 4; \ -- .word 98b, __retl_one; \ -+ .word 98b, y; \ - .text; \ - .align 4; - --#define EX_ST_FP(x) \ -+#define EX_ST_FP(x,y) \ - 98: x; \ - .section __ex_table,"a";\ - .align 4; \ -- .word 98b, __retl_one_fp;\ -+ .word 98b, y##_fp; \ - .text; \ - .align 4; - -diff --git a/arch/sparc/lib/U3memcpy.S b/arch/sparc/lib/U3memcpy.S -index 491ee69..54f9870 100644 ---- a/arch/sparc/lib/U3memcpy.S -+++ b/arch/sparc/lib/U3memcpy.S -@@ -4,6 +4,7 @@ - */ - - #ifdef __KERNEL__ -+#include <linux/linkage.h> - #include <asm/visasm.h> - #include <asm/asi.h> - #define GLOBAL_SPARE %g7 -@@ -22,21 +23,17 @@ - #endif - - #ifndef EX_LD --#define EX_LD(x) x -+#define EX_LD(x,y) x - #endif - #ifndef EX_LD_FP --#define EX_LD_FP(x) x -+#define EX_LD_FP(x,y) x - #endif - - #ifndef EX_ST --#define EX_ST(x) x -+#define EX_ST(x,y) x - #endif - #ifndef EX_ST_FP --#define EX_ST_FP(x) x --#endif -- --#ifndef EX_RETVAL --#define EX_RETVAL(x) x -+#define EX_ST_FP(x,y) x - #endif - - #ifndef LOAD -@@ -77,6 +74,87 @@ - */ - - .text -+#ifndef EX_RETVAL -+#define EX_RETVAL(x) x -+__restore_fp: -+ VISExitHalf -+ retl -+ nop -+ENTRY(U3_retl_o2_plus_g2_plus_g1_plus_1_fp) -+ add %g1, 1, %g1 -+ add %g2, %g1, %g2 -+ ba,pt %xcc, __restore_fp -+ add %o2, %g2, %o0 -+ENDPROC(U3_retl_o2_plus_g2_plus_g1_plus_1_fp) -+ENTRY(U3_retl_o2_plus_g2_fp) -+ ba,pt %xcc, __restore_fp -+ add %o2, %g2, %o0 -+ENDPROC(U3_retl_o2_plus_g2_fp) -+ENTRY(U3_retl_o2_plus_g2_plus_8_fp) -+ add %g2, 8, %g2 -+ ba,pt %xcc, __restore_fp -+ add %o2, %g2, %o0 -+ENDPROC(U3_retl_o2_plus_g2_plus_8_fp) -+ENTRY(U3_retl_o2) -+ retl -+ mov %o2, %o0 -+ENDPROC(U3_retl_o2) -+ENTRY(U3_retl_o2_plus_1) -+ retl -+ add %o2, 1, %o0 -+ENDPROC(U3_retl_o2_plus_1) -+ENTRY(U3_retl_o2_plus_4) -+ retl -+ add %o2, 4, %o0 -+ENDPROC(U3_retl_o2_plus_4) -+ENTRY(U3_retl_o2_plus_8) -+ retl -+ add %o2, 8, %o0 -+ENDPROC(U3_retl_o2_plus_8) -+ENTRY(U3_retl_o2_plus_g1_plus_1) -+ add %g1, 1, %g1 -+ retl -+ add %o2, %g1, %o0 -+ENDPROC(U3_retl_o2_plus_g1_plus_1) -+ENTRY(U3_retl_o2_fp) -+ ba,pt %xcc, __restore_fp -+ mov %o2, %o0 -+ENDPROC(U3_retl_o2_fp) -+ENTRY(U3_retl_o2_plus_o3_sll_6_plus_0x80_fp) -+ sll %o3, 6, %o3 -+ add %o3, 0x80, %o3 -+ ba,pt %xcc, __restore_fp -+ add %o2, %o3, %o0 -+ENDPROC(U3_retl_o2_plus_o3_sll_6_plus_0x80_fp) -+ENTRY(U3_retl_o2_plus_o3_sll_6_plus_0x40_fp) -+ sll %o3, 6, %o3 -+ add %o3, 0x40, %o3 -+ ba,pt %xcc, __restore_fp -+ add %o2, %o3, %o0 -+ENDPROC(U3_retl_o2_plus_o3_sll_6_plus_0x40_fp) -+ENTRY(U3_retl_o2_plus_GS_plus_0x10) -+ add GLOBAL_SPARE, 0x10, GLOBAL_SPARE -+ retl -+ add %o2, GLOBAL_SPARE, %o0 -+ENDPROC(U3_retl_o2_plus_GS_plus_0x10) -+ENTRY(U3_retl_o2_plus_GS_plus_0x08) -+ add GLOBAL_SPARE, 0x08, GLOBAL_SPARE -+ retl -+ add %o2, GLOBAL_SPARE, %o0 -+ENDPROC(U3_retl_o2_plus_GS_plus_0x08) -+ENTRY(U3_retl_o2_and_7_plus_GS) -+ and %o2, 7, %o2 -+ retl -+ add %o2, GLOBAL_SPARE, %o2 -+ENDPROC(U3_retl_o2_and_7_plus_GS) -+ENTRY(U3_retl_o2_and_7_plus_GS_plus_8) -+ add GLOBAL_SPARE, 8, GLOBAL_SPARE -+ and %o2, 7, %o2 -+ retl -+ add %o2, GLOBAL_SPARE, %o2 -+ENDPROC(U3_retl_o2_and_7_plus_GS_plus_8) -+#endif -+ - .align 64 - - /* The cheetah's flexible spine, oversized liver, enlarged heart, -@@ -126,8 +204,8 @@ FUNC_NAME: /* %o0=dst, %o1=src, %o2=len */ - and %g2, 0x38, %g2 - - 1: subcc %g1, 0x1, %g1 -- EX_LD_FP(LOAD(ldub, %o1 + 0x00, %o3)) -- EX_ST_FP(STORE(stb, %o3, %o1 + GLOBAL_SPARE)) -+ EX_LD_FP(LOAD(ldub, %o1 + 0x00, %o3), U3_retl_o2_plus_g2_plus_g1_plus_1) -+ EX_ST_FP(STORE(stb, %o3, %o1 + GLOBAL_SPARE), U3_retl_o2_plus_g2_plus_g1_plus_1) - bgu,pt %XCC, 1b - add %o1, 0x1, %o1 - -@@ -138,20 +216,20 @@ FUNC_NAME: /* %o0=dst, %o1=src, %o2=len */ - be,pt %icc, 3f - alignaddr %o1, %g0, %o1 - -- EX_LD_FP(LOAD(ldd, %o1, %f4)) --1: EX_LD_FP(LOAD(ldd, %o1 + 0x8, %f6)) -+ EX_LD_FP(LOAD(ldd, %o1, %f4), U3_retl_o2_plus_g2) -+1: EX_LD_FP(LOAD(ldd, %o1 + 0x8, %f6), U3_retl_o2_plus_g2) - add %o1, 0x8, %o1 - subcc %g2, 0x8, %g2 - faligndata %f4, %f6, %f0 -- EX_ST_FP(STORE(std, %f0, %o0)) -+ EX_ST_FP(STORE(std, %f0, %o0), U3_retl_o2_plus_g2_plus_8) - be,pn %icc, 3f - add %o0, 0x8, %o0 - -- EX_LD_FP(LOAD(ldd, %o1 + 0x8, %f4)) -+ EX_LD_FP(LOAD(ldd, %o1 + 0x8, %f4), U3_retl_o2_plus_g2) - add %o1, 0x8, %o1 - subcc %g2, 0x8, %g2 - faligndata %f6, %f4, %f2 -- EX_ST_FP(STORE(std, %f2, %o0)) -+ EX_ST_FP(STORE(std, %f2, %o0), U3_retl_o2_plus_g2_plus_8) - bne,pt %icc, 1b - add %o0, 0x8, %o0 - -@@ -161,25 +239,25 @@ FUNC_NAME: /* %o0=dst, %o1=src, %o2=len */ - LOAD(prefetch, %o1 + 0x080, #one_read) - LOAD(prefetch, %o1 + 0x0c0, #one_read) - LOAD(prefetch, %o1 + 0x100, #one_read) -- EX_LD_FP(LOAD(ldd, %o1 + 0x000, %f0)) -+ EX_LD_FP(LOAD(ldd, %o1 + 0x000, %f0), U3_retl_o2) - LOAD(prefetch, %o1 + 0x140, #one_read) -- EX_LD_FP(LOAD(ldd, %o1 + 0x008, %f2)) -+ EX_LD_FP(LOAD(ldd, %o1 + 0x008, %f2), U3_retl_o2) - LOAD(prefetch, %o1 + 0x180, #one_read) -- EX_LD_FP(LOAD(ldd, %o1 + 0x010, %f4)) -+ EX_LD_FP(LOAD(ldd, %o1 + 0x010, %f4), U3_retl_o2) - LOAD(prefetch, %o1 + 0x1c0, #one_read) - faligndata %f0, %f2, %f16 -- EX_LD_FP(LOAD(ldd, %o1 + 0x018, %f6)) -+ EX_LD_FP(LOAD(ldd, %o1 + 0x018, %f6), U3_retl_o2) - faligndata %f2, %f4, %f18 -- EX_LD_FP(LOAD(ldd, %o1 + 0x020, %f8)) -+ EX_LD_FP(LOAD(ldd, %o1 + 0x020, %f8), U3_retl_o2) - faligndata %f4, %f6, %f20 -- EX_LD_FP(LOAD(ldd, %o1 + 0x028, %f10)) -+ EX_LD_FP(LOAD(ldd, %o1 + 0x028, %f10), U3_retl_o2) - faligndata %f6, %f8, %f22 - -- EX_LD_FP(LOAD(ldd, %o1 + 0x030, %f12)) -+ EX_LD_FP(LOAD(ldd, %o1 + 0x030, %f12), U3_retl_o2) - faligndata %f8, %f10, %f24 -- EX_LD_FP(LOAD(ldd, %o1 + 0x038, %f14)) -+ EX_LD_FP(LOAD(ldd, %o1 + 0x038, %f14), U3_retl_o2) - faligndata %f10, %f12, %f26 -- EX_LD_FP(LOAD(ldd, %o1 + 0x040, %f0)) -+ EX_LD_FP(LOAD(ldd, %o1 + 0x040, %f0), U3_retl_o2) - - subcc GLOBAL_SPARE, 0x80, GLOBAL_SPARE - add %o1, 0x40, %o1 -@@ -190,26 +268,26 @@ FUNC_NAME: /* %o0=dst, %o1=src, %o2=len */ - - .align 64 - 1: -- EX_LD_FP(LOAD(ldd, %o1 + 0x008, %f2)) -+ EX_LD_FP(LOAD(ldd, %o1 + 0x008, %f2), U3_retl_o2_plus_o3_sll_6_plus_0x80) - faligndata %f12, %f14, %f28 -- EX_LD_FP(LOAD(ldd, %o1 + 0x010, %f4)) -+ EX_LD_FP(LOAD(ldd, %o1 + 0x010, %f4), U3_retl_o2_plus_o3_sll_6_plus_0x80) - faligndata %f14, %f0, %f30 -- EX_ST_FP(STORE_BLK(%f16, %o0)) -- EX_LD_FP(LOAD(ldd, %o1 + 0x018, %f6)) -+ EX_ST_FP(STORE_BLK(%f16, %o0), U3_retl_o2_plus_o3_sll_6_plus_0x80) -+ EX_LD_FP(LOAD(ldd, %o1 + 0x018, %f6), U3_retl_o2_plus_o3_sll_6_plus_0x40) - faligndata %f0, %f2, %f16 - add %o0, 0x40, %o0 - -- EX_LD_FP(LOAD(ldd, %o1 + 0x020, %f8)) -+ EX_LD_FP(LOAD(ldd, %o1 + 0x020, %f8), U3_retl_o2_plus_o3_sll_6_plus_0x40) - faligndata %f2, %f4, %f18 -- EX_LD_FP(LOAD(ldd, %o1 + 0x028, %f10)) -+ EX_LD_FP(LOAD(ldd, %o1 + 0x028, %f10), U3_retl_o2_plus_o3_sll_6_plus_0x40) - faligndata %f4, %f6, %f20 -- EX_LD_FP(LOAD(ldd, %o1 + 0x030, %f12)) -+ EX_LD_FP(LOAD(ldd, %o1 + 0x030, %f12), U3_retl_o2_plus_o3_sll_6_plus_0x40) - subcc %o3, 0x01, %o3 - faligndata %f6, %f8, %f22 -- EX_LD_FP(LOAD(ldd, %o1 + 0x038, %f14)) -+ EX_LD_FP(LOAD(ldd, %o1 + 0x038, %f14), U3_retl_o2_plus_o3_sll_6_plus_0x80) - - faligndata %f8, %f10, %f24 -- EX_LD_FP(LOAD(ldd, %o1 + 0x040, %f0)) -+ EX_LD_FP(LOAD(ldd, %o1 + 0x040, %f0), U3_retl_o2_plus_o3_sll_6_plus_0x80) - LOAD(prefetch, %o1 + 0x1c0, #one_read) - faligndata %f10, %f12, %f26 - bg,pt %XCC, 1b -@@ -217,29 +295,29 @@ FUNC_NAME: /* %o0=dst, %o1=src, %o2=len */ - - /* Finally we copy the last full 64-byte block. */ - 2: -- EX_LD_FP(LOAD(ldd, %o1 + 0x008, %f2)) -+ EX_LD_FP(LOAD(ldd, %o1 + 0x008, %f2), U3_retl_o2_plus_o3_sll_6_plus_0x80) - faligndata %f12, %f14, %f28 -- EX_LD_FP(LOAD(ldd, %o1 + 0x010, %f4)) -+ EX_LD_FP(LOAD(ldd, %o1 + 0x010, %f4), U3_retl_o2_plus_o3_sll_6_plus_0x80) - faligndata %f14, %f0, %f30 -- EX_ST_FP(STORE_BLK(%f16, %o0)) -- EX_LD_FP(LOAD(ldd, %o1 + 0x018, %f6)) -+ EX_ST_FP(STORE_BLK(%f16, %o0), U3_retl_o2_plus_o3_sll_6_plus_0x80) -+ EX_LD_FP(LOAD(ldd, %o1 + 0x018, %f6), U3_retl_o2_plus_o3_sll_6_plus_0x40) - faligndata %f0, %f2, %f16 -- EX_LD_FP(LOAD(ldd, %o1 + 0x020, %f8)) -+ EX_LD_FP(LOAD(ldd, %o1 + 0x020, %f8), U3_retl_o2_plus_o3_sll_6_plus_0x40) - faligndata %f2, %f4, %f18 -- EX_LD_FP(LOAD(ldd, %o1 + 0x028, %f10)) -+ EX_LD_FP(LOAD(ldd, %o1 + 0x028, %f10), U3_retl_o2_plus_o3_sll_6_plus_0x40) - faligndata %f4, %f6, %f20 -- EX_LD_FP(LOAD(ldd, %o1 + 0x030, %f12)) -+ EX_LD_FP(LOAD(ldd, %o1 + 0x030, %f12), U3_retl_o2_plus_o3_sll_6_plus_0x40) - faligndata %f6, %f8, %f22 -- EX_LD_FP(LOAD(ldd, %o1 + 0x038, %f14)) -+ EX_LD_FP(LOAD(ldd, %o1 + 0x038, %f14), U3_retl_o2_plus_o3_sll_6_plus_0x40) - faligndata %f8, %f10, %f24 - cmp %g1, 0 - be,pt %XCC, 1f - add %o0, 0x40, %o0 -- EX_LD_FP(LOAD(ldd, %o1 + 0x040, %f0)) -+ EX_LD_FP(LOAD(ldd, %o1 + 0x040, %f0), U3_retl_o2_plus_o3_sll_6_plus_0x40) - 1: faligndata %f10, %f12, %f26 - faligndata %f12, %f14, %f28 - faligndata %f14, %f0, %f30 -- EX_ST_FP(STORE_BLK(%f16, %o0)) -+ EX_ST_FP(STORE_BLK(%f16, %o0), U3_retl_o2_plus_o3_sll_6_plus_0x40) - add %o0, 0x40, %o0 - add %o1, 0x40, %o1 - membar #Sync -@@ -259,20 +337,20 @@ FUNC_NAME: /* %o0=dst, %o1=src, %o2=len */ - - sub %o2, %g2, %o2 - be,a,pt %XCC, 1f -- EX_LD_FP(LOAD(ldd, %o1 + 0x00, %f0)) -+ EX_LD_FP(LOAD(ldd, %o1 + 0x00, %f0), U3_retl_o2_plus_g2) - --1: EX_LD_FP(LOAD(ldd, %o1 + 0x08, %f2)) -+1: EX_LD_FP(LOAD(ldd, %o1 + 0x08, %f2), U3_retl_o2_plus_g2) - add %o1, 0x8, %o1 - subcc %g2, 0x8, %g2 - faligndata %f0, %f2, %f8 -- EX_ST_FP(STORE(std, %f8, %o0)) -+ EX_ST_FP(STORE(std, %f8, %o0), U3_retl_o2_plus_g2_plus_8) - be,pn %XCC, 2f - add %o0, 0x8, %o0 -- EX_LD_FP(LOAD(ldd, %o1 + 0x08, %f0)) -+ EX_LD_FP(LOAD(ldd, %o1 + 0x08, %f0), U3_retl_o2_plus_g2) - add %o1, 0x8, %o1 - subcc %g2, 0x8, %g2 - faligndata %f2, %f0, %f8 -- EX_ST_FP(STORE(std, %f8, %o0)) -+ EX_ST_FP(STORE(std, %f8, %o0), U3_retl_o2_plus_g2_plus_8) - bne,pn %XCC, 1b - add %o0, 0x8, %o0 - -@@ -292,30 +370,33 @@ FUNC_NAME: /* %o0=dst, %o1=src, %o2=len */ - andcc %o2, 0x8, %g0 - be,pt %icc, 1f - nop -- EX_LD(LOAD(ldx, %o1, %o5)) -- EX_ST(STORE(stx, %o5, %o1 + %o3)) -+ EX_LD(LOAD(ldx, %o1, %o5), U3_retl_o2) -+ EX_ST(STORE(stx, %o5, %o1 + %o3), U3_retl_o2) - add %o1, 0x8, %o1 -+ sub %o2, 8, %o2 - - 1: andcc %o2, 0x4, %g0 - be,pt %icc, 1f - nop -- EX_LD(LOAD(lduw, %o1, %o5)) -- EX_ST(STORE(stw, %o5, %o1 + %o3)) -+ EX_LD(LOAD(lduw, %o1, %o5), U3_retl_o2) -+ EX_ST(STORE(stw, %o5, %o1 + %o3), U3_retl_o2) - add %o1, 0x4, %o1 -+ sub %o2, 4, %o2 - - 1: andcc %o2, 0x2, %g0 - be,pt %icc, 1f - nop -- EX_LD(LOAD(lduh, %o1, %o5)) -- EX_ST(STORE(sth, %o5, %o1 + %o3)) -+ EX_LD(LOAD(lduh, %o1, %o5), U3_retl_o2) -+ EX_ST(STORE(sth, %o5, %o1 + %o3), U3_retl_o2) - add %o1, 0x2, %o1 -+ sub %o2, 2, %o2 - - 1: andcc %o2, 0x1, %g0 - be,pt %icc, 85f - nop -- EX_LD(LOAD(ldub, %o1, %o5)) -+ EX_LD(LOAD(ldub, %o1, %o5), U3_retl_o2) - ba,pt %xcc, 85f -- EX_ST(STORE(stb, %o5, %o1 + %o3)) -+ EX_ST(STORE(stb, %o5, %o1 + %o3), U3_retl_o2) - - .align 64 - 70: /* 16 < len <= 64 */ -@@ -326,26 +407,26 @@ FUNC_NAME: /* %o0=dst, %o1=src, %o2=len */ - andn %o2, 0xf, GLOBAL_SPARE - and %o2, 0xf, %o2 - 1: subcc GLOBAL_SPARE, 0x10, GLOBAL_SPARE -- EX_LD(LOAD(ldx, %o1 + 0x00, %o5)) -- EX_LD(LOAD(ldx, %o1 + 0x08, %g1)) -- EX_ST(STORE(stx, %o5, %o1 + %o3)) -+ EX_LD(LOAD(ldx, %o1 + 0x00, %o5), U3_retl_o2_plus_GS_plus_0x10) -+ EX_LD(LOAD(ldx, %o1 + 0x08, %g1), U3_retl_o2_plus_GS_plus_0x10) -+ EX_ST(STORE(stx, %o5, %o1 + %o3), U3_retl_o2_plus_GS_plus_0x10) - add %o1, 0x8, %o1 -- EX_ST(STORE(stx, %g1, %o1 + %o3)) -+ EX_ST(STORE(stx, %g1, %o1 + %o3), U3_retl_o2_plus_GS_plus_0x08) - bgu,pt %XCC, 1b - add %o1, 0x8, %o1 - 73: andcc %o2, 0x8, %g0 - be,pt %XCC, 1f - nop - sub %o2, 0x8, %o2 -- EX_LD(LOAD(ldx, %o1, %o5)) -- EX_ST(STORE(stx, %o5, %o1 + %o3)) -+ EX_LD(LOAD(ldx, %o1, %o5), U3_retl_o2_plus_8) -+ EX_ST(STORE(stx, %o5, %o1 + %o3), U3_retl_o2_plus_8) - add %o1, 0x8, %o1 - 1: andcc %o2, 0x4, %g0 - be,pt %XCC, 1f - nop - sub %o2, 0x4, %o2 -- EX_LD(LOAD(lduw, %o1, %o5)) -- EX_ST(STORE(stw, %o5, %o1 + %o3)) -+ EX_LD(LOAD(lduw, %o1, %o5), U3_retl_o2_plus_4) -+ EX_ST(STORE(stw, %o5, %o1 + %o3), U3_retl_o2_plus_4) - add %o1, 0x4, %o1 - 1: cmp %o2, 0 - be,pt %XCC, 85f -@@ -361,8 +442,8 @@ FUNC_NAME: /* %o0=dst, %o1=src, %o2=len */ - sub %o2, %g1, %o2 - - 1: subcc %g1, 1, %g1 -- EX_LD(LOAD(ldub, %o1, %o5)) -- EX_ST(STORE(stb, %o5, %o1 + %o3)) -+ EX_LD(LOAD(ldub, %o1, %o5), U3_retl_o2_plus_g1_plus_1) -+ EX_ST(STORE(stb, %o5, %o1 + %o3), U3_retl_o2_plus_g1_plus_1) - bgu,pt %icc, 1b - add %o1, 1, %o1 - -@@ -378,16 +459,16 @@ FUNC_NAME: /* %o0=dst, %o1=src, %o2=len */ - - 8: mov 64, %o3 - andn %o1, 0x7, %o1 -- EX_LD(LOAD(ldx, %o1, %g2)) -+ EX_LD(LOAD(ldx, %o1, %g2), U3_retl_o2) - sub %o3, %g1, %o3 - andn %o2, 0x7, GLOBAL_SPARE - sllx %g2, %g1, %g2 --1: EX_LD(LOAD(ldx, %o1 + 0x8, %g3)) -+1: EX_LD(LOAD(ldx, %o1 + 0x8, %g3), U3_retl_o2_and_7_plus_GS) - subcc GLOBAL_SPARE, 0x8, GLOBAL_SPARE - add %o1, 0x8, %o1 - srlx %g3, %o3, %o5 - or %o5, %g2, %o5 -- EX_ST(STORE(stx, %o5, %o0)) -+ EX_ST(STORE(stx, %o5, %o0), U3_retl_o2_and_7_plus_GS_plus_8) - add %o0, 0x8, %o0 - bgu,pt %icc, 1b - sllx %g3, %g1, %g2 -@@ -407,8 +488,8 @@ FUNC_NAME: /* %o0=dst, %o1=src, %o2=len */ - - 1: - subcc %o2, 4, %o2 -- EX_LD(LOAD(lduw, %o1, %g1)) -- EX_ST(STORE(stw, %g1, %o1 + %o3)) -+ EX_LD(LOAD(lduw, %o1, %g1), U3_retl_o2_plus_4) -+ EX_ST(STORE(stw, %g1, %o1 + %o3), U3_retl_o2_plus_4) - bgu,pt %XCC, 1b - add %o1, 4, %o1 - -@@ -418,8 +499,8 @@ FUNC_NAME: /* %o0=dst, %o1=src, %o2=len */ - .align 32 - 90: - subcc %o2, 1, %o2 -- EX_LD(LOAD(ldub, %o1, %g1)) -- EX_ST(STORE(stb, %g1, %o1 + %o3)) -+ EX_LD(LOAD(ldub, %o1, %g1), U3_retl_o2_plus_1) -+ EX_ST(STORE(stb, %g1, %o1 + %o3), U3_retl_o2_plus_1) - bgu,pt %XCC, 90b - add %o1, 1, %o1 - retl -diff --git a/arch/sparc/lib/copy_in_user.S b/arch/sparc/lib/copy_in_user.S -index 302c0e6..4c89b48 100644 ---- a/arch/sparc/lib/copy_in_user.S -+++ b/arch/sparc/lib/copy_in_user.S -@@ -8,18 +8,33 @@ - - #define XCC xcc - --#define EX(x,y) \ -+#define EX(x,y,z) \ - 98: x,y; \ - .section __ex_table,"a";\ - .align 4; \ -- .word 98b, __retl_one; \ -+ .word 98b, z; \ - .text; \ - .align 4; - -+#define EX_O4(x,y) EX(x,y,__retl_o4_plus_8) -+#define EX_O2_4(x,y) EX(x,y,__retl_o2_plus_4) -+#define EX_O2_1(x,y) EX(x,y,__retl_o2_plus_1) -+ - .register %g2,#scratch - .register %g3,#scratch - - .text -+__retl_o4_plus_8: -+ add %o4, %o2, %o4 -+ retl -+ add %o4, 8, %o0 -+__retl_o2_plus_4: -+ retl -+ add %o2, 4, %o0 -+__retl_o2_plus_1: -+ retl -+ add %o2, 1, %o0 -+ - .align 32 - - /* Don't try to get too fancy here, just nice and -@@ -44,8 +59,8 @@ ENTRY(___copy_in_user) /* %o0=dst, %o1=src, %o2=len */ - andn %o2, 0x7, %o4 - and %o2, 0x7, %o2 - 1: subcc %o4, 0x8, %o4 -- EX(ldxa [%o1] %asi, %o5) -- EX(stxa %o5, [%o0] %asi) -+ EX_O4(ldxa [%o1] %asi, %o5) -+ EX_O4(stxa %o5, [%o0] %asi) - add %o1, 0x8, %o1 - bgu,pt %XCC, 1b - add %o0, 0x8, %o0 -@@ -53,8 +68,8 @@ ENTRY(___copy_in_user) /* %o0=dst, %o1=src, %o2=len */ - be,pt %XCC, 1f - nop - sub %o2, 0x4, %o2 -- EX(lduwa [%o1] %asi, %o5) -- EX(stwa %o5, [%o0] %asi) -+ EX_O2_4(lduwa [%o1] %asi, %o5) -+ EX_O2_4(stwa %o5, [%o0] %asi) - add %o1, 0x4, %o1 - add %o0, 0x4, %o0 - 1: cmp %o2, 0 -@@ -70,8 +85,8 @@ ENTRY(___copy_in_user) /* %o0=dst, %o1=src, %o2=len */ - - 82: - subcc %o2, 4, %o2 -- EX(lduwa [%o1] %asi, %g1) -- EX(stwa %g1, [%o0] %asi) -+ EX_O2_4(lduwa [%o1] %asi, %g1) -+ EX_O2_4(stwa %g1, [%o0] %asi) - add %o1, 4, %o1 - bgu,pt %XCC, 82b - add %o0, 4, %o0 -@@ -82,8 +97,8 @@ ENTRY(___copy_in_user) /* %o0=dst, %o1=src, %o2=len */ - .align 32 - 90: - subcc %o2, 1, %o2 -- EX(lduba [%o1] %asi, %g1) -- EX(stba %g1, [%o0] %asi) -+ EX_O2_1(lduba [%o1] %asi, %g1) -+ EX_O2_1(stba %g1, [%o0] %asi) - add %o1, 1, %o1 - bgu,pt %XCC, 90b - add %o0, 1, %o0 -diff --git a/arch/sparc/lib/user_fixup.c b/arch/sparc/lib/user_fixup.c -deleted file mode 100644 -index ac96ae2..0000000 ---- a/arch/sparc/lib/user_fixup.c -+++ /dev/null -@@ -1,71 +0,0 @@ --/* user_fixup.c: Fix up user copy faults. -- * -- * Copyright (C) 2004 David S. Miller <davem@redhat.com> -- */ -- --#include <linux/compiler.h> --#include <linux/kernel.h> --#include <linux/string.h> --#include <linux/errno.h> --#include <linux/module.h> -- --#include <asm/uaccess.h> -- --/* Calculating the exact fault address when using -- * block loads and stores can be very complicated. -- * -- * Instead of trying to be clever and handling all -- * of the cases, just fix things up simply here. -- */ -- --static unsigned long compute_size(unsigned long start, unsigned long size, unsigned long *offset) --{ -- unsigned long fault_addr = current_thread_info()->fault_address; -- unsigned long end = start + size; -- -- if (fault_addr < start || fault_addr >= end) { -- *offset = 0; -- } else { -- *offset = fault_addr - start; -- size = end - fault_addr; -- } -- return size; --} -- --unsigned long copy_from_user_fixup(void *to, const void __user *from, unsigned long size) --{ -- unsigned long offset; -- -- size = compute_size((unsigned long) from, size, &offset); -- if (likely(size)) -- memset(to + offset, 0, size); -- -- return size; --} --EXPORT_SYMBOL(copy_from_user_fixup); -- --unsigned long copy_to_user_fixup(void __user *to, const void *from, unsigned long size) --{ -- unsigned long offset; -- -- return compute_size((unsigned long) to, size, &offset); --} --EXPORT_SYMBOL(copy_to_user_fixup); -- --unsigned long copy_in_user_fixup(void __user *to, void __user *from, unsigned long size) --{ -- unsigned long fault_addr = current_thread_info()->fault_address; -- unsigned long start = (unsigned long) to; -- unsigned long end = start + size; -- -- if (fault_addr >= start && fault_addr < end) -- return end - fault_addr; -- -- start = (unsigned long) from; -- end = start + size; -- if (fault_addr >= start && fault_addr < end) -- return end - fault_addr; -- -- return size; --} --EXPORT_SYMBOL(copy_in_user_fixup); -diff --git a/arch/sparc/mm/tsb.c b/arch/sparc/mm/tsb.c -index f2b7711..e20fbba 100644 ---- a/arch/sparc/mm/tsb.c -+++ b/arch/sparc/mm/tsb.c -@@ -27,6 +27,20 @@ static inline int tag_compare(unsigned long tag, unsigned long vaddr) - return (tag == (vaddr >> 22)); - } - -+static void flush_tsb_kernel_range_scan(unsigned long start, unsigned long end) -+{ -+ unsigned long idx; -+ -+ for (idx = 0; idx < KERNEL_TSB_NENTRIES; idx++) { -+ struct tsb *ent = &swapper_tsb[idx]; -+ unsigned long match = idx << 13; -+ -+ match |= (ent->tag << 22); -+ if (match >= start && match < end) -+ ent->tag = (1UL << TSB_TAG_INVALID_BIT); -+ } -+} -+ - /* TSB flushes need only occur on the processor initiating the address - * space modification, not on each cpu the address space has run on. - * Only the TLB flush needs that treatment. -@@ -36,6 +50,9 @@ void flush_tsb_kernel_range(unsigned long start, unsigned long end) - { - unsigned long v; - -+ if ((end - start) >> PAGE_SHIFT >= 2 * KERNEL_TSB_NENTRIES) -+ return flush_tsb_kernel_range_scan(start, end); -+ - for (v = start; v < end; v += PAGE_SIZE) { - unsigned long hash = tsb_hash(v, PAGE_SHIFT, - KERNEL_TSB_NENTRIES); -diff --git a/arch/sparc/mm/ultra.S b/arch/sparc/mm/ultra.S -index b4f4733..5d2fd6c 100644 ---- a/arch/sparc/mm/ultra.S -+++ b/arch/sparc/mm/ultra.S -@@ -30,7 +30,7 @@ - .text - .align 32 - .globl __flush_tlb_mm --__flush_tlb_mm: /* 18 insns */ -+__flush_tlb_mm: /* 19 insns */ - /* %o0=(ctx & TAG_CONTEXT_BITS), %o1=SECONDARY_CONTEXT */ - ldxa [%o1] ASI_DMMU, %g2 - cmp %g2, %o0 -@@ -81,7 +81,7 @@ __flush_tlb_page: /* 22 insns */ - - .align 32 - .globl __flush_tlb_pending --__flush_tlb_pending: /* 26 insns */ -+__flush_tlb_pending: /* 27 insns */ - /* %o0 = context, %o1 = nr, %o2 = vaddrs[] */ - rdpr %pstate, %g7 - sllx %o1, 3, %o1 -@@ -113,12 +113,14 @@ __flush_tlb_pending: /* 26 insns */ - - .align 32 - .globl __flush_tlb_kernel_range --__flush_tlb_kernel_range: /* 16 insns */ -+__flush_tlb_kernel_range: /* 31 insns */ - /* %o0=start, %o1=end */ - cmp %o0, %o1 - be,pn %xcc, 2f -+ sub %o1, %o0, %o3 -+ srlx %o3, 18, %o4 -+ brnz,pn %o4, __spitfire_flush_tlb_kernel_range_slow - sethi %hi(PAGE_SIZE), %o4 -- sub %o1, %o0, %o3 - sub %o3, %o4, %o3 - or %o0, 0x20, %o0 ! Nucleus - 1: stxa %g0, [%o0 + %o3] ASI_DMMU_DEMAP -@@ -131,6 +133,41 @@ __flush_tlb_kernel_range: /* 16 insns */ - retl - nop - nop -+ nop -+ nop -+ nop -+ nop -+ nop -+ nop -+ nop -+ nop -+ nop -+ nop -+ nop -+ nop -+ nop -+ -+__spitfire_flush_tlb_kernel_range_slow: -+ mov 63 * 8, %o4 -+1: ldxa [%o4] ASI_ITLB_DATA_ACCESS, %o3 -+ andcc %o3, 0x40, %g0 /* _PAGE_L_4U */ -+ bne,pn %xcc, 2f -+ mov TLB_TAG_ACCESS, %o3 -+ stxa %g0, [%o3] ASI_IMMU -+ stxa %g0, [%o4] ASI_ITLB_DATA_ACCESS -+ membar #Sync -+2: ldxa [%o4] ASI_DTLB_DATA_ACCESS, %o3 -+ andcc %o3, 0x40, %g0 -+ bne,pn %xcc, 2f -+ mov TLB_TAG_ACCESS, %o3 -+ stxa %g0, [%o3] ASI_DMMU -+ stxa %g0, [%o4] ASI_DTLB_DATA_ACCESS -+ membar #Sync -+2: sub %o4, 8, %o4 -+ brgez,pt %o4, 1b -+ nop -+ retl -+ nop - - __spitfire_flush_tlb_mm_slow: - rdpr %pstate, %g1 -@@ -285,6 +322,40 @@ __cheetah_flush_tlb_pending: /* 27 insns */ - retl - wrpr %g7, 0x0, %pstate - -+__cheetah_flush_tlb_kernel_range: /* 31 insns */ -+ /* %o0=start, %o1=end */ -+ cmp %o0, %o1 -+ be,pn %xcc, 2f -+ sub %o1, %o0, %o3 -+ srlx %o3, 18, %o4 -+ brnz,pn %o4, 3f -+ sethi %hi(PAGE_SIZE), %o4 -+ sub %o3, %o4, %o3 -+ or %o0, 0x20, %o0 ! Nucleus -+1: stxa %g0, [%o0 + %o3] ASI_DMMU_DEMAP -+ stxa %g0, [%o0 + %o3] ASI_IMMU_DEMAP -+ membar #Sync -+ brnz,pt %o3, 1b -+ sub %o3, %o4, %o3 -+2: sethi %hi(KERNBASE), %o3 -+ flush %o3 -+ retl -+ nop -+3: mov 0x80, %o4 -+ stxa %g0, [%o4] ASI_DMMU_DEMAP -+ membar #Sync -+ stxa %g0, [%o4] ASI_IMMU_DEMAP -+ membar #Sync -+ retl -+ nop -+ nop -+ nop -+ nop -+ nop -+ nop -+ nop -+ nop -+ - #ifdef DCACHE_ALIASING_POSSIBLE - __cheetah_flush_dcache_page: /* 11 insns */ - sethi %hi(PAGE_OFFSET), %g1 -@@ -309,19 +380,28 @@ __hypervisor_tlb_tl0_error: - ret - restore - --__hypervisor_flush_tlb_mm: /* 10 insns */ -+__hypervisor_flush_tlb_mm: /* 19 insns */ - mov %o0, %o2 /* ARG2: mmu context */ - mov 0, %o0 /* ARG0: CPU lists unimplemented */ - mov 0, %o1 /* ARG1: CPU lists unimplemented */ - mov HV_MMU_ALL, %o3 /* ARG3: flags */ - mov HV_FAST_MMU_DEMAP_CTX, %o5 - ta HV_FAST_TRAP -- brnz,pn %o0, __hypervisor_tlb_tl0_error -+ brnz,pn %o0, 1f - mov HV_FAST_MMU_DEMAP_CTX, %o1 - retl - nop -+1: sethi %hi(__hypervisor_tlb_tl0_error), %o5 -+ jmpl %o5 + %lo(__hypervisor_tlb_tl0_error), %g0 -+ nop -+ nop -+ nop -+ nop -+ nop -+ nop -+ nop - --__hypervisor_flush_tlb_page: /* 11 insns */ -+__hypervisor_flush_tlb_page: /* 22 insns */ - /* %o0 = context, %o1 = vaddr */ - mov %o0, %g2 - mov %o1, %o0 /* ARG0: vaddr + IMMU-bit */ -@@ -330,12 +410,23 @@ __hypervisor_flush_tlb_page: /* 11 insns */ - srlx %o0, PAGE_SHIFT, %o0 - sllx %o0, PAGE_SHIFT, %o0 - ta HV_MMU_UNMAP_ADDR_TRAP -- brnz,pn %o0, __hypervisor_tlb_tl0_error -+ brnz,pn %o0, 1f - mov HV_MMU_UNMAP_ADDR_TRAP, %o1 - retl - nop -+1: sethi %hi(__hypervisor_tlb_tl0_error), %o2 -+ jmpl %o2 + %lo(__hypervisor_tlb_tl0_error), %g0 -+ nop -+ nop -+ nop -+ nop -+ nop -+ nop -+ nop -+ nop -+ nop - --__hypervisor_flush_tlb_pending: /* 16 insns */ -+__hypervisor_flush_tlb_pending: /* 27 insns */ - /* %o0 = context, %o1 = nr, %o2 = vaddrs[] */ - sllx %o1, 3, %g1 - mov %o2, %g2 -@@ -347,31 +438,57 @@ __hypervisor_flush_tlb_pending: /* 16 insns */ - srlx %o0, PAGE_SHIFT, %o0 - sllx %o0, PAGE_SHIFT, %o0 - ta HV_MMU_UNMAP_ADDR_TRAP -- brnz,pn %o0, __hypervisor_tlb_tl0_error -+ brnz,pn %o0, 1f - mov HV_MMU_UNMAP_ADDR_TRAP, %o1 - brnz,pt %g1, 1b - nop - retl - nop -+1: sethi %hi(__hypervisor_tlb_tl0_error), %o2 -+ jmpl %o2 + %lo(__hypervisor_tlb_tl0_error), %g0 -+ nop -+ nop -+ nop -+ nop -+ nop -+ nop -+ nop -+ nop -+ nop - --__hypervisor_flush_tlb_kernel_range: /* 16 insns */ -+__hypervisor_flush_tlb_kernel_range: /* 31 insns */ - /* %o0=start, %o1=end */ - cmp %o0, %o1 - be,pn %xcc, 2f -- sethi %hi(PAGE_SIZE), %g3 -- mov %o0, %g1 -- sub %o1, %g1, %g2 -+ sub %o1, %o0, %g2 -+ srlx %g2, 18, %g3 -+ brnz,pn %g3, 4f -+ mov %o0, %g1 -+ sethi %hi(PAGE_SIZE), %g3 - sub %g2, %g3, %g2 - 1: add %g1, %g2, %o0 /* ARG0: virtual address */ - mov 0, %o1 /* ARG1: mmu context */ - mov HV_MMU_ALL, %o2 /* ARG2: flags */ - ta HV_MMU_UNMAP_ADDR_TRAP -- brnz,pn %o0, __hypervisor_tlb_tl0_error -+ brnz,pn %o0, 3f - mov HV_MMU_UNMAP_ADDR_TRAP, %o1 - brnz,pt %g2, 1b - sub %g2, %g3, %g2 - 2: retl - nop -+3: sethi %hi(__hypervisor_tlb_tl0_error), %o2 -+ jmpl %o2 + %lo(__hypervisor_tlb_tl0_error), %g0 -+ nop -+4: mov 0, %o0 /* ARG0: CPU lists unimplemented */ -+ mov 0, %o1 /* ARG1: CPU lists unimplemented */ -+ mov 0, %o2 /* ARG2: mmu context == nucleus */ -+ mov HV_MMU_ALL, %o3 /* ARG3: flags */ -+ mov HV_FAST_MMU_DEMAP_CTX, %o5 -+ ta HV_FAST_TRAP -+ brnz,pn %o0, 3b -+ mov HV_FAST_MMU_DEMAP_CTX, %o1 -+ retl -+ nop - - #ifdef DCACHE_ALIASING_POSSIBLE - /* XXX Niagara and friends have an 8K cache, so no aliasing is -@@ -394,43 +511,6 @@ tlb_patch_one: - retl - nop - -- .globl cheetah_patch_cachetlbops --cheetah_patch_cachetlbops: -- save %sp, -128, %sp -- -- sethi %hi(__flush_tlb_mm), %o0 -- or %o0, %lo(__flush_tlb_mm), %o0 -- sethi %hi(__cheetah_flush_tlb_mm), %o1 -- or %o1, %lo(__cheetah_flush_tlb_mm), %o1 -- call tlb_patch_one -- mov 19, %o2 -- -- sethi %hi(__flush_tlb_page), %o0 -- or %o0, %lo(__flush_tlb_page), %o0 -- sethi %hi(__cheetah_flush_tlb_page), %o1 -- or %o1, %lo(__cheetah_flush_tlb_page), %o1 -- call tlb_patch_one -- mov 22, %o2 -- -- sethi %hi(__flush_tlb_pending), %o0 -- or %o0, %lo(__flush_tlb_pending), %o0 -- sethi %hi(__cheetah_flush_tlb_pending), %o1 -- or %o1, %lo(__cheetah_flush_tlb_pending), %o1 -- call tlb_patch_one -- mov 27, %o2 -- --#ifdef DCACHE_ALIASING_POSSIBLE -- sethi %hi(__flush_dcache_page), %o0 -- or %o0, %lo(__flush_dcache_page), %o0 -- sethi %hi(__cheetah_flush_dcache_page), %o1 -- or %o1, %lo(__cheetah_flush_dcache_page), %o1 -- call tlb_patch_one -- mov 11, %o2 --#endif /* DCACHE_ALIASING_POSSIBLE */ -- -- ret -- restore -- - #ifdef CONFIG_SMP - /* These are all called by the slaves of a cross call, at - * trap level 1, with interrupts fully disabled. -@@ -447,7 +527,7 @@ cheetah_patch_cachetlbops: - */ - .align 32 - .globl xcall_flush_tlb_mm --xcall_flush_tlb_mm: /* 21 insns */ -+xcall_flush_tlb_mm: /* 24 insns */ - mov PRIMARY_CONTEXT, %g2 - ldxa [%g2] ASI_DMMU, %g3 - srlx %g3, CTX_PGSZ1_NUC_SHIFT, %g4 -@@ -469,9 +549,12 @@ xcall_flush_tlb_mm: /* 21 insns */ - nop - nop - nop -+ nop -+ nop -+ nop - - .globl xcall_flush_tlb_page --xcall_flush_tlb_page: /* 17 insns */ -+xcall_flush_tlb_page: /* 20 insns */ - /* %g5=context, %g1=vaddr */ - mov PRIMARY_CONTEXT, %g4 - ldxa [%g4] ASI_DMMU, %g2 -@@ -490,15 +573,20 @@ xcall_flush_tlb_page: /* 17 insns */ - retry - nop - nop -+ nop -+ nop -+ nop - - .globl xcall_flush_tlb_kernel_range --xcall_flush_tlb_kernel_range: /* 25 insns */ -+xcall_flush_tlb_kernel_range: /* 44 insns */ - sethi %hi(PAGE_SIZE - 1), %g2 - or %g2, %lo(PAGE_SIZE - 1), %g2 - andn %g1, %g2, %g1 - andn %g7, %g2, %g7 - sub %g7, %g1, %g3 -- add %g2, 1, %g2 -+ srlx %g3, 18, %g2 -+ brnz,pn %g2, 2f -+ add %g2, 1, %g2 - sub %g3, %g2, %g3 - or %g1, 0x20, %g1 ! Nucleus - 1: stxa %g0, [%g1 + %g3] ASI_DMMU_DEMAP -@@ -507,8 +595,25 @@ xcall_flush_tlb_kernel_range: /* 25 insns */ - brnz,pt %g3, 1b - sub %g3, %g2, %g3 - retry -- nop -- nop -+2: mov 63 * 8, %g1 -+1: ldxa [%g1] ASI_ITLB_DATA_ACCESS, %g2 -+ andcc %g2, 0x40, %g0 /* _PAGE_L_4U */ -+ bne,pn %xcc, 2f -+ mov TLB_TAG_ACCESS, %g2 -+ stxa %g0, [%g2] ASI_IMMU -+ stxa %g0, [%g1] ASI_ITLB_DATA_ACCESS -+ membar #Sync -+2: ldxa [%g1] ASI_DTLB_DATA_ACCESS, %g2 -+ andcc %g2, 0x40, %g0 -+ bne,pn %xcc, 2f -+ mov TLB_TAG_ACCESS, %g2 -+ stxa %g0, [%g2] ASI_DMMU -+ stxa %g0, [%g1] ASI_DTLB_DATA_ACCESS -+ membar #Sync -+2: sub %g1, 8, %g1 -+ brgez,pt %g1, 1b -+ nop -+ retry - nop - nop - nop -@@ -637,6 +742,52 @@ xcall_fetch_glob_pmu_n4: - - retry - -+__cheetah_xcall_flush_tlb_kernel_range: /* 44 insns */ -+ sethi %hi(PAGE_SIZE - 1), %g2 -+ or %g2, %lo(PAGE_SIZE - 1), %g2 -+ andn %g1, %g2, %g1 -+ andn %g7, %g2, %g7 -+ sub %g7, %g1, %g3 -+ srlx %g3, 18, %g2 -+ brnz,pn %g2, 2f -+ add %g2, 1, %g2 -+ sub %g3, %g2, %g3 -+ or %g1, 0x20, %g1 ! Nucleus -+1: stxa %g0, [%g1 + %g3] ASI_DMMU_DEMAP -+ stxa %g0, [%g1 + %g3] ASI_IMMU_DEMAP -+ membar #Sync -+ brnz,pt %g3, 1b -+ sub %g3, %g2, %g3 -+ retry -+2: mov 0x80, %g2 -+ stxa %g0, [%g2] ASI_DMMU_DEMAP -+ membar #Sync -+ stxa %g0, [%g2] ASI_IMMU_DEMAP -+ membar #Sync -+ retry -+ nop -+ nop -+ nop -+ nop -+ nop -+ nop -+ nop -+ nop -+ nop -+ nop -+ nop -+ nop -+ nop -+ nop -+ nop -+ nop -+ nop -+ nop -+ nop -+ nop -+ nop -+ nop -+ - #ifdef DCACHE_ALIASING_POSSIBLE - .align 32 - .globl xcall_flush_dcache_page_cheetah -@@ -700,7 +851,7 @@ __hypervisor_tlb_xcall_error: - ba,a,pt %xcc, rtrap - - .globl __hypervisor_xcall_flush_tlb_mm --__hypervisor_xcall_flush_tlb_mm: /* 21 insns */ -+__hypervisor_xcall_flush_tlb_mm: /* 24 insns */ - /* %g5=ctx, g1,g2,g3,g4,g7=scratch, %g6=unusable */ - mov %o0, %g2 - mov %o1, %g3 -@@ -714,7 +865,7 @@ __hypervisor_xcall_flush_tlb_mm: /* 21 insns */ - mov HV_FAST_MMU_DEMAP_CTX, %o5 - ta HV_FAST_TRAP - mov HV_FAST_MMU_DEMAP_CTX, %g6 -- brnz,pn %o0, __hypervisor_tlb_xcall_error -+ brnz,pn %o0, 1f - mov %o0, %g5 - mov %g2, %o0 - mov %g3, %o1 -@@ -723,9 +874,12 @@ __hypervisor_xcall_flush_tlb_mm: /* 21 insns */ - mov %g7, %o5 - membar #Sync - retry -+1: sethi %hi(__hypervisor_tlb_xcall_error), %g4 -+ jmpl %g4 + %lo(__hypervisor_tlb_xcall_error), %g0 -+ nop - - .globl __hypervisor_xcall_flush_tlb_page --__hypervisor_xcall_flush_tlb_page: /* 17 insns */ -+__hypervisor_xcall_flush_tlb_page: /* 20 insns */ - /* %g5=ctx, %g1=vaddr */ - mov %o0, %g2 - mov %o1, %g3 -@@ -737,42 +891,64 @@ __hypervisor_xcall_flush_tlb_page: /* 17 insns */ - sllx %o0, PAGE_SHIFT, %o0 - ta HV_MMU_UNMAP_ADDR_TRAP - mov HV_MMU_UNMAP_ADDR_TRAP, %g6 -- brnz,a,pn %o0, __hypervisor_tlb_xcall_error -+ brnz,a,pn %o0, 1f - mov %o0, %g5 - mov %g2, %o0 - mov %g3, %o1 - mov %g4, %o2 - membar #Sync - retry -+1: sethi %hi(__hypervisor_tlb_xcall_error), %g4 -+ jmpl %g4 + %lo(__hypervisor_tlb_xcall_error), %g0 -+ nop - - .globl __hypervisor_xcall_flush_tlb_kernel_range --__hypervisor_xcall_flush_tlb_kernel_range: /* 25 insns */ -+__hypervisor_xcall_flush_tlb_kernel_range: /* 44 insns */ - /* %g1=start, %g7=end, g2,g3,g4,g5,g6=scratch */ - sethi %hi(PAGE_SIZE - 1), %g2 - or %g2, %lo(PAGE_SIZE - 1), %g2 - andn %g1, %g2, %g1 - andn %g7, %g2, %g7 - sub %g7, %g1, %g3 -+ srlx %g3, 18, %g7 - add %g2, 1, %g2 - sub %g3, %g2, %g3 - mov %o0, %g2 - mov %o1, %g4 -- mov %o2, %g7 -+ brnz,pn %g7, 2f -+ mov %o2, %g7 - 1: add %g1, %g3, %o0 /* ARG0: virtual address */ - mov 0, %o1 /* ARG1: mmu context */ - mov HV_MMU_ALL, %o2 /* ARG2: flags */ - ta HV_MMU_UNMAP_ADDR_TRAP - mov HV_MMU_UNMAP_ADDR_TRAP, %g6 -- brnz,pn %o0, __hypervisor_tlb_xcall_error -+ brnz,pn %o0, 1f - mov %o0, %g5 - sethi %hi(PAGE_SIZE), %o2 - brnz,pt %g3, 1b - sub %g3, %o2, %g3 -- mov %g2, %o0 -+5: mov %g2, %o0 - mov %g4, %o1 - mov %g7, %o2 - membar #Sync - retry -+1: sethi %hi(__hypervisor_tlb_xcall_error), %g4 -+ jmpl %g4 + %lo(__hypervisor_tlb_xcall_error), %g0 -+ nop -+2: mov %o3, %g1 -+ mov %o5, %g3 -+ mov 0, %o0 /* ARG0: CPU lists unimplemented */ -+ mov 0, %o1 /* ARG1: CPU lists unimplemented */ -+ mov 0, %o2 /* ARG2: mmu context == nucleus */ -+ mov HV_MMU_ALL, %o3 /* ARG3: flags */ -+ mov HV_FAST_MMU_DEMAP_CTX, %o5 -+ ta HV_FAST_TRAP -+ mov %g1, %o3 -+ brz,pt %o0, 5b -+ mov %g3, %o5 -+ mov HV_FAST_MMU_DEMAP_CTX, %g6 -+ ba,pt %xcc, 1b -+ clr %g5 - - /* These just get rescheduled to PIL vectors. */ - .globl xcall_call_function -@@ -809,6 +985,58 @@ xcall_kgdb_capture: - - #endif /* CONFIG_SMP */ - -+ .globl cheetah_patch_cachetlbops -+cheetah_patch_cachetlbops: -+ save %sp, -128, %sp -+ -+ sethi %hi(__flush_tlb_mm), %o0 -+ or %o0, %lo(__flush_tlb_mm), %o0 -+ sethi %hi(__cheetah_flush_tlb_mm), %o1 -+ or %o1, %lo(__cheetah_flush_tlb_mm), %o1 -+ call tlb_patch_one -+ mov 19, %o2 -+ -+ sethi %hi(__flush_tlb_page), %o0 -+ or %o0, %lo(__flush_tlb_page), %o0 -+ sethi %hi(__cheetah_flush_tlb_page), %o1 -+ or %o1, %lo(__cheetah_flush_tlb_page), %o1 -+ call tlb_patch_one -+ mov 22, %o2 -+ -+ sethi %hi(__flush_tlb_pending), %o0 -+ or %o0, %lo(__flush_tlb_pending), %o0 -+ sethi %hi(__cheetah_flush_tlb_pending), %o1 -+ or %o1, %lo(__cheetah_flush_tlb_pending), %o1 -+ call tlb_patch_one -+ mov 27, %o2 -+ -+ sethi %hi(__flush_tlb_kernel_range), %o0 -+ or %o0, %lo(__flush_tlb_kernel_range), %o0 -+ sethi %hi(__cheetah_flush_tlb_kernel_range), %o1 -+ or %o1, %lo(__cheetah_flush_tlb_kernel_range), %o1 -+ call tlb_patch_one -+ mov 31, %o2 -+ -+#ifdef DCACHE_ALIASING_POSSIBLE -+ sethi %hi(__flush_dcache_page), %o0 -+ or %o0, %lo(__flush_dcache_page), %o0 -+ sethi %hi(__cheetah_flush_dcache_page), %o1 -+ or %o1, %lo(__cheetah_flush_dcache_page), %o1 -+ call tlb_patch_one -+ mov 11, %o2 -+#endif /* DCACHE_ALIASING_POSSIBLE */ -+ -+#ifdef CONFIG_SMP -+ sethi %hi(xcall_flush_tlb_kernel_range), %o0 -+ or %o0, %lo(xcall_flush_tlb_kernel_range), %o0 -+ sethi %hi(__cheetah_xcall_flush_tlb_kernel_range), %o1 -+ or %o1, %lo(__cheetah_xcall_flush_tlb_kernel_range), %o1 -+ call tlb_patch_one -+ mov 44, %o2 -+#endif /* CONFIG_SMP */ -+ -+ ret -+ restore - - .globl hypervisor_patch_cachetlbops - hypervisor_patch_cachetlbops: -@@ -819,28 +1047,28 @@ hypervisor_patch_cachetlbops: - sethi %hi(__hypervisor_flush_tlb_mm), %o1 - or %o1, %lo(__hypervisor_flush_tlb_mm), %o1 - call tlb_patch_one -- mov 10, %o2 -+ mov 19, %o2 - - sethi %hi(__flush_tlb_page), %o0 - or %o0, %lo(__flush_tlb_page), %o0 - sethi %hi(__hypervisor_flush_tlb_page), %o1 - or %o1, %lo(__hypervisor_flush_tlb_page), %o1 - call tlb_patch_one -- mov 11, %o2 -+ mov 22, %o2 - - sethi %hi(__flush_tlb_pending), %o0 - or %o0, %lo(__flush_tlb_pending), %o0 - sethi %hi(__hypervisor_flush_tlb_pending), %o1 - or %o1, %lo(__hypervisor_flush_tlb_pending), %o1 - call tlb_patch_one -- mov 16, %o2 -+ mov 27, %o2 - - sethi %hi(__flush_tlb_kernel_range), %o0 - or %o0, %lo(__flush_tlb_kernel_range), %o0 - sethi %hi(__hypervisor_flush_tlb_kernel_range), %o1 - or %o1, %lo(__hypervisor_flush_tlb_kernel_range), %o1 - call tlb_patch_one -- mov 16, %o2 -+ mov 31, %o2 - - #ifdef DCACHE_ALIASING_POSSIBLE - sethi %hi(__flush_dcache_page), %o0 -@@ -857,21 +1085,21 @@ hypervisor_patch_cachetlbops: - sethi %hi(__hypervisor_xcall_flush_tlb_mm), %o1 - or %o1, %lo(__hypervisor_xcall_flush_tlb_mm), %o1 - call tlb_patch_one -- mov 21, %o2 -+ mov 24, %o2 - - sethi %hi(xcall_flush_tlb_page), %o0 - or %o0, %lo(xcall_flush_tlb_page), %o0 - sethi %hi(__hypervisor_xcall_flush_tlb_page), %o1 - or %o1, %lo(__hypervisor_xcall_flush_tlb_page), %o1 - call tlb_patch_one -- mov 17, %o2 -+ mov 20, %o2 - - sethi %hi(xcall_flush_tlb_kernel_range), %o0 - or %o0, %lo(xcall_flush_tlb_kernel_range), %o0 - sethi %hi(__hypervisor_xcall_flush_tlb_kernel_range), %o1 - or %o1, %lo(__hypervisor_xcall_flush_tlb_kernel_range), %o1 - call tlb_patch_one -- mov 25, %o2 -+ mov 44, %o2 - #endif /* CONFIG_SMP */ - - ret -diff --git a/drivers/net/ethernet/broadcom/bgmac.c b/drivers/net/ethernet/broadcom/bgmac.c -index c4751ec..45e87c9 100644 ---- a/drivers/net/ethernet/broadcom/bgmac.c -+++ b/drivers/net/ethernet/broadcom/bgmac.c -@@ -307,6 +307,10 @@ static void bgmac_dma_rx_enable(struct bgmac *bgmac, - u32 ctl; - - ctl = bgmac_read(bgmac, ring->mmio_base + BGMAC_DMA_RX_CTL); -+ -+ /* preserve ONLY bits 16-17 from current hardware value */ -+ ctl &= BGMAC_DMA_RX_ADDREXT_MASK; -+ - if (bgmac->feature_flags & BGMAC_FEAT_RX_MASK_SETUP) { - ctl &= ~BGMAC_DMA_RX_BL_MASK; - ctl |= BGMAC_DMA_RX_BL_128 << BGMAC_DMA_RX_BL_SHIFT; -@@ -317,7 +321,6 @@ static void bgmac_dma_rx_enable(struct bgmac *bgmac, - ctl &= ~BGMAC_DMA_RX_PT_MASK; - ctl |= BGMAC_DMA_RX_PT_1 << BGMAC_DMA_RX_PT_SHIFT; - } -- ctl &= BGMAC_DMA_RX_ADDREXT_MASK; - ctl |= BGMAC_DMA_RX_ENABLE; - ctl |= BGMAC_DMA_RX_PARITY_DISABLE; - ctl |= BGMAC_DMA_RX_OVERFLOW_CONT; -diff --git a/drivers/net/ethernet/broadcom/bnx2.c b/drivers/net/ethernet/broadcom/bnx2.c -index 505ceaf..2c850a9 100644 ---- a/drivers/net/ethernet/broadcom/bnx2.c -+++ b/drivers/net/ethernet/broadcom/bnx2.c -@@ -49,6 +49,7 @@ - #include <linux/firmware.h> - #include <linux/log2.h> - #include <linux/aer.h> -+#include <linux/crash_dump.h> - - #if defined(CONFIG_CNIC) || defined(CONFIG_CNIC_MODULE) - #define BCM_CNIC 1 -@@ -4759,15 +4760,16 @@ bnx2_setup_msix_tbl(struct bnx2 *bp) - BNX2_WR(bp, BNX2_PCI_GRC_WINDOW3_ADDR, BNX2_MSIX_PBA_ADDR); - } - --static int --bnx2_reset_chip(struct bnx2 *bp, u32 reset_code) -+static void -+bnx2_wait_dma_complete(struct bnx2 *bp) - { - u32 val; -- int i, rc = 0; -- u8 old_port; -+ int i; - -- /* Wait for the current PCI transaction to complete before -- * issuing a reset. */ -+ /* -+ * Wait for the current PCI transaction to complete before -+ * issuing a reset. -+ */ - if ((BNX2_CHIP(bp) == BNX2_CHIP_5706) || - (BNX2_CHIP(bp) == BNX2_CHIP_5708)) { - BNX2_WR(bp, BNX2_MISC_ENABLE_CLR_BITS, -@@ -4791,6 +4793,21 @@ bnx2_reset_chip(struct bnx2 *bp, u32 reset_code) - } - } - -+ return; -+} -+ -+ -+static int -+bnx2_reset_chip(struct bnx2 *bp, u32 reset_code) -+{ -+ u32 val; -+ int i, rc = 0; -+ u8 old_port; -+ -+ /* Wait for the current PCI transaction to complete before -+ * issuing a reset. */ -+ bnx2_wait_dma_complete(bp); -+ - /* Wait for the firmware to tell us it is ok to issue a reset. */ - bnx2_fw_sync(bp, BNX2_DRV_MSG_DATA_WAIT0 | reset_code, 1, 1); - -@@ -6356,6 +6373,10 @@ bnx2_open(struct net_device *dev) - struct bnx2 *bp = netdev_priv(dev); - int rc; - -+ rc = bnx2_request_firmware(bp); -+ if (rc < 0) -+ goto out; -+ - netif_carrier_off(dev); - - bnx2_disable_int(bp); -@@ -6424,6 +6445,7 @@ bnx2_open(struct net_device *dev) - bnx2_free_irq(bp); - bnx2_free_mem(bp); - bnx2_del_napi(bp); -+ bnx2_release_firmware(bp); - goto out; - } - -@@ -8570,12 +8592,15 @@ bnx2_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) - - pci_set_drvdata(pdev, dev); - -- rc = bnx2_request_firmware(bp); -- if (rc < 0) -- goto error; -- -+ /* -+ * In-flight DMA from 1st kernel could continue going in kdump kernel. -+ * New io-page table has been created before bnx2 does reset at open stage. -+ * We have to wait for the in-flight DMA to complete to avoid it look up -+ * into the newly created io-page table. -+ */ -+ if (is_kdump_kernel()) -+ bnx2_wait_dma_complete(bp); - -- bnx2_reset_chip(bp, BNX2_DRV_MSG_CODE_RESET); - memcpy(dev->dev_addr, bp->mac_addr, ETH_ALEN); - - dev->hw_features = NETIF_F_IP_CSUM | NETIF_F_SG | -@@ -8608,7 +8633,6 @@ bnx2_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) - return 0; - - error: -- bnx2_release_firmware(bp); - pci_iounmap(pdev, bp->regview); - pci_release_regions(pdev); - pci_disable_device(pdev); -diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c -index d48873b..5cdc96b 100644 ---- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c -+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c -@@ -231,7 +231,7 @@ mlxsw_sp_span_entry_create(struct mlxsw_sp_port *port) - - span_entry->used = true; - span_entry->id = index; -- span_entry->ref_count = 0; -+ span_entry->ref_count = 1; - span_entry->local_port = local_port; - return span_entry; - } -@@ -268,6 +268,7 @@ struct mlxsw_sp_span_entry *mlxsw_sp_span_entry_get(struct mlxsw_sp_port *port) - - span_entry = mlxsw_sp_span_entry_find(port); - if (span_entry) { -+ /* Already exists, just take a reference */ - span_entry->ref_count++; - return span_entry; - } -@@ -278,6 +279,7 @@ struct mlxsw_sp_span_entry *mlxsw_sp_span_entry_get(struct mlxsw_sp_port *port) - static int mlxsw_sp_span_entry_put(struct mlxsw_sp *mlxsw_sp, - struct mlxsw_sp_span_entry *span_entry) - { -+ WARN_ON(!span_entry->ref_count); - if (--span_entry->ref_count == 0) - mlxsw_sp_span_entry_destroy(mlxsw_sp, span_entry); - return 0; -diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c -index 3f5c51d..62514b9 100644 ---- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c -+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c -@@ -777,6 +777,26 @@ static void mlxsw_sp_router_neigh_rec_process(struct mlxsw_sp *mlxsw_sp, - } - } - -+static bool mlxsw_sp_router_rauhtd_is_full(char *rauhtd_pl) -+{ -+ u8 num_rec, last_rec_index, num_entries; -+ -+ num_rec = mlxsw_reg_rauhtd_num_rec_get(rauhtd_pl); -+ last_rec_index = num_rec - 1; -+ -+ if (num_rec < MLXSW_REG_RAUHTD_REC_MAX_NUM) -+ return false; -+ if (mlxsw_reg_rauhtd_rec_type_get(rauhtd_pl, last_rec_index) == -+ MLXSW_REG_RAUHTD_TYPE_IPV6) -+ return true; -+ -+ num_entries = mlxsw_reg_rauhtd_ipv4_rec_num_entries_get(rauhtd_pl, -+ last_rec_index); -+ if (++num_entries == MLXSW_REG_RAUHTD_IPV4_ENT_PER_REC) -+ return true; -+ return false; -+} -+ - static int mlxsw_sp_router_neighs_update_rauhtd(struct mlxsw_sp *mlxsw_sp) - { - char *rauhtd_pl; -@@ -803,7 +823,7 @@ static int mlxsw_sp_router_neighs_update_rauhtd(struct mlxsw_sp *mlxsw_sp) - for (i = 0; i < num_rec; i++) - mlxsw_sp_router_neigh_rec_process(mlxsw_sp, rauhtd_pl, - i); -- } while (num_rec); -+ } while (mlxsw_sp_router_rauhtd_is_full(rauhtd_pl)); - rtnl_unlock(); - - kfree(rauhtd_pl); -diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c -index 4c8c60a..fe9e7b1 100644 ---- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c -+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c -@@ -871,6 +871,13 @@ static int stmmac_init_phy(struct net_device *dev) - return -ENODEV; - } - -+ /* stmmac_adjust_link will change this to PHY_IGNORE_INTERRUPT to avoid -+ * subsequent PHY polling, make sure we force a link transition if -+ * we have a UP/DOWN/UP transition -+ */ -+ if (phydev->is_pseudo_fixed_link) -+ phydev->irq = PHY_POLL; -+ - pr_debug("stmmac_init_phy: %s: attached to PHY (UID 0x%x)" - " Link = %d\n", dev->name, phydev->phy_id, phydev->link); - -diff --git a/drivers/usb/gadget/function/f_fs.c b/drivers/usb/gadget/function/f_fs.c -index 5c8429f..3a5530d 100644 ---- a/drivers/usb/gadget/function/f_fs.c -+++ b/drivers/usb/gadget/function/f_fs.c -@@ -133,8 +133,60 @@ struct ffs_epfile { - /* - * Buffer for holding data from partial reads which may happen since - * we’re rounding user read requests to a multiple of a max packet size. -+ * -+ * The pointer is initialised with NULL value and may be set by -+ * __ffs_epfile_read_data function to point to a temporary buffer. -+ * -+ * In normal operation, calls to __ffs_epfile_read_buffered will consume -+ * data from said buffer and eventually free it. Importantly, while the -+ * function is using the buffer, it sets the pointer to NULL. This is -+ * all right since __ffs_epfile_read_data and __ffs_epfile_read_buffered -+ * can never run concurrently (they are synchronised by epfile->mutex) -+ * so the latter will not assign a new value to the pointer. -+ * -+ * Meanwhile ffs_func_eps_disable frees the buffer (if the pointer is -+ * valid) and sets the pointer to READ_BUFFER_DROP value. This special -+ * value is crux of the synchronisation between ffs_func_eps_disable and -+ * __ffs_epfile_read_data. -+ * -+ * Once __ffs_epfile_read_data is about to finish it will try to set the -+ * pointer back to its old value (as described above), but seeing as the -+ * pointer is not-NULL (namely READ_BUFFER_DROP) it will instead free -+ * the buffer. -+ * -+ * == State transitions == -+ * -+ * • ptr == NULL: (initial state) -+ * ◦ __ffs_epfile_read_buffer_free: go to ptr == DROP -+ * ◦ __ffs_epfile_read_buffered: nop -+ * ◦ __ffs_epfile_read_data allocates temp buffer: go to ptr == buf -+ * ◦ reading finishes: n/a, not in ‘and reading’ state -+ * • ptr == DROP: -+ * ◦ __ffs_epfile_read_buffer_free: nop -+ * ◦ __ffs_epfile_read_buffered: go to ptr == NULL -+ * ◦ __ffs_epfile_read_data allocates temp buffer: free buf, nop -+ * ◦ reading finishes: n/a, not in ‘and reading’ state -+ * • ptr == buf: -+ * ◦ __ffs_epfile_read_buffer_free: free buf, go to ptr == DROP -+ * ◦ __ffs_epfile_read_buffered: go to ptr == NULL and reading -+ * ◦ __ffs_epfile_read_data: n/a, __ffs_epfile_read_buffered -+ * is always called first -+ * ◦ reading finishes: n/a, not in ‘and reading’ state -+ * • ptr == NULL and reading: -+ * ◦ __ffs_epfile_read_buffer_free: go to ptr == DROP and reading -+ * ◦ __ffs_epfile_read_buffered: n/a, mutex is held -+ * ◦ __ffs_epfile_read_data: n/a, mutex is held -+ * ◦ reading finishes and … -+ * … all data read: free buf, go to ptr == NULL -+ * … otherwise: go to ptr == buf and reading -+ * • ptr == DROP and reading: -+ * ◦ __ffs_epfile_read_buffer_free: nop -+ * ◦ __ffs_epfile_read_buffered: n/a, mutex is held -+ * ◦ __ffs_epfile_read_data: n/a, mutex is held -+ * ◦ reading finishes: free buf, go to ptr == DROP - */ -- struct ffs_buffer *read_buffer; /* P: epfile->mutex */ -+ struct ffs_buffer *read_buffer; -+#define READ_BUFFER_DROP ((struct ffs_buffer *)ERR_PTR(-ESHUTDOWN)) - - char name[5]; - -@@ -733,25 +785,47 @@ static void ffs_epfile_async_io_complete(struct usb_ep *_ep, - schedule_work(&io_data->work); - } - -+static void __ffs_epfile_read_buffer_free(struct ffs_epfile *epfile) -+{ -+ /* -+ * See comment in struct ffs_epfile for full read_buffer pointer -+ * synchronisation story. -+ */ -+ struct ffs_buffer *buf = xchg(&epfile->read_buffer, READ_BUFFER_DROP); -+ if (buf && buf != READ_BUFFER_DROP) -+ kfree(buf); -+} -+ - /* Assumes epfile->mutex is held. */ - static ssize_t __ffs_epfile_read_buffered(struct ffs_epfile *epfile, - struct iov_iter *iter) - { -- struct ffs_buffer *buf = epfile->read_buffer; -+ /* -+ * Null out epfile->read_buffer so ffs_func_eps_disable does not free -+ * the buffer while we are using it. See comment in struct ffs_epfile -+ * for full read_buffer pointer synchronisation story. -+ */ -+ struct ffs_buffer *buf = xchg(&epfile->read_buffer, NULL); - ssize_t ret; -- if (!buf) -+ if (!buf || buf == READ_BUFFER_DROP) - return 0; - - ret = copy_to_iter(buf->data, buf->length, iter); - if (buf->length == ret) { - kfree(buf); -- epfile->read_buffer = NULL; -- } else if (unlikely(iov_iter_count(iter))) { -+ return ret; -+ } -+ -+ if (unlikely(iov_iter_count(iter))) { - ret = -EFAULT; - } else { - buf->length -= ret; - buf->data += ret; - } -+ -+ if (cmpxchg(&epfile->read_buffer, NULL, buf)) -+ kfree(buf); -+ - return ret; - } - -@@ -780,7 +854,15 @@ static ssize_t __ffs_epfile_read_data(struct ffs_epfile *epfile, - buf->length = data_len; - buf->data = buf->storage; - memcpy(buf->storage, data + ret, data_len); -- epfile->read_buffer = buf; -+ -+ /* -+ * At this point read_buffer is NULL or READ_BUFFER_DROP (if -+ * ffs_func_eps_disable has been called in the meanwhile). See comment -+ * in struct ffs_epfile for full read_buffer pointer synchronisation -+ * story. -+ */ -+ if (unlikely(cmpxchg(&epfile->read_buffer, NULL, buf))) -+ kfree(buf); - - return ret; - } -@@ -1094,8 +1176,7 @@ ffs_epfile_release(struct inode *inode, struct file *file) - - ENTER(); - -- kfree(epfile->read_buffer); -- epfile->read_buffer = NULL; -+ __ffs_epfile_read_buffer_free(epfile); - ffs_data_closed(epfile->ffs); - - return 0; -@@ -1721,24 +1802,20 @@ static void ffs_func_eps_disable(struct ffs_function *func) - unsigned count = func->ffs->eps_count; - unsigned long flags; - -+ spin_lock_irqsave(&func->ffs->eps_lock, flags); - do { -- if (epfile) -- mutex_lock(&epfile->mutex); -- spin_lock_irqsave(&func->ffs->eps_lock, flags); - /* pending requests get nuked */ - if (likely(ep->ep)) - usb_ep_disable(ep->ep); - ++ep; -- spin_unlock_irqrestore(&func->ffs->eps_lock, flags); - - if (epfile) { - epfile->ep = NULL; -- kfree(epfile->read_buffer); -- epfile->read_buffer = NULL; -- mutex_unlock(&epfile->mutex); -+ __ffs_epfile_read_buffer_free(epfile); - ++epfile; - } - } while (--count); -+ spin_unlock_irqrestore(&func->ffs->eps_lock, flags); - } - - static int ffs_func_eps_enable(struct ffs_function *func) -diff --git a/include/net/ip.h b/include/net/ip.h -index 156b0c1..0ccf6da 100644 ---- a/include/net/ip.h -+++ b/include/net/ip.h -@@ -47,7 +47,6 @@ struct inet_skb_parm { - #define IPSKB_REROUTED BIT(4) - #define IPSKB_DOREDIRECT BIT(5) - #define IPSKB_FRAG_PMTU BIT(6) --#define IPSKB_FRAG_SEGS BIT(7) - - u16 frag_max_size; - }; -diff --git a/include/net/ip6_tunnel.h b/include/net/ip6_tunnel.h -index 43a5a0e..b01d5d1 100644 ---- a/include/net/ip6_tunnel.h -+++ b/include/net/ip6_tunnel.h -@@ -145,6 +145,7 @@ static inline void ip6tunnel_xmit(struct sock *sk, struct sk_buff *skb, - { - int pkt_len, err; - -+ memset(skb->cb, 0, sizeof(struct inet6_skb_parm)); - pkt_len = skb->len - skb_inner_network_offset(skb); - err = ip6_local_out(dev_net(skb_dst(skb)->dev), sk, skb); - if (unlikely(net_xmit_eval(err))) -diff --git a/include/net/sock.h b/include/net/sock.h -index 8741988..c26eab9 100644 ---- a/include/net/sock.h -+++ b/include/net/sock.h -@@ -1587,11 +1587,11 @@ static inline void sock_put(struct sock *sk) - void sock_gen_put(struct sock *sk); - - int __sk_receive_skb(struct sock *sk, struct sk_buff *skb, const int nested, -- unsigned int trim_cap); -+ unsigned int trim_cap, bool refcounted); - static inline int sk_receive_skb(struct sock *sk, struct sk_buff *skb, - const int nested) - { -- return __sk_receive_skb(sk, skb, nested, 1); -+ return __sk_receive_skb(sk, skb, nested, 1, true); - } - - static inline void sk_tx_queue_set(struct sock *sk, int tx_queue) -diff --git a/include/net/tcp.h b/include/net/tcp.h -index 7717302..0de6989 100644 ---- a/include/net/tcp.h -+++ b/include/net/tcp.h -@@ -1164,6 +1164,7 @@ static inline void tcp_prequeue_init(struct tcp_sock *tp) - } - - bool tcp_prequeue(struct sock *sk, struct sk_buff *skb); -+int tcp_filter(struct sock *sk, struct sk_buff *skb); - - #undef STATE_TRACE - -diff --git a/include/uapi/linux/atm_zatm.h b/include/uapi/linux/atm_zatm.h -index 5cd4d4d..9c9c6ad 100644 ---- a/include/uapi/linux/atm_zatm.h -+++ b/include/uapi/linux/atm_zatm.h -@@ -14,7 +14,6 @@ - - #include <linux/atmapi.h> - #include <linux/atmioc.h> --#include <linux/time.h> - - #define ZATM_GETPOOL _IOW('a',ATMIOC_SARPRV+1,struct atmif_sioc) - /* get pool statistics */ -diff --git a/kernel/bpf/hashtab.c b/kernel/bpf/hashtab.c -index 570eeca..ad1bc67 100644 ---- a/kernel/bpf/hashtab.c -+++ b/kernel/bpf/hashtab.c -@@ -687,7 +687,8 @@ static void delete_all_elements(struct bpf_htab *htab) - - hlist_for_each_entry_safe(l, n, head, hash_node) { - hlist_del_rcu(&l->hash_node); -- htab_elem_free(htab, l); -+ if (l->state != HTAB_EXTRA_ELEM_USED) -+ htab_elem_free(htab, l); - } - } - } -diff --git a/net/core/dev.c b/net/core/dev.c -index 44b3ba4..9ce9d72 100644 ---- a/net/core/dev.c -+++ b/net/core/dev.c -@@ -2484,7 +2484,7 @@ int skb_checksum_help(struct sk_buff *skb) - goto out; - } - -- *(__sum16 *)(skb->data + offset) = csum_fold(csum); -+ *(__sum16 *)(skb->data + offset) = csum_fold(csum) ?: CSUM_MANGLED_0; - out_set_summed: - skb->ip_summed = CHECKSUM_NONE; - out: -diff --git a/net/core/flow_dissector.c b/net/core/flow_dissector.c -index 52742a0..5550a86 100644 ---- a/net/core/flow_dissector.c -+++ b/net/core/flow_dissector.c -@@ -118,7 +118,7 @@ bool __skb_flow_dissect(const struct sk_buff *skb, - struct flow_dissector_key_tags *key_tags; - struct flow_dissector_key_keyid *key_keyid; - u8 ip_proto = 0; -- bool ret = false; -+ bool ret; - - if (!data) { - data = skb->data; -@@ -481,12 +481,17 @@ bool __skb_flow_dissect(const struct sk_buff *skb, - out_good: - ret = true; - --out_bad: -+ key_control->thoff = (u16)nhoff; -+out: - key_basic->n_proto = proto; - key_basic->ip_proto = ip_proto; -- key_control->thoff = (u16)nhoff; - - return ret; -+ -+out_bad: -+ ret = false; -+ key_control->thoff = min_t(u16, nhoff, skb ? skb->len : hlen); -+ goto out; - } - EXPORT_SYMBOL(__skb_flow_dissect); - -diff --git a/net/core/sock.c b/net/core/sock.c -index fd7b41e..10acacc 100644 ---- a/net/core/sock.c -+++ b/net/core/sock.c -@@ -453,7 +453,7 @@ int sock_queue_rcv_skb(struct sock *sk, struct sk_buff *skb) - EXPORT_SYMBOL(sock_queue_rcv_skb); - - int __sk_receive_skb(struct sock *sk, struct sk_buff *skb, -- const int nested, unsigned int trim_cap) -+ const int nested, unsigned int trim_cap, bool refcounted) - { - int rc = NET_RX_SUCCESS; - -@@ -487,7 +487,8 @@ int __sk_receive_skb(struct sock *sk, struct sk_buff *skb, - - bh_unlock_sock(sk); - out: -- sock_put(sk); -+ if (refcounted) -+ sock_put(sk); - return rc; - discard_and_relse: - kfree_skb(skb); -@@ -1563,6 +1564,7 @@ struct sock *sk_clone_lock(const struct sock *sk, const gfp_t priority) - RCU_INIT_POINTER(newsk->sk_reuseport_cb, NULL); - - newsk->sk_err = 0; -+ newsk->sk_err_soft = 0; - newsk->sk_priority = 0; - newsk->sk_incoming_cpu = raw_smp_processor_id(); - atomic64_set(&newsk->sk_cookie, 0); -diff --git a/net/dccp/ipv4.c b/net/dccp/ipv4.c -index 345a3ae..b567c87 100644 ---- a/net/dccp/ipv4.c -+++ b/net/dccp/ipv4.c -@@ -235,7 +235,7 @@ static void dccp_v4_err(struct sk_buff *skb, u32 info) - { - const struct iphdr *iph = (struct iphdr *)skb->data; - const u8 offset = iph->ihl << 2; -- const struct dccp_hdr *dh = (struct dccp_hdr *)(skb->data + offset); -+ const struct dccp_hdr *dh; - struct dccp_sock *dp; - struct inet_sock *inet; - const int type = icmp_hdr(skb)->type; -@@ -245,11 +245,13 @@ static void dccp_v4_err(struct sk_buff *skb, u32 info) - int err; - struct net *net = dev_net(skb->dev); - -- if (skb->len < offset + sizeof(*dh) || -- skb->len < offset + __dccp_basic_hdr_len(dh)) { -- __ICMP_INC_STATS(net, ICMP_MIB_INERRORS); -- return; -- } -+ /* Only need dccph_dport & dccph_sport which are the first -+ * 4 bytes in dccp header. -+ * Our caller (icmp_socket_deliver()) already pulled 8 bytes for us. -+ */ -+ BUILD_BUG_ON(offsetofend(struct dccp_hdr, dccph_sport) > 8); -+ BUILD_BUG_ON(offsetofend(struct dccp_hdr, dccph_dport) > 8); -+ dh = (struct dccp_hdr *)(skb->data + offset); - - sk = __inet_lookup_established(net, &dccp_hashinfo, - iph->daddr, dh->dccph_dport, -@@ -868,7 +870,7 @@ static int dccp_v4_rcv(struct sk_buff *skb) - goto discard_and_relse; - nf_reset(skb); - -- return __sk_receive_skb(sk, skb, 1, dh->dccph_doff * 4); -+ return __sk_receive_skb(sk, skb, 1, dh->dccph_doff * 4, refcounted); - - no_dccp_socket: - if (!xfrm4_policy_check(NULL, XFRM_POLICY_IN, skb)) -diff --git a/net/dccp/ipv6.c b/net/dccp/ipv6.c -index 3828f94..715e5d1 100644 ---- a/net/dccp/ipv6.c -+++ b/net/dccp/ipv6.c -@@ -70,7 +70,7 @@ static void dccp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, - u8 type, u8 code, int offset, __be32 info) - { - const struct ipv6hdr *hdr = (const struct ipv6hdr *)skb->data; -- const struct dccp_hdr *dh = (struct dccp_hdr *)(skb->data + offset); -+ const struct dccp_hdr *dh; - struct dccp_sock *dp; - struct ipv6_pinfo *np; - struct sock *sk; -@@ -78,12 +78,13 @@ static void dccp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, - __u64 seq; - struct net *net = dev_net(skb->dev); - -- if (skb->len < offset + sizeof(*dh) || -- skb->len < offset + __dccp_basic_hdr_len(dh)) { -- __ICMP6_INC_STATS(net, __in6_dev_get(skb->dev), -- ICMP6_MIB_INERRORS); -- return; -- } -+ /* Only need dccph_dport & dccph_sport which are the first -+ * 4 bytes in dccp header. -+ * Our caller (icmpv6_notify()) already pulled 8 bytes for us. -+ */ -+ BUILD_BUG_ON(offsetofend(struct dccp_hdr, dccph_sport) > 8); -+ BUILD_BUG_ON(offsetofend(struct dccp_hdr, dccph_dport) > 8); -+ dh = (struct dccp_hdr *)(skb->data + offset); - - sk = __inet6_lookup_established(net, &dccp_hashinfo, - &hdr->daddr, dh->dccph_dport, -@@ -738,7 +739,8 @@ static int dccp_v6_rcv(struct sk_buff *skb) - if (!xfrm6_policy_check(sk, XFRM_POLICY_IN, skb)) - goto discard_and_relse; - -- return __sk_receive_skb(sk, skb, 1, dh->dccph_doff * 4) ? -1 : 0; -+ return __sk_receive_skb(sk, skb, 1, dh->dccph_doff * 4, -+ refcounted) ? -1 : 0; - - no_dccp_socket: - if (!xfrm6_policy_check(NULL, XFRM_POLICY_IN, skb)) -@@ -956,6 +958,7 @@ static const struct inet_connection_sock_af_ops dccp_ipv6_mapped = { - .getsockopt = ipv6_getsockopt, - .addr2sockaddr = inet6_csk_addr2sockaddr, - .sockaddr_len = sizeof(struct sockaddr_in6), -+ .bind_conflict = inet6_csk_bind_conflict, - #ifdef CONFIG_COMPAT - .compat_setsockopt = compat_ipv6_setsockopt, - .compat_getsockopt = compat_ipv6_getsockopt, -diff --git a/net/dccp/proto.c b/net/dccp/proto.c -index 41e6580..9fe25bf 100644 ---- a/net/dccp/proto.c -+++ b/net/dccp/proto.c -@@ -1009,6 +1009,10 @@ void dccp_close(struct sock *sk, long timeout) - __kfree_skb(skb); - } - -+ /* If socket has been already reset kill it. */ -+ if (sk->sk_state == DCCP_CLOSED) -+ goto adjudge_to_death; -+ - if (data_was_unread) { - /* Unread data was tossed, send an appropriate Reset Code */ - DCCP_WARN("ABORT with %u bytes unread\n", data_was_unread); -diff --git a/net/ipv4/fib_trie.c b/net/ipv4/fib_trie.c -index e2ffc2a..7ef7031 100644 ---- a/net/ipv4/fib_trie.c -+++ b/net/ipv4/fib_trie.c -@@ -2455,22 +2455,19 @@ static struct key_vector *fib_route_get_idx(struct fib_route_iter *iter, - struct key_vector *l, **tp = &iter->tnode; - t_key key; - -- /* use cache location of next-to-find key */ -+ /* use cached location of previously found key */ - if (iter->pos > 0 && pos >= iter->pos) { -- pos -= iter->pos; - key = iter->key; - } else { -- iter->pos = 0; -+ iter->pos = 1; - key = 0; - } - -- while ((l = leaf_walk_rcu(tp, key)) != NULL) { -+ pos -= iter->pos; -+ -+ while ((l = leaf_walk_rcu(tp, key)) && (pos-- > 0)) { - key = l->key + 1; - iter->pos++; -- -- if (--pos <= 0) -- break; -- - l = NULL; - - /* handle unlikely case of a key wrap */ -@@ -2479,7 +2476,7 @@ static struct key_vector *fib_route_get_idx(struct fib_route_iter *iter, - } - - if (l) -- iter->key = key; /* remember it */ -+ iter->key = l->key; /* remember it */ - else - iter->pos = 0; /* forget it */ - -@@ -2507,7 +2504,7 @@ static void *fib_route_seq_start(struct seq_file *seq, loff_t *pos) - return fib_route_get_idx(iter, *pos); - - iter->pos = 0; -- iter->key = 0; -+ iter->key = KEY_MAX; - - return SEQ_START_TOKEN; - } -@@ -2516,7 +2513,7 @@ static void *fib_route_seq_next(struct seq_file *seq, void *v, loff_t *pos) - { - struct fib_route_iter *iter = seq->private; - struct key_vector *l = NULL; -- t_key key = iter->key; -+ t_key key = iter->key + 1; - - ++*pos; - -@@ -2525,7 +2522,7 @@ static void *fib_route_seq_next(struct seq_file *seq, void *v, loff_t *pos) - l = leaf_walk_rcu(&iter->tnode, key); - - if (l) { -- iter->key = l->key + 1; -+ iter->key = l->key; - iter->pos++; - } else { - iter->pos = 0; -diff --git a/net/ipv4/icmp.c b/net/ipv4/icmp.c -index 38abe70..48734ee 100644 ---- a/net/ipv4/icmp.c -+++ b/net/ipv4/icmp.c -@@ -477,7 +477,7 @@ static struct rtable *icmp_route_lookup(struct net *net, - fl4->flowi4_proto = IPPROTO_ICMP; - fl4->fl4_icmp_type = type; - fl4->fl4_icmp_code = code; -- fl4->flowi4_oif = l3mdev_master_ifindex(skb_in->dev); -+ fl4->flowi4_oif = l3mdev_master_ifindex(skb_dst(skb_in)->dev); - - security_skb_classify_flow(skb_in, flowi4_to_flowi(fl4)); - rt = __ip_route_output_key_hash(net, fl4, -@@ -502,7 +502,7 @@ static struct rtable *icmp_route_lookup(struct net *net, - if (err) - goto relookup_failed; - -- if (inet_addr_type_dev_table(net, skb_in->dev, -+ if (inet_addr_type_dev_table(net, skb_dst(skb_in)->dev, - fl4_dec.saddr) == RTN_LOCAL) { - rt2 = __ip_route_output_key(net, &fl4_dec); - if (IS_ERR(rt2)) -diff --git a/net/ipv4/ip_forward.c b/net/ipv4/ip_forward.c -index 8b4ffd2..9f0a7b9 100644 ---- a/net/ipv4/ip_forward.c -+++ b/net/ipv4/ip_forward.c -@@ -117,7 +117,7 @@ int ip_forward(struct sk_buff *skb) - if (opt->is_strictroute && rt->rt_uses_gateway) - goto sr_failed; - -- IPCB(skb)->flags |= IPSKB_FORWARDED | IPSKB_FRAG_SEGS; -+ IPCB(skb)->flags |= IPSKB_FORWARDED; - mtu = ip_dst_mtu_maybe_forward(&rt->dst, true); - if (ip_exceeds_mtu(skb, mtu)) { - IP_INC_STATS(net, IPSTATS_MIB_FRAGFAILS); -diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c -index dde37fb..307daed 100644 ---- a/net/ipv4/ip_output.c -+++ b/net/ipv4/ip_output.c -@@ -223,11 +223,9 @@ static int ip_finish_output_gso(struct net *net, struct sock *sk, - struct sk_buff *segs; - int ret = 0; - -- /* common case: fragmentation of segments is not allowed, -- * or seglen is <= mtu -+ /* common case: seglen is <= mtu - */ -- if (((IPCB(skb)->flags & IPSKB_FRAG_SEGS) == 0) || -- skb_gso_validate_mtu(skb, mtu)) -+ if (skb_gso_validate_mtu(skb, mtu)) - return ip_finish_output2(net, sk, skb); - - /* Slowpath - GSO segment length is exceeding the dst MTU. -diff --git a/net/ipv4/ip_tunnel_core.c b/net/ipv4/ip_tunnel_core.c -index 0f227db..afd6b59 100644 ---- a/net/ipv4/ip_tunnel_core.c -+++ b/net/ipv4/ip_tunnel_core.c -@@ -63,7 +63,6 @@ void iptunnel_xmit(struct sock *sk, struct rtable *rt, struct sk_buff *skb, - int pkt_len = skb->len - skb_inner_network_offset(skb); - struct net *net = dev_net(rt->dst.dev); - struct net_device *dev = skb->dev; -- int skb_iif = skb->skb_iif; - struct iphdr *iph; - int err; - -@@ -73,16 +72,6 @@ void iptunnel_xmit(struct sock *sk, struct rtable *rt, struct sk_buff *skb, - skb_dst_set(skb, &rt->dst); - memset(IPCB(skb), 0, sizeof(*IPCB(skb))); - -- if (skb_iif && !(df & htons(IP_DF))) { -- /* Arrived from an ingress interface, got encapsulated, with -- * fragmentation of encapulating frames allowed. -- * If skb is gso, the resulting encapsulated network segments -- * may exceed dst mtu. -- * Allow IP Fragmentation of segments. -- */ -- IPCB(skb)->flags |= IPSKB_FRAG_SEGS; -- } -- - /* Push down and install the IP header. */ - skb_push(skb, sizeof(struct iphdr)); - skb_reset_network_header(skb); -diff --git a/net/ipv4/ipmr.c b/net/ipv4/ipmr.c -index 5f006e1..27089f5 100644 ---- a/net/ipv4/ipmr.c -+++ b/net/ipv4/ipmr.c -@@ -1749,7 +1749,7 @@ static void ipmr_queue_xmit(struct net *net, struct mr_table *mrt, - vif->dev->stats.tx_bytes += skb->len; - } - -- IPCB(skb)->flags |= IPSKB_FORWARDED | IPSKB_FRAG_SEGS; -+ IPCB(skb)->flags |= IPSKB_FORWARDED; - - /* RFC1584 teaches, that DVMRP/PIM router must deliver packets locally - * not only before forwarding, but after forwarding on all output -diff --git a/net/ipv4/route.c b/net/ipv4/route.c -index 62c3ed0..2f23ef1 100644 ---- a/net/ipv4/route.c -+++ b/net/ipv4/route.c -@@ -753,7 +753,9 @@ static void __ip_do_redirect(struct rtable *rt, struct sk_buff *skb, struct flow - goto reject_redirect; - } - -- n = ipv4_neigh_lookup(&rt->dst, NULL, &new_gw); -+ n = __ipv4_neigh_lookup(rt->dst.dev, new_gw); -+ if (!n) -+ n = neigh_create(&arp_tbl, &new_gw, rt->dst.dev); - if (!IS_ERR(n)) { - if (!(n->nud_state & NUD_VALID)) { - neigh_event_send(n, NULL); -diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c -index ffbb218..c876f5d 100644 ---- a/net/ipv4/tcp.c -+++ b/net/ipv4/tcp.c -@@ -1145,7 +1145,7 @@ int tcp_sendmsg(struct sock *sk, struct msghdr *msg, size_t size) - - err = -EPIPE; - if (sk->sk_err || (sk->sk_shutdown & SEND_SHUTDOWN)) -- goto out_err; -+ goto do_error; - - sg = !!(sk->sk_route_caps & NETIF_F_SG); - -@@ -1219,7 +1219,7 @@ int tcp_sendmsg(struct sock *sk, struct msghdr *msg, size_t size) - - if (!skb_can_coalesce(skb, i, pfrag->page, - pfrag->offset)) { -- if (i == sysctl_max_skb_frags || !sg) { -+ if (i >= sysctl_max_skb_frags || !sg) { - tcp_mark_push(tp, skb); - goto new_segment; - } -diff --git a/net/ipv4/tcp_dctcp.c b/net/ipv4/tcp_dctcp.c -index 10d728b..ab37c67 100644 ---- a/net/ipv4/tcp_dctcp.c -+++ b/net/ipv4/tcp_dctcp.c -@@ -56,6 +56,7 @@ struct dctcp { - u32 next_seq; - u32 ce_state; - u32 delayed_ack_reserved; -+ u32 loss_cwnd; - }; - - static unsigned int dctcp_shift_g __read_mostly = 4; /* g = 1/2^4 */ -@@ -96,6 +97,7 @@ static void dctcp_init(struct sock *sk) - ca->dctcp_alpha = min(dctcp_alpha_on_init, DCTCP_MAX_ALPHA); - - ca->delayed_ack_reserved = 0; -+ ca->loss_cwnd = 0; - ca->ce_state = 0; - - dctcp_reset(tp, ca); -@@ -111,9 +113,10 @@ static void dctcp_init(struct sock *sk) - - static u32 dctcp_ssthresh(struct sock *sk) - { -- const struct dctcp *ca = inet_csk_ca(sk); -+ struct dctcp *ca = inet_csk_ca(sk); - struct tcp_sock *tp = tcp_sk(sk); - -+ ca->loss_cwnd = tp->snd_cwnd; - return max(tp->snd_cwnd - ((tp->snd_cwnd * ca->dctcp_alpha) >> 11U), 2U); - } - -@@ -308,12 +311,20 @@ static size_t dctcp_get_info(struct sock *sk, u32 ext, int *attr, - return 0; - } - -+static u32 dctcp_cwnd_undo(struct sock *sk) -+{ -+ const struct dctcp *ca = inet_csk_ca(sk); -+ -+ return max(tcp_sk(sk)->snd_cwnd, ca->loss_cwnd); -+} -+ - static struct tcp_congestion_ops dctcp __read_mostly = { - .init = dctcp_init, - .in_ack_event = dctcp_update_alpha, - .cwnd_event = dctcp_cwnd_event, - .ssthresh = dctcp_ssthresh, - .cong_avoid = tcp_reno_cong_avoid, -+ .undo_cwnd = dctcp_cwnd_undo, - .set_state = dctcp_state, - .get_info = dctcp_get_info, - .flags = TCP_CONG_NEEDS_ECN, -diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c -index 7158d4f..7b235fa 100644 ---- a/net/ipv4/tcp_ipv4.c -+++ b/net/ipv4/tcp_ipv4.c -@@ -1537,6 +1537,21 @@ bool tcp_prequeue(struct sock *sk, struct sk_buff *skb) - } - EXPORT_SYMBOL(tcp_prequeue); - -+int tcp_filter(struct sock *sk, struct sk_buff *skb) -+{ -+ struct tcphdr *th = (struct tcphdr *)skb->data; -+ unsigned int eaten = skb->len; -+ int err; -+ -+ err = sk_filter_trim_cap(sk, skb, th->doff * 4); -+ if (!err) { -+ eaten -= skb->len; -+ TCP_SKB_CB(skb)->end_seq -= eaten; -+ } -+ return err; -+} -+EXPORT_SYMBOL(tcp_filter); -+ - /* - * From tcp_input.c - */ -@@ -1648,8 +1663,10 @@ int tcp_v4_rcv(struct sk_buff *skb) - - nf_reset(skb); - -- if (sk_filter(sk, skb)) -+ if (tcp_filter(sk, skb)) - goto discard_and_relse; -+ th = (const struct tcphdr *)skb->data; -+ iph = ip_hdr(skb); - - skb->dev = NULL; - -diff --git a/net/ipv6/icmp.c b/net/ipv6/icmp.c -index bd59c34..7370ad2 100644 ---- a/net/ipv6/icmp.c -+++ b/net/ipv6/icmp.c -@@ -448,7 +448,7 @@ static void icmp6_send(struct sk_buff *skb, u8 type, u8 code, __u32 info, - if (__ipv6_addr_needs_scope_id(addr_type)) - iif = skb->dev->ifindex; - else -- iif = l3mdev_master_ifindex(skb->dev); -+ iif = l3mdev_master_ifindex(skb_dst(skb)->dev); - - /* - * Must not send error if the source does not uniquely -diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c -index fc67822..af6a09e 100644 ---- a/net/ipv6/tcp_ipv6.c -+++ b/net/ipv6/tcp_ipv6.c -@@ -1228,7 +1228,7 @@ static int tcp_v6_do_rcv(struct sock *sk, struct sk_buff *skb) - if (skb->protocol == htons(ETH_P_IP)) - return tcp_v4_do_rcv(sk, skb); - -- if (sk_filter(sk, skb)) -+ if (tcp_filter(sk, skb)) - goto discard; - - /* -@@ -1455,8 +1455,10 @@ static int tcp_v6_rcv(struct sk_buff *skb) - if (tcp_v6_inbound_md5_hash(sk, skb)) - goto discard_and_relse; - -- if (sk_filter(sk, skb)) -+ if (tcp_filter(sk, skb)) - goto discard_and_relse; -+ th = (const struct tcphdr *)skb->data; -+ hdr = ipv6_hdr(skb); - - skb->dev = NULL; - -diff --git a/net/sctp/socket.c b/net/sctp/socket.c -index baccbf3..7b0e059 100644 ---- a/net/sctp/socket.c -+++ b/net/sctp/socket.c -@@ -1214,9 +1214,12 @@ static int __sctp_connect(struct sock *sk, - - timeo = sock_sndtimeo(sk, f_flags & O_NONBLOCK); - -- err = sctp_wait_for_connect(asoc, &timeo); -- if ((err == 0 || err == -EINPROGRESS) && assoc_id) -+ if (assoc_id) - *assoc_id = asoc->assoc_id; -+ err = sctp_wait_for_connect(asoc, &timeo); -+ /* Note: the asoc may be freed after the return of -+ * sctp_wait_for_connect. -+ */ - - /* Don't free association on exit. */ - asoc = NULL; -@@ -4278,19 +4281,18 @@ static void sctp_shutdown(struct sock *sk, int how) - { - struct net *net = sock_net(sk); - struct sctp_endpoint *ep; -- struct sctp_association *asoc; - - if (!sctp_style(sk, TCP)) - return; - -- if (how & SEND_SHUTDOWN) { -+ ep = sctp_sk(sk)->ep; -+ if (how & SEND_SHUTDOWN && !list_empty(&ep->asocs)) { -+ struct sctp_association *asoc; -+ - sk->sk_state = SCTP_SS_CLOSING; -- ep = sctp_sk(sk)->ep; -- if (!list_empty(&ep->asocs)) { -- asoc = list_entry(ep->asocs.next, -- struct sctp_association, asocs); -- sctp_primitive_SHUTDOWN(net, asoc, NULL); -- } -+ asoc = list_entry(ep->asocs.next, -+ struct sctp_association, asocs); -+ sctp_primitive_SHUTDOWN(net, asoc, NULL); - } - } - -diff --git a/net/socket.c b/net/socket.c -index a1bd161..03bc2c2 100644 ---- a/net/socket.c -+++ b/net/socket.c -@@ -2041,6 +2041,8 @@ int __sys_sendmmsg(int fd, struct mmsghdr __user *mmsg, unsigned int vlen, - if (err) - break; - ++datagrams; -+ if (msg_data_left(&msg_sys)) -+ break; - cond_resched(); - } - -diff --git a/tools/spi/spidev_test.c b/tools/spi/spidev_test.c -index f3825b6..f046b77 100644 ---- a/tools/spi/spidev_test.c -+++ b/tools/spi/spidev_test.c -@@ -19,6 +19,7 @@ - #include <getopt.h> - #include <fcntl.h> - #include <sys/ioctl.h> -+#include <linux/ioctl.h> - #include <sys/stat.h> - #include <linux/types.h> - #include <linux/spi/spidev.h> diff --git a/4.8.11/0000_README b/4.8.12/0000_README index a5a0953..e80d57a 100644 --- a/4.8.11/0000_README +++ b/4.8.12/0000_README @@ -2,19 +2,15 @@ README ----------------------------------------------------------------------------- Individual Patch Descriptions: ----------------------------------------------------------------------------- -Patch: 1008_linux-4.8.9.patch -From: http://www.kernel.org -Desc: Linux 4.8.9 - -Patch: 1009_linux-4.8.10.patch -From: http://www.kernel.org -Desc: Linux 4.8.10 - Patch: 1010_linux-4.8.11.patch From: http://www.kernel.org Desc: Linux 4.8.11 -Patch: 4420_grsecurity-3.1-4.8.11-201611271225.patch +Patch: 1011_linux-4.8.12.patch +From: http://www.kernel.org +Desc: Linux 4.8.12 + +Patch: 4420_grsecurity-3.1-4.8.12-201612031658.patch From: http://www.grsecurity.net Desc: hardened-sources base patch from upstream grsecurity diff --git a/4.8.11/1010_linux-4.8.11.patch b/4.8.12/1010_linux-4.8.11.patch index 5c67d71..5c67d71 100644 --- a/4.8.11/1010_linux-4.8.11.patch +++ b/4.8.12/1010_linux-4.8.11.patch diff --git a/4.8.12/1011_linux-4.8.12.patch b/4.8.12/1011_linux-4.8.12.patch new file mode 100644 index 0000000..6e460f1 --- /dev/null +++ b/4.8.12/1011_linux-4.8.12.patch @@ -0,0 +1,1563 @@ +diff --git a/Makefile b/Makefile +index 2b1bcba..7b0c92f 100644 +--- a/Makefile ++++ b/Makefile +@@ -1,6 +1,6 @@ + VERSION = 4 + PATCHLEVEL = 8 +-SUBLEVEL = 11 ++SUBLEVEL = 12 + EXTRAVERSION = + NAME = Psychotic Stoned Sheep + +diff --git a/arch/parisc/Kconfig b/arch/parisc/Kconfig +index af12c2d..81c11a6 100644 +--- a/arch/parisc/Kconfig ++++ b/arch/parisc/Kconfig +@@ -33,7 +33,9 @@ config PARISC + select HAVE_ARCH_HASH + select HAVE_ARCH_SECCOMP_FILTER + select HAVE_ARCH_TRACEHOOK +- select HAVE_UNSTABLE_SCHED_CLOCK if (SMP || !64BIT) ++ select GENERIC_SCHED_CLOCK ++ select HAVE_UNSTABLE_SCHED_CLOCK if SMP ++ select GENERIC_CLOCKEVENTS + select ARCH_NO_COHERENT_DMA_MMAP + select CPU_NO_EFFICIENT_FFS + +diff --git a/arch/parisc/kernel/cache.c b/arch/parisc/kernel/cache.c +index 6700127..c2259d4 100644 +--- a/arch/parisc/kernel/cache.c ++++ b/arch/parisc/kernel/cache.c +@@ -369,6 +369,7 @@ void __init parisc_setup_cache_timing(void) + { + unsigned long rangetime, alltime; + unsigned long size, start; ++ unsigned long threshold; + + alltime = mfctl(16); + flush_data_cache(); +@@ -382,17 +383,12 @@ void __init parisc_setup_cache_timing(void) + printk(KERN_DEBUG "Whole cache flush %lu cycles, flushing %lu bytes %lu cycles\n", + alltime, size, rangetime); + +- /* Racy, but if we see an intermediate value, it's ok too... */ +- parisc_cache_flush_threshold = size * alltime / rangetime; +- +- parisc_cache_flush_threshold = L1_CACHE_ALIGN(parisc_cache_flush_threshold); +- if (!parisc_cache_flush_threshold) +- parisc_cache_flush_threshold = FLUSH_THRESHOLD; +- +- if (parisc_cache_flush_threshold > cache_info.dc_size) +- parisc_cache_flush_threshold = cache_info.dc_size; +- +- printk(KERN_INFO "Setting cache flush threshold to %lu kB\n", ++ threshold = L1_CACHE_ALIGN(size * alltime / rangetime); ++ if (threshold > cache_info.dc_size) ++ threshold = cache_info.dc_size; ++ if (threshold) ++ parisc_cache_flush_threshold = threshold; ++ printk(KERN_INFO "Cache flush threshold set to %lu KiB\n", + parisc_cache_flush_threshold/1024); + + /* calculate TLB flush threshold */ +@@ -401,7 +397,7 @@ void __init parisc_setup_cache_timing(void) + flush_tlb_all(); + alltime = mfctl(16) - alltime; + +- size = PAGE_SIZE; ++ size = 0; + start = (unsigned long) _text; + rangetime = mfctl(16); + while (start < (unsigned long) _end) { +@@ -414,13 +410,10 @@ void __init parisc_setup_cache_timing(void) + printk(KERN_DEBUG "Whole TLB flush %lu cycles, flushing %lu bytes %lu cycles\n", + alltime, size, rangetime); + +- parisc_tlb_flush_threshold = size * alltime / rangetime; +- parisc_tlb_flush_threshold *= num_online_cpus(); +- parisc_tlb_flush_threshold = PAGE_ALIGN(parisc_tlb_flush_threshold); +- if (!parisc_tlb_flush_threshold) +- parisc_tlb_flush_threshold = FLUSH_TLB_THRESHOLD; +- +- printk(KERN_INFO "Setting TLB flush threshold to %lu kB\n", ++ threshold = PAGE_ALIGN(num_online_cpus() * size * alltime / rangetime); ++ if (threshold) ++ parisc_tlb_flush_threshold = threshold; ++ printk(KERN_INFO "TLB flush threshold set to %lu KiB\n", + parisc_tlb_flush_threshold/1024); + } + +diff --git a/arch/parisc/kernel/pacache.S b/arch/parisc/kernel/pacache.S +index b743a80..6755219 100644 +--- a/arch/parisc/kernel/pacache.S ++++ b/arch/parisc/kernel/pacache.S +@@ -96,7 +96,7 @@ fitmanyloop: /* Loop if LOOP >= 2 */ + + fitmanymiddle: /* Loop if LOOP >= 2 */ + addib,COND(>) -1, %r31, fitmanymiddle /* Adjusted inner loop decr */ +- pitlbe 0(%sr1, %r28) ++ pitlbe %r0(%sr1, %r28) + pitlbe,m %arg1(%sr1, %r28) /* Last pitlbe and addr adjust */ + addib,COND(>) -1, %r29, fitmanymiddle /* Middle loop decr */ + copy %arg3, %r31 /* Re-init inner loop count */ +@@ -139,7 +139,7 @@ fdtmanyloop: /* Loop if LOOP >= 2 */ + + fdtmanymiddle: /* Loop if LOOP >= 2 */ + addib,COND(>) -1, %r31, fdtmanymiddle /* Adjusted inner loop decr */ +- pdtlbe 0(%sr1, %r28) ++ pdtlbe %r0(%sr1, %r28) + pdtlbe,m %arg1(%sr1, %r28) /* Last pdtlbe and addr adjust */ + addib,COND(>) -1, %r29, fdtmanymiddle /* Middle loop decr */ + copy %arg3, %r31 /* Re-init inner loop count */ +@@ -620,12 +620,12 @@ ENTRY(copy_user_page_asm) + /* Purge any old translations */ + + #ifdef CONFIG_PA20 +- pdtlb,l 0(%r28) +- pdtlb,l 0(%r29) ++ pdtlb,l %r0(%r28) ++ pdtlb,l %r0(%r29) + #else + tlb_lock %r20,%r21,%r22 +- pdtlb 0(%r28) +- pdtlb 0(%r29) ++ pdtlb %r0(%r28) ++ pdtlb %r0(%r29) + tlb_unlock %r20,%r21,%r22 + #endif + +@@ -768,10 +768,10 @@ ENTRY(clear_user_page_asm) + /* Purge any old translation */ + + #ifdef CONFIG_PA20 +- pdtlb,l 0(%r28) ++ pdtlb,l %r0(%r28) + #else + tlb_lock %r20,%r21,%r22 +- pdtlb 0(%r28) ++ pdtlb %r0(%r28) + tlb_unlock %r20,%r21,%r22 + #endif + +@@ -852,10 +852,10 @@ ENTRY(flush_dcache_page_asm) + /* Purge any old translation */ + + #ifdef CONFIG_PA20 +- pdtlb,l 0(%r28) ++ pdtlb,l %r0(%r28) + #else + tlb_lock %r20,%r21,%r22 +- pdtlb 0(%r28) ++ pdtlb %r0(%r28) + tlb_unlock %r20,%r21,%r22 + #endif + +@@ -892,10 +892,10 @@ ENTRY(flush_dcache_page_asm) + sync + + #ifdef CONFIG_PA20 +- pdtlb,l 0(%r25) ++ pdtlb,l %r0(%r25) + #else + tlb_lock %r20,%r21,%r22 +- pdtlb 0(%r25) ++ pdtlb %r0(%r25) + tlb_unlock %r20,%r21,%r22 + #endif + +@@ -925,13 +925,18 @@ ENTRY(flush_icache_page_asm) + depwi 0, 31,PAGE_SHIFT, %r28 /* Clear any offset bits */ + #endif + +- /* Purge any old translation */ ++ /* Purge any old translation. Note that the FIC instruction ++ * may use either the instruction or data TLB. Given that we ++ * have a flat address space, it's not clear which TLB will be ++ * used. So, we purge both entries. */ + + #ifdef CONFIG_PA20 ++ pdtlb,l %r0(%r28) + pitlb,l %r0(%sr4,%r28) + #else + tlb_lock %r20,%r21,%r22 +- pitlb (%sr4,%r28) ++ pdtlb %r0(%r28) ++ pitlb %r0(%sr4,%r28) + tlb_unlock %r20,%r21,%r22 + #endif + +@@ -970,10 +975,12 @@ ENTRY(flush_icache_page_asm) + sync + + #ifdef CONFIG_PA20 ++ pdtlb,l %r0(%r28) + pitlb,l %r0(%sr4,%r25) + #else + tlb_lock %r20,%r21,%r22 +- pitlb (%sr4,%r25) ++ pdtlb %r0(%r28) ++ pitlb %r0(%sr4,%r25) + tlb_unlock %r20,%r21,%r22 + #endif + +diff --git a/arch/parisc/kernel/pci-dma.c b/arch/parisc/kernel/pci-dma.c +index 02d9ed0..494ff6e 100644 +--- a/arch/parisc/kernel/pci-dma.c ++++ b/arch/parisc/kernel/pci-dma.c +@@ -95,8 +95,8 @@ static inline int map_pte_uncached(pte_t * pte, + + if (!pte_none(*pte)) + printk(KERN_ERR "map_pte_uncached: page already exists\n"); +- set_pte(pte, __mk_pte(*paddr_ptr, PAGE_KERNEL_UNC)); + purge_tlb_start(flags); ++ set_pte(pte, __mk_pte(*paddr_ptr, PAGE_KERNEL_UNC)); + pdtlb_kernel(orig_vaddr); + purge_tlb_end(flags); + vaddr += PAGE_SIZE; +diff --git a/arch/parisc/kernel/setup.c b/arch/parisc/kernel/setup.c +index 81d6f63..2e66a88 100644 +--- a/arch/parisc/kernel/setup.c ++++ b/arch/parisc/kernel/setup.c +@@ -334,6 +334,10 @@ static int __init parisc_init(void) + /* tell PDC we're Linux. Nevermind failure. */ + pdc_stable_write(0x40, &osid, sizeof(osid)); + ++ /* start with known state */ ++ flush_cache_all_local(); ++ flush_tlb_all_local(NULL); ++ + processor_init(); + #ifdef CONFIG_SMP + pr_info("CPU(s): %d out of %d %s at %d.%06d MHz online\n", +diff --git a/arch/parisc/kernel/time.c b/arch/parisc/kernel/time.c +index 9b63b87..325f30d 100644 +--- a/arch/parisc/kernel/time.c ++++ b/arch/parisc/kernel/time.c +@@ -14,6 +14,7 @@ + #include <linux/module.h> + #include <linux/rtc.h> + #include <linux/sched.h> ++#include <linux/sched_clock.h> + #include <linux/kernel.h> + #include <linux/param.h> + #include <linux/string.h> +@@ -39,18 +40,6 @@ + + static unsigned long clocktick __read_mostly; /* timer cycles per tick */ + +-#ifndef CONFIG_64BIT +-/* +- * The processor-internal cycle counter (Control Register 16) is used as time +- * source for the sched_clock() function. This register is 64bit wide on a +- * 64-bit kernel and 32bit on a 32-bit kernel. Since sched_clock() always +- * requires a 64bit counter we emulate on the 32-bit kernel the higher 32bits +- * with a per-cpu variable which we increase every time the counter +- * wraps-around (which happens every ~4 secounds). +- */ +-static DEFINE_PER_CPU(unsigned long, cr16_high_32_bits); +-#endif +- + /* + * We keep time on PA-RISC Linux by using the Interval Timer which is + * a pair of registers; one is read-only and one is write-only; both +@@ -121,12 +110,6 @@ irqreturn_t __irq_entry timer_interrupt(int irq, void *dev_id) + */ + mtctl(next_tick, 16); + +-#if !defined(CONFIG_64BIT) +- /* check for overflow on a 32bit kernel (every ~4 seconds). */ +- if (unlikely(next_tick < now)) +- this_cpu_inc(cr16_high_32_bits); +-#endif +- + /* Skip one clocktick on purpose if we missed next_tick. + * The new CR16 must be "later" than current CR16 otherwise + * itimer would not fire until CR16 wrapped - e.g 4 seconds +@@ -208,7 +191,7 @@ EXPORT_SYMBOL(profile_pc); + + /* clock source code */ + +-static cycle_t read_cr16(struct clocksource *cs) ++static cycle_t notrace read_cr16(struct clocksource *cs) + { + return get_cycles(); + } +@@ -287,26 +270,9 @@ void read_persistent_clock(struct timespec *ts) + } + + +-/* +- * sched_clock() framework +- */ +- +-static u32 cyc2ns_mul __read_mostly; +-static u32 cyc2ns_shift __read_mostly; +- +-u64 sched_clock(void) ++static u64 notrace read_cr16_sched_clock(void) + { +- u64 now; +- +- /* Get current cycle counter (Control Register 16). */ +-#ifdef CONFIG_64BIT +- now = mfctl(16); +-#else +- now = mfctl(16) + (((u64) this_cpu_read(cr16_high_32_bits)) << 32); +-#endif +- +- /* return the value in ns (cycles_2_ns) */ +- return mul_u64_u32_shr(now, cyc2ns_mul, cyc2ns_shift); ++ return get_cycles(); + } + + +@@ -316,17 +282,16 @@ u64 sched_clock(void) + + void __init time_init(void) + { +- unsigned long current_cr16_khz; ++ unsigned long cr16_hz; + +- current_cr16_khz = PAGE0->mem_10msec/10; /* kHz */ + clocktick = (100 * PAGE0->mem_10msec) / HZ; +- +- /* calculate mult/shift values for cr16 */ +- clocks_calc_mult_shift(&cyc2ns_mul, &cyc2ns_shift, current_cr16_khz, +- NSEC_PER_MSEC, 0); +- + start_cpu_itimer(); /* get CPU 0 started */ + ++ cr16_hz = 100 * PAGE0->mem_10msec; /* Hz */ ++ + /* register at clocksource framework */ +- clocksource_register_khz(&clocksource_cr16, current_cr16_khz); ++ clocksource_register_hz(&clocksource_cr16, cr16_hz); ++ ++ /* register as sched_clock source */ ++ sched_clock_register(read_cr16_sched_clock, BITS_PER_LONG, cr16_hz); + } +diff --git a/arch/powerpc/boot/main.c b/arch/powerpc/boot/main.c +index d80161b..60522d2 100644 +--- a/arch/powerpc/boot/main.c ++++ b/arch/powerpc/boot/main.c +@@ -217,8 +217,12 @@ void start(void) + console_ops.close(); + + kentry = (kernel_entry_t) vmlinux.addr; +- if (ft_addr) +- kentry(ft_addr, 0, NULL); ++ if (ft_addr) { ++ if(platform_ops.kentry) ++ platform_ops.kentry(ft_addr, vmlinux.addr); ++ else ++ kentry(ft_addr, 0, NULL); ++ } + else + kentry((unsigned long)initrd.addr, initrd.size, + loader_info.promptr); +diff --git a/arch/powerpc/boot/opal-calls.S b/arch/powerpc/boot/opal-calls.S +index ff2f1b9..2a99fc9 100644 +--- a/arch/powerpc/boot/opal-calls.S ++++ b/arch/powerpc/boot/opal-calls.S +@@ -12,6 +12,19 @@ + + .text + ++ .globl opal_kentry ++opal_kentry: ++ /* r3 is the fdt ptr */ ++ mtctr r4 ++ li r4, 0 ++ li r5, 0 ++ li r6, 0 ++ li r7, 0 ++ ld r11,opal@got(r2) ++ ld r8,0(r11) ++ ld r9,8(r11) ++ bctr ++ + #define OPAL_CALL(name, token) \ + .globl name; \ + name: \ +diff --git a/arch/powerpc/boot/opal.c b/arch/powerpc/boot/opal.c +index 1f37e1c..d7b4fd4 100644 +--- a/arch/powerpc/boot/opal.c ++++ b/arch/powerpc/boot/opal.c +@@ -23,14 +23,25 @@ struct opal { + + static u32 opal_con_id; + ++/* see opal-wrappers.S */ + int64_t opal_console_write(int64_t term_number, u64 *length, const u8 *buffer); + int64_t opal_console_read(int64_t term_number, uint64_t *length, u8 *buffer); + int64_t opal_console_write_buffer_space(uint64_t term_number, uint64_t *length); + int64_t opal_console_flush(uint64_t term_number); + int64_t opal_poll_events(uint64_t *outstanding_event_mask); + ++void opal_kentry(unsigned long fdt_addr, void *vmlinux_addr); ++ + static int opal_con_open(void) + { ++ /* ++ * When OPAL loads the boot kernel it stashes the OPAL base and entry ++ * address in r8 and r9 so the kernel can use the OPAL console ++ * before unflattening the devicetree. While executing the wrapper will ++ * probably trash r8 and r9 so this kentry hook restores them before ++ * entering the decompressed kernel. ++ */ ++ platform_ops.kentry = opal_kentry; + return 0; + } + +diff --git a/arch/powerpc/boot/ops.h b/arch/powerpc/boot/ops.h +index e19b64e..deeae6f 100644 +--- a/arch/powerpc/boot/ops.h ++++ b/arch/powerpc/boot/ops.h +@@ -30,6 +30,7 @@ struct platform_ops { + void * (*realloc)(void *ptr, unsigned long size); + void (*exit)(void); + void * (*vmlinux_alloc)(unsigned long size); ++ void (*kentry)(unsigned long fdt_addr, void *vmlinux_addr); + }; + extern struct platform_ops platform_ops; + +diff --git a/arch/powerpc/include/asm/mmu.h b/arch/powerpc/include/asm/mmu.h +index e2fb408..fd10b58 100644 +--- a/arch/powerpc/include/asm/mmu.h ++++ b/arch/powerpc/include/asm/mmu.h +@@ -29,6 +29,12 @@ + */ + + /* ++ * Kernel read only support. ++ * We added the ppp value 0b110 in ISA 2.04. ++ */ ++#define MMU_FTR_KERNEL_RO ASM_CONST(0x00004000) ++ ++/* + * We need to clear top 16bits of va (from the remaining 64 bits )in + * tlbie* instructions + */ +@@ -103,10 +109,10 @@ + #define MMU_FTRS_POWER4 MMU_FTRS_DEFAULT_HPTE_ARCH_V2 + #define MMU_FTRS_PPC970 MMU_FTRS_POWER4 | MMU_FTR_TLBIE_CROP_VA + #define MMU_FTRS_POWER5 MMU_FTRS_POWER4 | MMU_FTR_LOCKLESS_TLBIE +-#define MMU_FTRS_POWER6 MMU_FTRS_POWER4 | MMU_FTR_LOCKLESS_TLBIE +-#define MMU_FTRS_POWER7 MMU_FTRS_POWER4 | MMU_FTR_LOCKLESS_TLBIE +-#define MMU_FTRS_POWER8 MMU_FTRS_POWER4 | MMU_FTR_LOCKLESS_TLBIE +-#define MMU_FTRS_POWER9 MMU_FTRS_POWER4 | MMU_FTR_LOCKLESS_TLBIE ++#define MMU_FTRS_POWER6 MMU_FTRS_POWER4 | MMU_FTR_LOCKLESS_TLBIE | MMU_FTR_KERNEL_RO ++#define MMU_FTRS_POWER7 MMU_FTRS_POWER4 | MMU_FTR_LOCKLESS_TLBIE | MMU_FTR_KERNEL_RO ++#define MMU_FTRS_POWER8 MMU_FTRS_POWER4 | MMU_FTR_LOCKLESS_TLBIE | MMU_FTR_KERNEL_RO ++#define MMU_FTRS_POWER9 MMU_FTRS_POWER4 | MMU_FTR_LOCKLESS_TLBIE | MMU_FTR_KERNEL_RO + #define MMU_FTRS_CELL MMU_FTRS_DEFAULT_HPTE_ARCH_V2 | \ + MMU_FTR_CI_LARGE_PAGE + #define MMU_FTRS_PA6T MMU_FTRS_DEFAULT_HPTE_ARCH_V2 | \ +diff --git a/arch/powerpc/include/asm/reg.h b/arch/powerpc/include/asm/reg.h +index 978dada..52cbf04 100644 +--- a/arch/powerpc/include/asm/reg.h ++++ b/arch/powerpc/include/asm/reg.h +@@ -355,6 +355,7 @@ + #define LPCR_PECE0 ASM_CONST(0x0000000000004000) /* ext. exceptions can cause exit */ + #define LPCR_PECE1 ASM_CONST(0x0000000000002000) /* decrementer can cause exit */ + #define LPCR_PECE2 ASM_CONST(0x0000000000001000) /* machine check etc can cause exit */ ++#define LPCR_PECE_HVEE ASM_CONST(0x0000400000000000) /* P9 Wakeup on HV interrupts */ + #define LPCR_MER ASM_CONST(0x0000000000000800) /* Mediated External Exception */ + #define LPCR_MER_SH 11 + #define LPCR_TC ASM_CONST(0x0000000000000200) /* Translation control */ +diff --git a/arch/powerpc/kernel/cpu_setup_power.S b/arch/powerpc/kernel/cpu_setup_power.S +index 52ff3f0..37c027c 100644 +--- a/arch/powerpc/kernel/cpu_setup_power.S ++++ b/arch/powerpc/kernel/cpu_setup_power.S +@@ -98,8 +98,8 @@ _GLOBAL(__setup_cpu_power9) + li r0,0 + mtspr SPRN_LPID,r0 + mfspr r3,SPRN_LPCR +- ori r3, r3, LPCR_PECEDH +- ori r3, r3, LPCR_HVICE ++ LOAD_REG_IMMEDIATE(r4, LPCR_PECEDH | LPCR_PECE_HVEE | LPCR_HVICE) ++ or r3, r3, r4 + bl __init_LPCR + bl __init_HFSCR + bl __init_tlb_power9 +@@ -118,8 +118,8 @@ _GLOBAL(__restore_cpu_power9) + li r0,0 + mtspr SPRN_LPID,r0 + mfspr r3,SPRN_LPCR +- ori r3, r3, LPCR_PECEDH +- ori r3, r3, LPCR_HVICE ++ LOAD_REG_IMMEDIATE(r4, LPCR_PECEDH | LPCR_PECE_HVEE | LPCR_HVICE) ++ or r3, r3, r4 + bl __init_LPCR + bl __init_HFSCR + bl __init_tlb_power9 +diff --git a/arch/powerpc/mm/hash_utils_64.c b/arch/powerpc/mm/hash_utils_64.c +index 28923b2..8dff9ce 100644 +--- a/arch/powerpc/mm/hash_utils_64.c ++++ b/arch/powerpc/mm/hash_utils_64.c +@@ -190,8 +190,12 @@ unsigned long htab_convert_pte_flags(unsigned long pteflags) + /* + * Kernel read only mapped with ppp bits 0b110 + */ +- if (!(pteflags & _PAGE_WRITE)) +- rflags |= (HPTE_R_PP0 | 0x2); ++ if (!(pteflags & _PAGE_WRITE)) { ++ if (mmu_has_feature(MMU_FTR_KERNEL_RO)) ++ rflags |= (HPTE_R_PP0 | 0x2); ++ else ++ rflags |= 0x3; ++ } + } else { + if (pteflags & _PAGE_RWX) + rflags |= 0x2; +diff --git a/arch/tile/kernel/time.c b/arch/tile/kernel/time.c +index 178989e..ea960d6 100644 +--- a/arch/tile/kernel/time.c ++++ b/arch/tile/kernel/time.c +@@ -218,8 +218,8 @@ void do_timer_interrupt(struct pt_regs *regs, int fault_num) + */ + unsigned long long sched_clock(void) + { +- return clocksource_cyc2ns(get_cycles(), +- sched_clock_mult, SCHED_CLOCK_SHIFT); ++ return mult_frac(get_cycles(), ++ sched_clock_mult, 1ULL << SCHED_CLOCK_SHIFT); + } + + int setup_profiling_timer(unsigned int multiplier) +diff --git a/arch/x86/events/intel/ds.c b/arch/x86/events/intel/ds.c +index 9b983a4..8fc714b 100644 +--- a/arch/x86/events/intel/ds.c ++++ b/arch/x86/events/intel/ds.c +@@ -1070,20 +1070,20 @@ static void setup_pebs_sample_data(struct perf_event *event, + } + + /* +- * We use the interrupt regs as a base because the PEBS record +- * does not contain a full regs set, specifically it seems to +- * lack segment descriptors, which get used by things like +- * user_mode(). ++ * We use the interrupt regs as a base because the PEBS record does not ++ * contain a full regs set, specifically it seems to lack segment ++ * descriptors, which get used by things like user_mode(). + * +- * In the simple case fix up only the IP and BP,SP regs, for +- * PERF_SAMPLE_IP and PERF_SAMPLE_CALLCHAIN to function properly. +- * A possible PERF_SAMPLE_REGS will have to transfer all regs. ++ * In the simple case fix up only the IP for PERF_SAMPLE_IP. ++ * ++ * We must however always use BP,SP from iregs for the unwinder to stay ++ * sane; the record BP,SP can point into thin air when the record is ++ * from a previous PMI context or an (I)RET happend between the record ++ * and PMI. + */ + *regs = *iregs; + regs->flags = pebs->flags; + set_linear_ip(regs, pebs->ip); +- regs->bp = pebs->bp; +- regs->sp = pebs->sp; + + if (sample_type & PERF_SAMPLE_REGS_INTR) { + regs->ax = pebs->ax; +@@ -1092,10 +1092,21 @@ static void setup_pebs_sample_data(struct perf_event *event, + regs->dx = pebs->dx; + regs->si = pebs->si; + regs->di = pebs->di; +- regs->bp = pebs->bp; +- regs->sp = pebs->sp; + +- regs->flags = pebs->flags; ++ /* ++ * Per the above; only set BP,SP if we don't need callchains. ++ * ++ * XXX: does this make sense? ++ */ ++ if (!(sample_type & PERF_SAMPLE_CALLCHAIN)) { ++ regs->bp = pebs->bp; ++ regs->sp = pebs->sp; ++ } ++ ++ /* ++ * Preserve PERF_EFLAGS_VM from set_linear_ip(). ++ */ ++ regs->flags = pebs->flags | (regs->flags & PERF_EFLAGS_VM); + #ifndef CONFIG_X86_32 + regs->r8 = pebs->r8; + regs->r9 = pebs->r9; +diff --git a/arch/x86/events/perf_event.h b/arch/x86/events/perf_event.h +index 8c4a477..181c238 100644 +--- a/arch/x86/events/perf_event.h ++++ b/arch/x86/events/perf_event.h +@@ -113,7 +113,7 @@ struct debug_store { + * Per register state. + */ + struct er_account { +- raw_spinlock_t lock; /* per-core: protect structure */ ++ raw_spinlock_t lock; /* per-core: protect structure */ + u64 config; /* extra MSR config */ + u64 reg; /* extra MSR number */ + atomic_t ref; /* reference count */ +diff --git a/arch/x86/kernel/fpu/core.c b/arch/x86/kernel/fpu/core.c +index 3fc03a0..c289e2f 100644 +--- a/arch/x86/kernel/fpu/core.c ++++ b/arch/x86/kernel/fpu/core.c +@@ -517,14 +517,14 @@ void fpu__clear(struct fpu *fpu) + { + WARN_ON_FPU(fpu != ¤t->thread.fpu); /* Almost certainly an anomaly */ + +- if (!use_eager_fpu() || !static_cpu_has(X86_FEATURE_FPU)) { +- /* FPU state will be reallocated lazily at the first use. */ +- fpu__drop(fpu); +- } else { +- if (!fpu->fpstate_active) { +- fpu__activate_curr(fpu); +- user_fpu_begin(); +- } ++ fpu__drop(fpu); ++ ++ /* ++ * Make sure fpstate is cleared and initialized. ++ */ ++ if (static_cpu_has(X86_FEATURE_FPU)) { ++ fpu__activate_curr(fpu); ++ user_fpu_begin(); + copy_init_fpstate_to_fpregs(); + } + } +diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c +index cbd7b92..a3ce9d2 100644 +--- a/arch/x86/kvm/emulate.c ++++ b/arch/x86/kvm/emulate.c +@@ -2105,16 +2105,10 @@ static int em_iret(struct x86_emulate_ctxt *ctxt) + static int em_jmp_far(struct x86_emulate_ctxt *ctxt) + { + int rc; +- unsigned short sel, old_sel; +- struct desc_struct old_desc, new_desc; +- const struct x86_emulate_ops *ops = ctxt->ops; ++ unsigned short sel; ++ struct desc_struct new_desc; + u8 cpl = ctxt->ops->cpl(ctxt); + +- /* Assignment of RIP may only fail in 64-bit mode */ +- if (ctxt->mode == X86EMUL_MODE_PROT64) +- ops->get_segment(ctxt, &old_sel, &old_desc, NULL, +- VCPU_SREG_CS); +- + memcpy(&sel, ctxt->src.valptr + ctxt->op_bytes, 2); + + rc = __load_segment_descriptor(ctxt, sel, VCPU_SREG_CS, cpl, +@@ -2124,12 +2118,10 @@ static int em_jmp_far(struct x86_emulate_ctxt *ctxt) + return rc; + + rc = assign_eip_far(ctxt, ctxt->src.val, &new_desc); +- if (rc != X86EMUL_CONTINUE) { +- WARN_ON(ctxt->mode != X86EMUL_MODE_PROT64); +- /* assigning eip failed; restore the old cs */ +- ops->set_segment(ctxt, old_sel, &old_desc, 0, VCPU_SREG_CS); +- return rc; +- } ++ /* Error handling is not implemented. */ ++ if (rc != X86EMUL_CONTINUE) ++ return X86EMUL_UNHANDLEABLE; ++ + return rc; + } + +@@ -2189,14 +2181,8 @@ static int em_ret_far(struct x86_emulate_ctxt *ctxt) + { + int rc; + unsigned long eip, cs; +- u16 old_cs; + int cpl = ctxt->ops->cpl(ctxt); +- struct desc_struct old_desc, new_desc; +- const struct x86_emulate_ops *ops = ctxt->ops; +- +- if (ctxt->mode == X86EMUL_MODE_PROT64) +- ops->get_segment(ctxt, &old_cs, &old_desc, NULL, +- VCPU_SREG_CS); ++ struct desc_struct new_desc; + + rc = emulate_pop(ctxt, &eip, ctxt->op_bytes); + if (rc != X86EMUL_CONTINUE) +@@ -2213,10 +2199,10 @@ static int em_ret_far(struct x86_emulate_ctxt *ctxt) + if (rc != X86EMUL_CONTINUE) + return rc; + rc = assign_eip_far(ctxt, eip, &new_desc); +- if (rc != X86EMUL_CONTINUE) { +- WARN_ON(ctxt->mode != X86EMUL_MODE_PROT64); +- ops->set_segment(ctxt, old_cs, &old_desc, 0, VCPU_SREG_CS); +- } ++ /* Error handling is not implemented. */ ++ if (rc != X86EMUL_CONTINUE) ++ return X86EMUL_UNHANDLEABLE; ++ + return rc; + } + +diff --git a/arch/x86/kvm/ioapic.c b/arch/x86/kvm/ioapic.c +index 1a22de7..6e219e5 100644 +--- a/arch/x86/kvm/ioapic.c ++++ b/arch/x86/kvm/ioapic.c +@@ -94,7 +94,7 @@ static unsigned long ioapic_read_indirect(struct kvm_ioapic *ioapic, + static void rtc_irq_eoi_tracking_reset(struct kvm_ioapic *ioapic) + { + ioapic->rtc_status.pending_eoi = 0; +- bitmap_zero(ioapic->rtc_status.dest_map.map, KVM_MAX_VCPUS); ++ bitmap_zero(ioapic->rtc_status.dest_map.map, KVM_MAX_VCPU_ID); + } + + static void kvm_rtc_eoi_tracking_restore_all(struct kvm_ioapic *ioapic); +diff --git a/arch/x86/kvm/ioapic.h b/arch/x86/kvm/ioapic.h +index 7d2692a..1cc6e54 100644 +--- a/arch/x86/kvm/ioapic.h ++++ b/arch/x86/kvm/ioapic.h +@@ -42,13 +42,13 @@ struct kvm_vcpu; + + struct dest_map { + /* vcpu bitmap where IRQ has been sent */ +- DECLARE_BITMAP(map, KVM_MAX_VCPUS); ++ DECLARE_BITMAP(map, KVM_MAX_VCPU_ID); + + /* + * Vector sent to a given vcpu, only valid when + * the vcpu's bit in map is set + */ +- u8 vectors[KVM_MAX_VCPUS]; ++ u8 vectors[KVM_MAX_VCPU_ID]; + }; + + +diff --git a/arch/x86/kvm/irq_comm.c b/arch/x86/kvm/irq_comm.c +index 25810b1..e7a112a 100644 +--- a/arch/x86/kvm/irq_comm.c ++++ b/arch/x86/kvm/irq_comm.c +@@ -41,6 +41,15 @@ static int kvm_set_pic_irq(struct kvm_kernel_irq_routing_entry *e, + bool line_status) + { + struct kvm_pic *pic = pic_irqchip(kvm); ++ ++ /* ++ * XXX: rejecting pic routes when pic isn't in use would be better, ++ * but the default routing table is installed while kvm->arch.vpic is ++ * NULL and KVM_CREATE_IRQCHIP can race with KVM_IRQ_LINE. ++ */ ++ if (!pic) ++ return -1; ++ + return kvm_pic_set_irq(pic, e->irqchip.pin, irq_source_id, level); + } + +@@ -49,6 +58,10 @@ static int kvm_set_ioapic_irq(struct kvm_kernel_irq_routing_entry *e, + bool line_status) + { + struct kvm_ioapic *ioapic = kvm->arch.vioapic; ++ ++ if (!ioapic) ++ return -1; ++ + return kvm_ioapic_set_irq(ioapic, e->irqchip.pin, irq_source_id, level, + line_status); + } +diff --git a/arch/x86/kvm/lapic.c b/arch/x86/kvm/lapic.c +index b62c852..d2255e4 100644 +--- a/arch/x86/kvm/lapic.c ++++ b/arch/x86/kvm/lapic.c +@@ -138,7 +138,7 @@ static inline bool kvm_apic_map_get_logical_dest(struct kvm_apic_map *map, + *mask = dest_id & 0xff; + return true; + case KVM_APIC_MODE_XAPIC_CLUSTER: +- *cluster = map->xapic_cluster_map[dest_id >> 4]; ++ *cluster = map->xapic_cluster_map[(dest_id >> 4) & 0xf]; + *mask = dest_id & 0xf; + return true; + default: +diff --git a/arch/x86/mm/extable.c b/arch/x86/mm/extable.c +index 832b98f..a3a983f 100644 +--- a/arch/x86/mm/extable.c ++++ b/arch/x86/mm/extable.c +@@ -135,7 +135,12 @@ void __init early_fixup_exception(struct pt_regs *regs, int trapnr) + if (early_recursion_flag > 2) + goto halt_loop; + +- if (regs->cs != __KERNEL_CS) ++ /* ++ * Old CPUs leave the high bits of CS on the stack ++ * undefined. I'm not sure which CPUs do this, but at least ++ * the 486 DX works this way. ++ */ ++ if ((regs->cs & 0xFFFF) != __KERNEL_CS) + goto fail; + + /* +diff --git a/crypto/asymmetric_keys/x509_cert_parser.c b/crypto/asymmetric_keys/x509_cert_parser.c +index 865f46e..c80765b 100644 +--- a/crypto/asymmetric_keys/x509_cert_parser.c ++++ b/crypto/asymmetric_keys/x509_cert_parser.c +@@ -133,7 +133,6 @@ struct x509_certificate *x509_cert_parse(const void *data, size_t datalen) + return cert; + + error_decode: +- kfree(cert->pub->key); + kfree(ctx); + error_no_ctx: + x509_free_certificate(cert); +diff --git a/drivers/dax/dax.c b/drivers/dax/dax.c +index 29f600f..ff64313 100644 +--- a/drivers/dax/dax.c ++++ b/drivers/dax/dax.c +@@ -323,8 +323,8 @@ static int check_vma(struct dax_dev *dax_dev, struct vm_area_struct *vma, + if (!dax_dev->alive) + return -ENXIO; + +- /* prevent private / writable mappings from being established */ +- if ((vma->vm_flags & (VM_NORESERVE|VM_SHARED|VM_WRITE)) == VM_WRITE) { ++ /* prevent private mappings from being established */ ++ if ((vma->vm_flags & VM_SHARED) != VM_SHARED) { + dev_info(dev, "%s: %s: fail, attempted private mapping\n", + current->comm, func); + return -EINVAL; +diff --git a/drivers/dax/pmem.c b/drivers/dax/pmem.c +index 73ae849..76dd42d 100644 +--- a/drivers/dax/pmem.c ++++ b/drivers/dax/pmem.c +@@ -77,7 +77,9 @@ static int dax_pmem_probe(struct device *dev) + nsio = to_nd_namespace_io(&ndns->dev); + + /* parse the 'pfn' info block via ->rw_bytes */ +- devm_nsio_enable(dev, nsio); ++ rc = devm_nsio_enable(dev, nsio); ++ if (rc) ++ return rc; + altmap = nvdimm_setup_pfn(nd_pfn, &res, &__altmap); + if (IS_ERR(altmap)) + return PTR_ERR(altmap); +diff --git a/drivers/iommu/dmar.c b/drivers/iommu/dmar.c +index 58470f5..8c53748 100644 +--- a/drivers/iommu/dmar.c ++++ b/drivers/iommu/dmar.c +@@ -338,7 +338,9 @@ static int dmar_pci_bus_notifier(struct notifier_block *nb, + struct pci_dev *pdev = to_pci_dev(data); + struct dmar_pci_notify_info *info; + +- /* Only care about add/remove events for physical functions */ ++ /* Only care about add/remove events for physical functions. ++ * For VFs we actually do the lookup based on the corresponding ++ * PF in device_to_iommu() anyway. */ + if (pdev->is_virtfn) + return NOTIFY_DONE; + if (action != BUS_NOTIFY_ADD_DEVICE && +diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c +index 1257b0b..7fb5387 100644 +--- a/drivers/iommu/intel-iommu.c ++++ b/drivers/iommu/intel-iommu.c +@@ -892,7 +892,13 @@ static struct intel_iommu *device_to_iommu(struct device *dev, u8 *bus, u8 *devf + return NULL; + + if (dev_is_pci(dev)) { ++ struct pci_dev *pf_pdev; ++ + pdev = to_pci_dev(dev); ++ /* VFs aren't listed in scope tables; we need to look up ++ * the PF instead to find the IOMMU. */ ++ pf_pdev = pci_physfn(pdev); ++ dev = &pf_pdev->dev; + segment = pci_domain_nr(pdev->bus); + } else if (has_acpi_companion(dev)) + dev = &ACPI_COMPANION(dev)->dev; +@@ -905,6 +911,13 @@ static struct intel_iommu *device_to_iommu(struct device *dev, u8 *bus, u8 *devf + for_each_active_dev_scope(drhd->devices, + drhd->devices_cnt, i, tmp) { + if (tmp == dev) { ++ /* For a VF use its original BDF# not that of the PF ++ * which we used for the IOMMU lookup. Strictly speaking ++ * we could do this for all PCI devices; we only need to ++ * get the BDF# from the scope table for ACPI matches. */ ++ if (pdev->is_virtfn) ++ goto got_pdev; ++ + *bus = drhd->devices[i].bus; + *devfn = drhd->devices[i].devfn; + goto out; +diff --git a/drivers/iommu/intel-svm.c b/drivers/iommu/intel-svm.c +index 8ebb353..cb72e00 100644 +--- a/drivers/iommu/intel-svm.c ++++ b/drivers/iommu/intel-svm.c +@@ -39,10 +39,18 @@ int intel_svm_alloc_pasid_tables(struct intel_iommu *iommu) + struct page *pages; + int order; + +- order = ecap_pss(iommu->ecap) + 7 - PAGE_SHIFT; +- if (order < 0) +- order = 0; +- ++ /* Start at 2 because it's defined as 2^(1+PSS) */ ++ iommu->pasid_max = 2 << ecap_pss(iommu->ecap); ++ ++ /* Eventually I'm promised we will get a multi-level PASID table ++ * and it won't have to be physically contiguous. Until then, ++ * limit the size because 8MiB contiguous allocations can be hard ++ * to come by. The limit of 0x20000, which is 1MiB for each of ++ * the PASID and PASID-state tables, is somewhat arbitrary. */ ++ if (iommu->pasid_max > 0x20000) ++ iommu->pasid_max = 0x20000; ++ ++ order = get_order(sizeof(struct pasid_entry) * iommu->pasid_max); + pages = alloc_pages(GFP_KERNEL | __GFP_ZERO, order); + if (!pages) { + pr_warn("IOMMU: %s: Failed to allocate PASID table\n", +@@ -53,6 +61,8 @@ int intel_svm_alloc_pasid_tables(struct intel_iommu *iommu) + pr_info("%s: Allocated order %d PASID table.\n", iommu->name, order); + + if (ecap_dis(iommu->ecap)) { ++ /* Just making it explicit... */ ++ BUILD_BUG_ON(sizeof(struct pasid_entry) != sizeof(struct pasid_state_entry)); + pages = alloc_pages(GFP_KERNEL | __GFP_ZERO, order); + if (pages) + iommu->pasid_state_table = page_address(pages); +@@ -68,11 +78,7 @@ int intel_svm_alloc_pasid_tables(struct intel_iommu *iommu) + + int intel_svm_free_pasid_tables(struct intel_iommu *iommu) + { +- int order; +- +- order = ecap_pss(iommu->ecap) + 7 - PAGE_SHIFT; +- if (order < 0) +- order = 0; ++ int order = get_order(sizeof(struct pasid_entry) * iommu->pasid_max); + + if (iommu->pasid_table) { + free_pages((unsigned long)iommu->pasid_table, order); +@@ -371,8 +377,8 @@ int intel_svm_bind_mm(struct device *dev, int *pasid, int flags, struct svm_dev_ + } + svm->iommu = iommu; + +- if (pasid_max > 2 << ecap_pss(iommu->ecap)) +- pasid_max = 2 << ecap_pss(iommu->ecap); ++ if (pasid_max > iommu->pasid_max) ++ pasid_max = iommu->pasid_max; + + /* Do not use PASID 0 in caching mode (virtualised IOMMU) */ + ret = idr_alloc(&iommu->pasid_idr, svm, +diff --git a/drivers/media/tuners/tuner-xc2028.c b/drivers/media/tuners/tuner-xc2028.c +index 317ef63..8d96a22 100644 +--- a/drivers/media/tuners/tuner-xc2028.c ++++ b/drivers/media/tuners/tuner-xc2028.c +@@ -281,6 +281,14 @@ static void free_firmware(struct xc2028_data *priv) + int i; + tuner_dbg("%s called\n", __func__); + ++ /* free allocated f/w string */ ++ if (priv->fname != firmware_name) ++ kfree(priv->fname); ++ priv->fname = NULL; ++ ++ priv->state = XC2028_NO_FIRMWARE; ++ memset(&priv->cur_fw, 0, sizeof(priv->cur_fw)); ++ + if (!priv->firm) + return; + +@@ -291,9 +299,6 @@ static void free_firmware(struct xc2028_data *priv) + + priv->firm = NULL; + priv->firm_size = 0; +- priv->state = XC2028_NO_FIRMWARE; +- +- memset(&priv->cur_fw, 0, sizeof(priv->cur_fw)); + } + + static int load_all_firmwares(struct dvb_frontend *fe, +@@ -884,9 +889,8 @@ static int check_firmware(struct dvb_frontend *fe, unsigned int type, + return 0; + + fail: +- priv->state = XC2028_NO_FIRMWARE; ++ free_firmware(priv); + +- memset(&priv->cur_fw, 0, sizeof(priv->cur_fw)); + if (retry_count < 8) { + msleep(50); + retry_count++; +@@ -1332,11 +1336,8 @@ static int xc2028_dvb_release(struct dvb_frontend *fe) + mutex_lock(&xc2028_list_mutex); + + /* only perform final cleanup if this is the last instance */ +- if (hybrid_tuner_report_instance_count(priv) == 1) { ++ if (hybrid_tuner_report_instance_count(priv) == 1) + free_firmware(priv); +- kfree(priv->ctrl.fname); +- priv->ctrl.fname = NULL; +- } + + if (priv) + hybrid_tuner_release_state(priv); +@@ -1399,19 +1400,8 @@ static int xc2028_set_config(struct dvb_frontend *fe, void *priv_cfg) + + /* + * Copy the config data. +- * For the firmware name, keep a local copy of the string, +- * in order to avoid troubles during device release. + */ +- kfree(priv->ctrl.fname); +- priv->ctrl.fname = NULL; + memcpy(&priv->ctrl, p, sizeof(priv->ctrl)); +- if (p->fname) { +- priv->ctrl.fname = kstrdup(p->fname, GFP_KERNEL); +- if (priv->ctrl.fname == NULL) { +- rc = -ENOMEM; +- goto unlock; +- } +- } + + /* + * If firmware name changed, frees firmware. As free_firmware will +@@ -1426,10 +1416,15 @@ static int xc2028_set_config(struct dvb_frontend *fe, void *priv_cfg) + + if (priv->state == XC2028_NO_FIRMWARE) { + if (!firmware_name[0]) +- priv->fname = priv->ctrl.fname; ++ priv->fname = kstrdup(p->fname, GFP_KERNEL); + else + priv->fname = firmware_name; + ++ if (!priv->fname) { ++ rc = -ENOMEM; ++ goto unlock; ++ } ++ + rc = request_firmware_nowait(THIS_MODULE, 1, + priv->fname, + priv->i2c_props.adap->dev.parent, +diff --git a/drivers/mmc/host/sdhci-of-esdhc.c b/drivers/mmc/host/sdhci-of-esdhc.c +index 239be2f..2267601 100644 +--- a/drivers/mmc/host/sdhci-of-esdhc.c ++++ b/drivers/mmc/host/sdhci-of-esdhc.c +@@ -66,6 +66,20 @@ static u32 esdhc_readl_fixup(struct sdhci_host *host, + return ret; + } + } ++ /* ++ * The DAT[3:0] line signal levels and the CMD line signal level are ++ * not compatible with standard SDHC register. The line signal levels ++ * DAT[7:0] are at bits 31:24 and the command line signal level is at ++ * bit 23. All other bits are the same as in the standard SDHC ++ * register. ++ */ ++ if (spec_reg == SDHCI_PRESENT_STATE) { ++ ret = value & 0x000fffff; ++ ret |= (value >> 4) & SDHCI_DATA_LVL_MASK; ++ ret |= (value << 1) & SDHCI_CMD_LVL; ++ return ret; ++ } ++ + ret = value; + return ret; + } +diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h +index 0411c9f..1b3bd1c 100644 +--- a/drivers/mmc/host/sdhci.h ++++ b/drivers/mmc/host/sdhci.h +@@ -73,6 +73,7 @@ + #define SDHCI_DATA_LVL_MASK 0x00F00000 + #define SDHCI_DATA_LVL_SHIFT 20 + #define SDHCI_DATA_0_LVL_MASK 0x00100000 ++#define SDHCI_CMD_LVL 0x01000000 + + #define SDHCI_HOST_CONTROL 0x28 + #define SDHCI_CTRL_LED 0x01 +diff --git a/drivers/scsi/mpt3sas/mpt3sas_scsih.c b/drivers/scsi/mpt3sas/mpt3sas_scsih.c +index 46c0f5e..58e6029 100644 +--- a/drivers/scsi/mpt3sas/mpt3sas_scsih.c ++++ b/drivers/scsi/mpt3sas/mpt3sas_scsih.c +@@ -3894,6 +3894,11 @@ _scsih_temp_threshold_events(struct MPT3SAS_ADAPTER *ioc, + } + } + ++static inline bool ata_12_16_cmd(struct scsi_cmnd *scmd) ++{ ++ return (scmd->cmnd[0] == ATA_12 || scmd->cmnd[0] == ATA_16); ++} ++ + /** + * _scsih_flush_running_cmds - completing outstanding commands. + * @ioc: per adapter object +@@ -3915,6 +3920,9 @@ _scsih_flush_running_cmds(struct MPT3SAS_ADAPTER *ioc) + if (!scmd) + continue; + count++; ++ if (ata_12_16_cmd(scmd)) ++ scsi_internal_device_unblock(scmd->device, ++ SDEV_RUNNING); + mpt3sas_base_free_smid(ioc, smid); + scsi_dma_unmap(scmd); + if (ioc->pci_error_recovery) +@@ -4019,8 +4027,6 @@ _scsih_eedp_error_handling(struct scsi_cmnd *scmd, u16 ioc_status) + SAM_STAT_CHECK_CONDITION; + } + +- +- + /** + * scsih_qcmd - main scsi request entry point + * @scmd: pointer to scsi command object +@@ -4047,6 +4053,13 @@ scsih_qcmd(struct Scsi_Host *shost, struct scsi_cmnd *scmd) + if (ioc->logging_level & MPT_DEBUG_SCSI) + scsi_print_command(scmd); + ++ /* ++ * Lock the device for any subsequent command until command is ++ * done. ++ */ ++ if (ata_12_16_cmd(scmd)) ++ scsi_internal_device_block(scmd->device); ++ + sas_device_priv_data = scmd->device->hostdata; + if (!sas_device_priv_data || !sas_device_priv_data->sas_target) { + scmd->result = DID_NO_CONNECT << 16; +@@ -4622,6 +4635,9 @@ _scsih_io_done(struct MPT3SAS_ADAPTER *ioc, u16 smid, u8 msix_index, u32 reply) + if (scmd == NULL) + return 1; + ++ if (ata_12_16_cmd(scmd)) ++ scsi_internal_device_unblock(scmd->device, SDEV_RUNNING); ++ + mpi_request = mpt3sas_base_get_msg_frame(ioc, smid); + + if (mpi_reply == NULL) { +diff --git a/drivers/thermal/intel_powerclamp.c b/drivers/thermal/intel_powerclamp.c +index 7a22307..afada65 100644 +--- a/drivers/thermal/intel_powerclamp.c ++++ b/drivers/thermal/intel_powerclamp.c +@@ -669,9 +669,16 @@ static struct thermal_cooling_device_ops powerclamp_cooling_ops = { + .set_cur_state = powerclamp_set_cur_state, + }; + ++static const struct x86_cpu_id __initconst intel_powerclamp_ids[] = { ++ { X86_VENDOR_INTEL, X86_FAMILY_ANY, X86_MODEL_ANY, X86_FEATURE_MWAIT }, ++ {} ++}; ++MODULE_DEVICE_TABLE(x86cpu, intel_powerclamp_ids); ++ + static int __init powerclamp_probe(void) + { +- if (!boot_cpu_has(X86_FEATURE_MWAIT)) { ++ ++ if (!x86_match_cpu(intel_powerclamp_ids)) { + pr_err("CPU does not support MWAIT"); + return -ENODEV; + } +diff --git a/drivers/usb/chipidea/core.c b/drivers/usb/chipidea/core.c +index 69426e6..3dbb4a2 100644 +--- a/drivers/usb/chipidea/core.c ++++ b/drivers/usb/chipidea/core.c +@@ -914,6 +914,7 @@ static int ci_hdrc_probe(struct platform_device *pdev) + if (!ci) + return -ENOMEM; + ++ spin_lock_init(&ci->lock); + ci->dev = dev; + ci->platdata = dev_get_platdata(dev); + ci->imx28_write_fix = !!(ci->platdata->flags & +diff --git a/drivers/usb/chipidea/udc.c b/drivers/usb/chipidea/udc.c +index b933568..bced28f 100644 +--- a/drivers/usb/chipidea/udc.c ++++ b/drivers/usb/chipidea/udc.c +@@ -1895,8 +1895,6 @@ static int udc_start(struct ci_hdrc *ci) + struct usb_otg_caps *otg_caps = &ci->platdata->ci_otg_caps; + int retval = 0; + +- spin_lock_init(&ci->lock); +- + ci->gadget.ops = &usb_gadget_ops; + ci->gadget.speed = USB_SPEED_UNKNOWN; + ci->gadget.max_speed = USB_SPEED_HIGH; +diff --git a/drivers/usb/serial/cp210x.c b/drivers/usb/serial/cp210x.c +index f61477b..243ac5e 100644 +--- a/drivers/usb/serial/cp210x.c ++++ b/drivers/usb/serial/cp210x.c +@@ -131,6 +131,7 @@ static const struct usb_device_id id_table[] = { + { USB_DEVICE(0x10C4, 0x88A4) }, /* MMB Networks ZigBee USB Device */ + { USB_DEVICE(0x10C4, 0x88A5) }, /* Planet Innovation Ingeni ZigBee USB Device */ + { USB_DEVICE(0x10C4, 0x8946) }, /* Ketra N1 Wireless Interface */ ++ { USB_DEVICE(0x10C4, 0x8962) }, /* Brim Brothers charging dock */ + { USB_DEVICE(0x10C4, 0x8977) }, /* CEL MeshWorks DevKit Device */ + { USB_DEVICE(0x10C4, 0x8998) }, /* KCF Technologies PRN */ + { USB_DEVICE(0x10C4, 0x8A2A) }, /* HubZ dual ZigBee and Z-Wave dongle */ +diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c +index 0ff7f38..6e9fc8b 100644 +--- a/drivers/usb/serial/ftdi_sio.c ++++ b/drivers/usb/serial/ftdi_sio.c +@@ -1012,6 +1012,8 @@ static const struct usb_device_id id_table_combined[] = { + { USB_DEVICE(ICPDAS_VID, ICPDAS_I7561U_PID) }, + { USB_DEVICE(ICPDAS_VID, ICPDAS_I7563U_PID) }, + { USB_DEVICE(WICED_VID, WICED_USB20706V2_PID) }, ++ { USB_DEVICE(TI_VID, TI_CC3200_LAUNCHPAD_PID), ++ .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk }, + { } /* Terminating entry */ + }; + +diff --git a/drivers/usb/serial/ftdi_sio_ids.h b/drivers/usb/serial/ftdi_sio_ids.h +index 21011c0..48ee04c 100644 +--- a/drivers/usb/serial/ftdi_sio_ids.h ++++ b/drivers/usb/serial/ftdi_sio_ids.h +@@ -596,6 +596,12 @@ + #define STK541_PID 0x2109 /* Zigbee Controller */ + + /* ++ * Texas Instruments ++ */ ++#define TI_VID 0x0451 ++#define TI_CC3200_LAUNCHPAD_PID 0xC32A /* SimpleLink Wi-Fi CC3200 LaunchPad */ ++ ++/* + * Blackfin gnICE JTAG + * http://docs.blackfin.uclinux.org/doku.php?id=hw:jtag:gnice + */ +diff --git a/drivers/usb/storage/transport.c b/drivers/usb/storage/transport.c +index ffd0867..1a59f33 100644 +--- a/drivers/usb/storage/transport.c ++++ b/drivers/usb/storage/transport.c +@@ -954,10 +954,15 @@ int usb_stor_CB_transport(struct scsi_cmnd *srb, struct us_data *us) + + /* COMMAND STAGE */ + /* let's send the command via the control pipe */ ++ /* ++ * Command is sometime (f.e. after scsi_eh_prep_cmnd) on the stack. ++ * Stack may be vmallocated. So no DMA for us. Make a copy. ++ */ ++ memcpy(us->iobuf, srb->cmnd, srb->cmd_len); + result = usb_stor_ctrl_transfer(us, us->send_ctrl_pipe, + US_CBI_ADSC, + USB_TYPE_CLASS | USB_RECIP_INTERFACE, 0, +- us->ifnum, srb->cmnd, srb->cmd_len); ++ us->ifnum, us->iobuf, srb->cmd_len); + + /* check the return code for the command */ + usb_stor_dbg(us, "Call to usb_stor_ctrl_transfer() returned %d\n", +diff --git a/fs/nfs/callback.c b/fs/nfs/callback.c +index 52a2831..48efe62 100644 +--- a/fs/nfs/callback.c ++++ b/fs/nfs/callback.c +@@ -261,7 +261,7 @@ static int nfs_callback_up_net(int minorversion, struct svc_serv *serv, + } + + ret = -EPROTONOSUPPORT; +- if (minorversion == 0) ++ if (!IS_ENABLED(CONFIG_NFS_V4_1) || minorversion == 0) + ret = nfs4_callback_up_net(serv, net); + else if (xprt->ops->bc_up) + ret = xprt->ops->bc_up(serv, net); +diff --git a/include/linux/intel-iommu.h b/include/linux/intel-iommu.h +index 2d9b6500..d49e26c 100644 +--- a/include/linux/intel-iommu.h ++++ b/include/linux/intel-iommu.h +@@ -429,6 +429,7 @@ struct intel_iommu { + struct page_req_dsc *prq; + unsigned char prq_name[16]; /* Name for PRQ interrupt */ + struct idr pasid_idr; ++ u32 pasid_max; + #endif + struct q_inval *qi; /* Queued invalidation info */ + u32 *iommu_state; /* Store iommu states between suspend and resume.*/ +diff --git a/kernel/events/core.c b/kernel/events/core.c +index fc9bb22..f8c5f5e 100644 +--- a/kernel/events/core.c ++++ b/kernel/events/core.c +@@ -7908,6 +7908,7 @@ static void perf_event_addr_filters_apply(struct perf_event *event) + * if <size> is not specified, the range is treated as a single address. + */ + enum { ++ IF_ACT_NONE = -1, + IF_ACT_FILTER, + IF_ACT_START, + IF_ACT_STOP, +@@ -7931,6 +7932,7 @@ static const match_table_t if_tokens = { + { IF_SRC_KERNEL, "%u/%u" }, + { IF_SRC_FILEADDR, "%u@%s" }, + { IF_SRC_KERNELADDR, "%u" }, ++ { IF_ACT_NONE, NULL }, + }; + + /* +diff --git a/lib/mpi/mpi-pow.c b/lib/mpi/mpi-pow.c +index 5464c87..e24388a 100644 +--- a/lib/mpi/mpi-pow.c ++++ b/lib/mpi/mpi-pow.c +@@ -64,8 +64,13 @@ int mpi_powm(MPI res, MPI base, MPI exp, MPI mod) + if (!esize) { + /* Exponent is zero, result is 1 mod MOD, i.e., 1 or 0 + * depending on if MOD equals 1. */ +- rp[0] = 1; + res->nlimbs = (msize == 1 && mod->d[0] == 1) ? 0 : 1; ++ if (res->nlimbs) { ++ if (mpi_resize(res, 1) < 0) ++ goto enomem; ++ rp = res->d; ++ rp[0] = 1; ++ } + res->sign = 0; + goto leave; + } +diff --git a/mm/page_alloc.c b/mm/page_alloc.c +index a2214c6..7401e99 100644 +--- a/mm/page_alloc.c ++++ b/mm/page_alloc.c +@@ -3161,6 +3161,16 @@ should_compact_retry(struct alloc_context *ac, unsigned int order, int alloc_fla + if (!order || order > PAGE_ALLOC_COSTLY_ORDER) + return false; + ++#ifdef CONFIG_COMPACTION ++ /* ++ * This is a gross workaround to compensate a lack of reliable compaction ++ * operation. We cannot simply go OOM with the current state of the compaction ++ * code because this can lead to pre mature OOM declaration. ++ */ ++ if (order <= PAGE_ALLOC_COSTLY_ORDER) ++ return true; ++#endif ++ + /* + * There are setups with compaction disabled which would prefer to loop + * inside the allocator rather than hit the oom killer prematurely. +diff --git a/net/can/bcm.c b/net/can/bcm.c +index 8af9d25..436a753 100644 +--- a/net/can/bcm.c ++++ b/net/can/bcm.c +@@ -77,7 +77,7 @@ + (CAN_EFF_MASK | CAN_EFF_FLAG | CAN_RTR_FLAG) : \ + (CAN_SFF_MASK | CAN_EFF_FLAG | CAN_RTR_FLAG)) + +-#define CAN_BCM_VERSION "20160617" ++#define CAN_BCM_VERSION "20161123" + + MODULE_DESCRIPTION("PF_CAN broadcast manager protocol"); + MODULE_LICENSE("Dual BSD/GPL"); +@@ -109,8 +109,9 @@ struct bcm_op { + u32 count; + u32 nframes; + u32 currframe; +- struct canfd_frame *frames; +- struct canfd_frame *last_frames; ++ /* void pointers to arrays of struct can[fd]_frame */ ++ void *frames; ++ void *last_frames; + struct canfd_frame sframe; + struct canfd_frame last_sframe; + struct sock *sk; +@@ -681,7 +682,7 @@ static void bcm_rx_handler(struct sk_buff *skb, void *data) + + if (op->flags & RX_FILTER_ID) { + /* the easiest case */ +- bcm_rx_update_and_send(op, &op->last_frames[0], rxframe); ++ bcm_rx_update_and_send(op, op->last_frames, rxframe); + goto rx_starttimer; + } + +@@ -1068,7 +1069,7 @@ static int bcm_rx_setup(struct bcm_msg_head *msg_head, struct msghdr *msg, + + if (msg_head->nframes) { + /* update CAN frames content */ +- err = memcpy_from_msg((u8 *)op->frames, msg, ++ err = memcpy_from_msg(op->frames, msg, + msg_head->nframes * op->cfsiz); + if (err < 0) + return err; +@@ -1118,7 +1119,7 @@ static int bcm_rx_setup(struct bcm_msg_head *msg_head, struct msghdr *msg, + } + + if (msg_head->nframes) { +- err = memcpy_from_msg((u8 *)op->frames, msg, ++ err = memcpy_from_msg(op->frames, msg, + msg_head->nframes * op->cfsiz); + if (err < 0) { + if (op->frames != &op->sframe) +@@ -1163,6 +1164,7 @@ static int bcm_rx_setup(struct bcm_msg_head *msg_head, struct msghdr *msg, + /* check flags */ + + if (op->flags & RX_RTR_FRAME) { ++ struct canfd_frame *frame0 = op->frames; + + /* no timers in RTR-mode */ + hrtimer_cancel(&op->thrtimer); +@@ -1174,8 +1176,8 @@ static int bcm_rx_setup(struct bcm_msg_head *msg_head, struct msghdr *msg, + * prevent a full-load-loopback-test ... ;-] + */ + if ((op->flags & TX_CP_CAN_ID) || +- (op->frames[0].can_id == op->can_id)) +- op->frames[0].can_id = op->can_id & ~CAN_RTR_FLAG; ++ (frame0->can_id == op->can_id)) ++ frame0->can_id = op->can_id & ~CAN_RTR_FLAG; + + } else { + if (op->flags & SETTIMER) { +diff --git a/net/core/flow_dissector.c b/net/core/flow_dissector.c +index 5550a86..396aac7 100644 +--- a/net/core/flow_dissector.c ++++ b/net/core/flow_dissector.c +@@ -945,4 +945,4 @@ static int __init init_default_flow_dissectors(void) + return 0; + } + +-late_initcall_sync(init_default_flow_dissectors); ++core_initcall(init_default_flow_dissectors); +diff --git a/net/wireless/core.h b/net/wireless/core.h +index eee9144..66f2a11 100644 +--- a/net/wireless/core.h ++++ b/net/wireless/core.h +@@ -71,6 +71,7 @@ struct cfg80211_registered_device { + struct list_head bss_list; + struct rb_root bss_tree; + u32 bss_generation; ++ u32 bss_entries; + struct cfg80211_scan_request *scan_req; /* protected by RTNL */ + struct sk_buff *scan_msg; + struct cfg80211_sched_scan_request __rcu *sched_scan_req; +diff --git a/net/wireless/scan.c b/net/wireless/scan.c +index 0358e12..438143a 100644 +--- a/net/wireless/scan.c ++++ b/net/wireless/scan.c +@@ -57,6 +57,19 @@ + * also linked into the probe response struct. + */ + ++/* ++ * Limit the number of BSS entries stored in mac80211. Each one is ++ * a bit over 4k at most, so this limits to roughly 4-5M of memory. ++ * If somebody wants to really attack this though, they'd likely ++ * use small beacons, and only one type of frame, limiting each of ++ * the entries to a much smaller size (in order to generate more ++ * entries in total, so overhead is bigger.) ++ */ ++static int bss_entries_limit = 1000; ++module_param(bss_entries_limit, int, 0644); ++MODULE_PARM_DESC(bss_entries_limit, ++ "limit to number of scan BSS entries (per wiphy, default 1000)"); ++ + #define IEEE80211_SCAN_RESULT_EXPIRE (30 * HZ) + + static void bss_free(struct cfg80211_internal_bss *bss) +@@ -137,6 +150,10 @@ static bool __cfg80211_unlink_bss(struct cfg80211_registered_device *rdev, + + list_del_init(&bss->list); + rb_erase(&bss->rbn, &rdev->bss_tree); ++ rdev->bss_entries--; ++ WARN_ONCE((rdev->bss_entries == 0) ^ list_empty(&rdev->bss_list), ++ "rdev bss entries[%d]/list[empty:%d] corruption\n", ++ rdev->bss_entries, list_empty(&rdev->bss_list)); + bss_ref_put(rdev, bss); + return true; + } +@@ -163,6 +180,40 @@ static void __cfg80211_bss_expire(struct cfg80211_registered_device *rdev, + rdev->bss_generation++; + } + ++static bool cfg80211_bss_expire_oldest(struct cfg80211_registered_device *rdev) ++{ ++ struct cfg80211_internal_bss *bss, *oldest = NULL; ++ bool ret; ++ ++ lockdep_assert_held(&rdev->bss_lock); ++ ++ list_for_each_entry(bss, &rdev->bss_list, list) { ++ if (atomic_read(&bss->hold)) ++ continue; ++ ++ if (!list_empty(&bss->hidden_list) && ++ !bss->pub.hidden_beacon_bss) ++ continue; ++ ++ if (oldest && time_before(oldest->ts, bss->ts)) ++ continue; ++ oldest = bss; ++ } ++ ++ if (WARN_ON(!oldest)) ++ return false; ++ ++ /* ++ * The callers make sure to increase rdev->bss_generation if anything ++ * gets removed (and a new entry added), so there's no need to also do ++ * it here. ++ */ ++ ++ ret = __cfg80211_unlink_bss(rdev, oldest); ++ WARN_ON(!ret); ++ return ret; ++} ++ + void ___cfg80211_scan_done(struct cfg80211_registered_device *rdev, + bool send_message) + { +@@ -693,6 +744,7 @@ static bool cfg80211_combine_bsses(struct cfg80211_registered_device *rdev, + const u8 *ie; + int i, ssidlen; + u8 fold = 0; ++ u32 n_entries = 0; + + ies = rcu_access_pointer(new->pub.beacon_ies); + if (WARN_ON(!ies)) +@@ -716,6 +768,12 @@ static bool cfg80211_combine_bsses(struct cfg80211_registered_device *rdev, + /* This is the bad part ... */ + + list_for_each_entry(bss, &rdev->bss_list, list) { ++ /* ++ * we're iterating all the entries anyway, so take the ++ * opportunity to validate the list length accounting ++ */ ++ n_entries++; ++ + if (!ether_addr_equal(bss->pub.bssid, new->pub.bssid)) + continue; + if (bss->pub.channel != new->pub.channel) +@@ -744,6 +802,10 @@ static bool cfg80211_combine_bsses(struct cfg80211_registered_device *rdev, + new->pub.beacon_ies); + } + ++ WARN_ONCE(n_entries != rdev->bss_entries, ++ "rdev bss entries[%d]/list[len:%d] corruption\n", ++ rdev->bss_entries, n_entries); ++ + return true; + } + +@@ -898,7 +960,14 @@ cfg80211_bss_update(struct cfg80211_registered_device *rdev, + } + } + ++ if (rdev->bss_entries >= bss_entries_limit && ++ !cfg80211_bss_expire_oldest(rdev)) { ++ kfree(new); ++ goto drop; ++ } ++ + list_add_tail(&new->list, &rdev->bss_list); ++ rdev->bss_entries++; + rb_insert_bss(rdev, new); + found = new; + } +diff --git a/security/apparmor/domain.c b/security/apparmor/domain.c +index fc3036b..a4d90aa 100644 +--- a/security/apparmor/domain.c ++++ b/security/apparmor/domain.c +@@ -621,8 +621,8 @@ int aa_change_hat(const char *hats[], int count, u64 token, bool permtest) + /* released below */ + cred = get_current_cred(); + cxt = cred_cxt(cred); +- profile = aa_cred_profile(cred); +- previous_profile = cxt->previous; ++ profile = aa_get_newest_profile(aa_cred_profile(cred)); ++ previous_profile = aa_get_newest_profile(cxt->previous); + + if (unconfined(profile)) { + info = "unconfined"; +@@ -718,6 +718,8 @@ int aa_change_hat(const char *hats[], int count, u64 token, bool permtest) + out: + aa_put_profile(hat); + kfree(name); ++ aa_put_profile(profile); ++ aa_put_profile(previous_profile); + put_cred(cred); + + return error; diff --git a/4.8.11/4420_grsecurity-3.1-4.8.11-201611271225.patch b/4.8.12/4420_grsecurity-3.1-4.8.12-201612031658.patch index ec53570..4ae7f33 100644 --- a/4.8.11/4420_grsecurity-3.1-4.8.11-201611271225.patch +++ b/4.8.12/4420_grsecurity-3.1-4.8.12-201612031658.patch @@ -407,7 +407,7 @@ index ffab8b5..b8fcd61 100644 A toggle value indicating if modules are allowed to be loaded diff --git a/Makefile b/Makefile -index 2b1bcba..e6f635b 100644 +index 7b0c92f..8fa3c72 100644 --- a/Makefile +++ b/Makefile @@ -302,7 +302,9 @@ CONFIG_SHELL := $(shell if [ -x "$$BASH" ]; then echo $$BASH; \ @@ -9160,7 +9160,7 @@ index 4ba26dd..2d1137d 100644 #define PAGE_KERNEL_RO __pgprot(_PAGE_BASE | _PAGE_KERNEL_RO) #define PAGE_KERNEL_ROX __pgprot(_PAGE_BASE | _PAGE_KERNEL_ROX) diff --git a/arch/powerpc/include/asm/reg.h b/arch/powerpc/include/asm/reg.h -index 978dada..5d29335 100644 +index 52cbf04..c41eb7e 100644 --- a/arch/powerpc/include/asm/reg.h +++ b/arch/powerpc/include/asm/reg.h @@ -270,6 +270,7 @@ @@ -19264,7 +19264,7 @@ index 3ca87b5..207a386 100644 static ssize_t cstate_get_attr_cpumask(struct device *dev, diff --git a/arch/x86/events/intel/ds.c b/arch/x86/events/intel/ds.c -index 9b983a4..b31c136 100644 +index 8fc714b..0ce11c3 100644 --- a/arch/x86/events/intel/ds.c +++ b/arch/x86/events/intel/ds.c @@ -601,7 +601,7 @@ unlock: @@ -19293,7 +19293,7 @@ index 9b983a4..b31c136 100644 do { struct insn insn; -@@ -1109,7 +1110,7 @@ static void setup_pebs_sample_data(struct perf_event *event, +@@ -1120,7 +1121,7 @@ static void setup_pebs_sample_data(struct perf_event *event, } if (event->attr.precise_ip > 1 && x86_pmu.intel_cap.pebs_format >= 2) { @@ -19500,7 +19500,7 @@ index 78b9c23..2f5c61e 100644 static inline unsigned uncore_pci_box_ctl(struct intel_uncore_box *box) diff --git a/arch/x86/events/perf_event.h b/arch/x86/events/perf_event.h -index 8c4a477..bd8370d 100644 +index 181c238..5634d77 100644 --- a/arch/x86/events/perf_event.h +++ b/arch/x86/events/perf_event.h @@ -801,7 +801,7 @@ static inline void set_linear_ip(struct pt_regs *regs, unsigned long ip) @@ -27760,7 +27760,7 @@ index 04f89ca..43ad7de 100644 unlock_done: mutex_unlock(&espfix_init_mutex); diff --git a/arch/x86/kernel/fpu/core.c b/arch/x86/kernel/fpu/core.c -index 3fc03a0..37177e4 100644 +index c289e2f..e2d3af1a 100644 --- a/arch/x86/kernel/fpu/core.c +++ b/arch/x86/kernel/fpu/core.c @@ -135,7 +135,7 @@ void __kernel_fpu_end(void) @@ -32767,7 +32767,7 @@ index 3235e0f..60b5e71 100644 out: diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c -index cbd7b92..d7ea4b9 100644 +index a3ce9d2..0c0ef16 100644 --- a/arch/x86/kvm/emulate.c +++ b/arch/x86/kvm/emulate.c @@ -971,7 +971,7 @@ static int em_bsr_c(struct x86_emulate_ctxt *ctxt) @@ -32797,7 +32797,7 @@ index cbd7b92..d7ea4b9 100644 return rc; } -@@ -3882,7 +3882,7 @@ static int check_cr_write(struct x86_emulate_ctxt *ctxt) +@@ -3868,7 +3868,7 @@ static int check_cr_write(struct x86_emulate_ctxt *ctxt) int cr = ctxt->modrm_reg; u64 efer = 0; @@ -32806,7 +32806,7 @@ index cbd7b92..d7ea4b9 100644 0xffffffff00000000ULL, 0, 0, 0, /* CR3 checked later */ CR4_RESERVED_BITS, -@@ -4968,7 +4968,10 @@ done_prefixes: +@@ -4954,7 +4954,10 @@ done_prefixes: if (ctxt->d == 0) return EMULATION_FAILED; @@ -32818,7 +32818,7 @@ index cbd7b92..d7ea4b9 100644 if (unlikely(ctxt->ud) && likely(!(ctxt->d & EmulateOnUD))) return EMULATION_FAILED; -@@ -5283,15 +5286,14 @@ special_insn: +@@ -5269,15 +5272,14 @@ special_insn: else ctxt->eflags &= ~X86_EFLAGS_RF; @@ -32907,7 +32907,7 @@ index 7cc2360..6ae1236 100644 { struct kvm_kpic_state *s = opaque; diff --git a/arch/x86/kvm/ioapic.c b/arch/x86/kvm/ioapic.c -index 1a22de7..699421c 100644 +index 6e219e5..ccaf115 100644 --- a/arch/x86/kvm/ioapic.c +++ b/arch/x86/kvm/ioapic.c @@ -415,6 +415,8 @@ static void kvm_ioapic_eoi_inject_work(struct work_struct *work) @@ -32920,7 +32920,7 @@ index 1a22de7..699421c 100644 { struct dest_map *dest_map = &ioapic->rtc_status.dest_map; diff --git a/arch/x86/kvm/lapic.c b/arch/x86/kvm/lapic.c -index b62c852..bbf49f2 100644 +index d2255e4..65d458a 100644 --- a/arch/x86/kvm/lapic.c +++ b/arch/x86/kvm/lapic.c @@ -57,7 +57,7 @@ @@ -36144,7 +36144,7 @@ index ea9c49a..7ab033a 100644 } else { walk_pud_level(m, &st, *start, diff --git a/arch/x86/mm/extable.c b/arch/x86/mm/extable.c -index 832b98f..f107868 100644 +index a3a983f..69f6099 100644 --- a/arch/x86/mm/extable.c +++ b/arch/x86/mm/extable.c @@ -102,7 +102,7 @@ int fixup_exception(struct pt_regs *regs, int trapnr) @@ -40906,18 +40906,6 @@ index 0774799..a0012ea 100644 { return jiffies_to_clock_t(q->sg_timeout); } -diff --git a/crypto/asymmetric_keys/x509_cert_parser.c b/crypto/asymmetric_keys/x509_cert_parser.c -index 865f46e..c80765b 100644 ---- a/crypto/asymmetric_keys/x509_cert_parser.c -+++ b/crypto/asymmetric_keys/x509_cert_parser.c -@@ -133,7 +133,6 @@ struct x509_certificate *x509_cert_parse(const void *data, size_t datalen) - return cert; - - error_decode: -- kfree(cert->pub->key); - kfree(ctx); - error_no_ctx: - x509_free_certificate(cert); diff --git a/crypto/cast6_generic.c b/crypto/cast6_generic.c index 058c8d7..55229dd 100644 --- a/crypto/cast6_generic.c @@ -75192,7 +75180,7 @@ index 750f82c..956cdf0 100644 int ret = param_set_int(val, kp); struct MPT3SAS_ADAPTER *ioc; diff --git a/drivers/scsi/mpt3sas/mpt3sas_scsih.c b/drivers/scsi/mpt3sas/mpt3sas_scsih.c -index 46c0f5e..f3228ca 100644 +index 58e6029..03e41fa 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_scsih.c +++ b/drivers/scsi/mpt3sas/mpt3sas_scsih.c @@ -280,7 +280,7 @@ struct _scsi_io_transfer { @@ -75204,7 +75192,7 @@ index 46c0f5e..f3228ca 100644 { int ret = param_set_int(val, kp); struct MPT3SAS_ADAPTER *ioc; -@@ -8934,7 +8934,7 @@ scsih_resume(struct pci_dev *pdev) +@@ -8950,7 +8950,7 @@ scsih_resume(struct pci_dev *pdev) * PCI_ERS_RESULT_NEED_RESET or PCI_ERS_RESULT_DISCONNECT */ pci_ers_result_t @@ -82849,7 +82837,7 @@ index 8967715..4a3791b 100644 struct usb_serial *serial; int retval = -ENODEV; diff --git a/drivers/usb/storage/transport.c b/drivers/usb/storage/transport.c -index ffd0867..eb28464 100644 +index 1a59f33..35f4c56 100644 --- a/drivers/usb/storage/transport.c +++ b/drivers/usb/storage/transport.c @@ -709,7 +709,7 @@ void usb_stor_invoke_transport(struct scsi_cmnd *srb, struct us_data *us) @@ -144062,7 +144050,7 @@ index e9fdb52..cfb547d 100644 new_table.data = &new_value; ret = proc_dointvec_minmax(&new_table, write, buffer, lenp, ppos); diff --git a/kernel/events/core.c b/kernel/events/core.c -index fc9bb22..bedc98b 100644 +index f8c5f5e..00671d2 100644 --- a/kernel/events/core.c +++ b/kernel/events/core.c @@ -389,8 +389,15 @@ static struct srcu_struct pmus_srcu; @@ -144174,7 +144162,7 @@ index fc9bb22..bedc98b 100644 } if (read_format & PERF_FORMAT_ID) values[n++] = primary_event_id(event); -@@ -8562,8 +8570,7 @@ perf_event_mux_interval_ms_store(struct device *dev, +@@ -8564,8 +8572,7 @@ perf_event_mux_interval_ms_store(struct device *dev, cpuctx = per_cpu_ptr(pmu->pmu_cpu_context, cpu); cpuctx->hrtimer_interval = ns_to_ktime(NSEC_PER_MSEC * timer); @@ -144184,7 +144172,7 @@ index fc9bb22..bedc98b 100644 } put_online_cpus(); mutex_unlock(&mux_interval_mutex); -@@ -9004,7 +9011,7 @@ perf_event_alloc(struct perf_event_attr *attr, int cpu, +@@ -9006,7 +9013,7 @@ perf_event_alloc(struct perf_event_attr *attr, int cpu, event->parent = parent_event; event->ns = get_pid_ns(task_active_pid_ns(current)); @@ -144193,7 +144181,7 @@ index fc9bb22..bedc98b 100644 event->state = PERF_EVENT_STATE_INACTIVE; -@@ -9395,6 +9402,11 @@ SYSCALL_DEFINE5(perf_event_open, +@@ -9397,6 +9404,11 @@ SYSCALL_DEFINE5(perf_event_open, if (flags & ~PERF_FLAG_ALL) return -EINVAL; @@ -144205,7 +144193,7 @@ index fc9bb22..bedc98b 100644 err = perf_copy_attr(attr_uptr, &attr); if (err) return err; -@@ -9912,10 +9924,10 @@ static void sync_child_event(struct perf_event *child_event, +@@ -9914,10 +9926,10 @@ static void sync_child_event(struct perf_event *child_event, /* * Add back the child's count to the parent's count: */ @@ -151544,25 +151532,6 @@ index 5a92189..d77978d 100644 retval = 1; } spin_unlock(&lockref->lock); -diff --git a/lib/mpi/mpi-pow.c b/lib/mpi/mpi-pow.c -index 5464c87..e24388a 100644 ---- a/lib/mpi/mpi-pow.c -+++ b/lib/mpi/mpi-pow.c -@@ -64,8 +64,13 @@ int mpi_powm(MPI res, MPI base, MPI exp, MPI mod) - if (!esize) { - /* Exponent is zero, result is 1 mod MOD, i.e., 1 or 0 - * depending on if MOD equals 1. */ -- rp[0] = 1; - res->nlimbs = (msize == 1 && mod->d[0] == 1) ? 0 : 1; -+ if (res->nlimbs) { -+ if (mpi_resize(res, 1) < 0) -+ goto enomem; -+ rp = res->d; -+ rp[0] = 1; -+ } - res->sign = 0; - goto leave; - } diff --git a/lib/nlattr.c b/lib/nlattr.c index fce1e9a..d44559b 100644 --- a/lib/nlattr.c @@ -155157,7 +155126,7 @@ index f4cd7d8..982c35d 100644 struct bdi_writeback *wb = dtc->wb; unsigned long write_bw = wb->avg_write_bandwidth; diff --git a/mm/page_alloc.c b/mm/page_alloc.c -index a2214c6..72191b7 100644 +index 7401e99..a9d6624 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c @@ -64,6 +64,7 @@ @@ -158896,10 +158865,10 @@ index 1108079..1871d16 100644 }; diff --git a/net/can/bcm.c b/net/can/bcm.c -index 8af9d25..44e9458 100644 +index 436a753..4d61e73 100644 --- a/net/can/bcm.c +++ b/net/can/bcm.c -@@ -1688,7 +1688,7 @@ static int __init bcm_module_init(void) +@@ -1690,7 +1690,7 @@ static int __init bcm_module_init(void) } /* create /proc/net/can-bcm directory */ @@ -167525,10 +167494,10 @@ index 21e591d..f3a0afc 100644 + .process_negotiate = vmci_transport_notify_pkt_process_negotiate, }; diff --git a/net/wireless/scan.c b/net/wireless/scan.c -index 0358e12..db46495 100644 +index 438143a..b88cdf6 100644 --- a/net/wireless/scan.c +++ b/net/wireless/scan.c -@@ -1663,8 +1663,9 @@ static int ieee80211_scan_results(struct cfg80211_registered_device *rdev, +@@ -1732,8 +1732,9 @@ static int ieee80211_scan_results(struct cfg80211_registered_device *rdev, int cfg80211_wext_giwscan(struct net_device *dev, struct iw_request_info *info, diff --git a/4.8.11/4425_grsec_remove_EI_PAX.patch b/4.8.12/4425_grsec_remove_EI_PAX.patch index 594598a..594598a 100644 --- a/4.8.11/4425_grsec_remove_EI_PAX.patch +++ b/4.8.12/4425_grsec_remove_EI_PAX.patch diff --git a/4.8.11/4427_force_XATTR_PAX_tmpfs.patch b/4.8.12/4427_force_XATTR_PAX_tmpfs.patch index 2562d2f..2562d2f 100644 --- a/4.8.11/4427_force_XATTR_PAX_tmpfs.patch +++ b/4.8.12/4427_force_XATTR_PAX_tmpfs.patch diff --git a/4.8.11/4430_grsec-remove-localversion-grsec.patch b/4.8.12/4430_grsec-remove-localversion-grsec.patch index 31cf878..31cf878 100644 --- a/4.8.11/4430_grsec-remove-localversion-grsec.patch +++ b/4.8.12/4430_grsec-remove-localversion-grsec.patch diff --git a/4.8.11/4435_grsec-mute-warnings.patch b/4.8.12/4435_grsec-mute-warnings.patch index 8929222..8929222 100644 --- a/4.8.11/4435_grsec-mute-warnings.patch +++ b/4.8.12/4435_grsec-mute-warnings.patch diff --git a/4.8.11/4440_grsec-remove-protected-paths.patch b/4.8.12/4440_grsec-remove-protected-paths.patch index 741546d..741546d 100644 --- a/4.8.11/4440_grsec-remove-protected-paths.patch +++ b/4.8.12/4440_grsec-remove-protected-paths.patch diff --git a/4.8.11/4450_grsec-kconfig-default-gids.patch b/4.8.12/4450_grsec-kconfig-default-gids.patch index 6fd0511..6fd0511 100644 --- a/4.8.11/4450_grsec-kconfig-default-gids.patch +++ b/4.8.12/4450_grsec-kconfig-default-gids.patch diff --git a/4.8.11/4465_selinux-avc_audit-log-curr_ip.patch b/4.8.12/4465_selinux-avc_audit-log-curr_ip.patch index 7248385..7248385 100644 --- a/4.8.11/4465_selinux-avc_audit-log-curr_ip.patch +++ b/4.8.12/4465_selinux-avc_audit-log-curr_ip.patch diff --git a/4.8.11/4470_disable-compat_vdso.patch b/4.8.12/4470_disable-compat_vdso.patch index 1e4b84a..1e4b84a 100644 --- a/4.8.11/4470_disable-compat_vdso.patch +++ b/4.8.12/4470_disable-compat_vdso.patch diff --git a/4.8.11/4475_emutramp_default_on.patch b/4.8.12/4475_emutramp_default_on.patch index 7b468ee..7b468ee 100644 --- a/4.8.11/4475_emutramp_default_on.patch +++ b/4.8.12/4475_emutramp_default_on.patch |