public inbox for gentoo-commits@lists.gentoo.org
 help / color / mirror / Atom feed
* [gentoo-commits] linux-patches r2783 - genpatches-2.6/trunk/3.10
@ 2014-05-13 13:56 Mike Pagano (mpagano)
  0 siblings, 0 replies; only message in thread
From: Mike Pagano (mpagano) @ 2014-05-13 13:56 UTC (permalink / raw
  To: gentoo-commits

Author: mpagano
Date: 2014-05-13 13:56:46 +0000 (Tue, 13 May 2014)
New Revision: 2783

Added:
   genpatches-2.6/trunk/3.10/1039_linux-3.10.40.patch
Modified:
   genpatches-2.6/trunk/3.10/0000_README
Log:
Linux patch 3.10.40

Modified: genpatches-2.6/trunk/3.10/0000_README
===================================================================
--- genpatches-2.6/trunk/3.10/0000_README	2014-05-13 12:34:34 UTC (rev 2782)
+++ genpatches-2.6/trunk/3.10/0000_README	2014-05-13 13:56:46 UTC (rev 2783)
@@ -198,6 +198,10 @@
 From:   http://www.kernel.org
 Desc:   Linux 3.10.39
 
+Patch:  1039_linux-3.10.40.patch
+From:   http://www.kernel.org
+Desc:   Linux 3.10.40
+
 Patch:  1500_XATTR_USER_PREFIX.patch
 From:   https://bugs.gentoo.org/show_bug.cgi?id=470644
 Desc:   Support for namespace user.pax.* on tmpfs.

Added: genpatches-2.6/trunk/3.10/1039_linux-3.10.40.patch
===================================================================
--- genpatches-2.6/trunk/3.10/1039_linux-3.10.40.patch	                        (rev 0)
+++ genpatches-2.6/trunk/3.10/1039_linux-3.10.40.patch	2014-05-13 13:56:46 UTC (rev 2783)
@@ -0,0 +1,2267 @@
+diff --git a/Makefile b/Makefile
+index 1e07514be6f8..b2285cababb0 100644
+--- a/Makefile
++++ b/Makefile
+@@ -1,6 +1,6 @@
+ VERSION = 3
+ PATCHLEVEL = 10
+-SUBLEVEL = 39
++SUBLEVEL = 40
+ EXTRAVERSION =
+ NAME = TOSSUG Baby Fish
+ 
+diff --git a/arch/arc/include/asm/irqflags.h b/arch/arc/include/asm/irqflags.h
+index eac071668201..c29d56587bf0 100644
+--- a/arch/arc/include/asm/irqflags.h
++++ b/arch/arc/include/asm/irqflags.h
+@@ -137,13 +137,6 @@ static inline void arch_unmask_irq(unsigned int irq)
+ 	flag	\scratch
+ .endm
+ 
+-.macro IRQ_DISABLE_SAVE  scratch, save
+-	lr	\scratch, [status32]
+-	mov	\save, \scratch		/* Make a copy */
+-	bic	\scratch, \scratch, (STATUS_E1_MASK | STATUS_E2_MASK)
+-	flag	\scratch
+-.endm
+-
+ .macro IRQ_ENABLE  scratch
+ 	lr	\scratch, [status32]
+ 	or	\scratch, \scratch, (STATUS_E1_MASK | STATUS_E2_MASK)
+diff --git a/arch/arc/kernel/entry.S b/arch/arc/kernel/entry.S
+index 6dbe359c760d..6f3cd0fb4b54 100644
+--- a/arch/arc/kernel/entry.S
++++ b/arch/arc/kernel/entry.S
+@@ -589,11 +589,7 @@ ARC_ENTRY ret_from_exception
+ 	; Pre-{IRQ,Trap,Exception} K/U mode from pt_regs->status32
+ 	ld  r8, [sp, PT_status32]   ; returning to User/Kernel Mode
+ 
+-#ifdef CONFIG_PREEMPT
+ 	bbit0  r8, STATUS_U_BIT, resume_kernel_mode
+-#else
+-	bbit0  r8, STATUS_U_BIT, restore_regs
+-#endif
+ 
+ 	; Before returning to User mode check-for-and-complete any pending work
+ 	; such as rescheduling/signal-delivery etc.
+@@ -653,10 +649,15 @@ resume_user_mode_begin:
+ 	b      resume_user_mode_begin	; unconditionally back to U mode ret chks
+ 					; for single exit point from this block
+ 
+-#ifdef CONFIG_PREEMPT
+-
+ resume_kernel_mode:
+ 
++	; Disable Interrupts from this point on
++	; CONFIG_PREEMPT: This is a must for preempt_schedule_irq()
++	; !CONFIG_PREEMPT: To ensure restore_regs is intr safe
++	IRQ_DISABLE	r9
++
++#ifdef CONFIG_PREEMPT
++
+ 	; Can't preempt if preemption disabled
+ 	GET_CURR_THR_INFO_FROM_SP   r10
+ 	ld  r8, [r10, THREAD_INFO_PREEMPT_COUNT]
+@@ -666,8 +667,6 @@ resume_kernel_mode:
+ 	ld  r9, [r10, THREAD_INFO_FLAGS]
+ 	bbit0  r9, TIF_NEED_RESCHED, restore_regs
+ 
+-	IRQ_DISABLE	r9
+-
+ 	; Invoke PREEMPTION
+ 	bl      preempt_schedule_irq
+ 
+@@ -680,12 +679,11 @@ resume_kernel_mode:
+ ;
+ ; Restore the saved sys context (common exit-path for EXCPN/IRQ/Trap)
+ ; IRQ shd definitely not happen between now and rtie
++; All 2 entry points to here already disable interrupts
+ 
+ restore_regs :
+ 
+-	; Disable Interrupts while restoring reg-file back
+-	; XXX can this be optimised out
+-	IRQ_DISABLE_SAVE    r9, r10	;@r10 has prisitine (pre-disable) copy
++	lr	r10, [status32]
+ 
+ #ifdef CONFIG_ARC_CURR_IN_REG
+ 	; Restore User R25
+diff --git a/arch/arm/mm/mmap.c b/arch/arm/mm/mmap.c
+index f0ef2f7d4ad7..5ef506c6f492 100644
+--- a/arch/arm/mm/mmap.c
++++ b/arch/arm/mm/mmap.c
+@@ -204,13 +204,11 @@ int valid_phys_addr_range(phys_addr_t addr, size_t size)
+ }
+ 
+ /*
+- * We don't use supersection mappings for mmap() on /dev/mem, which
+- * means that we can't map the memory area above the 4G barrier into
+- * userspace.
++ * Do not allow /dev/mem mappings beyond the supported physical range.
+  */
+ int valid_mmap_phys_addr_range(unsigned long pfn, size_t size)
+ {
+-	return !(pfn + (size >> PAGE_SHIFT) > 0x00100000);
++	return (pfn + (size >> PAGE_SHIFT)) <= (1 + (PHYS_MASK >> PAGE_SHIFT));
+ }
+ 
+ #ifdef CONFIG_STRICT_DEVMEM
+diff --git a/arch/mips/kvm/kvm_mips_emul.c b/arch/mips/kvm/kvm_mips_emul.c
+index 4b6274b47f33..e75ef8219caf 100644
+--- a/arch/mips/kvm/kvm_mips_emul.c
++++ b/arch/mips/kvm/kvm_mips_emul.c
+@@ -1571,17 +1571,17 @@ kvm_mips_handle_ri(unsigned long cause, uint32_t *opc,
+ 			arch->gprs[rt] = kvm_read_c0_guest_userlocal(cop0);
+ #else
+ 			/* UserLocal not implemented */
+-			er = kvm_mips_emulate_ri_exc(cause, opc, run, vcpu);
++			er = EMULATE_FAIL;
+ #endif
+ 			break;
+ 
+ 		default:
+-			printk("RDHWR not supported\n");
++			kvm_debug("RDHWR %#x not supported @ %p\n", rd, opc);
+ 			er = EMULATE_FAIL;
+ 			break;
+ 		}
+ 	} else {
+-		printk("Emulate RI not supported @ %p: %#x\n", opc, inst);
++		kvm_debug("Emulate RI not supported @ %p: %#x\n", opc, inst);
+ 		er = EMULATE_FAIL;
+ 	}
+ 
+@@ -1590,6 +1590,7 @@ kvm_mips_handle_ri(unsigned long cause, uint32_t *opc,
+ 	 */
+ 	if (er == EMULATE_FAIL) {
+ 		vcpu->arch.pc = curr_pc;
++		er = kvm_mips_emulate_ri_exc(cause, opc, run, vcpu);
+ 	}
+ 	return er;
+ }
+diff --git a/arch/mips/power/hibernate.S b/arch/mips/power/hibernate.S
+index 7e0277a1048f..32a7c828f073 100644
+--- a/arch/mips/power/hibernate.S
++++ b/arch/mips/power/hibernate.S
+@@ -43,6 +43,7 @@ LEAF(swsusp_arch_resume)
+ 	bne t1, t3, 1b
+ 	PTR_L t0, PBE_NEXT(t0)
+ 	bnez t0, 0b
++	jal local_flush_tlb_all /* Avoid TLB mismatch after kernel resume */
+ 	PTR_LA t0, saved_regs
+ 	PTR_L ra, PT_R31(t0)
+ 	PTR_L sp, PT_R29(t0)
+diff --git a/arch/powerpc/include/asm/compat.h b/arch/powerpc/include/asm/compat.h
+index 84fdf6857c31..ef22898daa93 100644
+--- a/arch/powerpc/include/asm/compat.h
++++ b/arch/powerpc/include/asm/compat.h
+@@ -8,7 +8,11 @@
+ #include <linux/sched.h>
+ 
+ #define COMPAT_USER_HZ		100
++#ifdef __BIG_ENDIAN__
+ #define COMPAT_UTS_MACHINE	"ppc\0\0"
++#else
++#define COMPAT_UTS_MACHINE	"ppcle\0\0"
++#endif
+ 
+ typedef u32		compat_size_t;
+ typedef s32		compat_ssize_t;
+diff --git a/arch/powerpc/include/asm/reg.h b/arch/powerpc/include/asm/reg.h
+index e1fb161252ef..795f67792ea9 100644
+--- a/arch/powerpc/include/asm/reg.h
++++ b/arch/powerpc/include/asm/reg.h
+@@ -208,6 +208,7 @@
+ #define SPRN_ACOP	0x1F	/* Available Coprocessor Register */
+ #define SPRN_TFIAR	0x81	/* Transaction Failure Inst Addr   */
+ #define SPRN_TEXASR	0x82	/* Transaction EXception & Summary */
++#define   TEXASR_FS	__MASK(63-36)	/* Transaction Failure Summary */
+ #define SPRN_TEXASRU	0x83	/* ''	   ''	   ''	 Upper 32  */
+ #define SPRN_TFHAR	0x80	/* Transaction Failure Handler Addr */
+ #define SPRN_CTRLF	0x088
+diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c
+index 7baa27b7abbe..1e1c995ddacc 100644
+--- a/arch/powerpc/kernel/process.c
++++ b/arch/powerpc/kernel/process.c
+@@ -523,6 +523,31 @@ out_and_saveregs:
+ 	tm_save_sprs(thr);
+ }
+ 
++extern void __tm_recheckpoint(struct thread_struct *thread,
++			      unsigned long orig_msr);
++
++void tm_recheckpoint(struct thread_struct *thread,
++		     unsigned long orig_msr)
++{
++	unsigned long flags;
++
++	/* We really can't be interrupted here as the TEXASR registers can't
++	 * change and later in the trecheckpoint code, we have a userspace R1.
++	 * So let's hard disable over this region.
++	 */
++	local_irq_save(flags);
++	hard_irq_disable();
++
++	/* The TM SPRs are restored here, so that TEXASR.FS can be set
++	 * before the trecheckpoint and no explosion occurs.
++	 */
++	tm_restore_sprs(thread);
++
++	__tm_recheckpoint(thread, orig_msr);
++
++	local_irq_restore(flags);
++}
++
+ static inline void tm_recheckpoint_new_task(struct task_struct *new)
+ {
+ 	unsigned long msr;
+@@ -541,13 +566,10 @@ static inline void tm_recheckpoint_new_task(struct task_struct *new)
+ 	if (!new->thread.regs)
+ 		return;
+ 
+-	/* The TM SPRs are restored here, so that TEXASR.FS can be set
+-	 * before the trecheckpoint and no explosion occurs.
+-	 */
+-	tm_restore_sprs(&new->thread);
+-
+-	if (!MSR_TM_ACTIVE(new->thread.regs->msr))
++	if (!MSR_TM_ACTIVE(new->thread.regs->msr)){
++		tm_restore_sprs(&new->thread);
+ 		return;
++	}
+ 	msr = new->thread.tm_orig_msr;
+ 	/* Recheckpoint to restore original checkpointed register state. */
+ 	TM_DEBUG("*** tm_recheckpoint of pid %d "
+diff --git a/arch/powerpc/kernel/signal_32.c b/arch/powerpc/kernel/signal_32.c
+index 7e9dff80e1dc..81f929f026f2 100644
+--- a/arch/powerpc/kernel/signal_32.c
++++ b/arch/powerpc/kernel/signal_32.c
+@@ -863,6 +863,8 @@ static long restore_tm_user_regs(struct pt_regs *regs,
+ 	 * transactional versions should be loaded.
+ 	 */
+ 	tm_enable();
++	/* Make sure the transaction is marked as failed */
++	current->thread.tm_texasr |= TEXASR_FS;
+ 	/* This loads the checkpointed FP/VEC state, if used */
+ 	tm_recheckpoint(&current->thread, msr);
+ 	/* Get the top half of the MSR */
+diff --git a/arch/powerpc/kernel/signal_64.c b/arch/powerpc/kernel/signal_64.c
+index 35c20a1fb365..74d9615a6bb6 100644
+--- a/arch/powerpc/kernel/signal_64.c
++++ b/arch/powerpc/kernel/signal_64.c
+@@ -513,6 +513,8 @@ static long restore_tm_sigcontexts(struct pt_regs *regs,
+ 	}
+ #endif
+ 	tm_enable();
++	/* Make sure the transaction is marked as failed */
++	current->thread.tm_texasr |= TEXASR_FS;
+ 	/* This loads the checkpointed FP/VEC state, if used */
+ 	tm_recheckpoint(&current->thread, msr);
+ 
+diff --git a/arch/powerpc/kernel/tm.S b/arch/powerpc/kernel/tm.S
+index f2abb219a17b..1e43ed404b95 100644
+--- a/arch/powerpc/kernel/tm.S
++++ b/arch/powerpc/kernel/tm.S
+@@ -296,7 +296,7 @@ dont_backup_fp:
+ 	 *	Call with IRQs off, stacks get all out of sync for
+ 	 *	some periods in here!
+ 	 */
+-_GLOBAL(tm_recheckpoint)
++_GLOBAL(__tm_recheckpoint)
+ 	mfcr	r5
+ 	mflr	r0
+ 	std	r5, 8(r1)
+diff --git a/arch/s390/net/bpf_jit_comp.c b/arch/s390/net/bpf_jit_comp.c
+index 1919db6c0607..3bc6b7e43b24 100644
+--- a/arch/s390/net/bpf_jit_comp.c
++++ b/arch/s390/net/bpf_jit_comp.c
+@@ -243,7 +243,6 @@ static void bpf_jit_noleaks(struct bpf_jit *jit, struct sock_filter *filter)
+ 	case BPF_S_LD_W_IND:
+ 	case BPF_S_LD_H_IND:
+ 	case BPF_S_LD_B_IND:
+-	case BPF_S_LDX_B_MSH:
+ 	case BPF_S_LD_IMM:
+ 	case BPF_S_LD_MEM:
+ 	case BPF_S_MISC_TXA:
+diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c
+index 8b8cbe9bcb92..9cf616b5210b 100644
+--- a/drivers/ata/libata-core.c
++++ b/drivers/ata/libata-core.c
+@@ -4765,21 +4765,26 @@ void swap_buf_le16(u16 *buf, unsigned int buf_words)
+ static struct ata_queued_cmd *ata_qc_new(struct ata_port *ap)
+ {
+ 	struct ata_queued_cmd *qc = NULL;
+-	unsigned int i;
++	unsigned int i, tag;
+ 
+ 	/* no command while frozen */
+ 	if (unlikely(ap->pflags & ATA_PFLAG_FROZEN))
+ 		return NULL;
+ 
+-	/* the last tag is reserved for internal command. */
+-	for (i = 0; i < ATA_MAX_QUEUE - 1; i++)
+-		if (!test_and_set_bit(i, &ap->qc_allocated)) {
+-			qc = __ata_qc_from_tag(ap, i);
++	for (i = 0; i < ATA_MAX_QUEUE; i++) {
++		tag = (i + ap->last_tag + 1) % ATA_MAX_QUEUE;
++
++		/* the last tag is reserved for internal command. */
++		if (tag == ATA_TAG_INTERNAL)
++			continue;
++
++		if (!test_and_set_bit(tag, &ap->qc_allocated)) {
++			qc = __ata_qc_from_tag(ap, tag);
++			qc->tag = tag;
++			ap->last_tag = tag;
+ 			break;
+ 		}
+-
+-	if (qc)
+-		qc->tag = i;
++	}
+ 
+ 	return qc;
+ }
+diff --git a/drivers/block/floppy.c b/drivers/block/floppy.c
+index 04ceb7e2fadd..eb3575b3fbf0 100644
+--- a/drivers/block/floppy.c
++++ b/drivers/block/floppy.c
+@@ -3053,7 +3053,10 @@ static int raw_cmd_copyout(int cmd, void __user *param,
+ 	int ret;
+ 
+ 	while (ptr) {
+-		ret = copy_to_user(param, ptr, sizeof(*ptr));
++		struct floppy_raw_cmd cmd = *ptr;
++		cmd.next = NULL;
++		cmd.kernel_data = NULL;
++		ret = copy_to_user(param, &cmd, sizeof(cmd));
+ 		if (ret)
+ 			return -EFAULT;
+ 		param += sizeof(struct floppy_raw_cmd);
+@@ -3107,10 +3110,11 @@ loop:
+ 		return -ENOMEM;
+ 	*rcmd = ptr;
+ 	ret = copy_from_user(ptr, param, sizeof(*ptr));
+-	if (ret)
+-		return -EFAULT;
+ 	ptr->next = NULL;
+ 	ptr->buffer_length = 0;
++	ptr->kernel_data = NULL;
++	if (ret)
++		return -EFAULT;
+ 	param += sizeof(struct floppy_raw_cmd);
+ 	if (ptr->cmd_count > 33)
+ 			/* the command may now also take up the space
+@@ -3126,7 +3130,6 @@ loop:
+ 	for (i = 0; i < 16; i++)
+ 		ptr->reply[i] = 0;
+ 	ptr->resultcode = 0;
+-	ptr->kernel_data = NULL;
+ 
+ 	if (ptr->flags & (FD_RAW_READ | FD_RAW_WRITE)) {
+ 		if (ptr->length <= 0)
+diff --git a/drivers/gpio/gpio-mxs.c b/drivers/gpio/gpio-mxs.c
+index f8e6af20dfbf..d599fc42ae8b 100644
+--- a/drivers/gpio/gpio-mxs.c
++++ b/drivers/gpio/gpio-mxs.c
+@@ -214,7 +214,8 @@ static void __init mxs_gpio_init_gc(struct mxs_gpio_port *port, int irq_base)
+ 	ct->regs.ack = PINCTRL_IRQSTAT(port) + MXS_CLR;
+ 	ct->regs.mask = PINCTRL_IRQEN(port);
+ 
+-	irq_setup_generic_chip(gc, IRQ_MSK(32), 0, IRQ_NOREQUEST, 0);
++	irq_setup_generic_chip(gc, IRQ_MSK(32), IRQ_GC_INIT_NESTED_LOCK,
++			       IRQ_NOREQUEST, 0);
+ }
+ 
+ static int mxs_gpio_to_irq(struct gpio_chip *gc, unsigned offset)
+diff --git a/drivers/gpu/drm/cirrus/cirrus_drv.c b/drivers/gpu/drm/cirrus/cirrus_drv.c
+index 8ecb601152ef..64bfc235021a 100644
+--- a/drivers/gpu/drm/cirrus/cirrus_drv.c
++++ b/drivers/gpu/drm/cirrus/cirrus_drv.c
+@@ -11,6 +11,7 @@
+ #include <linux/module.h>
+ #include <linux/console.h>
+ #include <drm/drmP.h>
++#include <drm/drm_crtc_helper.h>
+ 
+ #include "cirrus_drv.h"
+ 
+@@ -75,6 +76,41 @@ static void cirrus_pci_remove(struct pci_dev *pdev)
+ 	drm_put_dev(dev);
+ }
+ 
++static int cirrus_pm_suspend(struct device *dev)
++{
++	struct pci_dev *pdev = to_pci_dev(dev);
++	struct drm_device *drm_dev = pci_get_drvdata(pdev);
++	struct cirrus_device *cdev = drm_dev->dev_private;
++
++	drm_kms_helper_poll_disable(drm_dev);
++
++	if (cdev->mode_info.gfbdev) {
++		console_lock();
++		fb_set_suspend(cdev->mode_info.gfbdev->helper.fbdev, 1);
++		console_unlock();
++	}
++
++	return 0;
++}
++
++static int cirrus_pm_resume(struct device *dev)
++{
++	struct pci_dev *pdev = to_pci_dev(dev);
++	struct drm_device *drm_dev = pci_get_drvdata(pdev);
++	struct cirrus_device *cdev = drm_dev->dev_private;
++
++	drm_helper_resume_force_mode(drm_dev);
++
++	if (cdev->mode_info.gfbdev) {
++		console_lock();
++		fb_set_suspend(cdev->mode_info.gfbdev->helper.fbdev, 0);
++		console_unlock();
++	}
++
++	drm_kms_helper_poll_enable(drm_dev);
++	return 0;
++}
++
+ static const struct file_operations cirrus_driver_fops = {
+ 	.owner = THIS_MODULE,
+ 	.open = drm_open,
+@@ -105,11 +141,17 @@ static struct drm_driver driver = {
+ 	.dumb_destroy = cirrus_dumb_destroy,
+ };
+ 
++static const struct dev_pm_ops cirrus_pm_ops = {
++	SET_SYSTEM_SLEEP_PM_OPS(cirrus_pm_suspend,
++				cirrus_pm_resume)
++};
++
+ static struct pci_driver cirrus_pci_driver = {
+ 	.name = DRIVER_NAME,
+ 	.id_table = pciidlist,
+ 	.probe = cirrus_pci_probe,
+ 	.remove = cirrus_pci_remove,
++	.driver.pm = &cirrus_pm_ops,
+ };
+ 
+ static int __init cirrus_init(void)
+diff --git a/drivers/gpu/drm/cirrus/cirrus_mode.c b/drivers/gpu/drm/cirrus/cirrus_mode.c
+index 379a47ea99f6..b86f68d8b726 100644
+--- a/drivers/gpu/drm/cirrus/cirrus_mode.c
++++ b/drivers/gpu/drm/cirrus/cirrus_mode.c
+@@ -308,6 +308,9 @@ static int cirrus_crtc_mode_set(struct drm_crtc *crtc,
+ 
+ 	WREG_HDR(hdr);
+ 	cirrus_crtc_do_set_base(crtc, old_fb, x, y, 0);
++
++	/* Unblank (needed on S3 resume, vgabios doesn't do it then) */
++	outb(0x20, 0x3c0);
+ 	return 0;
+ }
+ 
+diff --git a/drivers/gpu/drm/i915/intel_crt.c b/drivers/gpu/drm/i915/intel_crt.c
+index 58b4a53715cd..4a809969c5ac 100644
+--- a/drivers/gpu/drm/i915/intel_crt.c
++++ b/drivers/gpu/drm/i915/intel_crt.c
+@@ -717,6 +717,14 @@ static const struct dmi_system_id intel_no_crt[] = {
+ 			DMI_MATCH(DMI_PRODUCT_NAME, "ZGB"),
+ 		},
+ 	},
++	{
++		.callback = intel_no_crt_dmi_callback,
++		.ident = "DELL XPS 8700",
++		.matches = {
++			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
++			DMI_MATCH(DMI_PRODUCT_NAME, "XPS 8700"),
++		},
++	},
+ 	{ }
+ };
+ 
+diff --git a/drivers/infiniband/ulp/isert/ib_isert.c b/drivers/infiniband/ulp/isert/ib_isert.c
+index 588a5eca63d8..ce6c603a3cc9 100644
+--- a/drivers/infiniband/ulp/isert/ib_isert.c
++++ b/drivers/infiniband/ulp/isert/ib_isert.c
+@@ -1201,7 +1201,7 @@ isert_unmap_cmd(struct isert_cmd *isert_cmd, struct isert_conn *isert_conn)
+ }
+ 
+ static void
+-isert_put_cmd(struct isert_cmd *isert_cmd)
++isert_put_cmd(struct isert_cmd *isert_cmd, bool comp_err)
+ {
+ 	struct iscsi_cmd *cmd = &isert_cmd->iscsi_cmd;
+ 	struct isert_conn *isert_conn = isert_cmd->conn;
+@@ -1216,8 +1216,21 @@ isert_put_cmd(struct isert_cmd *isert_cmd)
+ 			list_del_init(&cmd->i_conn_node);
+ 		spin_unlock_bh(&conn->cmd_lock);
+ 
+-		if (cmd->data_direction == DMA_TO_DEVICE)
++		if (cmd->data_direction == DMA_TO_DEVICE) {
+ 			iscsit_stop_dataout_timer(cmd);
++			/*
++			 * Check for special case during comp_err where
++			 * WRITE_PENDING has been handed off from core,
++			 * but requires an extra target_put_sess_cmd()
++			 * before transport_generic_free_cmd() below.
++			 */
++			if (comp_err &&
++			    cmd->se_cmd.t_state == TRANSPORT_WRITE_PENDING) {
++				struct se_cmd *se_cmd = &cmd->se_cmd;
++
++				target_put_sess_cmd(se_cmd->se_sess, se_cmd);
++			}
++		}
+ 
+ 		isert_unmap_cmd(isert_cmd, isert_conn);
+ 		transport_generic_free_cmd(&cmd->se_cmd, 0);
+@@ -1271,7 +1284,7 @@ isert_unmap_tx_desc(struct iser_tx_desc *tx_desc, struct ib_device *ib_dev)
+ 
+ static void
+ isert_completion_put(struct iser_tx_desc *tx_desc, struct isert_cmd *isert_cmd,
+-		     struct ib_device *ib_dev)
++		     struct ib_device *ib_dev, bool comp_err)
+ {
+ 	if (isert_cmd->sense_buf_dma != 0) {
+ 		pr_debug("Calling ib_dma_unmap_single for isert_cmd->sense_buf_dma\n");
+@@ -1281,7 +1294,7 @@ isert_completion_put(struct iser_tx_desc *tx_desc, struct isert_cmd *isert_cmd,
+ 	}
+ 
+ 	isert_unmap_tx_desc(tx_desc, ib_dev);
+-	isert_put_cmd(isert_cmd);
++	isert_put_cmd(isert_cmd, comp_err);
+ }
+ 
+ static void
+@@ -1336,14 +1349,14 @@ isert_do_control_comp(struct work_struct *work)
+ 		iscsit_tmr_post_handler(cmd, cmd->conn);
+ 
+ 		cmd->i_state = ISTATE_SENT_STATUS;
+-		isert_completion_put(&isert_cmd->tx_desc, isert_cmd, ib_dev);
++		isert_completion_put(&isert_cmd->tx_desc, isert_cmd, ib_dev, false);
+ 		break;
+ 	case ISTATE_SEND_REJECT:
+ 		pr_debug("Got isert_do_control_comp ISTATE_SEND_REJECT: >>>\n");
+ 		atomic_dec(&isert_conn->post_send_buf_count);
+ 
+ 		cmd->i_state = ISTATE_SENT_STATUS;
+-		isert_completion_put(&isert_cmd->tx_desc, isert_cmd, ib_dev);
++		isert_completion_put(&isert_cmd->tx_desc, isert_cmd, ib_dev, false);
+ 		break;
+ 	case ISTATE_SEND_LOGOUTRSP:
+ 		pr_debug("Calling iscsit_logout_post_handler >>>>>>>>>>>>>>\n");
+@@ -1382,7 +1395,7 @@ isert_response_completion(struct iser_tx_desc *tx_desc,
+ 	atomic_sub(wr->send_wr_num + 1, &isert_conn->post_send_buf_count);
+ 
+ 	cmd->i_state = ISTATE_SENT_STATUS;
+-	isert_completion_put(tx_desc, isert_cmd, ib_dev);
++	isert_completion_put(tx_desc, isert_cmd, ib_dev, false);
+ }
+ 
+ static void
+@@ -1436,7 +1449,7 @@ isert_cq_tx_comp_err(struct iser_tx_desc *tx_desc, struct isert_conn *isert_conn
+ 	if (!isert_cmd)
+ 		isert_unmap_tx_desc(tx_desc, ib_dev);
+ 	else
+-		isert_completion_put(tx_desc, isert_cmd, ib_dev);
++		isert_completion_put(tx_desc, isert_cmd, ib_dev, true);
+ }
+ 
+ static void
+diff --git a/drivers/input/mouse/synaptics.c b/drivers/input/mouse/synaptics.c
+index c69c81608f43..d60c9b7ad1b8 100644
+--- a/drivers/input/mouse/synaptics.c
++++ b/drivers/input/mouse/synaptics.c
+@@ -1515,6 +1515,22 @@ static const struct dmi_system_id min_max_dmi_table[] __initconst = {
+ 		.driver_data = (int []){1232, 5710, 1156, 4696},
+ 	},
+ 	{
++		/* Lenovo ThinkPad Edge E431 */
++		.matches = {
++			DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
++			DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad Edge E431"),
++		},
++		.driver_data = (int []){1024, 5022, 2508, 4832},
++	},
++	{
++		/* Lenovo ThinkPad T431s */
++		.matches = {
++			DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
++			DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad T431"),
++		},
++		.driver_data = (int []){1024, 5112, 2024, 4832},
++	},
++	{
+ 		/* Lenovo ThinkPad T440s */
+ 		.matches = {
+ 			DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
+@@ -1523,6 +1539,14 @@ static const struct dmi_system_id min_max_dmi_table[] __initconst = {
+ 		.driver_data = (int []){1024, 5112, 2024, 4832},
+ 	},
+ 	{
++		/* Lenovo ThinkPad L440 */
++		.matches = {
++			DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
++			DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad L440"),
++		},
++		.driver_data = (int []){1024, 5112, 2024, 4832},
++	},
++	{
+ 		/* Lenovo ThinkPad T540p */
+ 		.matches = {
+ 			DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
+@@ -1530,6 +1554,32 @@ static const struct dmi_system_id min_max_dmi_table[] __initconst = {
+ 		},
+ 		.driver_data = (int []){1024, 5056, 2058, 4832},
+ 	},
++	{
++		/* Lenovo ThinkPad L540 */
++		.matches = {
++			DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
++			DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad L540"),
++		},
++		.driver_data = (int []){1024, 5112, 2024, 4832},
++	},
++	{
++		/* Lenovo Yoga S1 */
++		.matches = {
++			DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
++			DMI_EXACT_MATCH(DMI_PRODUCT_VERSION,
++					"ThinkPad S1 Yoga"),
++		},
++		.driver_data = (int []){1232, 5710, 1156, 4696},
++	},
++	{
++		/* Lenovo ThinkPad X1 Carbon Haswell (3rd generation) */
++		.matches = {
++			DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
++			DMI_MATCH(DMI_PRODUCT_VERSION,
++					"ThinkPad X1 Carbon 2nd"),
++		},
++		.driver_data = (int []){1024, 5112, 2024, 4832},
++	},
+ #endif
+ 	{ }
+ };
+diff --git a/drivers/md/dm-cache-metadata.c b/drivers/md/dm-cache-metadata.c
+index 1af7255bbffb..a33e07f4222e 100644
+--- a/drivers/md/dm-cache-metadata.c
++++ b/drivers/md/dm-cache-metadata.c
+@@ -511,8 +511,9 @@ static int __begin_transaction_flags(struct dm_cache_metadata *cmd,
+ 	disk_super = dm_block_data(sblock);
+ 	update_flags(disk_super, mutator);
+ 	read_superblock_fields(cmd, disk_super);
++	dm_bm_unlock(sblock);
+ 
+-	return dm_bm_flush_and_unlock(cmd->bm, sblock);
++	return dm_bm_flush(cmd->bm);
+ }
+ 
+ static int __begin_transaction(struct dm_cache_metadata *cmd)
+diff --git a/drivers/md/dm-thin.c b/drivers/md/dm-thin.c
+index 901aac27e522..7d0ac0a6e724 100644
+--- a/drivers/md/dm-thin.c
++++ b/drivers/md/dm-thin.c
+@@ -1322,9 +1322,9 @@ static void process_deferred_bios(struct pool *pool)
+ 		 */
+ 		if (ensure_next_mapping(pool)) {
+ 			spin_lock_irqsave(&pool->lock, flags);
++			bio_list_add(&pool->deferred_bios, bio);
+ 			bio_list_merge(&pool->deferred_bios, &bios);
+ 			spin_unlock_irqrestore(&pool->lock, flags);
+-
+ 			break;
+ 		}
+ 
+diff --git a/drivers/md/persistent-data/dm-block-manager.c b/drivers/md/persistent-data/dm-block-manager.c
+index 81b513890e2b..6372d0bea532 100644
+--- a/drivers/md/persistent-data/dm-block-manager.c
++++ b/drivers/md/persistent-data/dm-block-manager.c
+@@ -595,25 +595,14 @@ int dm_bm_unlock(struct dm_block *b)
+ }
+ EXPORT_SYMBOL_GPL(dm_bm_unlock);
+ 
+-int dm_bm_flush_and_unlock(struct dm_block_manager *bm,
+-			   struct dm_block *superblock)
++int dm_bm_flush(struct dm_block_manager *bm)
+ {
+-	int r;
+-
+ 	if (bm->read_only)
+ 		return -EPERM;
+ 
+-	r = dm_bufio_write_dirty_buffers(bm->bufio);
+-	if (unlikely(r)) {
+-		dm_bm_unlock(superblock);
+-		return r;
+-	}
+-
+-	dm_bm_unlock(superblock);
+-
+ 	return dm_bufio_write_dirty_buffers(bm->bufio);
+ }
+-EXPORT_SYMBOL_GPL(dm_bm_flush_and_unlock);
++EXPORT_SYMBOL_GPL(dm_bm_flush);
+ 
+ void dm_bm_set_read_only(struct dm_block_manager *bm)
+ {
+diff --git a/drivers/md/persistent-data/dm-block-manager.h b/drivers/md/persistent-data/dm-block-manager.h
+index be5bff61be28..f74c0462e5e4 100644
+--- a/drivers/md/persistent-data/dm-block-manager.h
++++ b/drivers/md/persistent-data/dm-block-manager.h
+@@ -105,8 +105,7 @@ int dm_bm_unlock(struct dm_block *b);
+  *
+  * This method always blocks.
+  */
+-int dm_bm_flush_and_unlock(struct dm_block_manager *bm,
+-			   struct dm_block *superblock);
++int dm_bm_flush(struct dm_block_manager *bm);
+ 
+ /*
+  * Switches the bm to a read only mode.  Once read-only mode
+diff --git a/drivers/md/persistent-data/dm-transaction-manager.c b/drivers/md/persistent-data/dm-transaction-manager.c
+index 81da1a26042e..3bc30a0ae3d6 100644
+--- a/drivers/md/persistent-data/dm-transaction-manager.c
++++ b/drivers/md/persistent-data/dm-transaction-manager.c
+@@ -154,7 +154,7 @@ int dm_tm_pre_commit(struct dm_transaction_manager *tm)
+ 	if (r < 0)
+ 		return r;
+ 
+-	return 0;
++	return dm_bm_flush(tm->bm);
+ }
+ EXPORT_SYMBOL_GPL(dm_tm_pre_commit);
+ 
+@@ -164,8 +164,9 @@ int dm_tm_commit(struct dm_transaction_manager *tm, struct dm_block *root)
+ 		return -EWOULDBLOCK;
+ 
+ 	wipe_shadow_table(tm);
++	dm_bm_unlock(root);
+ 
+-	return dm_bm_flush_and_unlock(tm->bm, root);
++	return dm_bm_flush(tm->bm);
+ }
+ EXPORT_SYMBOL_GPL(dm_tm_commit);
+ 
+diff --git a/drivers/md/persistent-data/dm-transaction-manager.h b/drivers/md/persistent-data/dm-transaction-manager.h
+index b5b139076ca5..2772ed2a781a 100644
+--- a/drivers/md/persistent-data/dm-transaction-manager.h
++++ b/drivers/md/persistent-data/dm-transaction-manager.h
+@@ -38,18 +38,17 @@ struct dm_transaction_manager *dm_tm_create_non_blocking_clone(struct dm_transac
+ /*
+  * We use a 2-phase commit here.
+  *
+- * i) In the first phase the block manager is told to start flushing, and
+- * the changes to the space map are written to disk.  You should interrogate
+- * your particular space map to get detail of its root node etc. to be
+- * included in your superblock.
++ * i) Make all changes for the transaction *except* for the superblock.
++ * Then call dm_tm_pre_commit() to flush them to disk.
+  *
+- * ii) @root will be committed last.  You shouldn't use more than the
+- * first 512 bytes of @root if you wish the transaction to survive a power
+- * failure.  You *must* have a write lock held on @root for both stage (i)
+- * and (ii).  The commit will drop the write lock.
++ * ii) Lock your superblock.  Update.  Then call dm_tm_commit() which will
++ * unlock the superblock and flush it.  No other blocks should be updated
++ * during this period.  Care should be taken to never unlock a partially
++ * updated superblock; perform any operations that could fail *before* you
++ * take the superblock lock.
+  */
+ int dm_tm_pre_commit(struct dm_transaction_manager *tm);
+-int dm_tm_commit(struct dm_transaction_manager *tm, struct dm_block *root);
++int dm_tm_commit(struct dm_transaction_manager *tm, struct dm_block *superblock);
+ 
+ /*
+  * These methods are the only way to get hold of a writeable block.
+diff --git a/drivers/mtd/nand/atmel_nand.c b/drivers/mtd/nand/atmel_nand.c
+index 2d23d2929438..cc69e415df35 100644
+--- a/drivers/mtd/nand/atmel_nand.c
++++ b/drivers/mtd/nand/atmel_nand.c
+@@ -1096,6 +1096,7 @@ static int __init atmel_pmecc_nand_init_params(struct platform_device *pdev,
+ 		goto err_pmecc_data_alloc;
+ 	}
+ 
++	nand_chip->options |= NAND_NO_SUBPAGE_WRITE;
+ 	nand_chip->ecc.read_page = atmel_nand_pmecc_read_page;
+ 	nand_chip->ecc.write_page = atmel_nand_pmecc_write_page;
+ 
+diff --git a/drivers/mtd/nand/nuc900_nand.c b/drivers/mtd/nand/nuc900_nand.c
+index cd6be2ed53a8..14203f3bb0cd 100644
+--- a/drivers/mtd/nand/nuc900_nand.c
++++ b/drivers/mtd/nand/nuc900_nand.c
+@@ -225,7 +225,7 @@ static void nuc900_nand_enable(struct nuc900_nand *nand)
+ 	val = __raw_readl(nand->reg + REG_FMICSR);
+ 
+ 	if (!(val & NAND_EN))
+-		__raw_writel(val | NAND_EN, REG_FMICSR);
++		__raw_writel(val | NAND_EN, nand->reg + REG_FMICSR);
+ 
+ 	val = __raw_readl(nand->reg + REG_SMCSR);
+ 
+diff --git a/drivers/mtd/sm_ftl.c b/drivers/mtd/sm_ftl.c
+index f9d5615c5727..4b55cd45287b 100644
+--- a/drivers/mtd/sm_ftl.c
++++ b/drivers/mtd/sm_ftl.c
+@@ -59,15 +59,12 @@ struct attribute_group *sm_create_sysfs_attributes(struct sm_ftl *ftl)
+ 	struct attribute_group *attr_group;
+ 	struct attribute **attributes;
+ 	struct sm_sysfs_attribute *vendor_attribute;
++	char *vendor;
+ 
+-	int vendor_len = strnlen(ftl->cis_buffer + SM_CIS_VENDOR_OFFSET,
+-					SM_SMALL_PAGE - SM_CIS_VENDOR_OFFSET);
+-
+-	char *vendor = kmalloc(vendor_len, GFP_KERNEL);
++	vendor = kstrndup(ftl->cis_buffer + SM_CIS_VENDOR_OFFSET,
++			  SM_SMALL_PAGE - SM_CIS_VENDOR_OFFSET, GFP_KERNEL);
+ 	if (!vendor)
+ 		goto error1;
+-	memcpy(vendor, ftl->cis_buffer + SM_CIS_VENDOR_OFFSET, vendor_len);
+-	vendor[vendor_len] = 0;
+ 
+ 	/* Initialize sysfs attributes */
+ 	vendor_attribute =
+@@ -78,7 +75,7 @@ struct attribute_group *sm_create_sysfs_attributes(struct sm_ftl *ftl)
+ 	sysfs_attr_init(&vendor_attribute->dev_attr.attr);
+ 
+ 	vendor_attribute->data = vendor;
+-	vendor_attribute->len = vendor_len;
++	vendor_attribute->len = strlen(vendor);
+ 	vendor_attribute->dev_attr.attr.name = "vendor";
+ 	vendor_attribute->dev_attr.attr.mode = S_IRUGO;
+ 	vendor_attribute->dev_attr.show = sm_attr_show;
+diff --git a/drivers/net/wireless/b43/phy_n.c b/drivers/net/wireless/b43/phy_n.c
+index 7c970d3ae358..80ecca3e1465 100644
+--- a/drivers/net/wireless/b43/phy_n.c
++++ b/drivers/net/wireless/b43/phy_n.c
+@@ -5175,22 +5175,22 @@ static void b43_nphy_channel_setup(struct b43_wldev *dev,
+ 	int ch = new_channel->hw_value;
+ 
+ 	u16 old_band_5ghz;
+-	u32 tmp32;
++	u16 tmp16;
+ 
+ 	old_band_5ghz =
+ 		b43_phy_read(dev, B43_NPHY_BANDCTL) & B43_NPHY_BANDCTL_5GHZ;
+ 	if (new_channel->band == IEEE80211_BAND_5GHZ && !old_band_5ghz) {
+-		tmp32 = b43_read32(dev, B43_MMIO_PSM_PHY_HDR);
+-		b43_write32(dev, B43_MMIO_PSM_PHY_HDR, tmp32 | 4);
++		tmp16 = b43_read16(dev, B43_MMIO_PSM_PHY_HDR);
++		b43_write16(dev, B43_MMIO_PSM_PHY_HDR, tmp16 | 4);
+ 		b43_phy_set(dev, B43_PHY_B_BBCFG, 0xC000);
+-		b43_write32(dev, B43_MMIO_PSM_PHY_HDR, tmp32);
++		b43_write16(dev, B43_MMIO_PSM_PHY_HDR, tmp16);
+ 		b43_phy_set(dev, B43_NPHY_BANDCTL, B43_NPHY_BANDCTL_5GHZ);
+ 	} else if (new_channel->band == IEEE80211_BAND_2GHZ && old_band_5ghz) {
+ 		b43_phy_mask(dev, B43_NPHY_BANDCTL, ~B43_NPHY_BANDCTL_5GHZ);
+-		tmp32 = b43_read32(dev, B43_MMIO_PSM_PHY_HDR);
+-		b43_write32(dev, B43_MMIO_PSM_PHY_HDR, tmp32 | 4);
++		tmp16 = b43_read16(dev, B43_MMIO_PSM_PHY_HDR);
++		b43_write16(dev, B43_MMIO_PSM_PHY_HDR, tmp16 | 4);
+ 		b43_phy_mask(dev, B43_PHY_B_BBCFG, 0x3FFF);
+-		b43_write32(dev, B43_MMIO_PSM_PHY_HDR, tmp32);
++		b43_write16(dev, B43_MMIO_PSM_PHY_HDR, tmp16);
+ 	}
+ 
+ 	b43_chantab_phy_upload(dev, e);
+diff --git a/drivers/net/wireless/iwlwifi/dvm/main.c b/drivers/net/wireless/iwlwifi/dvm/main.c
+index a8afc7bee545..c2b8e49d00d3 100644
+--- a/drivers/net/wireless/iwlwifi/dvm/main.c
++++ b/drivers/net/wireless/iwlwifi/dvm/main.c
+@@ -252,13 +252,17 @@ static void iwl_bg_bt_runtime_config(struct work_struct *work)
+ 	struct iwl_priv *priv =
+ 		container_of(work, struct iwl_priv, bt_runtime_config);
+ 
++	mutex_lock(&priv->mutex);
+ 	if (test_bit(STATUS_EXIT_PENDING, &priv->status))
+-		return;
++		goto out;
+ 
+ 	/* dont send host command if rf-kill is on */
+ 	if (!iwl_is_ready_rf(priv))
+-		return;
++		goto out;
++
+ 	iwlagn_send_advance_bt_config(priv);
++out:
++	mutex_unlock(&priv->mutex);
+ }
+ 
+ static void iwl_bg_bt_full_concurrency(struct work_struct *work)
+diff --git a/drivers/net/wireless/rtlwifi/rtl8188ee/hw.c b/drivers/net/wireless/rtlwifi/rtl8188ee/hw.c
+index e06971be7df7..f923d8c9a296 100644
+--- a/drivers/net/wireless/rtlwifi/rtl8188ee/hw.c
++++ b/drivers/net/wireless/rtlwifi/rtl8188ee/hw.c
+@@ -1025,9 +1025,20 @@ int rtl88ee_hw_init(struct ieee80211_hw *hw)
+ 	bool rtstatus = true;
+ 	int err = 0;
+ 	u8 tmp_u1b, u1byte;
++	unsigned long flags;
+ 
+ 	RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "Rtl8188EE hw init\n");
+ 	rtlpriv->rtlhal.being_init_adapter = true;
++	/* As this function can take a very long time (up to 350 ms)
++	 * and can be called with irqs disabled, reenable the irqs
++	 * to let the other devices continue being serviced.
++	 *
++	 * It is safe doing so since our own interrupts will only be enabled
++	 * in a subsequent step.
++	 */
++	local_save_flags(flags);
++	local_irq_enable();
++
+ 	rtlpriv->intf_ops->disable_aspm(hw);
+ 
+ 	tmp_u1b = rtl_read_byte(rtlpriv, REG_SYS_CLKR+1);
+@@ -1043,7 +1054,7 @@ int rtl88ee_hw_init(struct ieee80211_hw *hw)
+ 	if (rtstatus != true) {
+ 		RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, "Init MAC failed\n");
+ 		err = 1;
+-		return err;
++		goto exit;
+ 	}
+ 
+ 	err = rtl88e_download_fw(hw, false);
+@@ -1051,8 +1062,7 @@ int rtl88ee_hw_init(struct ieee80211_hw *hw)
+ 		RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING,
+ 			 "Failed to download FW. Init HW without FW now..\n");
+ 		err = 1;
+-		rtlhal->fw_ready = false;
+-		return err;
++		goto exit;
+ 	} else {
+ 		rtlhal->fw_ready = true;
+ 	}
+@@ -1135,10 +1145,12 @@ int rtl88ee_hw_init(struct ieee80211_hw *hw)
+ 	}
+ 	rtl_write_byte(rtlpriv, REG_NAV_CTRL+2,  ((30000+127)/128));
+ 	rtl88e_dm_init(hw);
++exit:
++	local_irq_restore(flags);
+ 	rtlpriv->rtlhal.being_init_adapter = false;
+ 	RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "end of Rtl8188EE hw init %x\n",
+ 		 err);
+-	return 0;
++	return err;
+ }
+ 
+ static enum version_8188e _rtl88ee_read_chip_version(struct ieee80211_hw *hw)
+diff --git a/drivers/net/wireless/rtlwifi/rtl8188ee/trx.c b/drivers/net/wireless/rtlwifi/rtl8188ee/trx.c
+index a8871d66d56a..ea4d014a2884 100644
+--- a/drivers/net/wireless/rtlwifi/rtl8188ee/trx.c
++++ b/drivers/net/wireless/rtlwifi/rtl8188ee/trx.c
+@@ -293,7 +293,7 @@ static void _rtl88ee_translate_rx_signal_stuff(struct ieee80211_hw *hw,
+ 	u8 *psaddr;
+ 	__le16 fc;
+ 	u16 type, ufc;
+-	bool match_bssid, packet_toself, packet_beacon, addr;
++	bool match_bssid, packet_toself, packet_beacon = false, addr;
+ 
+ 	tmp_buf = skb->data + pstatus->rx_drvinfo_size + pstatus->rx_bufshift;
+ 
+diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/hw.c b/drivers/net/wireless/rtlwifi/rtl8192cu/hw.c
+index 189ba124a8c6..324aa581938e 100644
+--- a/drivers/net/wireless/rtlwifi/rtl8192cu/hw.c
++++ b/drivers/net/wireless/rtlwifi/rtl8192cu/hw.c
+@@ -985,6 +985,17 @@ int rtl92cu_hw_init(struct ieee80211_hw *hw)
+ 	struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
+ 	int err = 0;
+ 	static bool iqk_initialized;
++	unsigned long flags;
++
++	/* As this function can take a very long time (up to 350 ms)
++	 * and can be called with irqs disabled, reenable the irqs
++	 * to let the other devices continue being serviced.
++	 *
++	 * It is safe doing so since our own interrupts will only be enabled
++	 * in a subsequent step.
++	 */
++	local_save_flags(flags);
++	local_irq_enable();
+ 
+ 	rtlhal->hw_type = HARDWARE_TYPE_RTL8192CU;
+ 	err = _rtl92cu_init_mac(hw);
+@@ -997,7 +1008,7 @@ int rtl92cu_hw_init(struct ieee80211_hw *hw)
+ 		RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING,
+ 			 "Failed to download FW. Init HW without FW now..\n");
+ 		err = 1;
+-		return err;
++		goto exit;
+ 	}
+ 	rtlhal->last_hmeboxnum = 0; /* h2c */
+ 	_rtl92cu_phy_param_tab_init(hw);
+@@ -1034,6 +1045,8 @@ int rtl92cu_hw_init(struct ieee80211_hw *hw)
+ 	_InitPABias(hw);
+ 	_update_mac_setting(hw);
+ 	rtl92c_dm_init(hw);
++exit:
++	local_irq_restore(flags);
+ 	return err;
+ }
+ 
+diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/hw.c b/drivers/net/wireless/rtlwifi/rtl8192se/hw.c
+index 4f461786a7eb..c471400fe8f0 100644
+--- a/drivers/net/wireless/rtlwifi/rtl8192se/hw.c
++++ b/drivers/net/wireless/rtlwifi/rtl8192se/hw.c
+@@ -955,7 +955,7 @@ int rtl92se_hw_init(struct ieee80211_hw *hw)
+ 	struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
+ 	struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
+ 	u8 tmp_byte = 0;
+-
++	unsigned long flags;
+ 	bool rtstatus = true;
+ 	u8 tmp_u1b;
+ 	int err = false;
+@@ -967,6 +967,16 @@ int rtl92se_hw_init(struct ieee80211_hw *hw)
+ 
+ 	rtlpci->being_init_adapter = true;
+ 
++	/* As this function can take a very long time (up to 350 ms)
++	 * and can be called with irqs disabled, reenable the irqs
++	 * to let the other devices continue being serviced.
++	 *
++	 * It is safe doing so since our own interrupts will only be enabled
++	 * in a subsequent step.
++	 */
++	local_save_flags(flags);
++	local_irq_enable();
++
+ 	rtlpriv->intf_ops->disable_aspm(hw);
+ 
+ 	/* 1. MAC Initialize */
+@@ -984,7 +994,8 @@ int rtl92se_hw_init(struct ieee80211_hw *hw)
+ 		RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING,
+ 			 "Failed to download FW. Init HW without FW now... "
+ 			 "Please copy FW into /lib/firmware/rtlwifi\n");
+-		return 1;
++		err = 1;
++		goto exit;
+ 	}
+ 
+ 	/* After FW download, we have to reset MAC register */
+@@ -997,7 +1008,8 @@ int rtl92se_hw_init(struct ieee80211_hw *hw)
+ 	/* 3. Initialize MAC/PHY Config by MACPHY_reg.txt */
+ 	if (!rtl92s_phy_mac_config(hw)) {
+ 		RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, "MAC Config failed\n");
+-		return rtstatus;
++		err = rtstatus;
++		goto exit;
+ 	}
+ 
+ 	/* because last function modify RCR, so we update
+@@ -1016,7 +1028,8 @@ int rtl92se_hw_init(struct ieee80211_hw *hw)
+ 	/* 4. Initialize BB After MAC Config PHY_reg.txt, AGC_Tab.txt */
+ 	if (!rtl92s_phy_bb_config(hw)) {
+ 		RT_TRACE(rtlpriv, COMP_INIT, DBG_EMERG, "BB Config failed\n");
+-		return rtstatus;
++		err = rtstatus;
++		goto exit;
+ 	}
+ 
+ 	/* 5. Initiailze RF RAIO_A.txt RF RAIO_B.txt */
+@@ -1033,7 +1046,8 @@ int rtl92se_hw_init(struct ieee80211_hw *hw)
+ 
+ 	if (!rtl92s_phy_rf_config(hw)) {
+ 		RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "RF Config failed\n");
+-		return rtstatus;
++		err = rtstatus;
++		goto exit;
+ 	}
+ 
+ 	/* After read predefined TXT, we must set BB/MAC/RF
+@@ -1122,8 +1136,9 @@ int rtl92se_hw_init(struct ieee80211_hw *hw)
+ 
+ 	rtlpriv->cfg->ops->led_control(hw, LED_CTL_POWER_ON);
+ 	rtl92s_dm_init(hw);
++exit:
++	local_irq_restore(flags);
+ 	rtlpci->being_init_adapter = false;
+-
+ 	return err;
+ }
+ 
+diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/trx.c b/drivers/net/wireless/rtlwifi/rtl8192se/trx.c
+index 7d0f2e20f1a2..c240b7591cf0 100644
+--- a/drivers/net/wireless/rtlwifi/rtl8192se/trx.c
++++ b/drivers/net/wireless/rtlwifi/rtl8192se/trx.c
+@@ -49,6 +49,12 @@ static u8 _rtl92se_map_hwqueue_to_fwqueue(struct sk_buff *skb,	u8 skb_queue)
+ 	if (ieee80211_is_nullfunc(fc))
+ 		return QSLT_HIGH;
+ 
++	/* Kernel commit 1bf4bbb4024dcdab changed EAPOL packets to use
++	 * queue V0 at priority 7; however, the RTL8192SE appears to have
++	 * that queue at priority 6
++	 */
++	if (skb->priority == 7)
++		return QSLT_VO;
+ 	return skb->priority;
+ }
+ 
+diff --git a/drivers/net/wireless/rtlwifi/rtl8723ae/hw.c b/drivers/net/wireless/rtlwifi/rtl8723ae/hw.c
+index c333dfd116b8..99f6bc5fa986 100644
+--- a/drivers/net/wireless/rtlwifi/rtl8723ae/hw.c
++++ b/drivers/net/wireless/rtlwifi/rtl8723ae/hw.c
+@@ -880,14 +880,25 @@ int rtl8723ae_hw_init(struct ieee80211_hw *hw)
+ 	bool rtstatus = true;
+ 	int err;
+ 	u8 tmp_u1b;
++	unsigned long flags;
+ 
+ 	rtlpriv->rtlhal.being_init_adapter = true;
++	/* As this function can take a very long time (up to 350 ms)
++	 * and can be called with irqs disabled, reenable the irqs
++	 * to let the other devices continue being serviced.
++	 *
++	 * It is safe doing so since our own interrupts will only be enabled
++	 * in a subsequent step.
++	 */
++	local_save_flags(flags);
++	local_irq_enable();
++
+ 	rtlpriv->intf_ops->disable_aspm(hw);
+ 	rtstatus = _rtl8712e_init_mac(hw);
+ 	if (rtstatus != true) {
+ 		RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, "Init MAC failed\n");
+ 		err = 1;
+-		return err;
++		goto exit;
+ 	}
+ 
+ 	err = rtl8723ae_download_fw(hw);
+@@ -895,8 +906,7 @@ int rtl8723ae_hw_init(struct ieee80211_hw *hw)
+ 		RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING,
+ 			 "Failed to download FW. Init HW without FW now..\n");
+ 		err = 1;
+-		rtlhal->fw_ready = false;
+-		return err;
++		goto exit;
+ 	} else {
+ 		rtlhal->fw_ready = true;
+ 	}
+@@ -971,6 +981,8 @@ int rtl8723ae_hw_init(struct ieee80211_hw *hw)
+ 		RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, "under 1.5V\n");
+ 	}
+ 	rtl8723ae_dm_init(hw);
++exit:
++	local_irq_restore(flags);
+ 	rtlpriv->rtlhal.being_init_adapter = false;
+ 	return err;
+ }
+diff --git a/drivers/s390/cio/chsc.c b/drivers/s390/cio/chsc.c
+index 8ea7d9b2c671..815e290a1afb 100644
+--- a/drivers/s390/cio/chsc.c
++++ b/drivers/s390/cio/chsc.c
+@@ -500,18 +500,27 @@ static void chsc_process_sei_nt0(struct chsc_sei_nt0_area *sei_area)
+ 
+ static void chsc_process_event_information(struct chsc_sei *sei, u64 ntsm)
+ {
+-	do {
++	static int ntsm_unsupported;
++
++	while (true) {
+ 		memset(sei, 0, sizeof(*sei));
+ 		sei->request.length = 0x0010;
+ 		sei->request.code = 0x000e;
+-		sei->ntsm = ntsm;
++		if (!ntsm_unsupported)
++			sei->ntsm = ntsm;
+ 
+ 		if (chsc(sei))
+ 			break;
+ 
+ 		if (sei->response.code != 0x0001) {
+-			CIO_CRW_EVENT(2, "chsc: sei failed (rc=%04x)\n",
+-				      sei->response.code);
++			CIO_CRW_EVENT(2, "chsc: sei failed (rc=%04x, ntsm=%llx)\n",
++				      sei->response.code, sei->ntsm);
++
++			if (sei->response.code == 3 && sei->ntsm) {
++				/* Fallback for old firmware. */
++				ntsm_unsupported = 1;
++				continue;
++			}
+ 			break;
+ 		}
+ 
+@@ -527,7 +536,10 @@ static void chsc_process_event_information(struct chsc_sei *sei, u64 ntsm)
+ 			CIO_CRW_EVENT(2, "chsc: unhandled nt: %d\n", sei->nt);
+ 			break;
+ 		}
+-	} while (sei->u.nt0_area.flags & 0x80);
++
++		if (!(sei->u.nt0_area.flags & 0x80))
++			break;
++	}
+ }
+ 
+ /*
+diff --git a/drivers/scsi/mpt2sas/mpt2sas_scsih.c b/drivers/scsi/mpt2sas/mpt2sas_scsih.c
+index 8dbe500c935d..fe76185cd79a 100644
+--- a/drivers/scsi/mpt2sas/mpt2sas_scsih.c
++++ b/drivers/scsi/mpt2sas/mpt2sas_scsih.c
+@@ -8174,7 +8174,6 @@ _scsih_suspend(struct pci_dev *pdev, pm_message_t state)
+ 
+ 	mpt2sas_base_free_resources(ioc);
+ 	pci_save_state(pdev);
+-	pci_disable_device(pdev);
+ 	pci_set_power_state(pdev, device_state);
+ 	return 0;
+ }
+diff --git a/drivers/scsi/virtio_scsi.c b/drivers/scsi/virtio_scsi.c
+index b26f1a5cc0ec..95a5d73e675c 100644
+--- a/drivers/scsi/virtio_scsi.c
++++ b/drivers/scsi/virtio_scsi.c
+@@ -751,8 +751,12 @@ static void __virtscsi_set_affinity(struct virtio_scsi *vscsi, bool affinity)
+ 
+ 		vscsi->affinity_hint_set = true;
+ 	} else {
+-		for (i = 0; i < vscsi->num_queues; i++)
++		for (i = 0; i < vscsi->num_queues; i++) {
++			if (!vscsi->req_vqs[i].vq)
++				continue;
++
+ 			virtqueue_set_affinity(vscsi->req_vqs[i].vq, -1);
++		}
+ 
+ 		vscsi->affinity_hint_set = false;
+ 	}
+diff --git a/drivers/tty/hvc/hvc_console.c b/drivers/tty/hvc/hvc_console.c
+index a2a2645b296c..f179033eaa3e 100644
+--- a/drivers/tty/hvc/hvc_console.c
++++ b/drivers/tty/hvc/hvc_console.c
+@@ -190,7 +190,7 @@ static struct tty_driver *hvc_console_device(struct console *c, int *index)
+ 	return hvc_driver;
+ }
+ 
+-static int __init hvc_console_setup(struct console *co, char *options)
++static int hvc_console_setup(struct console *co, char *options)
+ {	
+ 	if (co->index < 0 || co->index >= MAX_NR_HVC_CONSOLES)
+ 		return -ENODEV;
+diff --git a/drivers/tty/n_tty.c b/drivers/tty/n_tty.c
+index 6c7fe90ad72d..6cfe4019abc6 100644
+--- a/drivers/tty/n_tty.c
++++ b/drivers/tty/n_tty.c
+@@ -2066,8 +2066,12 @@ static ssize_t n_tty_write(struct tty_struct *tty, struct file *file,
+ 			if (tty->ops->flush_chars)
+ 				tty->ops->flush_chars(tty);
+ 		} else {
++			struct n_tty_data *ldata = tty->disc_data;
++
+ 			while (nr > 0) {
++				mutex_lock(&ldata->output_lock);
+ 				c = tty->ops->write(tty, b, nr);
++				mutex_unlock(&ldata->output_lock);
+ 				if (c < 0) {
+ 					retval = c;
+ 					goto break_out;
+diff --git a/drivers/tty/serial/8250/8250_core.c b/drivers/tty/serial/8250/8250_core.c
+index d28d7afc128a..b167665b7de2 100644
+--- a/drivers/tty/serial/8250/8250_core.c
++++ b/drivers/tty/serial/8250/8250_core.c
+@@ -555,7 +555,7 @@ static void serial8250_set_sleep(struct uart_8250_port *p, int sleep)
+ 	 */
+ 	if ((p->port.type == PORT_XR17V35X) ||
+ 	   (p->port.type == PORT_XR17D15X)) {
+-		serial_out(p, UART_EXAR_SLEEP, 0xff);
++		serial_out(p, UART_EXAR_SLEEP, sleep ? 0xff : 0);
+ 		return;
+ 	}
+ 
+diff --git a/drivers/video/aty/mach64_accel.c b/drivers/video/aty/mach64_accel.c
+index e45833ce975b..182bd680141f 100644
+--- a/drivers/video/aty/mach64_accel.c
++++ b/drivers/video/aty/mach64_accel.c
+@@ -4,6 +4,7 @@
+  */
+ 
+ #include <linux/delay.h>
++#include <asm/unaligned.h>
+ #include <linux/fb.h>
+ #include <video/mach64.h>
+ #include "atyfb.h"
+@@ -419,7 +420,7 @@ void atyfb_imageblit(struct fb_info *info, const struct fb_image *image)
+ 		u32 *pbitmap, dwords = (src_bytes + 3) / 4;
+ 		for (pbitmap = (u32*)(image->data); dwords; dwords--, pbitmap++) {
+ 			wait_for_fifo(1, par);
+-			aty_st_le32(HOST_DATA0, le32_to_cpup(pbitmap), par);
++			aty_st_le32(HOST_DATA0, get_unaligned_le32(pbitmap), par);
+ 		}
+ 	}
+ 
+diff --git a/drivers/video/aty/mach64_cursor.c b/drivers/video/aty/mach64_cursor.c
+index 95ec042ddbf8..0fe02e22d9a4 100644
+--- a/drivers/video/aty/mach64_cursor.c
++++ b/drivers/video/aty/mach64_cursor.c
+@@ -5,6 +5,7 @@
+ #include <linux/fb.h>
+ #include <linux/init.h>
+ #include <linux/string.h>
++#include "../fb_draw.h"
+ 
+ #include <asm/io.h>
+ 
+@@ -157,24 +158,33 @@ static int atyfb_cursor(struct fb_info *info, struct fb_cursor *cursor)
+ 
+ 	    for (i = 0; i < height; i++) {
+ 		for (j = 0; j < width; j++) {
++			u16 l = 0xaaaa;
+ 			b = *src++;
+ 			m = *msk++;
+ 			switch (cursor->rop) {
+ 			case ROP_XOR:
+ 			    // Upper 4 bits of mask data
+-			    fb_writeb(cursor_bits_lookup[(b ^ m) >> 4], dst++);
++			    l = cursor_bits_lookup[(b ^ m) >> 4] |
+ 			    // Lower 4 bits of mask
+-			    fb_writeb(cursor_bits_lookup[(b ^ m) & 0x0f],
+-				      dst++);
++				    (cursor_bits_lookup[(b ^ m) & 0x0f] << 8);
+ 			    break;
+ 			case ROP_COPY:
+ 			    // Upper 4 bits of mask data
+-			    fb_writeb(cursor_bits_lookup[(b & m) >> 4], dst++);
++			    l = cursor_bits_lookup[(b & m) >> 4] |
+ 			    // Lower 4 bits of mask
+-			    fb_writeb(cursor_bits_lookup[(b & m) & 0x0f],
+-				      dst++);
++				    (cursor_bits_lookup[(b & m) & 0x0f] << 8);
+ 			    break;
+ 			}
++			/*
++			 * If cursor size is not a multiple of 8 characters
++			 * we must pad it with transparent pattern (0xaaaa).
++			 */
++			if ((j + 1) * 8 > cursor->image.width) {
++				l = comp(l, 0xaaaa,
++				    (1 << ((cursor->image.width & 7) * 2)) - 1);
++			}
++			fb_writeb(l & 0xff, dst++);
++			fb_writeb(l >> 8, dst++);
+ 		}
+ 		dst += offset;
+ 	    }
+diff --git a/drivers/video/cfbcopyarea.c b/drivers/video/cfbcopyarea.c
+index bb5a96b1645d..bcb57235fcc7 100644
+--- a/drivers/video/cfbcopyarea.c
++++ b/drivers/video/cfbcopyarea.c
+@@ -43,13 +43,22 @@
+      */
+ 
+ static void
+-bitcpy(struct fb_info *p, unsigned long __iomem *dst, int dst_idx,
+-		const unsigned long __iomem *src, int src_idx, int bits,
++bitcpy(struct fb_info *p, unsigned long __iomem *dst, unsigned dst_idx,
++		const unsigned long __iomem *src, unsigned src_idx, int bits,
+ 		unsigned n, u32 bswapmask)
+ {
+ 	unsigned long first, last;
+ 	int const shift = dst_idx-src_idx;
+-	int left, right;
++
++#if 0
++	/*
++	 * If you suspect bug in this function, compare it with this simple
++	 * memmove implementation.
++	 */
++	fb_memmove((char *)dst + ((dst_idx & (bits - 1))) / 8,
++		   (char *)src + ((src_idx & (bits - 1))) / 8, n / 8);
++	return;
++#endif
+ 
+ 	first = fb_shifted_pixels_mask_long(p, dst_idx, bswapmask);
+ 	last = ~fb_shifted_pixels_mask_long(p, (dst_idx+n) % bits, bswapmask);
+@@ -98,9 +107,8 @@ bitcpy(struct fb_info *p, unsigned long __iomem *dst, int dst_idx,
+ 		unsigned long d0, d1;
+ 		int m;
+ 
+-		right = shift & (bits - 1);
+-		left = -shift & (bits - 1);
+-		bswapmask &= shift;
++		int const left = shift & (bits - 1);
++		int const right = -shift & (bits - 1);
+ 
+ 		if (dst_idx+n <= bits) {
+ 			// Single destination word
+@@ -110,15 +118,15 @@ bitcpy(struct fb_info *p, unsigned long __iomem *dst, int dst_idx,
+ 			d0 = fb_rev_pixels_in_long(d0, bswapmask);
+ 			if (shift > 0) {
+ 				// Single source word
+-				d0 >>= right;
++				d0 <<= left;
+ 			} else if (src_idx+n <= bits) {
+ 				// Single source word
+-				d0 <<= left;
++				d0 >>= right;
+ 			} else {
+ 				// 2 source words
+ 				d1 = FB_READL(src + 1);
+ 				d1 = fb_rev_pixels_in_long(d1, bswapmask);
+-				d0 = d0<<left | d1>>right;
++				d0 = d0 >> right | d1 << left;
+ 			}
+ 			d0 = fb_rev_pixels_in_long(d0, bswapmask);
+ 			FB_WRITEL(comp(d0, FB_READL(dst), first), dst);
+@@ -135,60 +143,59 @@ bitcpy(struct fb_info *p, unsigned long __iomem *dst, int dst_idx,
+ 			if (shift > 0) {
+ 				// Single source word
+ 				d1 = d0;
+-				d0 >>= right;
+-				dst++;
++				d0 <<= left;
+ 				n -= bits - dst_idx;
+ 			} else {
+ 				// 2 source words
+ 				d1 = FB_READL(src++);
+ 				d1 = fb_rev_pixels_in_long(d1, bswapmask);
+ 
+-				d0 = d0<<left | d1>>right;
+-				dst++;
++				d0 = d0 >> right | d1 << left;
+ 				n -= bits - dst_idx;
+ 			}
+ 			d0 = fb_rev_pixels_in_long(d0, bswapmask);
+ 			FB_WRITEL(comp(d0, FB_READL(dst), first), dst);
+ 			d0 = d1;
++			dst++;
+ 
+ 			// Main chunk
+ 			m = n % bits;
+ 			n /= bits;
+ 			while ((n >= 4) && !bswapmask) {
+ 				d1 = FB_READL(src++);
+-				FB_WRITEL(d0 << left | d1 >> right, dst++);
++				FB_WRITEL(d0 >> right | d1 << left, dst++);
+ 				d0 = d1;
+ 				d1 = FB_READL(src++);
+-				FB_WRITEL(d0 << left | d1 >> right, dst++);
++				FB_WRITEL(d0 >> right | d1 << left, dst++);
+ 				d0 = d1;
+ 				d1 = FB_READL(src++);
+-				FB_WRITEL(d0 << left | d1 >> right, dst++);
++				FB_WRITEL(d0 >> right | d1 << left, dst++);
+ 				d0 = d1;
+ 				d1 = FB_READL(src++);
+-				FB_WRITEL(d0 << left | d1 >> right, dst++);
++				FB_WRITEL(d0 >> right | d1 << left, dst++);
+ 				d0 = d1;
+ 				n -= 4;
+ 			}
+ 			while (n--) {
+ 				d1 = FB_READL(src++);
+ 				d1 = fb_rev_pixels_in_long(d1, bswapmask);
+-				d0 = d0 << left | d1 >> right;
++				d0 = d0 >> right | d1 << left;
+ 				d0 = fb_rev_pixels_in_long(d0, bswapmask);
+ 				FB_WRITEL(d0, dst++);
+ 				d0 = d1;
+ 			}
+ 
+ 			// Trailing bits
+-			if (last) {
+-				if (m <= right) {
++			if (m) {
++				if (m <= bits - right) {
+ 					// Single source word
+-					d0 <<= left;
++					d0 >>= right;
+ 				} else {
+ 					// 2 source words
+ 					d1 = FB_READL(src);
+ 					d1 = fb_rev_pixels_in_long(d1,
+ 								bswapmask);
+-					d0 = d0<<left | d1>>right;
++					d0 = d0 >> right | d1 << left;
+ 				}
+ 				d0 = fb_rev_pixels_in_long(d0, bswapmask);
+ 				FB_WRITEL(comp(d0, FB_READL(dst), last), dst);
+@@ -202,43 +209,46 @@ bitcpy(struct fb_info *p, unsigned long __iomem *dst, int dst_idx,
+      */
+ 
+ static void
+-bitcpy_rev(struct fb_info *p, unsigned long __iomem *dst, int dst_idx,
+-		const unsigned long __iomem *src, int src_idx, int bits,
++bitcpy_rev(struct fb_info *p, unsigned long __iomem *dst, unsigned dst_idx,
++		const unsigned long __iomem *src, unsigned src_idx, int bits,
+ 		unsigned n, u32 bswapmask)
+ {
+ 	unsigned long first, last;
+ 	int shift;
+ 
+-	dst += (n-1)/bits;
+-	src += (n-1)/bits;
+-	if ((n-1) % bits) {
+-		dst_idx += (n-1) % bits;
+-		dst += dst_idx >> (ffs(bits) - 1);
+-		dst_idx &= bits - 1;
+-		src_idx += (n-1) % bits;
+-		src += src_idx >> (ffs(bits) - 1);
+-		src_idx &= bits - 1;
+-	}
++#if 0
++	/*
++	 * If you suspect bug in this function, compare it with this simple
++	 * memmove implementation.
++	 */
++	fb_memmove((char *)dst + ((dst_idx & (bits - 1))) / 8,
++		   (char *)src + ((src_idx & (bits - 1))) / 8, n / 8);
++	return;
++#endif
++
++	dst += (dst_idx + n - 1) / bits;
++	src += (src_idx + n - 1) / bits;
++	dst_idx = (dst_idx + n - 1) % bits;
++	src_idx = (src_idx + n - 1) % bits;
+ 
+ 	shift = dst_idx-src_idx;
+ 
+-	first = fb_shifted_pixels_mask_long(p, bits - 1 - dst_idx, bswapmask);
+-	last = ~fb_shifted_pixels_mask_long(p, bits - 1 - ((dst_idx-n) % bits),
+-					    bswapmask);
++	first = ~fb_shifted_pixels_mask_long(p, (dst_idx + 1) % bits, bswapmask);
++	last = fb_shifted_pixels_mask_long(p, (bits + dst_idx + 1 - n) % bits, bswapmask);
+ 
+ 	if (!shift) {
+ 		// Same alignment for source and dest
+ 
+ 		if ((unsigned long)dst_idx+1 >= n) {
+ 			// Single word
+-			if (last)
+-				first &= last;
+-			FB_WRITEL( comp( FB_READL(src), FB_READL(dst), first), dst);
++			if (first)
++				last &= first;
++			FB_WRITEL( comp( FB_READL(src), FB_READL(dst), last), dst);
+ 		} else {
+ 			// Multiple destination words
+ 
+ 			// Leading bits
+-			if (first != ~0UL) {
++			if (first) {
+ 				FB_WRITEL( comp( FB_READL(src), FB_READL(dst), first), dst);
+ 				dst--;
+ 				src--;
+@@ -262,7 +272,7 @@ bitcpy_rev(struct fb_info *p, unsigned long __iomem *dst, int dst_idx,
+ 				FB_WRITEL(FB_READL(src--), dst--);
+ 
+ 			// Trailing bits
+-			if (last)
++			if (last != -1UL)
+ 				FB_WRITEL( comp( FB_READL(src), FB_READL(dst), last), dst);
+ 		}
+ 	} else {
+@@ -270,29 +280,28 @@ bitcpy_rev(struct fb_info *p, unsigned long __iomem *dst, int dst_idx,
+ 		unsigned long d0, d1;
+ 		int m;
+ 
+-		int const left = -shift & (bits-1);
+-		int const right = shift & (bits-1);
+-		bswapmask &= shift;
++		int const left = shift & (bits-1);
++		int const right = -shift & (bits-1);
+ 
+ 		if ((unsigned long)dst_idx+1 >= n) {
+ 			// Single destination word
+-			if (last)
+-				first &= last;
++			if (first)
++				last &= first;
+ 			d0 = FB_READL(src);
+ 			if (shift < 0) {
+ 				// Single source word
+-				d0 <<= left;
++				d0 >>= right;
+ 			} else if (1+(unsigned long)src_idx >= n) {
+ 				// Single source word
+-				d0 >>= right;
++				d0 <<= left;
+ 			} else {
+ 				// 2 source words
+ 				d1 = FB_READL(src - 1);
+ 				d1 = fb_rev_pixels_in_long(d1, bswapmask);
+-				d0 = d0>>right | d1<<left;
++				d0 = d0 << left | d1 >> right;
+ 			}
+ 			d0 = fb_rev_pixels_in_long(d0, bswapmask);
+-			FB_WRITEL(comp(d0, FB_READL(dst), first), dst);
++			FB_WRITEL(comp(d0, FB_READL(dst), last), dst);
+ 		} else {
+ 			// Multiple destination words
+ 			/** We must always remember the last value read, because in case
+@@ -307,12 +316,12 @@ bitcpy_rev(struct fb_info *p, unsigned long __iomem *dst, int dst_idx,
+ 			if (shift < 0) {
+ 				// Single source word
+ 				d1 = d0;
+-				d0 <<= left;
++				d0 >>= right;
+ 			} else {
+ 				// 2 source words
+ 				d1 = FB_READL(src--);
+ 				d1 = fb_rev_pixels_in_long(d1, bswapmask);
+-				d0 = d0>>right | d1<<left;
++				d0 = d0 << left | d1 >> right;
+ 			}
+ 			d0 = fb_rev_pixels_in_long(d0, bswapmask);
+ 			FB_WRITEL(comp(d0, FB_READL(dst), first), dst);
+@@ -325,39 +334,39 @@ bitcpy_rev(struct fb_info *p, unsigned long __iomem *dst, int dst_idx,
+ 			n /= bits;
+ 			while ((n >= 4) && !bswapmask) {
+ 				d1 = FB_READL(src--);
+-				FB_WRITEL(d0 >> right | d1 << left, dst--);
++				FB_WRITEL(d0 << left | d1 >> right, dst--);
+ 				d0 = d1;
+ 				d1 = FB_READL(src--);
+-				FB_WRITEL(d0 >> right | d1 << left, dst--);
++				FB_WRITEL(d0 << left | d1 >> right, dst--);
+ 				d0 = d1;
+ 				d1 = FB_READL(src--);
+-				FB_WRITEL(d0 >> right | d1 << left, dst--);
++				FB_WRITEL(d0 << left | d1 >> right, dst--);
+ 				d0 = d1;
+ 				d1 = FB_READL(src--);
+-				FB_WRITEL(d0 >> right | d1 << left, dst--);
++				FB_WRITEL(d0 << left | d1 >> right, dst--);
+ 				d0 = d1;
+ 				n -= 4;
+ 			}
+ 			while (n--) {
+ 				d1 = FB_READL(src--);
+ 				d1 = fb_rev_pixels_in_long(d1, bswapmask);
+-				d0 = d0 >> right | d1 << left;
++				d0 = d0 << left | d1 >> right;
+ 				d0 = fb_rev_pixels_in_long(d0, bswapmask);
+ 				FB_WRITEL(d0, dst--);
+ 				d0 = d1;
+ 			}
+ 
+ 			// Trailing bits
+-			if (last) {
+-				if (m <= left) {
++			if (m) {
++				if (m <= bits - left) {
+ 					// Single source word
+-					d0 >>= right;
++					d0 <<= left;
+ 				} else {
+ 					// 2 source words
+ 					d1 = FB_READL(src);
+ 					d1 = fb_rev_pixels_in_long(d1,
+ 								bswapmask);
+-					d0 = d0>>right | d1<<left;
++					d0 = d0 << left | d1 >> right;
+ 				}
+ 				d0 = fb_rev_pixels_in_long(d0, bswapmask);
+ 				FB_WRITEL(comp(d0, FB_READL(dst), last), dst);
+@@ -371,9 +380,9 @@ void cfb_copyarea(struct fb_info *p, const struct fb_copyarea *area)
+ 	u32 dx = area->dx, dy = area->dy, sx = area->sx, sy = area->sy;
+ 	u32 height = area->height, width = area->width;
+ 	unsigned long const bits_per_line = p->fix.line_length*8u;
+-	unsigned long __iomem *dst = NULL, *src = NULL;
++	unsigned long __iomem *base = NULL;
+ 	int bits = BITS_PER_LONG, bytes = bits >> 3;
+-	int dst_idx = 0, src_idx = 0, rev_copy = 0;
++	unsigned dst_idx = 0, src_idx = 0, rev_copy = 0;
+ 	u32 bswapmask = fb_compute_bswapmask(p);
+ 
+ 	if (p->state != FBINFO_STATE_RUNNING)
+@@ -389,7 +398,7 @@ void cfb_copyarea(struct fb_info *p, const struct fb_copyarea *area)
+ 
+ 	// split the base of the framebuffer into a long-aligned address and the
+ 	// index of the first bit
+-	dst = src = (unsigned long __iomem *)((unsigned long)p->screen_base & ~(bytes-1));
++	base = (unsigned long __iomem *)((unsigned long)p->screen_base & ~(bytes-1));
+ 	dst_idx = src_idx = 8*((unsigned long)p->screen_base & (bytes-1));
+ 	// add offset of source and target area
+ 	dst_idx += dy*bits_per_line + dx*p->var.bits_per_pixel;
+@@ -402,20 +411,14 @@ void cfb_copyarea(struct fb_info *p, const struct fb_copyarea *area)
+ 		while (height--) {
+ 			dst_idx -= bits_per_line;
+ 			src_idx -= bits_per_line;
+-			dst += dst_idx >> (ffs(bits) - 1);
+-			dst_idx &= (bytes - 1);
+-			src += src_idx >> (ffs(bits) - 1);
+-			src_idx &= (bytes - 1);
+-			bitcpy_rev(p, dst, dst_idx, src, src_idx, bits,
++			bitcpy_rev(p, base + (dst_idx / bits), dst_idx % bits,
++				base + (src_idx / bits), src_idx % bits, bits,
+ 				width*p->var.bits_per_pixel, bswapmask);
+ 		}
+ 	} else {
+ 		while (height--) {
+-			dst += dst_idx >> (ffs(bits) - 1);
+-			dst_idx &= (bytes - 1);
+-			src += src_idx >> (ffs(bits) - 1);
+-			src_idx &= (bytes - 1);
+-			bitcpy(p, dst, dst_idx, src, src_idx, bits,
++			bitcpy(p, base + (dst_idx / bits), dst_idx % bits,
++				base + (src_idx / bits), src_idx % bits, bits,
+ 				width*p->var.bits_per_pixel, bswapmask);
+ 			dst_idx += bits_per_line;
+ 			src_idx += bits_per_line;
+diff --git a/drivers/video/matrox/matroxfb_accel.c b/drivers/video/matrox/matroxfb_accel.c
+index 8335a6fe303e..0d5cb85d071a 100644
+--- a/drivers/video/matrox/matroxfb_accel.c
++++ b/drivers/video/matrox/matroxfb_accel.c
+@@ -192,10 +192,18 @@ void matrox_cfbX_init(struct matrox_fb_info *minfo)
+ 	minfo->accel.m_dwg_rect = M_DWG_TRAP | M_DWG_SOLID | M_DWG_ARZERO | M_DWG_SGNZERO | M_DWG_SHIFTZERO;
+ 	if (isMilleniumII(minfo)) minfo->accel.m_dwg_rect |= M_DWG_TRANSC;
+ 	minfo->accel.m_opmode = mopmode;
++	minfo->accel.m_access = maccess;
++	minfo->accel.m_pitch = mpitch;
+ }
+ 
+ EXPORT_SYMBOL(matrox_cfbX_init);
+ 
++static void matrox_accel_restore_maccess(struct matrox_fb_info *minfo)
++{
++	mga_outl(M_MACCESS, minfo->accel.m_access);
++	mga_outl(M_PITCH, minfo->accel.m_pitch);
++}
++
+ static void matrox_accel_bmove(struct matrox_fb_info *minfo, int vxres, int sy,
+ 			       int sx, int dy, int dx, int height, int width)
+ {
+@@ -207,7 +215,8 @@ static void matrox_accel_bmove(struct matrox_fb_info *minfo, int vxres, int sy,
+ 	CRITBEGIN
+ 
+ 	if ((dy < sy) || ((dy == sy) && (dx <= sx))) {
+-		mga_fifo(2);
++		mga_fifo(4);
++		matrox_accel_restore_maccess(minfo);
+ 		mga_outl(M_DWGCTL, M_DWG_BITBLT | M_DWG_SHIFTZERO | M_DWG_SGNZERO |
+ 			 M_DWG_BFCOL | M_DWG_REPLACE);
+ 		mga_outl(M_AR5, vxres);
+@@ -215,7 +224,8 @@ static void matrox_accel_bmove(struct matrox_fb_info *minfo, int vxres, int sy,
+ 		start = sy*vxres+sx+curr_ydstorg(minfo);
+ 		end = start+width;
+ 	} else {
+-		mga_fifo(3);
++		mga_fifo(5);
++		matrox_accel_restore_maccess(minfo);
+ 		mga_outl(M_DWGCTL, M_DWG_BITBLT | M_DWG_SHIFTZERO | M_DWG_BFCOL | M_DWG_REPLACE);
+ 		mga_outl(M_SGN, 5);
+ 		mga_outl(M_AR5, -vxres);
+@@ -224,7 +234,8 @@ static void matrox_accel_bmove(struct matrox_fb_info *minfo, int vxres, int sy,
+ 		start = end+width;
+ 		dy += height-1;
+ 	}
+-	mga_fifo(4);
++	mga_fifo(6);
++	matrox_accel_restore_maccess(minfo);
+ 	mga_outl(M_AR0, end);
+ 	mga_outl(M_AR3, start);
+ 	mga_outl(M_FXBNDRY, ((dx+width)<<16) | dx);
+@@ -246,7 +257,8 @@ static void matrox_accel_bmove_lin(struct matrox_fb_info *minfo, int vxres,
+ 	CRITBEGIN
+ 
+ 	if ((dy < sy) || ((dy == sy) && (dx <= sx))) {
+-		mga_fifo(2);
++		mga_fifo(4);
++		matrox_accel_restore_maccess(minfo);
+ 		mga_outl(M_DWGCTL, M_DWG_BITBLT | M_DWG_SHIFTZERO | M_DWG_SGNZERO |
+ 			M_DWG_BFCOL | M_DWG_REPLACE);
+ 		mga_outl(M_AR5, vxres);
+@@ -254,7 +266,8 @@ static void matrox_accel_bmove_lin(struct matrox_fb_info *minfo, int vxres,
+ 		start = sy*vxres+sx+curr_ydstorg(minfo);
+ 		end = start+width;
+ 	} else {
+-		mga_fifo(3);
++		mga_fifo(5);
++		matrox_accel_restore_maccess(minfo);
+ 		mga_outl(M_DWGCTL, M_DWG_BITBLT | M_DWG_SHIFTZERO | M_DWG_BFCOL | M_DWG_REPLACE);
+ 		mga_outl(M_SGN, 5);
+ 		mga_outl(M_AR5, -vxres);
+@@ -263,7 +276,8 @@ static void matrox_accel_bmove_lin(struct matrox_fb_info *minfo, int vxres,
+ 		start = end+width;
+ 		dy += height-1;
+ 	}
+-	mga_fifo(5);
++	mga_fifo(7);
++	matrox_accel_restore_maccess(minfo);
+ 	mga_outl(M_AR0, end);
+ 	mga_outl(M_AR3, start);
+ 	mga_outl(M_FXBNDRY, ((dx+width)<<16) | dx);
+@@ -298,7 +312,8 @@ static void matroxfb_accel_clear(struct matrox_fb_info *minfo, u_int32_t color,
+ 
+ 	CRITBEGIN
+ 
+-	mga_fifo(5);
++	mga_fifo(7);
++	matrox_accel_restore_maccess(minfo);
+ 	mga_outl(M_DWGCTL, minfo->accel.m_dwg_rect | M_DWG_REPLACE);
+ 	mga_outl(M_FCOL, color);
+ 	mga_outl(M_FXBNDRY, ((sx + width) << 16) | sx);
+@@ -341,7 +356,8 @@ static void matroxfb_cfb4_clear(struct matrox_fb_info *minfo, u_int32_t bgx,
+ 	width >>= 1;
+ 	sx >>= 1;
+ 	if (width) {
+-		mga_fifo(5);
++		mga_fifo(7);
++		matrox_accel_restore_maccess(minfo);
+ 		mga_outl(M_DWGCTL, minfo->accel.m_dwg_rect | M_DWG_REPLACE2);
+ 		mga_outl(M_FCOL, bgx);
+ 		mga_outl(M_FXBNDRY, ((sx + width) << 16) | sx);
+@@ -415,7 +431,8 @@ static void matroxfb_1bpp_imageblit(struct matrox_fb_info *minfo, u_int32_t fgx,
+ 
+ 	CRITBEGIN
+ 
+-	mga_fifo(3);
++	mga_fifo(5);
++	matrox_accel_restore_maccess(minfo);
+ 	if (easy)
+ 		mga_outl(M_DWGCTL, M_DWG_ILOAD | M_DWG_SGNZERO | M_DWG_SHIFTZERO | M_DWG_BMONOWF | M_DWG_LINEAR | M_DWG_REPLACE);
+ 	else
+@@ -425,7 +442,8 @@ static void matroxfb_1bpp_imageblit(struct matrox_fb_info *minfo, u_int32_t fgx,
+ 	fxbndry = ((xx + width - 1) << 16) | xx;
+ 	mmio = minfo->mmio.vbase;
+ 
+-	mga_fifo(6);
++	mga_fifo(8);
++	matrox_accel_restore_maccess(minfo);
+ 	mga_writel(mmio, M_FXBNDRY, fxbndry);
+ 	mga_writel(mmio, M_AR0, ar0);
+ 	mga_writel(mmio, M_AR3, 0);
+diff --git a/drivers/video/matrox/matroxfb_base.h b/drivers/video/matrox/matroxfb_base.h
+index 11ed57bb704e..556d96ce40bf 100644
+--- a/drivers/video/matrox/matroxfb_base.h
++++ b/drivers/video/matrox/matroxfb_base.h
+@@ -307,6 +307,8 @@ struct matrox_accel_data {
+ #endif
+ 	u_int32_t	m_dwg_rect;
+ 	u_int32_t	m_opmode;
++	u_int32_t	m_access;
++	u_int32_t	m_pitch;
+ };
+ 
+ struct v4l2_queryctrl;
+diff --git a/drivers/video/tgafb.c b/drivers/video/tgafb.c
+index c9c8e5a1fdee..ba77f753649c 100644
+--- a/drivers/video/tgafb.c
++++ b/drivers/video/tgafb.c
+@@ -1142,222 +1142,57 @@ copyarea_line_32bpp(struct fb_info *info, u32 dy, u32 sy,
+ 	__raw_writel(TGA_MODE_SBM_24BPP|TGA_MODE_SIMPLE, tga_regs+TGA_MODE_REG);
+ }
+ 
+-/* The general case of forward copy in 8bpp mode.  */
++/* The (almost) general case of backward copy in 8bpp mode.  */
+ static inline void
+-copyarea_foreward_8bpp(struct fb_info *info, u32 dx, u32 dy, u32 sx, u32 sy,
+-		       u32 height, u32 width, u32 line_length)
++copyarea_8bpp(struct fb_info *info, u32 dx, u32 dy, u32 sx, u32 sy,
++	      u32 height, u32 width, u32 line_length,
++	      const struct fb_copyarea *area)
+ {
+ 	struct tga_par *par = (struct tga_par *) info->par;
+-	unsigned long i, copied, left;
+-	unsigned long dpos, spos, dalign, salign, yincr;
+-	u32 smask_first, dmask_first, dmask_last;
+-	int pixel_shift, need_prime, need_second;
+-	unsigned long n64, n32, xincr_first;
++	unsigned i, yincr;
++	int depos, sepos, backward, last_step, step;
++	u32 mask_last;
++	unsigned n32;
+ 	void __iomem *tga_regs;
+ 	void __iomem *tga_fb;
+ 
+-	yincr = line_length;
+-	if (dy > sy) {
+-		dy += height - 1;
+-		sy += height - 1;
+-		yincr = -yincr;
+-	}
+-
+-	/* Compute the offsets and alignments in the frame buffer.
+-	   More than anything else, these control how we do copies.  */
+-	dpos = dy * line_length + dx;
+-	spos = sy * line_length + sx;
+-	dalign = dpos & 7;
+-	salign = spos & 7;
+-	dpos &= -8;
+-	spos &= -8;
+-
+-	/* Compute the value for the PIXELSHIFT register.  This controls
+-	   both non-co-aligned source and destination and copy direction.  */
+-	if (dalign >= salign)
+-		pixel_shift = dalign - salign;
+-	else
+-		pixel_shift = 8 - (salign - dalign);
+-
+-	/* Figure out if we need an additional priming step for the
+-	   residue register.  */
+-	need_prime = (salign > dalign);
+-	if (need_prime)
+-		dpos -= 8;
+-
+-	/* Begin by copying the leading unaligned destination.  Copy enough
+-	   to make the next destination address 32-byte aligned.  */
+-	copied = 32 - (dalign + (dpos & 31));
+-	if (copied == 32)
+-		copied = 0;
+-	xincr_first = (copied + 7) & -8;
+-	smask_first = dmask_first = (1ul << copied) - 1;
+-	smask_first <<= salign;
+-	dmask_first <<= dalign + need_prime*8;
+-	if (need_prime && copied > 24)
+-		copied -= 8;
+-	left = width - copied;
+-
+-	/* Care for small copies.  */
+-	if (copied > width) {
+-		u32 t;
+-		t = (1ul << width) - 1;
+-		t <<= dalign + need_prime*8;
+-		dmask_first &= t;
+-		left = 0;
+-	}
+-
+-	/* Attempt to use 64-byte copies.  This is only possible if the
+-	   source and destination are co-aligned at 64 bytes.  */
+-	n64 = need_second = 0;
+-	if ((dpos & 63) == (spos & 63)
+-	    && (height == 1 || line_length % 64 == 0)) {
+-		/* We may need a 32-byte copy to ensure 64 byte alignment.  */
+-		need_second = (dpos + xincr_first) & 63;
+-		if ((need_second & 32) != need_second)
+-			printk(KERN_ERR "tgafb: need_second wrong\n");
+-		if (left >= need_second + 64) {
+-			left -= need_second;
+-			n64 = left / 64;
+-			left %= 64;
+-		} else
+-			need_second = 0;
+-	}
+-
+-	/* Copy trailing full 32-byte sections.  This will be the main
+-	   loop if the 64 byte loop can't be used.  */
+-	n32 = left / 32;
+-	left %= 32;
+-
+-	/* Copy the trailing unaligned destination.  */
+-	dmask_last = (1ul << left) - 1;
+-
+-	tga_regs = par->tga_regs_base;
+-	tga_fb = par->tga_fb_base;
+-
+-	/* Set up the MODE and PIXELSHIFT registers.  */
+-	__raw_writel(TGA_MODE_SBM_8BPP|TGA_MODE_COPY, tga_regs+TGA_MODE_REG);
+-	__raw_writel(pixel_shift, tga_regs+TGA_PIXELSHIFT_REG);
+-	wmb();
+-
+-	for (i = 0; i < height; ++i) {
+-		unsigned long j;
+-		void __iomem *sfb;
+-		void __iomem *dfb;
+-
+-		sfb = tga_fb + spos;
+-		dfb = tga_fb + dpos;
+-		if (dmask_first) {
+-			__raw_writel(smask_first, sfb);
+-			wmb();
+-			__raw_writel(dmask_first, dfb);
+-			wmb();
+-			sfb += xincr_first;
+-			dfb += xincr_first;
+-		}
+-
+-		if (need_second) {
+-			__raw_writel(0xffffffff, sfb);
+-			wmb();
+-			__raw_writel(0xffffffff, dfb);
+-			wmb();
+-			sfb += 32;
+-			dfb += 32;
+-		}
+-
+-		if (n64 && (((unsigned long)sfb | (unsigned long)dfb) & 63))
+-			printk(KERN_ERR
+-			       "tgafb: misaligned copy64 (s:%p, d:%p)\n",
+-			       sfb, dfb);
+-
+-		for (j = 0; j < n64; ++j) {
+-			__raw_writel(sfb - tga_fb, tga_regs+TGA_COPY64_SRC);
+-			wmb();
+-			__raw_writel(dfb - tga_fb, tga_regs+TGA_COPY64_DST);
+-			wmb();
+-			sfb += 64;
+-			dfb += 64;
+-		}
+-
+-		for (j = 0; j < n32; ++j) {
+-			__raw_writel(0xffffffff, sfb);
+-			wmb();
+-			__raw_writel(0xffffffff, dfb);
+-			wmb();
+-			sfb += 32;
+-			dfb += 32;
+-		}
+-
+-		if (dmask_last) {
+-			__raw_writel(0xffffffff, sfb);
+-			wmb();
+-			__raw_writel(dmask_last, dfb);
+-			wmb();
+-		}
+-
+-		spos += yincr;
+-		dpos += yincr;
++	/* Do acceleration only if we are aligned on 8 pixels */
++	if ((dx | sx | width) & 7) {
++		cfb_copyarea(info, area);
++		return;
+ 	}
+ 
+-	/* Reset the MODE register to normal.  */
+-	__raw_writel(TGA_MODE_SBM_8BPP|TGA_MODE_SIMPLE, tga_regs+TGA_MODE_REG);
+-}
+-
+-/* The (almost) general case of backward copy in 8bpp mode.  */
+-static inline void
+-copyarea_backward_8bpp(struct fb_info *info, u32 dx, u32 dy, u32 sx, u32 sy,
+-		       u32 height, u32 width, u32 line_length,
+-		       const struct fb_copyarea *area)
+-{
+-	struct tga_par *par = (struct tga_par *) info->par;
+-	unsigned long i, left, yincr;
+-	unsigned long depos, sepos, dealign, sealign;
+-	u32 mask_first, mask_last;
+-	unsigned long n32;
+-	void __iomem *tga_regs;
+-	void __iomem *tga_fb;
+-
+ 	yincr = line_length;
+ 	if (dy > sy) {
+ 		dy += height - 1;
+ 		sy += height - 1;
+ 		yincr = -yincr;
+ 	}
++	backward = dy == sy && dx > sx && dx < sx + width;
+ 
+ 	/* Compute the offsets and alignments in the frame buffer.
+ 	   More than anything else, these control how we do copies.  */
+-	depos = dy * line_length + dx + width;
+-	sepos = sy * line_length + sx + width;
+-	dealign = depos & 7;
+-	sealign = sepos & 7;
+-
+-	/* ??? The documentation appears to be incorrect (or very
+-	   misleading) wrt how pixel shifting works in backward copy
+-	   mode, i.e. when PIXELSHIFT is negative.  I give up for now.
+-	   Do handle the common case of co-aligned backward copies,
+-	   but frob everything else back on generic code.  */
+-	if (dealign != sealign) {
+-		cfb_copyarea(info, area);
+-		return;
+-	}
+-
+-	/* We begin the copy with the trailing pixels of the
+-	   unaligned destination.  */
+-	mask_first = (1ul << dealign) - 1;
+-	left = width - dealign;
+-
+-	/* Care for small copies.  */
+-	if (dealign > width) {
+-		mask_first ^= (1ul << (dealign - width)) - 1;
+-		left = 0;
+-	}
++	depos = dy * line_length + dx;
++	sepos = sy * line_length + sx;
++	if (backward)
++		depos += width, sepos += width;
+ 
+ 	/* Next copy full words at a time.  */
+-	n32 = left / 32;
+-	left %= 32;
++	n32 = width / 32;
++	last_step = width % 32;
+ 
+ 	/* Finally copy the unaligned head of the span.  */
+-	mask_last = -1 << (32 - left);
++	mask_last = (1ul << last_step) - 1;
++
++	if (!backward) {
++		step = 32;
++		last_step = 32;
++	} else {
++		step = -32;
++		last_step = -last_step;
++		sepos -= 32;
++		depos -= 32;
++	}
+ 
+ 	tga_regs = par->tga_regs_base;
+ 	tga_fb = par->tga_fb_base;
+@@ -1374,25 +1209,33 @@ copyarea_backward_8bpp(struct fb_info *info, u32 dx, u32 dy, u32 sx, u32 sy,
+ 
+ 		sfb = tga_fb + sepos;
+ 		dfb = tga_fb + depos;
+-		if (mask_first) {
+-			__raw_writel(mask_first, sfb);
+-			wmb();
+-			__raw_writel(mask_first, dfb);
+-			wmb();
+-		}
+ 
+-		for (j = 0; j < n32; ++j) {
+-			sfb -= 32;
+-			dfb -= 32;
++		for (j = 0; j < n32; j++) {
++			if (j < 2 && j + 1 < n32 && !backward &&
++			    !(((unsigned long)sfb | (unsigned long)dfb) & 63)) {
++				do {
++					__raw_writel(sfb - tga_fb, tga_regs+TGA_COPY64_SRC);
++					wmb();
++					__raw_writel(dfb - tga_fb, tga_regs+TGA_COPY64_DST);
++					wmb();
++					sfb += 64;
++					dfb += 64;
++					j += 2;
++				} while (j + 1 < n32);
++				j--;
++				continue;
++			}
+ 			__raw_writel(0xffffffff, sfb);
+ 			wmb();
+ 			__raw_writel(0xffffffff, dfb);
+ 			wmb();
++			sfb += step;
++			dfb += step;
+ 		}
+ 
+ 		if (mask_last) {
+-			sfb -= 32;
+-			dfb -= 32;
++			sfb += last_step - step;
++			dfb += last_step - step;
+ 			__raw_writel(mask_last, sfb);
+ 			wmb();
+ 			__raw_writel(mask_last, dfb);
+@@ -1453,14 +1296,9 @@ tgafb_copyarea(struct fb_info *info, const struct fb_copyarea *area)
+ 	else if (bpp == 32)
+ 		cfb_copyarea(info, area);
+ 
+-	/* Detect overlapping source and destination that requires
+-	   a backward copy.  */
+-	else if (dy == sy && dx > sx && dx < sx + width)
+-		copyarea_backward_8bpp(info, dx, dy, sx, sy, height,
+-				       width, line_length, area);
+ 	else
+-		copyarea_foreward_8bpp(info, dx, dy, sx, sy, height,
+-				       width, line_length);
++		copyarea_8bpp(info, dx, dy, sx, sy, height,
++			      width, line_length, area);
+ }
+ 
+ 
+diff --git a/drivers/virtio/virtio_balloon.c b/drivers/virtio/virtio_balloon.c
+index 71af7b5abe01..7d7add5ceba4 100644
+--- a/drivers/virtio/virtio_balloon.c
++++ b/drivers/virtio/virtio_balloon.c
+@@ -311,6 +311,12 @@ static int balloon(void *_vballoon)
+ 		else if (diff < 0)
+ 			leak_balloon(vb, -diff);
+ 		update_balloon_size(vb);
++
++		/*
++		 * For large balloon changes, we could spend a lot of time
++		 * and always have work to do.  Be nice if preempt disabled.
++		 */
++		cond_resched();
+ 	}
+ 	return 0;
+ }
+diff --git a/fs/lockd/svc.c b/fs/lockd/svc.c
+index a2aa97d45670..d56a9904e52a 100644
+--- a/fs/lockd/svc.c
++++ b/fs/lockd/svc.c
+@@ -235,6 +235,7 @@ out_err:
+ 	if (warned++ == 0)
+ 		printk(KERN_WARNING
+ 			"lockd_up: makesock failed, error=%d\n", err);
++	svc_shutdown_net(serv, net);
+ 	return err;
+ }
+ 
+diff --git a/fs/locks.c b/fs/locks.c
+index cb424a4fed71..0274c953b07d 100644
+--- a/fs/locks.c
++++ b/fs/locks.c
+@@ -1243,11 +1243,10 @@ int __break_lease(struct inode *inode, unsigned int mode)
+ 
+ restart:
+ 	break_time = flock->fl_break_time;
+-	if (break_time != 0) {
++	if (break_time != 0)
+ 		break_time -= jiffies;
+-		if (break_time == 0)
+-			break_time++;
+-	}
++	if (break_time == 0)
++		break_time++;
+ 	locks_insert_block(flock, new_fl);
+ 	unlock_flocks();
+ 	error = wait_event_interruptible_timeout(new_fl->fl_wait,
+diff --git a/include/linux/libata.h b/include/linux/libata.h
+index f33619d8ac52..eec130af2dfa 100644
+--- a/include/linux/libata.h
++++ b/include/linux/libata.h
+@@ -772,6 +772,7 @@ struct ata_port {
+ 	unsigned long		qc_allocated;
+ 	unsigned int		qc_active;
+ 	int			nr_active_links; /* #links with active qcs */
++	unsigned int		last_tag;	/* track next tag hw expects */
+ 
+ 	struct ata_link		link;		/* host default link */
+ 	struct ata_link		*slave_link;	/* see ata_slave_link_init() */
+diff --git a/net/mac80211/main.c b/net/mac80211/main.c
+index 8a7bfc47d577..6658c5809353 100644
+--- a/net/mac80211/main.c
++++ b/net/mac80211/main.c
+@@ -157,6 +157,8 @@ static u32 ieee80211_hw_conf_chan(struct ieee80211_local *local)
+ 	list_for_each_entry_rcu(sdata, &local->interfaces, list) {
+ 		if (!rcu_access_pointer(sdata->vif.chanctx_conf))
+ 			continue;
++		if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
++			continue;
+ 		power = min(power, sdata->vif.bss_conf.txpower);
+ 	}
+ 	rcu_read_unlock();
+diff --git a/net/mac80211/offchannel.c b/net/mac80211/offchannel.c
+index acd1f71adc03..11d3f227e11e 100644
+--- a/net/mac80211/offchannel.c
++++ b/net/mac80211/offchannel.c
+@@ -355,6 +355,7 @@ void ieee80211_sw_roc_work(struct work_struct *work)
+ 		struct ieee80211_roc_work *dep;
+ 
+ 		/* start this ROC */
++		ieee80211_offchannel_stop_vifs(local);
+ 
+ 		/* switch channel etc */
+ 		ieee80211_recalc_idle(local);
+diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
+index 6d5791d735f3..d566cdba24ec 100644
+--- a/net/mac80211/tx.c
++++ b/net/mac80211/tx.c
+@@ -2711,7 +2711,7 @@ ieee80211_get_buffered_bc(struct ieee80211_hw *hw,
+ 				cpu_to_le16(IEEE80211_FCTL_MOREDATA);
+ 		}
+ 
+-		if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
++		if (sdata->vif.type == NL80211_IFTYPE_AP)
+ 			sdata = IEEE80211_DEV_TO_SUB_IF(skb->dev);
+ 		if (!ieee80211_tx_prepare(sdata, &tx, skb))
+ 			break;
+diff --git a/virt/kvm/ioapic.c b/virt/kvm/ioapic.c
+index 2d682977ce82..39dc5bc742e0 100644
+--- a/virt/kvm/ioapic.c
++++ b/virt/kvm/ioapic.c
+@@ -306,7 +306,7 @@ static int ioapic_deliver(struct kvm_ioapic *ioapic, int irq, bool line_status)
+ 		BUG_ON(ioapic->rtc_status.pending_eoi != 0);
+ 		ret = kvm_irq_delivery_to_apic(ioapic->kvm, NULL, &irqe,
+ 				ioapic->rtc_status.dest_map);
+-		ioapic->rtc_status.pending_eoi = ret;
++		ioapic->rtc_status.pending_eoi = (ret < 0 ? 0 : ret);
+ 	} else
+ 		ret = kvm_irq_delivery_to_apic(ioapic->kvm, NULL, &irqe, NULL);
+ 



^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2014-05-13 13:56 UTC | newest]

Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2014-05-13 13:56 [gentoo-commits] linux-patches r2783 - genpatches-2.6/trunk/3.10 Mike Pagano (mpagano)

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox