mirror of
https://github.com/Divested-Mobile/DivestOS-Build.git
synced 2024-12-27 08:29:31 -05:00
6949 lines
231 KiB
Diff
6949 lines
231 KiB
Diff
From 25ef22166357fa72e257db6b9e56e32f676ed7ae Mon Sep 17 00:00:00 2001
|
|
From: Tad <tad@spotco.us>
|
|
Date: Wed, 28 Oct 2015 10:27:26 -0400
|
|
Subject: [PATCH] Linux 3.4.106 -> 3.4.107
|
|
|
|
---
|
|
Documentation/kernel-parameters.txt | 1 +
|
|
Makefile | 2 +-
|
|
arch/alpha/mm/fault.c | 2 +
|
|
arch/arm/mm/proc-xscale.S | 4 +-
|
|
arch/avr32/mm/fault.c | 2 +
|
|
arch/cris/mm/fault.c | 2 +
|
|
arch/frv/mm/fault.c | 2 +
|
|
arch/ia64/mm/fault.c | 2 +
|
|
arch/m32r/mm/fault.c | 2 +
|
|
arch/m68k/mm/fault.c | 2 +
|
|
arch/microblaze/mm/fault.c | 2 +
|
|
arch/mips/kernel/irq_cpu.c | 4 +
|
|
arch/mips/kernel/smp.c | 2 +-
|
|
arch/mips/loongson/common/Makefile | 3 +-
|
|
arch/mips/mm/fault.c | 2 +
|
|
arch/mn10300/mm/fault.c | 2 +
|
|
arch/openrisc/mm/fault.c | 2 +
|
|
arch/parisc/mm/fault.c | 2 +
|
|
arch/powerpc/mm/fault.c | 6 +-
|
|
arch/powerpc/platforms/cell/spu_fault.c | 2 +-
|
|
arch/powerpc/xmon/xmon.c | 7 +-
|
|
arch/s390/mm/fault.c | 6 ++
|
|
arch/score/mm/fault.c | 2 +
|
|
arch/sh/mm/fault_32.c | 2 +
|
|
arch/sh/mm/tlbflush_64.c | 2 +
|
|
arch/sparc/mm/fault_32.c | 2 +
|
|
arch/sparc/mm/fault_64.c | 2 +
|
|
arch/tile/mm/fault.c | 2 +
|
|
arch/um/kernel/trap.c | 2 +
|
|
arch/x86/include/asm/ldt.h | 7 ++
|
|
arch/x86/include/asm/msr-index.h | 1 +
|
|
arch/x86/kernel/cpu/amd.c | 10 ++
|
|
arch/x86/kernel/cpu/mshyperv.c | 1 +
|
|
arch/x86/kernel/kprobes.c | 20 +++-
|
|
arch/x86/kernel/process_64.c | 101 +++++++++++++-----
|
|
arch/x86/kernel/tls.c | 16 +++
|
|
arch/x86/mm/fault.c | 2 +
|
|
arch/x86/mm/mmap.c | 6 +-
|
|
arch/x86/um/sys_call_table_32.c | 2 +-
|
|
arch/x86/um/sys_call_table_64.c | 2 +-
|
|
arch/x86/vdso/vma.c | 36 +++++--
|
|
arch/xtensa/mm/fault.c | 2 +
|
|
block/genhd.c | 11 +-
|
|
crypto/af_alg.c | 3 +
|
|
drivers/ata/ahci.c | 26 +++++
|
|
drivers/ata/libata-core.c | 5 +-
|
|
drivers/ata/libata-sff.c | 12 +++
|
|
drivers/ata/sata_dwc_460ex.c | 26 +++--
|
|
drivers/ata/sata_fsl.c | 2 +-
|
|
drivers/ata/sata_sil24.c | 2 +-
|
|
drivers/base/bus.c | 8 +-
|
|
drivers/base/core.c | 111 +++++++++++++++-----
|
|
drivers/block/drbd/drbd_req.c | 1 +
|
|
drivers/gpio/gpiolib.c | 147 +++++++++++++++------------
|
|
drivers/gpu/drm/i915/i915_gem.c | 14 +++
|
|
drivers/gpu/drm/i915/intel_lvds.c | 24 ++---
|
|
drivers/gpu/drm/radeon/radeon_kms.c | 2 +
|
|
drivers/gpu/drm/radeon/radeon_ttm.c | 2 +-
|
|
drivers/gpu/drm/vmwgfx/vmwgfx_fence.c | 38 ++-----
|
|
drivers/hid/hid-roccat-pyra.c | 7 ++
|
|
drivers/hv/vmbus_drv.c | 8 +-
|
|
drivers/i2c/busses/i2c-davinci.c | 8 +-
|
|
drivers/input/joystick/xpad.c | 16 ++-
|
|
drivers/input/serio/i8042-x86ia64io.h | 39 +++++++
|
|
drivers/input/serio/i8042.c | 14 +++
|
|
drivers/iommu/intel-iommu.c | 8 +-
|
|
drivers/mfd/tc6393xb.c | 13 ++-
|
|
drivers/mtd/ubi/upd.c | 10 +-
|
|
drivers/net/can/dev.c | 8 +-
|
|
drivers/net/can/usb/peak_usb/pcan_usb_core.c | 17 ++--
|
|
drivers/net/can/usb/peak_usb/pcan_usb_pro.c | 3 +-
|
|
drivers/net/wireless/ath/ath5k/qcu.c | 8 +-
|
|
drivers/net/wireless/ath/ath9k/hw.h | 4 +-
|
|
drivers/net/wireless/ath/ath9k/mac.c | 9 +-
|
|
drivers/pci/probe.c | 3 +
|
|
drivers/pci/quirks.c | 41 +++++++-
|
|
drivers/platform/x86/hp_accel.c | 1 +
|
|
drivers/regulator/core.c | 2 +
|
|
drivers/s390/char/con3215.c | 20 +++-
|
|
drivers/scsi/NCR5380.c | 12 +--
|
|
drivers/scsi/aha1740.c | 2 +-
|
|
drivers/scsi/atari_NCR5380.c | 2 +-
|
|
drivers/scsi/bnx2fc/bnx2fc_fcoe.c | 7 ++
|
|
drivers/scsi/megaraid.c | 8 +-
|
|
drivers/scsi/megaraid/megaraid_sas_base.c | 2 +-
|
|
drivers/scsi/sd.c | 5 +-
|
|
drivers/scsi/storvsc_drv.c | 7 +-
|
|
drivers/scsi/sun3_NCR5380.c | 10 +-
|
|
drivers/spi/spi-dw-mid.c | 1 -
|
|
drivers/spi/spi-dw.c | 10 +-
|
|
drivers/staging/comedi/drivers/cb_pcidas64.c | 123 +++++++++++++---------
|
|
drivers/staging/iio/events.h | 2 +-
|
|
drivers/target/iscsi/iscsi_target_util.c | 26 ++---
|
|
drivers/tty/serial/samsung.c | 4 +
|
|
drivers/usb/class/cdc-acm.c | 10 +-
|
|
drivers/usb/core/config.c | 11 ++
|
|
drivers/usb/core/quirks.c | 11 ++
|
|
drivers/usb/host/pci-quirks.c | 18 +++-
|
|
drivers/usb/host/xhci-pci.c | 2 +-
|
|
drivers/usb/host/xhci-ring.c | 43 ++------
|
|
drivers/usb/host/xhci.c | 102 ++++++++++---------
|
|
drivers/usb/host/xhci.h | 2 +-
|
|
drivers/usb/renesas_usbhs/mod_gadget.c | 3 +
|
|
drivers/usb/serial/console.c | 15 ++-
|
|
drivers/usb/serial/cp210x.c | 3 +
|
|
drivers/usb/serial/ftdi_sio.c | 33 ++++++
|
|
drivers/usb/serial/ftdi_sio_ids.h | 39 ++++++-
|
|
drivers/usb/serial/keyspan.c | 97 +++++++++++-------
|
|
drivers/usb/serial/ssu100.c | 11 +-
|
|
drivers/usb/storage/scsiglue.c | 4 +
|
|
drivers/usb/storage/unusual_devs.h | 14 +++
|
|
drivers/video/logo/logo.c | 17 +++-
|
|
drivers/virtio/virtio.c | 19 ++--
|
|
drivers/virtio/virtio_pci.c | 13 +--
|
|
fs/binfmt_elf.c | 5 +-
|
|
fs/btrfs/disk-io.c | 6 --
|
|
fs/btrfs/extent-tree.c | 10 +-
|
|
fs/ecryptfs/file.c | 12 ---
|
|
fs/ecryptfs/main.c | 16 ++-
|
|
fs/fs-writeback.c | 28 +++--
|
|
fs/isofs/rock.c | 9 ++
|
|
fs/jfs/jfs_dtree.c | 4 +-
|
|
fs/ncpfs/ioctl.c | 1 -
|
|
fs/nfsd/nfs4callback.c | 8 +-
|
|
fs/nilfs2/nilfs.h | 2 -
|
|
fs/nilfs2/segment.c | 45 +++++++-
|
|
fs/nilfs2/segment.h | 5 +
|
|
fs/notify/inode_mark.c | 17 ++--
|
|
fs/ocfs2/aops.c | 16 ++-
|
|
fs/proc/stat.c | 2 +-
|
|
fs/proc/task_mmu.c | 10 ++
|
|
fs/udf/dir.c | 3 +-
|
|
fs/udf/inode.c | 14 +++
|
|
fs/udf/namei.c | 3 +-
|
|
fs/udf/symlink.c | 57 +++++++++--
|
|
fs/udf/udfdecl.h | 3 +-
|
|
fs/udf/unicode.c | 28 ++---
|
|
include/linux/device.h | 5 +
|
|
include/linux/kernel_stat.h | 5 +
|
|
include/linux/libata.h | 1 +
|
|
include/linux/mm.h | 7 +-
|
|
include/linux/rmap.h | 10 ++
|
|
include/linux/sysfs.h | 9 ++
|
|
include/linux/time.h | 13 +++
|
|
include/linux/usb/quirks.h | 11 ++
|
|
include/linux/usb_usual.h | 4 +-
|
|
include/linux/virtio.h | 6 +-
|
|
include/linux/writeback.h | 1 -
|
|
include/net/sctp/sctp.h | 5 +
|
|
include/net/sctp/sm.h | 6 +-
|
|
include/scsi/scsi_device.h | 1 +
|
|
include/sound/ak4113.h | 2 +-
|
|
include/sound/ak4114.h | 2 +-
|
|
kernel/irq/internals.h | 8 ++
|
|
kernel/irq/irqdesc.c | 52 ++++++++++
|
|
kernel/irq/proc.c | 22 +++-
|
|
kernel/sched/rt.c | 17 +++-
|
|
kernel/time.c | 4 +
|
|
kernel/time/ntp.c | 11 ++
|
|
lib/checksum.c | 12 ++-
|
|
mm/ksm.c | 2 +-
|
|
mm/memory.c | 63 +++++++-----
|
|
mm/mmap.c | 14 ++-
|
|
mm/page-writeback.c | 43 +++-----
|
|
mm/rmap.c | 49 ++++++++-
|
|
net/caif/chnl_net.c | 1 -
|
|
net/compat.c | 7 ++
|
|
net/core/dev.c | 14 +--
|
|
net/ipv6/ip6_fib.c | 45 ++++----
|
|
net/mac80211/rx.c | 11 +-
|
|
net/netfilter/ipvs/ip_vs_core.c | 32 ++++--
|
|
net/sctp/associola.c | 3 +-
|
|
net/sctp/sm_make_chunk.c | 104 +++++++++++--------
|
|
net/sctp/sm_statefuns.c | 18 +---
|
|
net/socket.c | 3 +
|
|
net/sunrpc/svcsock.c | 27 +++--
|
|
net/wireless/nl80211.c | 9 +-
|
|
scripts/recordmcount.pl | 1 -
|
|
security/keys/encrypted-keys/encrypted.c | 5 +-
|
|
sound/core/seq/seq_dummy.c | 31 ------
|
|
sound/i2c/other/ak4113.c | 17 ++--
|
|
sound/i2c/other/ak4114.c | 18 ++--
|
|
sound/pci/hda/hda_intel.c | 14 ++-
|
|
sound/pci/hda/patch_sigmatel.c | 4 +-
|
|
sound/soc/atmel/atmel_ssc_dai.c | 18 +---
|
|
sound/soc/codecs/sgtl5000.c | 3 +
|
|
sound/soc/codecs/sigmadsp.c | 7 ++
|
|
sound/soc/codecs/wm8960.c | 2 +-
|
|
sound/usb/midi.c | 2 +
|
|
sound/usb/mixer.c | 1 +
|
|
sound/usb/mixer_maps.c | 15 ++-
|
|
191 files changed, 1862 insertions(+), 881 deletions(-)
|
|
|
|
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
|
|
index 719a853..7b6fa39 100644
|
|
--- a/Documentation/kernel-parameters.txt
|
|
+++ b/Documentation/kernel-parameters.txt
|
|
@@ -988,6 +988,7 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
|
|
i8042.notimeout [HW] Ignore timeout condition signalled by controller
|
|
i8042.reset [HW] Reset the controller during init and cleanup
|
|
i8042.unlock [HW] Unlock (ignore) the keylock
|
|
+ i8042.kbdreset [HW] Reset device connected to KBD port
|
|
|
|
i810= [HW,DRM]
|
|
|
|
diff --git a/Makefile b/Makefile
|
|
index e08bf16..9830710 100644
|
|
--- a/Makefile
|
|
+++ b/Makefile
|
|
@@ -1,6 +1,6 @@
|
|
VERSION = 3
|
|
PATCHLEVEL = 4
|
|
-SUBLEVEL = 106
|
|
+SUBLEVEL = 107
|
|
EXTRAVERSION =
|
|
NAME = Saber-toothed Squirrel
|
|
|
|
diff --git a/arch/alpha/mm/fault.c b/arch/alpha/mm/fault.c
|
|
index 5eecab1..f153733 100644
|
|
--- a/arch/alpha/mm/fault.c
|
|
+++ b/arch/alpha/mm/fault.c
|
|
@@ -149,6 +149,8 @@ do_page_fault(unsigned long address, unsigned long mmcsr,
|
|
if (unlikely(fault & VM_FAULT_ERROR)) {
|
|
if (fault & VM_FAULT_OOM)
|
|
goto out_of_memory;
|
|
+ else if (fault & VM_FAULT_SIGSEGV)
|
|
+ goto bad_area;
|
|
else if (fault & VM_FAULT_SIGBUS)
|
|
goto do_sigbus;
|
|
BUG();
|
|
diff --git a/arch/arm/mm/proc-xscale.S b/arch/arm/mm/proc-xscale.S
|
|
index e766f88..08b51b7 100644
|
|
--- a/arch/arm/mm/proc-xscale.S
|
|
+++ b/arch/arm/mm/proc-xscale.S
|
|
@@ -535,7 +535,7 @@ ENTRY(cpu_xscale_do_suspend)
|
|
mrc p15, 0, r5, c15, c1, 0 @ CP access reg
|
|
mrc p15, 0, r6, c13, c0, 0 @ PID
|
|
mrc p15, 0, r7, c3, c0, 0 @ domain ID
|
|
- mrc p15, 0, r8, c1, c1, 0 @ auxiliary control reg
|
|
+ mrc p15, 0, r8, c1, c0, 1 @ auxiliary control reg
|
|
mrc p15, 0, r9, c1, c0, 0 @ control reg
|
|
bic r4, r4, #2 @ clear frequency change bit
|
|
stmia r0, {r4 - r9} @ store cp regs
|
|
@@ -552,7 +552,7 @@ ENTRY(cpu_xscale_do_resume)
|
|
mcr p15, 0, r6, c13, c0, 0 @ PID
|
|
mcr p15, 0, r7, c3, c0, 0 @ domain ID
|
|
mcr p15, 0, r1, c2, c0, 0 @ translation table base addr
|
|
- mcr p15, 0, r8, c1, c1, 0 @ auxiliary control reg
|
|
+ mcr p15, 0, r8, c1, c0, 1 @ auxiliary control reg
|
|
mov r0, r9 @ control register
|
|
b cpu_resume_mmu
|
|
ENDPROC(cpu_xscale_do_resume)
|
|
diff --git a/arch/avr32/mm/fault.c b/arch/avr32/mm/fault.c
|
|
index f7040a1..632b649 100644
|
|
--- a/arch/avr32/mm/fault.c
|
|
+++ b/arch/avr32/mm/fault.c
|
|
@@ -136,6 +136,8 @@ asmlinkage void do_page_fault(unsigned long ecr, struct pt_regs *regs)
|
|
if (unlikely(fault & VM_FAULT_ERROR)) {
|
|
if (fault & VM_FAULT_OOM)
|
|
goto out_of_memory;
|
|
+ else if (fault & VM_FAULT_SIGSEGV)
|
|
+ goto bad_area;
|
|
else if (fault & VM_FAULT_SIGBUS)
|
|
goto do_sigbus;
|
|
BUG();
|
|
diff --git a/arch/cris/mm/fault.c b/arch/cris/mm/fault.c
|
|
index b4760d8..b07c00c 100644
|
|
--- a/arch/cris/mm/fault.c
|
|
+++ b/arch/cris/mm/fault.c
|
|
@@ -167,6 +167,8 @@ do_page_fault(unsigned long address, struct pt_regs *regs,
|
|
if (unlikely(fault & VM_FAULT_ERROR)) {
|
|
if (fault & VM_FAULT_OOM)
|
|
goto out_of_memory;
|
|
+ else if (fault & VM_FAULT_SIGSEGV)
|
|
+ goto bad_area;
|
|
else if (fault & VM_FAULT_SIGBUS)
|
|
goto do_sigbus;
|
|
BUG();
|
|
diff --git a/arch/frv/mm/fault.c b/arch/frv/mm/fault.c
|
|
index 331c1e2..8545496 100644
|
|
--- a/arch/frv/mm/fault.c
|
|
+++ b/arch/frv/mm/fault.c
|
|
@@ -166,6 +166,8 @@ asmlinkage void do_page_fault(int datammu, unsigned long esr0, unsigned long ear
|
|
if (unlikely(fault & VM_FAULT_ERROR)) {
|
|
if (fault & VM_FAULT_OOM)
|
|
goto out_of_memory;
|
|
+ else if (fault & VM_FAULT_SIGSEGV)
|
|
+ goto bad_area;
|
|
else if (fault & VM_FAULT_SIGBUS)
|
|
goto do_sigbus;
|
|
BUG();
|
|
diff --git a/arch/ia64/mm/fault.c b/arch/ia64/mm/fault.c
|
|
index 02d29c2..3c820ea 100644
|
|
--- a/arch/ia64/mm/fault.c
|
|
+++ b/arch/ia64/mm/fault.c
|
|
@@ -162,6 +162,8 @@ ia64_do_page_fault (unsigned long address, unsigned long isr, struct pt_regs *re
|
|
*/
|
|
if (fault & VM_FAULT_OOM) {
|
|
goto out_of_memory;
|
|
+ } else if (fault & VM_FAULT_SIGSEGV) {
|
|
+ goto bad_area;
|
|
} else if (fault & VM_FAULT_SIGBUS) {
|
|
signal = SIGBUS;
|
|
goto bad_area;
|
|
diff --git a/arch/m32r/mm/fault.c b/arch/m32r/mm/fault.c
|
|
index 3cdfa9c..06827fc 100644
|
|
--- a/arch/m32r/mm/fault.c
|
|
+++ b/arch/m32r/mm/fault.c
|
|
@@ -198,6 +198,8 @@ asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long error_code,
|
|
if (unlikely(fault & VM_FAULT_ERROR)) {
|
|
if (fault & VM_FAULT_OOM)
|
|
goto out_of_memory;
|
|
+ else if (fault & VM_FAULT_SIGSEGV)
|
|
+ goto bad_area;
|
|
else if (fault & VM_FAULT_SIGBUS)
|
|
goto do_sigbus;
|
|
BUG();
|
|
diff --git a/arch/m68k/mm/fault.c b/arch/m68k/mm/fault.c
|
|
index 6b020a8..8646409 100644
|
|
--- a/arch/m68k/mm/fault.c
|
|
+++ b/arch/m68k/mm/fault.c
|
|
@@ -146,6 +146,8 @@ int do_page_fault(struct pt_regs *regs, unsigned long address,
|
|
if (unlikely(fault & VM_FAULT_ERROR)) {
|
|
if (fault & VM_FAULT_OOM)
|
|
goto out_of_memory;
|
|
+ else if (fault & VM_FAULT_SIGSEGV)
|
|
+ goto map_err;
|
|
else if (fault & VM_FAULT_SIGBUS)
|
|
goto bus_err;
|
|
BUG();
|
|
diff --git a/arch/microblaze/mm/fault.c b/arch/microblaze/mm/fault.c
|
|
index c38a265..c7fe3da 100644
|
|
--- a/arch/microblaze/mm/fault.c
|
|
+++ b/arch/microblaze/mm/fault.c
|
|
@@ -214,6 +214,8 @@ void do_page_fault(struct pt_regs *regs, unsigned long address,
|
|
if (unlikely(fault & VM_FAULT_ERROR)) {
|
|
if (fault & VM_FAULT_OOM)
|
|
goto out_of_memory;
|
|
+ else if (fault & VM_FAULT_SIGSEGV)
|
|
+ goto bad_area;
|
|
else if (fault & VM_FAULT_SIGBUS)
|
|
goto do_sigbus;
|
|
BUG();
|
|
diff --git a/arch/mips/kernel/irq_cpu.c b/arch/mips/kernel/irq_cpu.c
|
|
index 972263b..0ed44be 100644
|
|
--- a/arch/mips/kernel/irq_cpu.c
|
|
+++ b/arch/mips/kernel/irq_cpu.c
|
|
@@ -55,6 +55,8 @@ static struct irq_chip mips_cpu_irq_controller = {
|
|
.irq_mask_ack = mask_mips_irq,
|
|
.irq_unmask = unmask_mips_irq,
|
|
.irq_eoi = unmask_mips_irq,
|
|
+ .irq_disable = mask_mips_irq,
|
|
+ .irq_enable = unmask_mips_irq,
|
|
};
|
|
|
|
/*
|
|
@@ -91,6 +93,8 @@ static struct irq_chip mips_mt_cpu_irq_controller = {
|
|
.irq_mask_ack = mips_mt_cpu_irq_ack,
|
|
.irq_unmask = unmask_mips_irq,
|
|
.irq_eoi = unmask_mips_irq,
|
|
+ .irq_disable = mask_mips_irq,
|
|
+ .irq_enable = unmask_mips_irq,
|
|
};
|
|
|
|
void __init mips_cpu_irq_init(void)
|
|
diff --git a/arch/mips/kernel/smp.c b/arch/mips/kernel/smp.c
|
|
index 41079b2..1a9bcc2 100644
|
|
--- a/arch/mips/kernel/smp.c
|
|
+++ b/arch/mips/kernel/smp.c
|
|
@@ -105,10 +105,10 @@ asmlinkage __cpuinit void start_secondary(void)
|
|
if ((read_c0_tcbind() & TCBIND_CURTC) == 0)
|
|
#endif /* CONFIG_MIPS_MT_SMTC */
|
|
cpu_probe();
|
|
- cpu_report();
|
|
per_cpu_trap_init();
|
|
mips_clockevent_init();
|
|
mp_ops->init_secondary();
|
|
+ cpu_report();
|
|
|
|
/*
|
|
* XXX parity protection should be folded in here when it's converted
|
|
diff --git a/arch/mips/loongson/common/Makefile b/arch/mips/loongson/common/Makefile
|
|
index e526488..ce415f7 100644
|
|
--- a/arch/mips/loongson/common/Makefile
|
|
+++ b/arch/mips/loongson/common/Makefile
|
|
@@ -10,7 +10,8 @@ obj-$(CONFIG_GENERIC_GPIO) += gpio.o
|
|
# Serial port support
|
|
#
|
|
obj-$(CONFIG_EARLY_PRINTK) += early_printk.o
|
|
-obj-$(CONFIG_SERIAL_8250) += serial.o
|
|
+loongson-serial-$(CONFIG_SERIAL_8250) := serial.o
|
|
+obj-y += $(loongson-serial-m) $(loongson-serial-y)
|
|
obj-$(CONFIG_LOONGSON_UART_BASE) += uart_base.o
|
|
obj-$(CONFIG_LOONGSON_MC146818) += rtc.o
|
|
|
|
diff --git a/arch/mips/mm/fault.c b/arch/mips/mm/fault.c
|
|
index c14f6df..5c9ba6a 100644
|
|
--- a/arch/mips/mm/fault.c
|
|
+++ b/arch/mips/mm/fault.c
|
|
@@ -155,6 +155,8 @@ asmlinkage void __kprobes do_page_fault(struct pt_regs *regs, unsigned long writ
|
|
if (unlikely(fault & VM_FAULT_ERROR)) {
|
|
if (fault & VM_FAULT_OOM)
|
|
goto out_of_memory;
|
|
+ else if (fault & VM_FAULT_SIGSEGV)
|
|
+ goto bad_area;
|
|
else if (fault & VM_FAULT_SIGBUS)
|
|
goto do_sigbus;
|
|
BUG();
|
|
diff --git a/arch/mn10300/mm/fault.c b/arch/mn10300/mm/fault.c
|
|
index 90f346f..eb411b3 100644
|
|
--- a/arch/mn10300/mm/fault.c
|
|
+++ b/arch/mn10300/mm/fault.c
|
|
@@ -255,6 +255,8 @@ asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long fault_code,
|
|
if (unlikely(fault & VM_FAULT_ERROR)) {
|
|
if (fault & VM_FAULT_OOM)
|
|
goto out_of_memory;
|
|
+ else if (fault & VM_FAULT_SIGSEGV)
|
|
+ goto bad_area;
|
|
else if (fault & VM_FAULT_SIGBUS)
|
|
goto do_sigbus;
|
|
BUG();
|
|
diff --git a/arch/openrisc/mm/fault.c b/arch/openrisc/mm/fault.c
|
|
index a5dce82..162abfb 100644
|
|
--- a/arch/openrisc/mm/fault.c
|
|
+++ b/arch/openrisc/mm/fault.c
|
|
@@ -163,6 +163,8 @@ asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long address,
|
|
if (unlikely(fault & VM_FAULT_ERROR)) {
|
|
if (fault & VM_FAULT_OOM)
|
|
goto out_of_memory;
|
|
+ else if (fault & VM_FAULT_SIGSEGV)
|
|
+ goto bad_area;
|
|
else if (fault & VM_FAULT_SIGBUS)
|
|
goto do_sigbus;
|
|
BUG();
|
|
diff --git a/arch/parisc/mm/fault.c b/arch/parisc/mm/fault.c
|
|
index 18162ce..a9b765a 100644
|
|
--- a/arch/parisc/mm/fault.c
|
|
+++ b/arch/parisc/mm/fault.c
|
|
@@ -210,6 +210,8 @@ void do_page_fault(struct pt_regs *regs, unsigned long code,
|
|
*/
|
|
if (fault & VM_FAULT_OOM)
|
|
goto out_of_memory;
|
|
+ else if (fault & VM_FAULT_SIGSEGV)
|
|
+ goto bad_area;
|
|
else if (fault & VM_FAULT_SIGBUS)
|
|
goto bad_area;
|
|
BUG();
|
|
diff --git a/arch/powerpc/mm/fault.c b/arch/powerpc/mm/fault.c
|
|
index 08ffcf5..3d30a4a 100644
|
|
--- a/arch/powerpc/mm/fault.c
|
|
+++ b/arch/powerpc/mm/fault.c
|
|
@@ -419,7 +419,11 @@ int __kprobes do_page_fault(struct pt_regs *regs, unsigned long address,
|
|
*/
|
|
fault = handle_mm_fault(mm, vma, address, flags);
|
|
if (unlikely(fault & (VM_FAULT_RETRY|VM_FAULT_ERROR))) {
|
|
- int rc = mm_fault_error(regs, address, fault);
|
|
+ int rc;
|
|
+
|
|
+ if (fault & VM_FAULT_SIGSEGV)
|
|
+ goto bad_area;
|
|
+ rc = mm_fault_error(regs, address, fault);
|
|
if (rc >= MM_FAULT_RETURN)
|
|
return rc;
|
|
}
|
|
diff --git a/arch/powerpc/platforms/cell/spu_fault.c b/arch/powerpc/platforms/cell/spu_fault.c
|
|
index 641e727..62f3e4e 100644
|
|
--- a/arch/powerpc/platforms/cell/spu_fault.c
|
|
+++ b/arch/powerpc/platforms/cell/spu_fault.c
|
|
@@ -75,7 +75,7 @@ int spu_handle_mm_fault(struct mm_struct *mm, unsigned long ea,
|
|
if (*flt & VM_FAULT_OOM) {
|
|
ret = -ENOMEM;
|
|
goto out_unlock;
|
|
- } else if (*flt & VM_FAULT_SIGBUS) {
|
|
+ } else if (*flt & (VM_FAULT_SIGBUS | VM_FAULT_SIGSEGV)) {
|
|
ret = -EFAULT;
|
|
goto out_unlock;
|
|
}
|
|
diff --git a/arch/powerpc/xmon/xmon.c b/arch/powerpc/xmon/xmon.c
|
|
index eab3492..7729c6c 100644
|
|
--- a/arch/powerpc/xmon/xmon.c
|
|
+++ b/arch/powerpc/xmon/xmon.c
|
|
@@ -285,10 +285,11 @@ static inline void disable_surveillance(void)
|
|
args.token = rtas_token("set-indicator");
|
|
if (args.token == RTAS_UNKNOWN_SERVICE)
|
|
return;
|
|
- args.nargs = 3;
|
|
- args.nret = 1;
|
|
+ args.token = cpu_to_be32(args.token);
|
|
+ args.nargs = cpu_to_be32(3);
|
|
+ args.nret = cpu_to_be32(1);
|
|
args.rets = &args.args[3];
|
|
- args.args[0] = SURVEILLANCE_TOKEN;
|
|
+ args.args[0] = cpu_to_be32(SURVEILLANCE_TOKEN);
|
|
args.args[1] = 0;
|
|
args.args[2] = 0;
|
|
enter_rtas(__pa(&args));
|
|
diff --git a/arch/s390/mm/fault.c b/arch/s390/mm/fault.c
|
|
index f2b11ee..68ba1bb 100644
|
|
--- a/arch/s390/mm/fault.c
|
|
+++ b/arch/s390/mm/fault.c
|
|
@@ -237,6 +237,12 @@ static noinline void do_fault_error(struct pt_regs *regs, int fault)
|
|
do_no_context(regs);
|
|
else
|
|
pagefault_out_of_memory();
|
|
+ } else if (fault & VM_FAULT_SIGSEGV) {
|
|
+ /* Kernel mode? Handle exceptions or die */
|
|
+ if (!user_mode(regs))
|
|
+ do_no_context(regs);
|
|
+ else
|
|
+ do_sigsegv(regs, SEGV_MAPERR);
|
|
} else if (fault & VM_FAULT_SIGBUS) {
|
|
/* Kernel mode? Handle exceptions or die */
|
|
if (!(regs->psw.mask & PSW_MASK_PSTATE))
|
|
diff --git a/arch/score/mm/fault.c b/arch/score/mm/fault.c
|
|
index 47b600e..b3744ca 100644
|
|
--- a/arch/score/mm/fault.c
|
|
+++ b/arch/score/mm/fault.c
|
|
@@ -110,6 +110,8 @@ asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long write,
|
|
if (unlikely(fault & VM_FAULT_ERROR)) {
|
|
if (fault & VM_FAULT_OOM)
|
|
goto out_of_memory;
|
|
+ else if (fault & VM_FAULT_SIGSEGV)
|
|
+ goto bad_area;
|
|
else if (fault & VM_FAULT_SIGBUS)
|
|
goto do_sigbus;
|
|
BUG();
|
|
diff --git a/arch/sh/mm/fault_32.c b/arch/sh/mm/fault_32.c
|
|
index e99b104..a491963 100644
|
|
--- a/arch/sh/mm/fault_32.c
|
|
+++ b/arch/sh/mm/fault_32.c
|
|
@@ -206,6 +206,8 @@ asmlinkage void __kprobes do_page_fault(struct pt_regs *regs,
|
|
goto out_of_memory;
|
|
else if (fault & VM_FAULT_SIGBUS)
|
|
goto do_sigbus;
|
|
+ else if (fault & VM_FAULT_SIGSEGV)
|
|
+ goto bad_area;
|
|
BUG();
|
|
}
|
|
if (fault & VM_FAULT_MAJOR) {
|
|
diff --git a/arch/sh/mm/tlbflush_64.c b/arch/sh/mm/tlbflush_64.c
|
|
index 11c5a18f..92f0df9 100644
|
|
--- a/arch/sh/mm/tlbflush_64.c
|
|
+++ b/arch/sh/mm/tlbflush_64.c
|
|
@@ -194,6 +194,8 @@ asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long writeaccess,
|
|
goto out_of_memory;
|
|
else if (fault & VM_FAULT_SIGBUS)
|
|
goto do_sigbus;
|
|
+ else if (fault & VM_FAULT_SIGSEGV)
|
|
+ goto bad_area;
|
|
BUG();
|
|
}
|
|
|
|
diff --git a/arch/sparc/mm/fault_32.c b/arch/sparc/mm/fault_32.c
|
|
index df3155a..5c6238d 100644
|
|
--- a/arch/sparc/mm/fault_32.c
|
|
+++ b/arch/sparc/mm/fault_32.c
|
|
@@ -300,6 +300,8 @@ asmlinkage void do_sparc_fault(struct pt_regs *regs, int text_fault, int write,
|
|
if (unlikely(fault & VM_FAULT_ERROR)) {
|
|
if (fault & VM_FAULT_OOM)
|
|
goto out_of_memory;
|
|
+ else if (fault & VM_FAULT_SIGSEGV)
|
|
+ goto bad_area;
|
|
else if (fault & VM_FAULT_SIGBUS)
|
|
goto do_sigbus;
|
|
BUG();
|
|
diff --git a/arch/sparc/mm/fault_64.c b/arch/sparc/mm/fault_64.c
|
|
index 1387aca..0dc7b90 100644
|
|
--- a/arch/sparc/mm/fault_64.c
|
|
+++ b/arch/sparc/mm/fault_64.c
|
|
@@ -443,6 +443,8 @@ asmlinkage void __kprobes do_sparc64_fault(struct pt_regs *regs)
|
|
if (unlikely(fault & VM_FAULT_ERROR)) {
|
|
if (fault & VM_FAULT_OOM)
|
|
goto out_of_memory;
|
|
+ else if (fault & VM_FAULT_SIGSEGV)
|
|
+ goto bad_area;
|
|
else if (fault & VM_FAULT_SIGBUS)
|
|
goto do_sigbus;
|
|
BUG();
|
|
diff --git a/arch/tile/mm/fault.c b/arch/tile/mm/fault.c
|
|
index 22e58f5..a362926 100644
|
|
--- a/arch/tile/mm/fault.c
|
|
+++ b/arch/tile/mm/fault.c
|
|
@@ -433,6 +433,8 @@ static int handle_page_fault(struct pt_regs *regs,
|
|
if (unlikely(fault & VM_FAULT_ERROR)) {
|
|
if (fault & VM_FAULT_OOM)
|
|
goto out_of_memory;
|
|
+ else if (fault & VM_FAULT_SIGSEGV)
|
|
+ goto bad_area;
|
|
else if (fault & VM_FAULT_SIGBUS)
|
|
goto do_sigbus;
|
|
BUG();
|
|
diff --git a/arch/um/kernel/trap.c b/arch/um/kernel/trap.c
|
|
index dafc947..f79ffc9 100644
|
|
--- a/arch/um/kernel/trap.c
|
|
+++ b/arch/um/kernel/trap.c
|
|
@@ -69,6 +69,8 @@ int handle_page_fault(unsigned long address, unsigned long ip,
|
|
if (unlikely(fault & VM_FAULT_ERROR)) {
|
|
if (fault & VM_FAULT_OOM) {
|
|
goto out_of_memory;
|
|
+ } else if (fault & VM_FAULT_SIGSEGV) {
|
|
+ goto out;
|
|
} else if (fault & VM_FAULT_SIGBUS) {
|
|
err = -EACCES;
|
|
goto out;
|
|
diff --git a/arch/x86/include/asm/ldt.h b/arch/x86/include/asm/ldt.h
|
|
index 46727eb..6e1aaf7 100644
|
|
--- a/arch/x86/include/asm/ldt.h
|
|
+++ b/arch/x86/include/asm/ldt.h
|
|
@@ -28,6 +28,13 @@ struct user_desc {
|
|
unsigned int seg_not_present:1;
|
|
unsigned int useable:1;
|
|
#ifdef __x86_64__
|
|
+ /*
|
|
+ * Because this bit is not present in 32-bit user code, user
|
|
+ * programs can pass uninitialized values here. Therefore, in
|
|
+ * any context in which a user_desc comes from a 32-bit program,
|
|
+ * the kernel must act as though lm == 0, regardless of the
|
|
+ * actual value.
|
|
+ */
|
|
unsigned int lm:1;
|
|
#endif
|
|
};
|
|
diff --git a/arch/x86/include/asm/msr-index.h b/arch/x86/include/asm/msr-index.h
|
|
index ccb8059..e92e1e4 100644
|
|
--- a/arch/x86/include/asm/msr-index.h
|
|
+++ b/arch/x86/include/asm/msr-index.h
|
|
@@ -130,6 +130,7 @@
|
|
#define MSR_AMD64_PATCH_LOADER 0xc0010020
|
|
#define MSR_AMD64_OSVW_ID_LENGTH 0xc0010140
|
|
#define MSR_AMD64_OSVW_STATUS 0xc0010141
|
|
+#define MSR_AMD64_LS_CFG 0xc0011020
|
|
#define MSR_AMD64_DC_CFG 0xc0011022
|
|
#define MSR_AMD64_IBSFETCHCTL 0xc0011030
|
|
#define MSR_AMD64_IBSFETCHLINAD 0xc0011031
|
|
diff --git a/arch/x86/kernel/cpu/amd.c b/arch/x86/kernel/cpu/amd.c
|
|
index a9c8a46..5beec8a 100644
|
|
--- a/arch/x86/kernel/cpu/amd.c
|
|
+++ b/arch/x86/kernel/cpu/amd.c
|
|
@@ -417,6 +417,16 @@ static void __cpuinit early_init_amd_mc(struct cpuinfo_x86 *c)
|
|
|
|
c->x86_coreid_bits = bits;
|
|
#endif
|
|
+
|
|
+ /* F16h erratum 793, CVE-2013-6885 */
|
|
+ if (c->x86 == 0x16 && c->x86_model <= 0xf) {
|
|
+ u64 val;
|
|
+
|
|
+ if (!rdmsrl_amd_safe(MSR_AMD64_LS_CFG, &val) &&
|
|
+ !(val & BIT(15)))
|
|
+ wrmsrl_amd_safe(MSR_AMD64_LS_CFG, val | BIT(15));
|
|
+ }
|
|
+
|
|
}
|
|
|
|
static void __cpuinit bsp_init_amd(struct cpuinfo_x86 *c)
|
|
diff --git a/arch/x86/kernel/cpu/mshyperv.c b/arch/x86/kernel/cpu/mshyperv.c
|
|
index 646d192..c465584 100644
|
|
--- a/arch/x86/kernel/cpu/mshyperv.c
|
|
+++ b/arch/x86/kernel/cpu/mshyperv.c
|
|
@@ -55,6 +55,7 @@ static struct clocksource hyperv_cs = {
|
|
.rating = 400, /* use this when running on Hyperv*/
|
|
.read = read_hv_clock,
|
|
.mask = CLOCKSOURCE_MASK(64),
|
|
+ .flags = CLOCK_SOURCE_IS_CONTINUOUS,
|
|
};
|
|
|
|
static void __init ms_hyperv_init_platform(void)
|
|
diff --git a/arch/x86/kernel/kprobes.c b/arch/x86/kernel/kprobes.c
|
|
index e213fc8..15d3c45 100644
|
|
--- a/arch/x86/kernel/kprobes.c
|
|
+++ b/arch/x86/kernel/kprobes.c
|
|
@@ -1003,6 +1003,15 @@ int __kprobes setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs)
|
|
regs->flags &= ~X86_EFLAGS_IF;
|
|
trace_hardirqs_off();
|
|
regs->ip = (unsigned long)(jp->entry);
|
|
+
|
|
+ /*
|
|
+ * jprobes use jprobe_return() which skips the normal return
|
|
+ * path of the function, and this messes up the accounting of the
|
|
+ * function graph tracer to get messed up.
|
|
+ *
|
|
+ * Pause function graph tracing while performing the jprobe function.
|
|
+ */
|
|
+ pause_graph_tracing();
|
|
return 1;
|
|
}
|
|
|
|
@@ -1028,24 +1037,25 @@ int __kprobes longjmp_break_handler(struct kprobe *p, struct pt_regs *regs)
|
|
struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
|
|
u8 *addr = (u8 *) (regs->ip - 1);
|
|
struct jprobe *jp = container_of(p, struct jprobe, kp);
|
|
+ void *saved_sp = kcb->jprobe_saved_sp;
|
|
|
|
if ((addr > (u8 *) jprobe_return) &&
|
|
(addr < (u8 *) jprobe_return_end)) {
|
|
- if (stack_addr(regs) != kcb->jprobe_saved_sp) {
|
|
+ if (stack_addr(regs) != saved_sp) {
|
|
struct pt_regs *saved_regs = &kcb->jprobe_saved_regs;
|
|
printk(KERN_ERR
|
|
"current sp %p does not match saved sp %p\n",
|
|
- stack_addr(regs), kcb->jprobe_saved_sp);
|
|
+ stack_addr(regs), saved_sp);
|
|
printk(KERN_ERR "Saved registers for jprobe %p\n", jp);
|
|
show_registers(saved_regs);
|
|
printk(KERN_ERR "Current registers\n");
|
|
show_registers(regs);
|
|
BUG();
|
|
}
|
|
+ /* It's OK to start function graph tracing again */
|
|
+ unpause_graph_tracing();
|
|
*regs = kcb->jprobe_saved_regs;
|
|
- memcpy((kprobe_opcode_t *)(kcb->jprobe_saved_sp),
|
|
- kcb->jprobes_stack,
|
|
- MIN_STACK_SIZE(kcb->jprobe_saved_sp));
|
|
+ memcpy(saved_sp, kcb->jprobes_stack, MIN_STACK_SIZE(saved_sp));
|
|
preempt_enable_no_resched();
|
|
return 1;
|
|
}
|
|
diff --git a/arch/x86/kernel/process_64.c b/arch/x86/kernel/process_64.c
|
|
index 43d8b48..bb390e1 100644
|
|
--- a/arch/x86/kernel/process_64.c
|
|
+++ b/arch/x86/kernel/process_64.c
|
|
@@ -286,24 +286,9 @@ __switch_to(struct task_struct *prev_p, struct task_struct *next_p)
|
|
|
|
fpu = switch_fpu_prepare(prev_p, next_p, cpu);
|
|
|
|
- /*
|
|
- * Reload esp0, LDT and the page table pointer:
|
|
- */
|
|
+ /* Reload esp0 and ss1. */
|
|
load_sp0(tss, next);
|
|
|
|
- /*
|
|
- * Switch DS and ES.
|
|
- * This won't pick up thread selector changes, but I guess that is ok.
|
|
- */
|
|
- savesegment(es, prev->es);
|
|
- if (unlikely(next->es | prev->es))
|
|
- loadsegment(es, next->es);
|
|
-
|
|
- savesegment(ds, prev->ds);
|
|
- if (unlikely(next->ds | prev->ds))
|
|
- loadsegment(ds, next->ds);
|
|
-
|
|
-
|
|
/* We must save %fs and %gs before load_TLS() because
|
|
* %fs and %gs may be cleared by load_TLS().
|
|
*
|
|
@@ -312,41 +297,101 @@ __switch_to(struct task_struct *prev_p, struct task_struct *next_p)
|
|
savesegment(fs, fsindex);
|
|
savesegment(gs, gsindex);
|
|
|
|
+ /*
|
|
+ * Load TLS before restoring any segments so that segment loads
|
|
+ * reference the correct GDT entries.
|
|
+ */
|
|
load_TLS(next, cpu);
|
|
|
|
/*
|
|
- * Leave lazy mode, flushing any hypercalls made here.
|
|
- * This must be done before restoring TLS segments so
|
|
- * the GDT and LDT are properly updated, and must be
|
|
- * done before math_state_restore, so the TS bit is up
|
|
- * to date.
|
|
+ * Leave lazy mode, flushing any hypercalls made here. This
|
|
+ * must be done after loading TLS entries in the GDT but before
|
|
+ * loading segments that might reference them, and and it must
|
|
+ * be done before math_state_restore, so the TS bit is up to
|
|
+ * date.
|
|
*/
|
|
arch_end_context_switch(next_p);
|
|
|
|
+ /* Switch DS and ES.
|
|
+ *
|
|
+ * Reading them only returns the selectors, but writing them (if
|
|
+ * nonzero) loads the full descriptor from the GDT or LDT. The
|
|
+ * LDT for next is loaded in switch_mm, and the GDT is loaded
|
|
+ * above.
|
|
+ *
|
|
+ * We therefore need to write new values to the segment
|
|
+ * registers on every context switch unless both the new and old
|
|
+ * values are zero.
|
|
+ *
|
|
+ * Note that we don't need to do anything for CS and SS, as
|
|
+ * those are saved and restored as part of pt_regs.
|
|
+ */
|
|
+ savesegment(es, prev->es);
|
|
+ if (unlikely(next->es | prev->es))
|
|
+ loadsegment(es, next->es);
|
|
+
|
|
+ savesegment(ds, prev->ds);
|
|
+ if (unlikely(next->ds | prev->ds))
|
|
+ loadsegment(ds, next->ds);
|
|
+
|
|
/*
|
|
* Switch FS and GS.
|
|
*
|
|
- * Segment register != 0 always requires a reload. Also
|
|
- * reload when it has changed. When prev process used 64bit
|
|
- * base always reload to avoid an information leak.
|
|
+ * These are even more complicated than FS and GS: they have
|
|
+ * 64-bit bases are that controlled by arch_prctl. Those bases
|
|
+ * only differ from the values in the GDT or LDT if the selector
|
|
+ * is 0.
|
|
+ *
|
|
+ * Loading the segment register resets the hidden base part of
|
|
+ * the register to 0 or the value from the GDT / LDT. If the
|
|
+ * next base address zero, writing 0 to the segment register is
|
|
+ * much faster than using wrmsr to explicitly zero the base.
|
|
+ *
|
|
+ * The thread_struct.fs and thread_struct.gs values are 0
|
|
+ * if the fs and gs bases respectively are not overridden
|
|
+ * from the values implied by fsindex and gsindex. They
|
|
+ * are nonzero, and store the nonzero base addresses, if
|
|
+ * the bases are overridden.
|
|
+ *
|
|
+ * (fs != 0 && fsindex != 0) || (gs != 0 && gsindex != 0) should
|
|
+ * be impossible.
|
|
+ *
|
|
+ * Therefore we need to reload the segment registers if either
|
|
+ * the old or new selector is nonzero, and we need to override
|
|
+ * the base address if next thread expects it to be overridden.
|
|
+ *
|
|
+ * This code is unnecessarily slow in the case where the old and
|
|
+ * new indexes are zero and the new base is nonzero -- it will
|
|
+ * unnecessarily write 0 to the selector before writing the new
|
|
+ * base address.
|
|
+ *
|
|
+ * Note: This all depends on arch_prctl being the only way that
|
|
+ * user code can override the segment base. Once wrfsbase and
|
|
+ * wrgsbase are enabled, most of this code will need to change.
|
|
*/
|
|
if (unlikely(fsindex | next->fsindex | prev->fs)) {
|
|
loadsegment(fs, next->fsindex);
|
|
+
|
|
/*
|
|
- * Check if the user used a selector != 0; if yes
|
|
- * clear 64bit base, since overloaded base is always
|
|
- * mapped to the Null selector
|
|
+ * If user code wrote a nonzero value to FS, then it also
|
|
+ * cleared the overridden base address.
|
|
+ *
|
|
+ * XXX: if user code wrote 0 to FS and cleared the base
|
|
+ * address itself, we won't notice and we'll incorrectly
|
|
+ * restore the prior base address next time we reschdule
|
|
+ * the process.
|
|
*/
|
|
if (fsindex)
|
|
prev->fs = 0;
|
|
}
|
|
- /* when next process has a 64bit base use it */
|
|
if (next->fs)
|
|
wrmsrl(MSR_FS_BASE, next->fs);
|
|
prev->fsindex = fsindex;
|
|
|
|
if (unlikely(gsindex | next->gsindex | prev->gs)) {
|
|
load_gs_index(next->gsindex);
|
|
+
|
|
+ /* This works (and fails) the same way as fsindex above. */
|
|
if (gsindex)
|
|
prev->gs = 0;
|
|
}
|
|
diff --git a/arch/x86/kernel/tls.c b/arch/x86/kernel/tls.c
|
|
index 9d25a6e..fe2e363 100644
|
|
--- a/arch/x86/kernel/tls.c
|
|
+++ b/arch/x86/kernel/tls.c
|
|
@@ -60,6 +60,22 @@ static bool tls_desc_okay(const struct user_desc *info)
|
|
if (!info->seg_32bit)
|
|
return false;
|
|
|
|
+ /* Only allow data segments in the TLS array. */
|
|
+ if (info->contents > 1)
|
|
+ return false;
|
|
+
|
|
+ /*
|
|
+ * Non-present segments with DPL 3 present an interesting attack
|
|
+ * surface. The kernel should handle such segments correctly,
|
|
+ * but TLS is very difficult to protect in a sandbox, so prevent
|
|
+ * such segments from being created.
|
|
+ *
|
|
+ * If userspace needs to remove a TLS entry, it can still delete
|
|
+ * it outright.
|
|
+ */
|
|
+ if (info->seg_not_present)
|
|
+ return false;
|
|
+
|
|
return true;
|
|
}
|
|
|
|
diff --git a/arch/x86/mm/fault.c b/arch/x86/mm/fault.c
|
|
index 4a0a2e8..b723f2e 100644
|
|
--- a/arch/x86/mm/fault.c
|
|
+++ b/arch/x86/mm/fault.c
|
|
@@ -887,6 +887,8 @@ mm_fault_error(struct pt_regs *regs, unsigned long error_code,
|
|
if (fault & (VM_FAULT_SIGBUS|VM_FAULT_HWPOISON|
|
|
VM_FAULT_HWPOISON_LARGE))
|
|
do_sigbus(regs, error_code, address, fault);
|
|
+ else if (fault & VM_FAULT_SIGSEGV)
|
|
+ bad_area_nosemaphore(regs, error_code, address);
|
|
else
|
|
BUG();
|
|
}
|
|
diff --git a/arch/x86/mm/mmap.c b/arch/x86/mm/mmap.c
|
|
index 5c1ae28..75f9e5d 100644
|
|
--- a/arch/x86/mm/mmap.c
|
|
+++ b/arch/x86/mm/mmap.c
|
|
@@ -35,12 +35,12 @@ struct __read_mostly va_alignment va_align = {
|
|
.flags = -1,
|
|
};
|
|
|
|
-static unsigned int stack_maxrandom_size(void)
|
|
+static unsigned long stack_maxrandom_size(void)
|
|
{
|
|
- unsigned int max = 0;
|
|
+ unsigned long max = 0;
|
|
if ((current->flags & PF_RANDOMIZE) &&
|
|
!(current->personality & ADDR_NO_RANDOMIZE)) {
|
|
- max = ((-1U) & STACK_RND_MASK) << PAGE_SHIFT;
|
|
+ max = ((-1UL) & STACK_RND_MASK) << PAGE_SHIFT;
|
|
}
|
|
|
|
return max;
|
|
diff --git a/arch/x86/um/sys_call_table_32.c b/arch/x86/um/sys_call_table_32.c
|
|
index 68d1dc9..bd8b159 100644
|
|
--- a/arch/x86/um/sys_call_table_32.c
|
|
+++ b/arch/x86/um/sys_call_table_32.c
|
|
@@ -43,7 +43,7 @@ typedef asmlinkage void (*sys_call_ptr_t)(void);
|
|
|
|
extern asmlinkage void sys_ni_syscall(void);
|
|
|
|
-const sys_call_ptr_t sys_call_table[] __cacheline_aligned = {
|
|
+const sys_call_ptr_t sys_call_table[] ____cacheline_aligned = {
|
|
/*
|
|
* Smells like a compiler bug -- it doesn't work
|
|
* when the & below is removed.
|
|
diff --git a/arch/x86/um/sys_call_table_64.c b/arch/x86/um/sys_call_table_64.c
|
|
index 9924776..cbdab94 100644
|
|
--- a/arch/x86/um/sys_call_table_64.c
|
|
+++ b/arch/x86/um/sys_call_table_64.c
|
|
@@ -48,7 +48,7 @@ typedef void (*sys_call_ptr_t)(void);
|
|
|
|
extern void sys_ni_syscall(void);
|
|
|
|
-const sys_call_ptr_t sys_call_table[] __cacheline_aligned = {
|
|
+const sys_call_ptr_t sys_call_table[] ____cacheline_aligned = {
|
|
/*
|
|
* Smells like a compiler bug -- it doesn't work
|
|
* when the & below is removed.
|
|
diff --git a/arch/x86/vdso/vma.c b/arch/x86/vdso/vma.c
|
|
index 00aaf04..47aa108 100644
|
|
--- a/arch/x86/vdso/vma.c
|
|
+++ b/arch/x86/vdso/vma.c
|
|
@@ -117,23 +117,39 @@ subsys_initcall(init_vdso);
|
|
|
|
struct linux_binprm;
|
|
|
|
-/* Put the vdso above the (randomized) stack with another randomized offset.
|
|
- This way there is no hole in the middle of address space.
|
|
- To save memory make sure it is still in the same PTE as the stack top.
|
|
- This doesn't give that many random bits */
|
|
+/*
|
|
+ * Put the vdso above the (randomized) stack with another randomized
|
|
+ * offset. This way there is no hole in the middle of address space.
|
|
+ * To save memory make sure it is still in the same PTE as the stack
|
|
+ * top. This doesn't give that many random bits.
|
|
+ *
|
|
+ * Note that this algorithm is imperfect: the distribution of the vdso
|
|
+ * start address within a PMD is biased toward the end.
|
|
+ *
|
|
+ */
|
|
static unsigned long vdso_addr(unsigned long start, unsigned len)
|
|
{
|
|
unsigned long addr, end;
|
|
unsigned offset;
|
|
- end = (start + PMD_SIZE - 1) & PMD_MASK;
|
|
+
|
|
+ /*
|
|
+ * Round up the start address. It can start out unaligned as a result
|
|
+ * of stack start randomization.
|
|
+ */
|
|
+ start = PAGE_ALIGN(start);
|
|
+
|
|
+ /* Round the lowest possible end address up to a PMD boundary. */
|
|
+ end = (start + len + PMD_SIZE - 1) & PMD_MASK;
|
|
if (end >= TASK_SIZE_MAX)
|
|
end = TASK_SIZE_MAX;
|
|
end -= len;
|
|
- /* This loses some more bits than a modulo, but is cheaper */
|
|
- offset = get_random_int() & (PTRS_PER_PTE - 1);
|
|
- addr = start + (offset << PAGE_SHIFT);
|
|
- if (addr >= end)
|
|
- addr = end;
|
|
+
|
|
+ if (end > start) {
|
|
+ offset = get_random_int() % (((end - start) >> PAGE_SHIFT) + 1);
|
|
+ addr = start + (offset << PAGE_SHIFT);
|
|
+ } else {
|
|
+ addr = start;
|
|
+ }
|
|
|
|
/*
|
|
* page-align it here so that get_unmapped_area doesn't
|
|
diff --git a/arch/xtensa/mm/fault.c b/arch/xtensa/mm/fault.c
|
|
index b17885a..b3877be 100644
|
|
--- a/arch/xtensa/mm/fault.c
|
|
+++ b/arch/xtensa/mm/fault.c
|
|
@@ -108,6 +108,8 @@ void do_page_fault(struct pt_regs *regs)
|
|
if (unlikely(fault & VM_FAULT_ERROR)) {
|
|
if (fault & VM_FAULT_OOM)
|
|
goto out_of_memory;
|
|
+ else if (fault & VM_FAULT_SIGSEGV)
|
|
+ goto bad_area;
|
|
else if (fault & VM_FAULT_SIGBUS)
|
|
goto do_sigbus;
|
|
BUG();
|
|
diff --git a/block/genhd.c b/block/genhd.c
|
|
index da61520..6542b9b 100644
|
|
--- a/block/genhd.c
|
|
+++ b/block/genhd.c
|
|
@@ -1069,9 +1069,16 @@ int disk_expand_part_tbl(struct gendisk *disk, int partno)
|
|
struct disk_part_tbl *old_ptbl = disk->part_tbl;
|
|
struct disk_part_tbl *new_ptbl;
|
|
int len = old_ptbl ? old_ptbl->len : 0;
|
|
- int target = partno + 1;
|
|
+ int i, target;
|
|
size_t size;
|
|
- int i;
|
|
+
|
|
+ /*
|
|
+ * check for int overflow, since we can get here from blkpg_ioctl()
|
|
+ * with a user passed 'partno'.
|
|
+ */
|
|
+ target = partno + 1;
|
|
+ if (target < 0)
|
|
+ return -EINVAL;
|
|
|
|
/* disk_max_parts() is zero during initialization, ignore if so */
|
|
if (disk_max_parts(disk) && target > disk_max_parts(disk))
|
|
diff --git a/crypto/af_alg.c b/crypto/af_alg.c
|
|
index bf948e1..6ef6e2a 100644
|
|
--- a/crypto/af_alg.c
|
|
+++ b/crypto/af_alg.c
|
|
@@ -449,6 +449,9 @@ void af_alg_complete(struct crypto_async_request *req, int err)
|
|
{
|
|
struct af_alg_completion *completion = req->data;
|
|
|
|
+ if (err == -EINPROGRESS)
|
|
+ return;
|
|
+
|
|
completion->err = err;
|
|
complete(&completion->completion);
|
|
}
|
|
diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c
|
|
index ca9a287..6fc61eb 100644
|
|
--- a/drivers/ata/ahci.c
|
|
+++ b/drivers/ata/ahci.c
|
|
@@ -61,6 +61,8 @@ enum board_ids {
|
|
/* board IDs by feature in alphabetical order */
|
|
board_ahci,
|
|
board_ahci_ign_iferr,
|
|
+ board_ahci_nomsi,
|
|
+ board_ahci_noncq,
|
|
board_ahci_nosntf,
|
|
board_ahci_yes_fbs,
|
|
|
|
@@ -121,6 +123,20 @@ static const struct ata_port_info ahci_port_info[] = {
|
|
.udma_mask = ATA_UDMA6,
|
|
.port_ops = &ahci_ops,
|
|
},
|
|
+ [board_ahci_nomsi] = {
|
|
+ AHCI_HFLAGS (AHCI_HFLAG_NO_MSI),
|
|
+ .flags = AHCI_FLAG_COMMON,
|
|
+ .pio_mask = ATA_PIO4,
|
|
+ .udma_mask = ATA_UDMA6,
|
|
+ .port_ops = &ahci_ops,
|
|
+ },
|
|
+ [board_ahci_noncq] = {
|
|
+ AHCI_HFLAGS (AHCI_HFLAG_NO_NCQ),
|
|
+ .flags = AHCI_FLAG_COMMON,
|
|
+ .pio_mask = ATA_PIO4,
|
|
+ .udma_mask = ATA_UDMA6,
|
|
+ .port_ops = &ahci_ops,
|
|
+ },
|
|
[board_ahci_nosntf] =
|
|
{
|
|
AHCI_HFLAGS (AHCI_HFLAG_NO_SNTF),
|
|
@@ -313,6 +329,9 @@ static const struct pci_device_id ahci_pci_tbl[] = {
|
|
{ PCI_VDEVICE(INTEL, 0x8c87), board_ahci }, /* 9 Series RAID */
|
|
{ PCI_VDEVICE(INTEL, 0x8c8e), board_ahci }, /* 9 Series RAID */
|
|
{ PCI_VDEVICE(INTEL, 0x8c8f), board_ahci }, /* 9 Series RAID */
|
|
+ { PCI_VDEVICE(INTEL, 0x9d03), board_ahci }, /* Sunrise Point-LP AHCI */
|
|
+ { PCI_VDEVICE(INTEL, 0x9d05), board_ahci }, /* Sunrise Point-LP RAID */
|
|
+ { PCI_VDEVICE(INTEL, 0x9d07), board_ahci }, /* Sunrise Point-LP RAID */
|
|
{ PCI_VDEVICE(INTEL, 0xa103), board_ahci }, /* Sunrise Point-H AHCI */
|
|
{ PCI_VDEVICE(INTEL, 0xa103), board_ahci }, /* Sunrise Point-H RAID */
|
|
{ PCI_VDEVICE(INTEL, 0xa105), board_ahci }, /* Sunrise Point-H RAID */
|
|
@@ -469,6 +488,13 @@ static const struct pci_device_id ahci_pci_tbl[] = {
|
|
{ PCI_VDEVICE(ASMEDIA, 0x0611), board_ahci }, /* ASM1061 */
|
|
{ PCI_VDEVICE(ASMEDIA, 0x0612), board_ahci }, /* ASM1062 */
|
|
|
|
+ /*
|
|
+ * Samsung SSDs found on some macbooks. NCQ times out if MSI is
|
|
+ * enabled. https://bugzilla.kernel.org/show_bug.cgi?id=60731
|
|
+ */
|
|
+ { PCI_VDEVICE(SAMSUNG, 0x1600), board_ahci_nomsi },
|
|
+ { PCI_VDEVICE(SAMSUNG, 0xa800), board_ahci_nomsi },
|
|
+
|
|
/* Enmotus */
|
|
{ PCI_DEVICE(0x1c44, 0x8000), board_ahci },
|
|
|
|
diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c
|
|
index 6b92236..adaf994 100644
|
|
--- a/drivers/ata/libata-core.c
|
|
+++ b/drivers/ata/libata-core.c
|
|
@@ -4712,7 +4712,10 @@ static struct ata_queued_cmd *ata_qc_new(struct ata_port *ap)
|
|
return NULL;
|
|
|
|
for (i = 0, tag = ap->last_tag + 1; i < max_queue; i++, tag++) {
|
|
- tag = tag < max_queue ? tag : 0;
|
|
+ if (ap->flags & ATA_FLAG_LOWTAG)
|
|
+ tag = i;
|
|
+ else
|
|
+ tag = tag < max_queue ? tag : 0;
|
|
|
|
/* the last tag is reserved for internal command. */
|
|
if (tag == ATA_TAG_INTERNAL)
|
|
diff --git a/drivers/ata/libata-sff.c b/drivers/ata/libata-sff.c
|
|
index 3723e5e..fad2734 100644
|
|
--- a/drivers/ata/libata-sff.c
|
|
+++ b/drivers/ata/libata-sff.c
|
|
@@ -1333,7 +1333,19 @@ void ata_sff_flush_pio_task(struct ata_port *ap)
|
|
DPRINTK("ENTER\n");
|
|
|
|
cancel_delayed_work_sync(&ap->sff_pio_task);
|
|
+
|
|
+ /*
|
|
+ * We wanna reset the HSM state to IDLE. If we do so without
|
|
+ * grabbing the port lock, critical sections protected by it which
|
|
+ * expect the HSM state to stay stable may get surprised. For
|
|
+ * example, we may set IDLE in between the time
|
|
+ * __ata_sff_port_intr() checks for HSM_ST_IDLE and before it calls
|
|
+ * ata_sff_hsm_move() causing ata_sff_hsm_move() to BUG().
|
|
+ */
|
|
+ spin_lock_irq(ap->lock);
|
|
ap->hsm_task_state = HSM_ST_IDLE;
|
|
+ spin_unlock_irq(ap->lock);
|
|
+
|
|
ap->sff_pio_task_link = NULL;
|
|
|
|
if (ata_msg_ctl(ap))
|
|
diff --git a/drivers/ata/sata_dwc_460ex.c b/drivers/ata/sata_dwc_460ex.c
|
|
index 69f7cde..9d6eb14 100644
|
|
--- a/drivers/ata/sata_dwc_460ex.c
|
|
+++ b/drivers/ata/sata_dwc_460ex.c
|
|
@@ -791,7 +791,7 @@ static int dma_dwc_init(struct sata_dwc_device *hsdev, int irq)
|
|
if (err) {
|
|
dev_err(host_pvt.dwc_dev, "%s: dma_request_interrupts returns"
|
|
" %d\n", __func__, err);
|
|
- goto error_out;
|
|
+ return err;
|
|
}
|
|
|
|
/* Enabe DMA */
|
|
@@ -802,11 +802,6 @@ static int dma_dwc_init(struct sata_dwc_device *hsdev, int irq)
|
|
sata_dma_regs);
|
|
|
|
return 0;
|
|
-
|
|
-error_out:
|
|
- dma_dwc_exit(hsdev);
|
|
-
|
|
- return err;
|
|
}
|
|
|
|
static int sata_dwc_scr_read(struct ata_link *link, unsigned int scr, u32 *val)
|
|
@@ -1634,7 +1629,7 @@ static int sata_dwc_probe(struct platform_device *ofdev)
|
|
char *ver = (char *)&versionr;
|
|
u8 *base = NULL;
|
|
int err = 0;
|
|
- int irq, rc;
|
|
+ int irq;
|
|
struct ata_host *host;
|
|
struct ata_port_info pi = sata_dwc_port_info[0];
|
|
const struct ata_port_info *ppi[] = { &pi, NULL };
|
|
@@ -1688,7 +1683,7 @@ static int sata_dwc_probe(struct platform_device *ofdev)
|
|
if (irq == NO_IRQ) {
|
|
dev_err(&ofdev->dev, "no SATA DMA irq\n");
|
|
err = -ENODEV;
|
|
- goto error_out;
|
|
+ goto error_iomap;
|
|
}
|
|
|
|
/* Get physical SATA DMA register base address */
|
|
@@ -1697,14 +1692,16 @@ static int sata_dwc_probe(struct platform_device *ofdev)
|
|
dev_err(&ofdev->dev, "ioremap failed for AHBDMA register"
|
|
" address\n");
|
|
err = -ENODEV;
|
|
- goto error_out;
|
|
+ goto error_iomap;
|
|
}
|
|
|
|
/* Save dev for later use in dev_xxx() routines */
|
|
host_pvt.dwc_dev = &ofdev->dev;
|
|
|
|
/* Initialize AHB DMAC */
|
|
- dma_dwc_init(hsdev, irq);
|
|
+ err = dma_dwc_init(hsdev, irq);
|
|
+ if (err)
|
|
+ goto error_dma_iomap;
|
|
|
|
/* Enable SATA Interrupts */
|
|
sata_dwc_enable_interrupts(hsdev);
|
|
@@ -1722,9 +1719,8 @@ static int sata_dwc_probe(struct platform_device *ofdev)
|
|
* device discovery process, invoking our port_start() handler &
|
|
* error_handler() to execute a dummy Softreset EH session
|
|
*/
|
|
- rc = ata_host_activate(host, irq, sata_dwc_isr, 0, &sata_dwc_sht);
|
|
-
|
|
- if (rc != 0)
|
|
+ err = ata_host_activate(host, irq, sata_dwc_isr, 0, &sata_dwc_sht);
|
|
+ if (err)
|
|
dev_err(&ofdev->dev, "failed to activate host");
|
|
|
|
dev_set_drvdata(&ofdev->dev, host);
|
|
@@ -1733,7 +1729,8 @@ static int sata_dwc_probe(struct platform_device *ofdev)
|
|
error_out:
|
|
/* Free SATA DMA resources */
|
|
dma_dwc_exit(hsdev);
|
|
-
|
|
+error_dma_iomap:
|
|
+ iounmap((void __iomem *)host_pvt.sata_dma_regs);
|
|
error_iomap:
|
|
iounmap(base);
|
|
error_kmalloc:
|
|
@@ -1754,6 +1751,7 @@ static int sata_dwc_remove(struct platform_device *ofdev)
|
|
/* Free SATA DMA resources */
|
|
dma_dwc_exit(hsdev);
|
|
|
|
+ iounmap((void __iomem *)host_pvt.sata_dma_regs);
|
|
iounmap(hsdev->reg_base);
|
|
kfree(hsdev);
|
|
kfree(host);
|
|
diff --git a/drivers/ata/sata_fsl.c b/drivers/ata/sata_fsl.c
|
|
index d6577b9..3d3b59a 100644
|
|
--- a/drivers/ata/sata_fsl.c
|
|
+++ b/drivers/ata/sata_fsl.c
|
|
@@ -1426,7 +1426,7 @@ static int sata_fsl_probe(struct platform_device *ofdev)
|
|
host_priv->csr_base = csr_base;
|
|
|
|
irq = irq_of_parse_and_map(ofdev->dev.of_node, 0);
|
|
- if (irq < 0) {
|
|
+ if (!irq) {
|
|
dev_err(&ofdev->dev, "invalid irq from platform\n");
|
|
goto error_exit_with_cleanup;
|
|
}
|
|
diff --git a/drivers/ata/sata_sil24.c b/drivers/ata/sata_sil24.c
|
|
index e7e610a..cb68aa3 100644
|
|
--- a/drivers/ata/sata_sil24.c
|
|
+++ b/drivers/ata/sata_sil24.c
|
|
@@ -246,7 +246,7 @@ enum {
|
|
/* host flags */
|
|
SIL24_COMMON_FLAGS = ATA_FLAG_SATA | ATA_FLAG_PIO_DMA |
|
|
ATA_FLAG_NCQ | ATA_FLAG_ACPI_SATA |
|
|
- ATA_FLAG_AN | ATA_FLAG_PMP,
|
|
+ ATA_FLAG_AN | ATA_FLAG_PMP | ATA_FLAG_LOWTAG,
|
|
SIL24_FLAG_PCIX_IRQ_WOC = (1 << 24), /* IRQ loss errata on PCI-X */
|
|
|
|
IRQ_STAT_4PORTS = 0xf,
|
|
diff --git a/drivers/base/bus.c b/drivers/base/bus.c
|
|
index feb30c1..b23bb9c 100644
|
|
--- a/drivers/base/bus.c
|
|
+++ b/drivers/base/bus.c
|
|
@@ -245,13 +245,15 @@ static ssize_t store_drivers_probe(struct bus_type *bus,
|
|
const char *buf, size_t count)
|
|
{
|
|
struct device *dev;
|
|
+ int err = -EINVAL;
|
|
|
|
dev = bus_find_device_by_name(bus, NULL, buf);
|
|
if (!dev)
|
|
return -ENODEV;
|
|
- if (bus_rescan_devices_helper(dev, NULL) != 0)
|
|
- return -EINVAL;
|
|
- return count;
|
|
+ if (bus_rescan_devices_helper(dev, NULL) == 0)
|
|
+ err = count;
|
|
+ put_device(dev);
|
|
+ return err;
|
|
}
|
|
#endif
|
|
|
|
diff --git a/drivers/base/core.c b/drivers/base/core.c
|
|
index bde1832..b1726a0 100644
|
|
--- a/drivers/base/core.c
|
|
+++ b/drivers/base/core.c
|
|
@@ -1500,34 +1500,11 @@ static void device_create_release(struct device *dev)
|
|
kfree(dev);
|
|
}
|
|
|
|
-/**
|
|
- * device_create_vargs - creates a device and registers it with sysfs
|
|
- * @class: pointer to the struct class that this device should be registered to
|
|
- * @parent: pointer to the parent struct device of this new device, if any
|
|
- * @devt: the dev_t for the char device to be added
|
|
- * @drvdata: the data to be added to the device for callbacks
|
|
- * @fmt: string for the device's name
|
|
- * @args: va_list for the device's name
|
|
- *
|
|
- * This function can be used by char device classes. A struct device
|
|
- * will be created in sysfs, registered to the specified class.
|
|
- *
|
|
- * A "dev" file will be created, showing the dev_t for the device, if
|
|
- * the dev_t is not 0,0.
|
|
- * If a pointer to a parent struct device is passed in, the newly created
|
|
- * struct device will be a child of that device in sysfs.
|
|
- * The pointer to the struct device will be returned from the call.
|
|
- * Any further sysfs files that might be required can be created using this
|
|
- * pointer.
|
|
- *
|
|
- * Returns &struct device pointer on success, or ERR_PTR() on error.
|
|
- *
|
|
- * Note: the struct class passed to this function must have previously
|
|
- * been created with a call to class_create().
|
|
- */
|
|
-struct device *device_create_vargs(struct class *class, struct device *parent,
|
|
- dev_t devt, void *drvdata, const char *fmt,
|
|
- va_list args)
|
|
+static struct device *
|
|
+device_create_groups_vargs(struct class *class, struct device *parent,
|
|
+ dev_t devt, void *drvdata,
|
|
+ const struct attribute_group **groups,
|
|
+ const char *fmt, va_list args)
|
|
{
|
|
struct device *dev = NULL;
|
|
int retval = -ENODEV;
|
|
@@ -1544,6 +1521,7 @@ struct device *device_create_vargs(struct class *class, struct device *parent,
|
|
dev->devt = devt;
|
|
dev->class = class;
|
|
dev->parent = parent;
|
|
+ dev->groups = groups;
|
|
dev->release = device_create_release;
|
|
dev_set_drvdata(dev, drvdata);
|
|
|
|
@@ -1561,6 +1539,39 @@ struct device *device_create_vargs(struct class *class, struct device *parent,
|
|
put_device(dev);
|
|
return ERR_PTR(retval);
|
|
}
|
|
+
|
|
+/**
|
|
+ * device_create_vargs - creates a device and registers it with sysfs
|
|
+ * @class: pointer to the struct class that this device should be registered to
|
|
+ * @parent: pointer to the parent struct device of this new device, if any
|
|
+ * @devt: the dev_t for the char device to be added
|
|
+ * @drvdata: the data to be added to the device for callbacks
|
|
+ * @fmt: string for the device's name
|
|
+ * @args: va_list for the device's name
|
|
+ *
|
|
+ * This function can be used by char device classes. A struct device
|
|
+ * will be created in sysfs, registered to the specified class.
|
|
+ *
|
|
+ * A "dev" file will be created, showing the dev_t for the device, if
|
|
+ * the dev_t is not 0,0.
|
|
+ * If a pointer to a parent struct device is passed in, the newly created
|
|
+ * struct device will be a child of that device in sysfs.
|
|
+ * The pointer to the struct device will be returned from the call.
|
|
+ * Any further sysfs files that might be required can be created using this
|
|
+ * pointer.
|
|
+ *
|
|
+ * Returns &struct device pointer on success, or ERR_PTR() on error.
|
|
+ *
|
|
+ * Note: the struct class passed to this function must have previously
|
|
+ * been created with a call to class_create().
|
|
+ */
|
|
+struct device *device_create_vargs(struct class *class, struct device *parent,
|
|
+ dev_t devt, void *drvdata, const char *fmt,
|
|
+ va_list args)
|
|
+{
|
|
+ return device_create_groups_vargs(class, parent, devt, drvdata, NULL,
|
|
+ fmt, args);
|
|
+}
|
|
EXPORT_SYMBOL_GPL(device_create_vargs);
|
|
|
|
/**
|
|
@@ -1600,6 +1611,50 @@ struct device *device_create(struct class *class, struct device *parent,
|
|
}
|
|
EXPORT_SYMBOL_GPL(device_create);
|
|
|
|
+/**
|
|
+ * device_create_with_groups - creates a device and registers it with sysfs
|
|
+ * @class: pointer to the struct class that this device should be registered to
|
|
+ * @parent: pointer to the parent struct device of this new device, if any
|
|
+ * @devt: the dev_t for the char device to be added
|
|
+ * @drvdata: the data to be added to the device for callbacks
|
|
+ * @groups: NULL-terminated list of attribute groups to be created
|
|
+ * @fmt: string for the device's name
|
|
+ *
|
|
+ * This function can be used by char device classes. A struct device
|
|
+ * will be created in sysfs, registered to the specified class.
|
|
+ * Additional attributes specified in the groups parameter will also
|
|
+ * be created automatically.
|
|
+ *
|
|
+ * A "dev" file will be created, showing the dev_t for the device, if
|
|
+ * the dev_t is not 0,0.
|
|
+ * If a pointer to a parent struct device is passed in, the newly created
|
|
+ * struct device will be a child of that device in sysfs.
|
|
+ * The pointer to the struct device will be returned from the call.
|
|
+ * Any further sysfs files that might be required can be created using this
|
|
+ * pointer.
|
|
+ *
|
|
+ * Returns &struct device pointer on success, or ERR_PTR() on error.
|
|
+ *
|
|
+ * Note: the struct class passed to this function must have previously
|
|
+ * been created with a call to class_create().
|
|
+ */
|
|
+struct device *device_create_with_groups(struct class *class,
|
|
+ struct device *parent, dev_t devt,
|
|
+ void *drvdata,
|
|
+ const struct attribute_group **groups,
|
|
+ const char *fmt, ...)
|
|
+{
|
|
+ va_list vargs;
|
|
+ struct device *dev;
|
|
+
|
|
+ va_start(vargs, fmt);
|
|
+ dev = device_create_groups_vargs(class, parent, devt, drvdata, groups,
|
|
+ fmt, vargs);
|
|
+ va_end(vargs);
|
|
+ return dev;
|
|
+}
|
|
+EXPORT_SYMBOL_GPL(device_create_with_groups);
|
|
+
|
|
static int __match_devt(struct device *dev, void *data)
|
|
{
|
|
dev_t *devt = data;
|
|
diff --git a/drivers/block/drbd/drbd_req.c b/drivers/block/drbd/drbd_req.c
|
|
index be984e0..43da226 100644
|
|
--- a/drivers/block/drbd/drbd_req.c
|
|
+++ b/drivers/block/drbd/drbd_req.c
|
|
@@ -1184,6 +1184,7 @@ int drbd_merge_bvec(struct request_queue *q, struct bvec_merge_data *bvm, struct
|
|
struct request_queue * const b =
|
|
mdev->ldev->backing_bdev->bd_disk->queue;
|
|
if (b->merge_bvec_fn) {
|
|
+ bvm->bi_bdev = mdev->ldev->backing_bdev;
|
|
backing_limit = b->merge_bvec_fn(b, bvm, bvec);
|
|
limit = min(limit, backing_limit);
|
|
}
|
|
diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c
|
|
index 234cb1e..06d916b 100644
|
|
--- a/drivers/gpio/gpiolib.c
|
|
+++ b/drivers/gpio/gpiolib.c
|
|
@@ -60,6 +60,7 @@ struct gpio_desc {
|
|
#define FLAG_ACTIVE_LOW 7 /* sysfs value has active low */
|
|
#define FLAG_OPEN_DRAIN 8 /* Gpio is open drain type */
|
|
#define FLAG_OPEN_SOURCE 9 /* Gpio is open source type */
|
|
+#define FLAG_SYSFS_DIR 10 /* show sysfs direction attribute */
|
|
|
|
#define ID_SHIFT 16 /* add new flags before this one */
|
|
|
|
@@ -319,7 +320,7 @@ static ssize_t gpio_value_store(struct device *dev,
|
|
return status;
|
|
}
|
|
|
|
-static const DEVICE_ATTR(value, 0644,
|
|
+static DEVICE_ATTR(value, 0644,
|
|
gpio_value_show, gpio_value_store);
|
|
|
|
static irqreturn_t gpio_sysfs_irq(int irq, void *priv)
|
|
@@ -542,17 +543,47 @@ static ssize_t gpio_active_low_store(struct device *dev,
|
|
return status ? : size;
|
|
}
|
|
|
|
-static const DEVICE_ATTR(active_low, 0644,
|
|
+static DEVICE_ATTR(active_low, 0644,
|
|
gpio_active_low_show, gpio_active_low_store);
|
|
|
|
-static const struct attribute *gpio_attrs[] = {
|
|
+static umode_t gpio_is_visible(struct kobject *kobj, struct attribute *attr,
|
|
+ int n)
|
|
+{
|
|
+ struct device *dev = container_of(kobj, struct device, kobj);
|
|
+ struct gpio_desc *desc = dev_get_drvdata(dev);
|
|
+ unsigned gpio = desc - gpio_desc;
|
|
+ umode_t mode = attr->mode;
|
|
+ bool show_direction = test_bit(FLAG_SYSFS_DIR, &desc->flags);
|
|
+
|
|
+ if (attr == &dev_attr_direction.attr) {
|
|
+ if (!show_direction)
|
|
+ mode = 0;
|
|
+ } else if (attr == &dev_attr_edge.attr) {
|
|
+ if (gpio_to_irq(gpio) < 0)
|
|
+ mode = 0;
|
|
+ if (!show_direction && test_bit(FLAG_IS_OUT, &desc->flags))
|
|
+ mode = 0;
|
|
+ }
|
|
+
|
|
+ return mode;
|
|
+}
|
|
+
|
|
+static struct attribute *gpio_attrs[] = {
|
|
+ &dev_attr_direction.attr,
|
|
+ &dev_attr_edge.attr,
|
|
&dev_attr_value.attr,
|
|
&dev_attr_active_low.attr,
|
|
NULL,
|
|
};
|
|
|
|
-static const struct attribute_group gpio_attr_group = {
|
|
- .attrs = (struct attribute **) gpio_attrs,
|
|
+static const struct attribute_group gpio_group = {
|
|
+ .attrs = gpio_attrs,
|
|
+ .is_visible = gpio_is_visible,
|
|
+};
|
|
+
|
|
+static const struct attribute_group *gpio_groups[] = {
|
|
+ &gpio_group,
|
|
+ NULL
|
|
};
|
|
|
|
/*
|
|
@@ -589,16 +620,13 @@ static ssize_t chip_ngpio_show(struct device *dev,
|
|
}
|
|
static DEVICE_ATTR(ngpio, 0444, chip_ngpio_show, NULL);
|
|
|
|
-static const struct attribute *gpiochip_attrs[] = {
|
|
+static struct attribute *gpiochip_attrs[] = {
|
|
&dev_attr_base.attr,
|
|
&dev_attr_label.attr,
|
|
&dev_attr_ngpio.attr,
|
|
NULL,
|
|
};
|
|
-
|
|
-static const struct attribute_group gpiochip_attr_group = {
|
|
- .attrs = (struct attribute **) gpiochip_attrs,
|
|
-};
|
|
+ATTRIBUTE_GROUPS(gpiochip);
|
|
|
|
/*
|
|
* /sys/class/gpio/export ... write-only
|
|
@@ -704,8 +732,9 @@ int gpio_export(unsigned gpio, bool direction_may_change)
|
|
{
|
|
unsigned long flags;
|
|
struct gpio_desc *desc;
|
|
- int status = -EINVAL;
|
|
+ int status;
|
|
const char *ioname = NULL;
|
|
+ struct device *dev;
|
|
|
|
/* can't export until sysfs is available ... */
|
|
if (!gpio_class.p) {
|
|
@@ -713,59 +742,50 @@ int gpio_export(unsigned gpio, bool direction_may_change)
|
|
return -ENOENT;
|
|
}
|
|
|
|
- if (!gpio_is_valid(gpio))
|
|
- goto done;
|
|
+ if (!gpio_is_valid(gpio)) {
|
|
+ pr_debug("%s: gpio %d is not valid\n", __func__, gpio);
|
|
+ return -EINVAL;
|
|
+ }
|
|
|
|
mutex_lock(&sysfs_lock);
|
|
|
|
spin_lock_irqsave(&gpio_lock, flags);
|
|
desc = &gpio_desc[gpio];
|
|
- if (test_bit(FLAG_REQUESTED, &desc->flags)
|
|
- && !test_bit(FLAG_EXPORT, &desc->flags)) {
|
|
- status = 0;
|
|
- if (!desc->chip->direction_input
|
|
- || !desc->chip->direction_output)
|
|
- direction_may_change = false;
|
|
+ if (!test_bit(FLAG_REQUESTED, &desc->flags) ||
|
|
+ test_bit(FLAG_EXPORT, &desc->flags)) {
|
|
+ spin_unlock_irqrestore(&gpio_lock, flags);
|
|
+ pr_debug("%s: gpio %d unavailable (requested=%d, exported=%d)\n",
|
|
+ __func__, gpio,
|
|
+ test_bit(FLAG_REQUESTED, &desc->flags),
|
|
+ test_bit(FLAG_EXPORT, &desc->flags));
|
|
+ return -EPERM;
|
|
+ }
|
|
+
|
|
+ if (desc->chip->direction_input && desc->chip->direction_output &&
|
|
+ direction_may_change) {
|
|
+ set_bit(FLAG_SYSFS_DIR, &desc->flags);
|
|
}
|
|
+
|
|
spin_unlock_irqrestore(&gpio_lock, flags);
|
|
|
|
if (desc->chip->names && desc->chip->names[gpio - desc->chip->base])
|
|
ioname = desc->chip->names[gpio - desc->chip->base];
|
|
|
|
- if (status == 0) {
|
|
- struct device *dev;
|
|
-
|
|
- dev = device_create(&gpio_class, desc->chip->dev, MKDEV(0, 0),
|
|
- desc, ioname ? ioname : "gpio%u", gpio);
|
|
- if (!IS_ERR(dev)) {
|
|
- status = sysfs_create_group(&dev->kobj,
|
|
- &gpio_attr_group);
|
|
-
|
|
- if (!status && direction_may_change)
|
|
- status = device_create_file(dev,
|
|
- &dev_attr_direction);
|
|
-
|
|
- if (!status && gpio_to_irq(gpio) >= 0
|
|
- && (direction_may_change
|
|
- || !test_bit(FLAG_IS_OUT,
|
|
- &desc->flags)))
|
|
- status = device_create_file(dev,
|
|
- &dev_attr_edge);
|
|
-
|
|
- if (status != 0)
|
|
- device_unregister(dev);
|
|
- } else
|
|
- status = PTR_ERR(dev);
|
|
- if (status == 0)
|
|
- set_bit(FLAG_EXPORT, &desc->flags);
|
|
+ dev = device_create_with_groups(&gpio_class, desc->chip->dev,
|
|
+ MKDEV(0, 0), desc, gpio_groups,
|
|
+ ioname ? ioname : "gpio%u", gpio);
|
|
+ if (IS_ERR(dev)) {
|
|
+ status = PTR_ERR(dev);
|
|
+ goto fail_unlock;
|
|
}
|
|
|
|
+ set_bit(FLAG_EXPORT, &desc->flags);
|
|
mutex_unlock(&sysfs_lock);
|
|
+ return 0;
|
|
|
|
-done:
|
|
- if (status)
|
|
- pr_debug("%s: gpio%d status %d\n", __func__, gpio, status);
|
|
-
|
|
+fail_unlock:
|
|
+ mutex_unlock(&sysfs_lock);
|
|
+ pr_debug("%s: gpio%d status %d\n", __func__, gpio, status);
|
|
return status;
|
|
}
|
|
EXPORT_SYMBOL_GPL(gpio_export);
|
|
@@ -805,6 +825,7 @@ int gpio_export_link(struct device *dev, const char *name, unsigned gpio)
|
|
if (tdev != NULL) {
|
|
status = sysfs_create_link(&dev->kobj, &tdev->kobj,
|
|
name);
|
|
+ put_device(tdev);
|
|
} else {
|
|
status = -ENODEV;
|
|
}
|
|
@@ -855,7 +876,7 @@ int gpio_sysfs_set_active_low(unsigned gpio, int value)
|
|
}
|
|
|
|
status = sysfs_set_active_low(desc, dev, value);
|
|
-
|
|
+ put_device(dev);
|
|
unlock:
|
|
mutex_unlock(&sysfs_lock);
|
|
|
|
@@ -893,6 +914,7 @@ void gpio_unexport(unsigned gpio)
|
|
dev = class_find_device(&gpio_class, NULL, desc, match_export);
|
|
if (dev) {
|
|
gpio_setup_irq(desc, dev, 0);
|
|
+ clear_bit(FLAG_SYSFS_DIR, &desc->flags);
|
|
clear_bit(FLAG_EXPORT, &desc->flags);
|
|
} else
|
|
status = -ENODEV;
|
|
@@ -924,13 +946,13 @@ static int gpiochip_export(struct gpio_chip *chip)
|
|
|
|
/* use chip->base for the ID; it's already known to be unique */
|
|
mutex_lock(&sysfs_lock);
|
|
- dev = device_create(&gpio_class, chip->dev, MKDEV(0, 0), chip,
|
|
- "gpiochip%d", chip->base);
|
|
- if (!IS_ERR(dev)) {
|
|
- status = sysfs_create_group(&dev->kobj,
|
|
- &gpiochip_attr_group);
|
|
- } else
|
|
+ dev = device_create_with_groups(&gpio_class, chip->dev, MKDEV(0, 0),
|
|
+ chip, gpiochip_groups,
|
|
+ "gpiochip%d", chip->base);
|
|
+ if (IS_ERR(dev))
|
|
status = PTR_ERR(dev);
|
|
+ else
|
|
+ status = 0;
|
|
chip->exported = (status == 0);
|
|
mutex_unlock(&sysfs_lock);
|
|
|
|
@@ -1081,23 +1103,22 @@ int gpiochip_add(struct gpio_chip *chip)
|
|
? (1 << FLAG_IS_OUT)
|
|
: 0;
|
|
}
|
|
- }
|
|
|
|
#ifdef CONFIG_PINCTRL
|
|
INIT_LIST_HEAD(&chip->pin_ranges);
|
|
#endif
|
|
-
|
|
- of_gpiochip_add(chip);
|
|
+
|
|
+ of_gpiochip_add(chip);
|
|
+ }
|
|
|
|
unlock:
|
|
spin_unlock_irqrestore(&gpio_lock, flags);
|
|
|
|
- if (status)
|
|
- goto fail;
|
|
-
|
|
status = gpiochip_export(chip);
|
|
- if (status)
|
|
+ if (status) {
|
|
+ of_gpiochip_remove(chip);
|
|
goto fail;
|
|
+ }
|
|
|
|
pr_info("gpiochip_add: registered GPIOs %d to %d on device: %s\n",
|
|
chip->base, chip->base + chip->ngpio - 1,
|
|
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
|
|
index 2ac4ded..b1f1d10 100644
|
|
--- a/drivers/gpu/drm/i915/i915_gem.c
|
|
+++ b/drivers/gpu/drm/i915/i915_gem.c
|
|
@@ -2193,6 +2193,13 @@ static int sandybridge_write_fence_reg(struct drm_i915_gem_object *obj,
|
|
int regnum = obj->fence_reg;
|
|
uint64_t val;
|
|
|
|
+ /* Adjust fence size to match tiled area */
|
|
+ if (obj->tiling_mode != I915_TILING_NONE) {
|
|
+ uint32_t row_size = obj->stride *
|
|
+ (obj->tiling_mode == I915_TILING_Y ? 32 : 8);
|
|
+ size = (size / row_size) * row_size;
|
|
+ }
|
|
+
|
|
val = (uint64_t)((obj->gtt_offset + size - 4096) &
|
|
0xfffff000) << 32;
|
|
val |= obj->gtt_offset & 0xfffff000;
|
|
@@ -2230,6 +2237,13 @@ static int i965_write_fence_reg(struct drm_i915_gem_object *obj,
|
|
int regnum = obj->fence_reg;
|
|
uint64_t val;
|
|
|
|
+ /* Adjust fence size to match tiled area */
|
|
+ if (obj->tiling_mode != I915_TILING_NONE) {
|
|
+ uint32_t row_size = obj->stride *
|
|
+ (obj->tiling_mode == I915_TILING_Y ? 32 : 8);
|
|
+ size = (size / row_size) * row_size;
|
|
+ }
|
|
+
|
|
val = (uint64_t)((obj->gtt_offset + size - 4096) &
|
|
0xfffff000) << 32;
|
|
val |= obj->gtt_offset & 0xfffff000;
|
|
diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c
|
|
index 77190cc..3febe29 100644
|
|
--- a/drivers/gpu/drm/i915/intel_lvds.c
|
|
+++ b/drivers/gpu/drm/i915/intel_lvds.c
|
|
@@ -932,6 +932,17 @@ bool intel_lvds_init(struct drm_device *dev)
|
|
int pipe;
|
|
u8 pin;
|
|
|
|
+ /*
|
|
+ * Unlock registers and just leave them unlocked. Do this before
|
|
+ * checking quirk lists to avoid bogus WARNINGs.
|
|
+ */
|
|
+ if (HAS_PCH_SPLIT(dev)) {
|
|
+ I915_WRITE(PCH_PP_CONTROL,
|
|
+ I915_READ(PCH_PP_CONTROL) | PANEL_UNLOCK_REGS);
|
|
+ } else {
|
|
+ I915_WRITE(PP_CONTROL,
|
|
+ I915_READ(PP_CONTROL) | PANEL_UNLOCK_REGS);
|
|
+ }
|
|
if (!intel_lvds_supported(dev))
|
|
return false;
|
|
|
|
@@ -1109,19 +1120,6 @@ bool intel_lvds_init(struct drm_device *dev)
|
|
pwm = I915_READ(BLC_PWM_PCH_CTL1);
|
|
pwm |= PWM_PCH_ENABLE;
|
|
I915_WRITE(BLC_PWM_PCH_CTL1, pwm);
|
|
- /*
|
|
- * Unlock registers and just
|
|
- * leave them unlocked
|
|
- */
|
|
- I915_WRITE(PCH_PP_CONTROL,
|
|
- I915_READ(PCH_PP_CONTROL) | PANEL_UNLOCK_REGS);
|
|
- } else {
|
|
- /*
|
|
- * Unlock registers and just
|
|
- * leave them unlocked
|
|
- */
|
|
- I915_WRITE(PP_CONTROL,
|
|
- I915_READ(PP_CONTROL) | PANEL_UNLOCK_REGS);
|
|
}
|
|
dev_priv->lid_notifier.notifier_call = intel_lid_notify;
|
|
if (acpi_lid_notifier_register(&dev_priv->lid_notifier)) {
|
|
diff --git a/drivers/gpu/drm/radeon/radeon_kms.c b/drivers/gpu/drm/radeon/radeon_kms.c
|
|
index 9b46238..b731686 100644
|
|
--- a/drivers/gpu/drm/radeon/radeon_kms.c
|
|
+++ b/drivers/gpu/drm/radeon/radeon_kms.c
|
|
@@ -428,6 +428,8 @@ int radeon_get_vblank_timestamp_kms(struct drm_device *dev, int crtc,
|
|
|
|
/* Get associated drm_crtc: */
|
|
drmcrtc = &rdev->mode_info.crtcs[crtc]->base;
|
|
+ if (!drmcrtc)
|
|
+ return -EINVAL;
|
|
|
|
/* Helper routine in DRM core does all the work: */
|
|
return drm_calc_vbltimestamp_from_scanoutpos(dev, crtc, max_error,
|
|
diff --git a/drivers/gpu/drm/radeon/radeon_ttm.c b/drivers/gpu/drm/radeon/radeon_ttm.c
|
|
index 49b55ed..15042d0 100644
|
|
--- a/drivers/gpu/drm/radeon/radeon_ttm.c
|
|
+++ b/drivers/gpu/drm/radeon/radeon_ttm.c
|
|
@@ -188,7 +188,7 @@ static void radeon_evict_flags(struct ttm_buffer_object *bo,
|
|
rbo = container_of(bo, struct radeon_bo, tbo);
|
|
switch (bo->mem.mem_type) {
|
|
case TTM_PL_VRAM:
|
|
- if (rbo->rdev->ring[RADEON_RING_TYPE_GFX_INDEX].ready == false)
|
|
+ if (rbo->rdev->ring[radeon_copy_ring_index(rbo->rdev)].ready == false)
|
|
radeon_ttm_placement_from_domain(rbo, RADEON_GEM_DOMAIN_CPU);
|
|
else
|
|
radeon_ttm_placement_from_domain(rbo, RADEON_GEM_DOMAIN_GTT);
|
|
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_fence.c b/drivers/gpu/drm/vmwgfx/vmwgfx_fence.c
|
|
index 7e07433..992b46b 100644
|
|
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_fence.c
|
|
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_fence.c
|
|
@@ -485,14 +485,7 @@ void vmw_fence_obj_flush(struct vmw_fence_obj *fence)
|
|
|
|
static void vmw_fence_destroy(struct vmw_fence_obj *fence)
|
|
{
|
|
- struct vmw_fence_manager *fman = fence->fman;
|
|
-
|
|
kfree(fence);
|
|
- /*
|
|
- * Free kernel space accounting.
|
|
- */
|
|
- ttm_mem_global_free(vmw_mem_glob(fman->dev_priv),
|
|
- fman->fence_size);
|
|
}
|
|
|
|
int vmw_fence_create(struct vmw_fence_manager *fman,
|
|
@@ -500,20 +493,12 @@ int vmw_fence_create(struct vmw_fence_manager *fman,
|
|
uint32_t mask,
|
|
struct vmw_fence_obj **p_fence)
|
|
{
|
|
- struct ttm_mem_global *mem_glob = vmw_mem_glob(fman->dev_priv);
|
|
struct vmw_fence_obj *fence;
|
|
int ret;
|
|
|
|
- ret = ttm_mem_global_alloc(mem_glob, fman->fence_size,
|
|
- false, false);
|
|
- if (unlikely(ret != 0))
|
|
- return ret;
|
|
-
|
|
fence = kzalloc(sizeof(*fence), GFP_KERNEL);
|
|
- if (unlikely(fence == NULL)) {
|
|
- ret = -ENOMEM;
|
|
- goto out_no_object;
|
|
- }
|
|
+ if (unlikely(fence == NULL))
|
|
+ return -ENOMEM;
|
|
|
|
ret = vmw_fence_obj_init(fman, fence, seqno, mask,
|
|
vmw_fence_destroy);
|
|
@@ -525,8 +510,6 @@ int vmw_fence_create(struct vmw_fence_manager *fman,
|
|
|
|
out_err_init:
|
|
kfree(fence);
|
|
-out_no_object:
|
|
- ttm_mem_global_free(mem_glob, fman->fence_size);
|
|
return ret;
|
|
}
|
|
|
|
@@ -1049,6 +1032,8 @@ int vmw_event_fence_action_create(struct drm_file *file_priv,
|
|
if (ret != 0)
|
|
goto out_no_queue;
|
|
|
|
+ return 0;
|
|
+
|
|
out_no_queue:
|
|
event->base.destroy(&event->base);
|
|
out_no_event:
|
|
@@ -1123,17 +1108,10 @@ int vmw_fence_event_ioctl(struct drm_device *dev, void *data,
|
|
|
|
BUG_ON(fence == NULL);
|
|
|
|
- if (arg->flags & DRM_VMW_FE_FLAG_REQ_TIME)
|
|
- ret = vmw_event_fence_action_create(file_priv, fence,
|
|
- arg->flags,
|
|
- arg->user_data,
|
|
- true);
|
|
- else
|
|
- ret = vmw_event_fence_action_create(file_priv, fence,
|
|
- arg->flags,
|
|
- arg->user_data,
|
|
- true);
|
|
-
|
|
+ ret = vmw_event_fence_action_create(file_priv, fence,
|
|
+ arg->flags,
|
|
+ arg->user_data,
|
|
+ true);
|
|
if (unlikely(ret != 0)) {
|
|
if (ret != -ERESTARTSYS)
|
|
DRM_ERROR("Failed to attach event to fence.\n");
|
|
diff --git a/drivers/hid/hid-roccat-pyra.c b/drivers/hid/hid-roccat-pyra.c
|
|
index df05c1b1..5346647 100644
|
|
--- a/drivers/hid/hid-roccat-pyra.c
|
|
+++ b/drivers/hid/hid-roccat-pyra.c
|
|
@@ -35,6 +35,8 @@ static struct class *pyra_class;
|
|
static void profile_activated(struct pyra_device *pyra,
|
|
unsigned int new_profile)
|
|
{
|
|
+ if (new_profile >= ARRAY_SIZE(pyra->profile_settings))
|
|
+ return;
|
|
pyra->actual_profile = new_profile;
|
|
pyra->actual_cpi = pyra->profile_settings[pyra->actual_profile].y_cpi;
|
|
}
|
|
@@ -299,10 +301,15 @@ static ssize_t pyra_sysfs_write_settings(struct file *fp,
|
|
int retval = 0;
|
|
int difference;
|
|
struct pyra_roccat_report roccat_report;
|
|
+ struct pyra_settings const *settings;
|
|
|
|
if (off != 0 || count != sizeof(struct pyra_settings))
|
|
return -EINVAL;
|
|
|
|
+ settings = (struct pyra_settings const *)buf;
|
|
+ if (settings->startup_profile >= ARRAY_SIZE(pyra->profile_settings))
|
|
+ return -EINVAL;
|
|
+
|
|
mutex_lock(&pyra->pyra_lock);
|
|
difference = memcmp(buf, &pyra->settings, sizeof(struct pyra_settings));
|
|
if (difference) {
|
|
diff --git a/drivers/hv/vmbus_drv.c b/drivers/hv/vmbus_drv.c
|
|
index 10619b3..1ec309d 100644
|
|
--- a/drivers/hv/vmbus_drv.c
|
|
+++ b/drivers/hv/vmbus_drv.c
|
|
@@ -681,7 +681,7 @@ int vmbus_device_register(struct hv_device *child_device_obj)
|
|
if (ret)
|
|
pr_err("Unable to register child device\n");
|
|
else
|
|
- pr_info("child device %s registered\n",
|
|
+ pr_debug("child device %s registered\n",
|
|
dev_name(&child_device_obj->device));
|
|
|
|
return ret;
|
|
@@ -693,14 +693,14 @@ int vmbus_device_register(struct hv_device *child_device_obj)
|
|
*/
|
|
void vmbus_device_unregister(struct hv_device *device_obj)
|
|
{
|
|
+ pr_debug("child device %s unregistered\n",
|
|
+ dev_name(&device_obj->device));
|
|
+
|
|
/*
|
|
* Kick off the process of unregistering the device.
|
|
* This will call vmbus_remove() and eventually vmbus_device_release()
|
|
*/
|
|
device_unregister(&device_obj->device);
|
|
-
|
|
- pr_info("child device %s unregistered\n",
|
|
- dev_name(&device_obj->device));
|
|
}
|
|
|
|
|
|
diff --git a/drivers/i2c/busses/i2c-davinci.c b/drivers/i2c/busses/i2c-davinci.c
|
|
index 79b4bcb..1837fe6 100644
|
|
--- a/drivers/i2c/busses/i2c-davinci.c
|
|
+++ b/drivers/i2c/busses/i2c-davinci.c
|
|
@@ -416,11 +416,9 @@ i2c_davinci_xfer_msg(struct i2c_adapter *adap, struct i2c_msg *msg, int stop)
|
|
if (dev->cmd_err & DAVINCI_I2C_STR_NACK) {
|
|
if (msg->flags & I2C_M_IGNORE_NAK)
|
|
return msg->len;
|
|
- if (stop) {
|
|
- w = davinci_i2c_read_reg(dev, DAVINCI_I2C_MDR_REG);
|
|
- w |= DAVINCI_I2C_MDR_STP;
|
|
- davinci_i2c_write_reg(dev, DAVINCI_I2C_MDR_REG, w);
|
|
- }
|
|
+ w = davinci_i2c_read_reg(dev, DAVINCI_I2C_MDR_REG);
|
|
+ w |= DAVINCI_I2C_MDR_STP;
|
|
+ davinci_i2c_write_reg(dev, DAVINCI_I2C_MDR_REG, w);
|
|
return -EREMOTEIO;
|
|
}
|
|
return -EIO;
|
|
diff --git a/drivers/input/joystick/xpad.c b/drivers/input/joystick/xpad.c
|
|
index 42f7b25..b4e8db8 100644
|
|
--- a/drivers/input/joystick/xpad.c
|
|
+++ b/drivers/input/joystick/xpad.c
|
|
@@ -979,9 +979,19 @@ static int xpad_probe(struct usb_interface *intf, const struct usb_device_id *id
|
|
}
|
|
|
|
ep_irq_in = &intf->cur_altsetting->endpoint[1].desc;
|
|
- usb_fill_bulk_urb(xpad->bulk_out, udev,
|
|
- usb_sndbulkpipe(udev, ep_irq_in->bEndpointAddress),
|
|
- xpad->bdata, XPAD_PKT_LEN, xpad_bulk_out, xpad);
|
|
+ if (usb_endpoint_is_bulk_out(ep_irq_in)) {
|
|
+ usb_fill_bulk_urb(xpad->bulk_out, udev,
|
|
+ usb_sndbulkpipe(udev,
|
|
+ ep_irq_in->bEndpointAddress),
|
|
+ xpad->bdata, XPAD_PKT_LEN,
|
|
+ xpad_bulk_out, xpad);
|
|
+ } else {
|
|
+ usb_fill_int_urb(xpad->bulk_out, udev,
|
|
+ usb_sndintpipe(udev,
|
|
+ ep_irq_in->bEndpointAddress),
|
|
+ xpad->bdata, XPAD_PKT_LEN,
|
|
+ xpad_bulk_out, xpad, 0);
|
|
+ }
|
|
|
|
/*
|
|
* Submit the int URB immediately rather than waiting for open
|
|
diff --git a/drivers/input/serio/i8042-x86ia64io.h b/drivers/input/serio/i8042-x86ia64io.h
|
|
index ce715b1..78227f3 100644
|
|
--- a/drivers/input/serio/i8042-x86ia64io.h
|
|
+++ b/drivers/input/serio/i8042-x86ia64io.h
|
|
@@ -408,6 +408,13 @@ static const struct dmi_system_id __initconst i8042_dmi_nomux_table[] = {
|
|
},
|
|
},
|
|
{
|
|
+ /* Acer Aspire 7738 */
|
|
+ .matches = {
|
|
+ DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
|
|
+ DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 7738"),
|
|
+ },
|
|
+ },
|
|
+ {
|
|
/* Gericom Bellagio */
|
|
.matches = {
|
|
DMI_MATCH(DMI_SYS_VENDOR, "Gericom"),
|
|
@@ -721,6 +728,35 @@ static const struct dmi_system_id __initconst i8042_dmi_dritek_table[] = {
|
|
{ }
|
|
};
|
|
|
|
+/*
|
|
+ * Some laptops need keyboard reset before probing for the trackpad to get
|
|
+ * it detected, initialised & finally work.
|
|
+ */
|
|
+static const struct dmi_system_id __initconst i8042_dmi_kbdreset_table[] = {
|
|
+ {
|
|
+ /* Gigabyte P35 v2 - Elantech touchpad */
|
|
+ .matches = {
|
|
+ DMI_MATCH(DMI_SYS_VENDOR, "GIGABYTE"),
|
|
+ DMI_MATCH(DMI_PRODUCT_NAME, "P35V2"),
|
|
+ },
|
|
+ },
|
|
+ {
|
|
+ /* Aorus branded Gigabyte X3 Plus - Elantech touchpad */
|
|
+ .matches = {
|
|
+ DMI_MATCH(DMI_SYS_VENDOR, "GIGABYTE"),
|
|
+ DMI_MATCH(DMI_PRODUCT_NAME, "X3"),
|
|
+ },
|
|
+ },
|
|
+ {
|
|
+ /* Gigabyte P34 - Elantech touchpad */
|
|
+ .matches = {
|
|
+ DMI_MATCH(DMI_SYS_VENDOR, "GIGABYTE"),
|
|
+ DMI_MATCH(DMI_PRODUCT_NAME, "P34"),
|
|
+ },
|
|
+ },
|
|
+ { }
|
|
+};
|
|
+
|
|
#endif /* CONFIG_X86 */
|
|
|
|
#ifdef CONFIG_PNP
|
|
@@ -1001,6 +1037,9 @@ static int __init i8042_platform_init(void)
|
|
if (dmi_check_system(i8042_dmi_dritek_table))
|
|
i8042_dritek = true;
|
|
|
|
+ if (dmi_check_system(i8042_dmi_kbdreset_table))
|
|
+ i8042_kbdreset = true;
|
|
+
|
|
/*
|
|
* A20 was already enabled during early kernel init. But some buggy
|
|
* BIOSes (in MSI Laptops) require A20 to be enabled using 8042 to
|
|
diff --git a/drivers/input/serio/i8042.c b/drivers/input/serio/i8042.c
|
|
index 8656441..178e75d 100644
|
|
--- a/drivers/input/serio/i8042.c
|
|
+++ b/drivers/input/serio/i8042.c
|
|
@@ -67,6 +67,10 @@ static bool i8042_notimeout;
|
|
module_param_named(notimeout, i8042_notimeout, bool, 0);
|
|
MODULE_PARM_DESC(notimeout, "Ignore timeouts signalled by i8042");
|
|
|
|
+static bool i8042_kbdreset;
|
|
+module_param_named(kbdreset, i8042_kbdreset, bool, 0);
|
|
+MODULE_PARM_DESC(kbdreset, "Reset device connected to KBD port");
|
|
+
|
|
#ifdef CONFIG_X86
|
|
static bool i8042_dritek;
|
|
module_param_named(dritek, i8042_dritek, bool, 0);
|
|
@@ -783,6 +787,16 @@ static int __init i8042_check_aux(void)
|
|
return -1;
|
|
|
|
/*
|
|
+ * Reset keyboard (needed on some laptops to successfully detect
|
|
+ * touchpad, e.g., some Gigabyte laptop models with Elantech
|
|
+ * touchpads).
|
|
+ */
|
|
+ if (i8042_kbdreset) {
|
|
+ pr_warn("Attempting to reset device connected to KBD port\n");
|
|
+ i8042_kbd_write(NULL, (unsigned char) 0xff);
|
|
+ }
|
|
+
|
|
+/*
|
|
* Test AUX IRQ delivery to make sure BIOS did not grab the IRQ and
|
|
* used it for a PCI card or somethig else.
|
|
*/
|
|
diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c
|
|
index a5f4359..2e48b22 100644
|
|
--- a/drivers/iommu/intel-iommu.c
|
|
+++ b/drivers/iommu/intel-iommu.c
|
|
@@ -1792,7 +1792,7 @@ static int __domain_mapping(struct dmar_domain *domain, unsigned long iov_pfn,
|
|
struct dma_pte *first_pte = NULL, *pte = NULL;
|
|
phys_addr_t uninitialized_var(pteval);
|
|
int addr_width = agaw_to_width(domain->agaw) - VTD_PAGE_SHIFT;
|
|
- unsigned long sg_res;
|
|
+ unsigned long sg_res = 0;
|
|
unsigned int largepage_lvl = 0;
|
|
unsigned long lvl_pages = 0;
|
|
|
|
@@ -1803,10 +1803,8 @@ static int __domain_mapping(struct dmar_domain *domain, unsigned long iov_pfn,
|
|
|
|
prot &= DMA_PTE_READ | DMA_PTE_WRITE | DMA_PTE_SNP;
|
|
|
|
- if (sg)
|
|
- sg_res = 0;
|
|
- else {
|
|
- sg_res = nr_pages + 1;
|
|
+ if (!sg) {
|
|
+ sg_res = nr_pages;
|
|
pteval = ((phys_addr_t)phys_pfn << VTD_PAGE_SHIFT) | prot;
|
|
}
|
|
|
|
diff --git a/drivers/mfd/tc6393xb.c b/drivers/mfd/tc6393xb.c
|
|
index 9612264..b69d91b 100644
|
|
--- a/drivers/mfd/tc6393xb.c
|
|
+++ b/drivers/mfd/tc6393xb.c
|
|
@@ -263,6 +263,17 @@ static int tc6393xb_ohci_disable(struct platform_device *dev)
|
|
return 0;
|
|
}
|
|
|
|
+static int tc6393xb_ohci_suspend(struct platform_device *dev)
|
|
+{
|
|
+ struct tc6393xb_platform_data *tcpd = dev_get_platdata(dev->dev.parent);
|
|
+
|
|
+ /* We can't properly store/restore OHCI state, so fail here */
|
|
+ if (tcpd->resume_restore)
|
|
+ return -EBUSY;
|
|
+
|
|
+ return tc6393xb_ohci_disable(dev);
|
|
+}
|
|
+
|
|
static int tc6393xb_fb_enable(struct platform_device *dev)
|
|
{
|
|
struct tc6393xb *tc6393xb = dev_get_drvdata(dev->dev.parent);
|
|
@@ -403,7 +414,7 @@ static struct mfd_cell __devinitdata tc6393xb_cells[] = {
|
|
.num_resources = ARRAY_SIZE(tc6393xb_ohci_resources),
|
|
.resources = tc6393xb_ohci_resources,
|
|
.enable = tc6393xb_ohci_enable,
|
|
- .suspend = tc6393xb_ohci_disable,
|
|
+ .suspend = tc6393xb_ohci_suspend,
|
|
.resume = tc6393xb_ohci_enable,
|
|
.disable = tc6393xb_ohci_disable,
|
|
},
|
|
diff --git a/drivers/mtd/ubi/upd.c b/drivers/mtd/ubi/upd.c
|
|
index 425bf5a..068a246 100644
|
|
--- a/drivers/mtd/ubi/upd.c
|
|
+++ b/drivers/mtd/ubi/upd.c
|
|
@@ -135,6 +135,10 @@ int ubi_start_update(struct ubi_device *ubi, struct ubi_volume *vol,
|
|
ubi_assert(!vol->updating && !vol->changing_leb);
|
|
vol->updating = 1;
|
|
|
|
+ vol->upd_buf = vmalloc(ubi->leb_size);
|
|
+ if (!vol->upd_buf)
|
|
+ return -ENOMEM;
|
|
+
|
|
err = set_update_marker(ubi, vol);
|
|
if (err)
|
|
return err;
|
|
@@ -154,14 +158,12 @@ int ubi_start_update(struct ubi_device *ubi, struct ubi_volume *vol,
|
|
err = clear_update_marker(ubi, vol, 0);
|
|
if (err)
|
|
return err;
|
|
+
|
|
+ vfree(vol->upd_buf);
|
|
vol->updating = 0;
|
|
return 0;
|
|
}
|
|
|
|
- vol->upd_buf = vmalloc(ubi->leb_size);
|
|
- if (!vol->upd_buf)
|
|
- return -ENOMEM;
|
|
-
|
|
vol->upd_ebs = div_u64(bytes + vol->usable_leb_size - 1,
|
|
vol->usable_leb_size);
|
|
vol->upd_bytes = bytes;
|
|
diff --git a/drivers/net/can/dev.c b/drivers/net/can/dev.c
|
|
index d4f7f95..88c39e4 100644
|
|
--- a/drivers/net/can/dev.c
|
|
+++ b/drivers/net/can/dev.c
|
|
@@ -612,10 +612,14 @@ static int can_changelink(struct net_device *dev,
|
|
if (dev->flags & IFF_UP)
|
|
return -EBUSY;
|
|
cm = nla_data(data[IFLA_CAN_CTRLMODE]);
|
|
- if (cm->flags & ~priv->ctrlmode_supported)
|
|
+
|
|
+ /* check whether changed bits are allowed to be modified */
|
|
+ if (cm->mask & ~priv->ctrlmode_supported)
|
|
return -EOPNOTSUPP;
|
|
+
|
|
+ /* clear bits to be modified and copy the flag values */
|
|
priv->ctrlmode &= ~cm->mask;
|
|
- priv->ctrlmode |= cm->flags;
|
|
+ priv->ctrlmode |= (cm->flags & cm->mask);
|
|
}
|
|
|
|
if (data[IFLA_CAN_BITTIMING]) {
|
|
diff --git a/drivers/net/can/usb/peak_usb/pcan_usb_core.c b/drivers/net/can/usb/peak_usb/pcan_usb_core.c
|
|
index d2f91f7..925c7e1 100644
|
|
--- a/drivers/net/can/usb/peak_usb/pcan_usb_core.c
|
|
+++ b/drivers/net/can/usb/peak_usb/pcan_usb_core.c
|
|
@@ -737,7 +737,7 @@ static int peak_usb_create_dev(struct peak_usb_adapter *peak_usb_adapter,
|
|
dev_err(&intf->dev, "%s: couldn't alloc cmd buffer\n",
|
|
PCAN_USB_DRIVER_NAME);
|
|
err = -ENOMEM;
|
|
- goto lbl_set_intf_data;
|
|
+ goto lbl_free_candev;
|
|
}
|
|
|
|
dev->udev = usb_dev;
|
|
@@ -776,7 +776,7 @@ static int peak_usb_create_dev(struct peak_usb_adapter *peak_usb_adapter,
|
|
err = register_candev(netdev);
|
|
if (err) {
|
|
dev_err(&intf->dev, "couldn't register CAN device: %d\n", err);
|
|
- goto lbl_free_cmd_buf;
|
|
+ goto lbl_restore_intf_data;
|
|
}
|
|
|
|
if (dev->prev_siblings)
|
|
@@ -789,14 +789,14 @@ static int peak_usb_create_dev(struct peak_usb_adapter *peak_usb_adapter,
|
|
if (dev->adapter->dev_init) {
|
|
err = dev->adapter->dev_init(dev);
|
|
if (err)
|
|
- goto lbl_free_cmd_buf;
|
|
+ goto lbl_unregister_candev;
|
|
}
|
|
|
|
/* set bus off */
|
|
if (dev->adapter->dev_set_bus) {
|
|
err = dev->adapter->dev_set_bus(dev, 0);
|
|
if (err)
|
|
- goto lbl_free_cmd_buf;
|
|
+ goto lbl_unregister_candev;
|
|
}
|
|
|
|
/* get device number early */
|
|
@@ -808,11 +808,14 @@ static int peak_usb_create_dev(struct peak_usb_adapter *peak_usb_adapter,
|
|
|
|
return 0;
|
|
|
|
-lbl_free_cmd_buf:
|
|
- kfree(dev->cmd_buf);
|
|
+lbl_unregister_candev:
|
|
+ unregister_candev(netdev);
|
|
|
|
-lbl_set_intf_data:
|
|
+lbl_restore_intf_data:
|
|
usb_set_intfdata(intf, dev->prev_siblings);
|
|
+ kfree(dev->cmd_buf);
|
|
+
|
|
+lbl_free_candev:
|
|
free_candev(netdev);
|
|
|
|
return err;
|
|
diff --git a/drivers/net/can/usb/peak_usb/pcan_usb_pro.c b/drivers/net/can/usb/peak_usb/pcan_usb_pro.c
|
|
index c95913a..5fe28be 100644
|
|
--- a/drivers/net/can/usb/peak_usb/pcan_usb_pro.c
|
|
+++ b/drivers/net/can/usb/peak_usb/pcan_usb_pro.c
|
|
@@ -333,8 +333,6 @@ static int pcan_usb_pro_send_req(struct peak_usb_device *dev, int req_id,
|
|
if (!(dev->state & PCAN_USB_STATE_CONNECTED))
|
|
return 0;
|
|
|
|
- memset(req_addr, '\0', req_size);
|
|
-
|
|
req_type = USB_TYPE_VENDOR | USB_RECIP_OTHER;
|
|
|
|
switch (req_id) {
|
|
@@ -345,6 +343,7 @@ static int pcan_usb_pro_send_req(struct peak_usb_device *dev, int req_id,
|
|
default:
|
|
p = usb_rcvctrlpipe(dev->udev, 0);
|
|
req_type |= USB_DIR_IN;
|
|
+ memset(req_addr, '\0', req_size);
|
|
break;
|
|
}
|
|
|
|
diff --git a/drivers/net/wireless/ath/ath5k/qcu.c b/drivers/net/wireless/ath/ath5k/qcu.c
|
|
index 30b50f9..19ba204 100644
|
|
--- a/drivers/net/wireless/ath/ath5k/qcu.c
|
|
+++ b/drivers/net/wireless/ath/ath5k/qcu.c
|
|
@@ -223,13 +223,7 @@ ath5k_hw_setup_tx_queue(struct ath5k_hw *ah, enum ath5k_tx_queue queue_type,
|
|
} else {
|
|
switch (queue_type) {
|
|
case AR5K_TX_QUEUE_DATA:
|
|
- for (queue = AR5K_TX_QUEUE_ID_DATA_MIN;
|
|
- ah->ah_txq[queue].tqi_type !=
|
|
- AR5K_TX_QUEUE_INACTIVE; queue++) {
|
|
-
|
|
- if (queue > AR5K_TX_QUEUE_ID_DATA_MAX)
|
|
- return -EINVAL;
|
|
- }
|
|
+ queue = queue_info->tqi_subtype;
|
|
break;
|
|
case AR5K_TX_QUEUE_UAPSD:
|
|
queue = AR5K_TX_QUEUE_ID_UAPSD;
|
|
diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h
|
|
index f49be96..d4f09b4 100644
|
|
--- a/drivers/net/wireless/ath/ath9k/hw.h
|
|
+++ b/drivers/net/wireless/ath/ath9k/hw.h
|
|
@@ -181,8 +181,8 @@
|
|
#define PAPRD_IDEAL_AGC2_PWR_RANGE 0xe0
|
|
|
|
enum ath_hw_txq_subtype {
|
|
- ATH_TXQ_AC_BE = 0,
|
|
- ATH_TXQ_AC_BK = 1,
|
|
+ ATH_TXQ_AC_BK = 0,
|
|
+ ATH_TXQ_AC_BE = 1,
|
|
ATH_TXQ_AC_VI = 2,
|
|
ATH_TXQ_AC_VO = 3,
|
|
};
|
|
diff --git a/drivers/net/wireless/ath/ath9k/mac.c b/drivers/net/wireless/ath/ath9k/mac.c
|
|
index f7bd253..2d628f9 100644
|
|
--- a/drivers/net/wireless/ath/ath9k/mac.c
|
|
+++ b/drivers/net/wireless/ath/ath9k/mac.c
|
|
@@ -303,14 +303,7 @@ int ath9k_hw_setuptxqueue(struct ath_hw *ah, enum ath9k_tx_queue type,
|
|
q = ATH9K_NUM_TX_QUEUES - 3;
|
|
break;
|
|
case ATH9K_TX_QUEUE_DATA:
|
|
- for (q = 0; q < ATH9K_NUM_TX_QUEUES; q++)
|
|
- if (ah->txq[q].tqi_type ==
|
|
- ATH9K_TX_QUEUE_INACTIVE)
|
|
- break;
|
|
- if (q == ATH9K_NUM_TX_QUEUES) {
|
|
- ath_err(common, "No available TX queue\n");
|
|
- return -1;
|
|
- }
|
|
+ q = qinfo->tqi_subtype;
|
|
break;
|
|
default:
|
|
ath_err(common, "Invalid TX queue type: %u\n", type);
|
|
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
|
|
index 63e0199..d62ad0b 100644
|
|
--- a/drivers/pci/probe.c
|
|
+++ b/drivers/pci/probe.c
|
|
@@ -254,14 +254,17 @@ int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type,
|
|
res->flags |= IORESOURCE_SIZEALIGN;
|
|
if (res->flags & IORESOURCE_IO) {
|
|
l &= PCI_BASE_ADDRESS_IO_MASK;
|
|
+ sz &= PCI_BASE_ADDRESS_IO_MASK;
|
|
mask = PCI_BASE_ADDRESS_IO_MASK & (u32) IO_SPACE_LIMIT;
|
|
} else {
|
|
l &= PCI_BASE_ADDRESS_MEM_MASK;
|
|
+ sz &= PCI_BASE_ADDRESS_MEM_MASK;
|
|
mask = (u32)PCI_BASE_ADDRESS_MEM_MASK;
|
|
}
|
|
} else {
|
|
res->flags |= (l & IORESOURCE_ROM_ENABLE);
|
|
l &= PCI_ROM_ADDRESS_MASK;
|
|
+ sz &= PCI_ROM_ADDRESS_MASK;
|
|
mask = (u32)PCI_ROM_ADDRESS_MASK;
|
|
}
|
|
|
|
diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c
|
|
index e587d00..ffde183 100644
|
|
--- a/drivers/pci/quirks.c
|
|
+++ b/drivers/pci/quirks.c
|
|
@@ -327,19 +327,52 @@ static void __devinit quirk_s3_64M(struct pci_dev *dev)
|
|
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_S3, PCI_DEVICE_ID_S3_868, quirk_s3_64M);
|
|
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_S3, PCI_DEVICE_ID_S3_968, quirk_s3_64M);
|
|
|
|
+static void quirk_io(struct pci_dev *dev, int pos, unsigned size,
|
|
+ const char *name)
|
|
+{
|
|
+ u32 region;
|
|
+ struct pci_bus_region bus_region;
|
|
+ struct resource *res = dev->resource + pos;
|
|
+
|
|
+ pci_read_config_dword(dev, PCI_BASE_ADDRESS_0 + (pos << 2), ®ion);
|
|
+
|
|
+ if (!region)
|
|
+ return;
|
|
+
|
|
+ res->name = pci_name(dev);
|
|
+ res->flags = region & ~PCI_BASE_ADDRESS_IO_MASK;
|
|
+ res->flags |=
|
|
+ (IORESOURCE_IO | IORESOURCE_PCI_FIXED | IORESOURCE_SIZEALIGN);
|
|
+ region &= ~(size - 1);
|
|
+
|
|
+ /* Convert from PCI bus to resource space */
|
|
+ bus_region.start = region;
|
|
+ bus_region.end = region + size - 1;
|
|
+ pcibios_bus_to_resource(dev->bus, res, &bus_region);
|
|
+
|
|
+ dev_info(&dev->dev, FW_BUG "%s quirk: reg 0x%x: %pR\n",
|
|
+ name, PCI_BASE_ADDRESS_0 + (pos << 2), res);
|
|
+}
|
|
+
|
|
/*
|
|
* Some CS5536 BIOSes (for example, the Soekris NET5501 board w/ comBIOS
|
|
* ver. 1.33 20070103) don't set the correct ISA PCI region header info.
|
|
* BAR0 should be 8 bytes; instead, it may be set to something like 8k
|
|
* (which conflicts w/ BAR1's memory range).
|
|
+ *
|
|
+ * CS553x's ISA PCI BARs may also be read-only (ref:
|
|
+ * https://bugzilla.kernel.org/show_bug.cgi?id=85991 - Comment #4 forward).
|
|
*/
|
|
static void __devinit quirk_cs5536_vsa(struct pci_dev *dev)
|
|
{
|
|
+ static char *name = "CS5536 ISA bridge";
|
|
+
|
|
if (pci_resource_len(dev, 0) != 8) {
|
|
- struct resource *res = &dev->resource[0];
|
|
- res->end = res->start + 8 - 1;
|
|
- dev_info(&dev->dev, "CS5536 ISA bridge bug detected "
|
|
- "(incorrect header); workaround applied.\n");
|
|
+ quirk_io(dev, 0, 8, name); /* SMB */
|
|
+ quirk_io(dev, 1, 256, name); /* GPIO */
|
|
+ quirk_io(dev, 2, 64, name); /* MFGPT */
|
|
+ dev_info(&dev->dev, "%s bug detected (incorrect header); workaround applied\n",
|
|
+ name);
|
|
}
|
|
}
|
|
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_CS5536_ISA, quirk_cs5536_vsa);
|
|
diff --git a/drivers/platform/x86/hp_accel.c b/drivers/platform/x86/hp_accel.c
|
|
index 0076fea..be6b648 100644
|
|
--- a/drivers/platform/x86/hp_accel.c
|
|
+++ b/drivers/platform/x86/hp_accel.c
|
|
@@ -237,6 +237,7 @@ static struct dmi_system_id lis3lv02d_dmi_ids[] = {
|
|
AXIS_DMI_MATCH("HPB64xx", "HP ProBook 64", xy_swap),
|
|
AXIS_DMI_MATCH("HPB64xx", "HP EliteBook 84", xy_swap),
|
|
AXIS_DMI_MATCH("HPB65xx", "HP ProBook 65", x_inverted),
|
|
+ AXIS_DMI_MATCH("HPZBook15", "HP ZBook 15", x_inverted),
|
|
{ NULL, }
|
|
/* Laptop models without axis info (yet):
|
|
* "NC6910" "HP Compaq 6910"
|
|
diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c
|
|
index c45c2dc..98ccd6a 100644
|
|
--- a/drivers/regulator/core.c
|
|
+++ b/drivers/regulator/core.c
|
|
@@ -1427,12 +1427,14 @@ void regulator_put(struct regulator *regulator)
|
|
device_remove_file(regulator->dev, ®ulator->dev_attr);
|
|
kfree(regulator->dev_attr.attr.name);
|
|
}
|
|
+ mutex_lock(&rdev->mutex);
|
|
kfree(regulator->supply_name);
|
|
list_del(®ulator->list);
|
|
kfree(regulator);
|
|
|
|
rdev->open_count--;
|
|
rdev->exclusive = 0;
|
|
+ mutex_unlock(&rdev->mutex);
|
|
|
|
module_put(rdev->owner);
|
|
mutex_unlock(®ulator_list_mutex);
|
|
diff --git a/drivers/s390/char/con3215.c b/drivers/s390/char/con3215.c
|
|
index 4f9f1dc..fa47d8d 100644
|
|
--- a/drivers/s390/char/con3215.c
|
|
+++ b/drivers/s390/char/con3215.c
|
|
@@ -997,12 +997,26 @@ static int tty3215_write(struct tty_struct * tty,
|
|
const unsigned char *buf, int count)
|
|
{
|
|
struct raw3215_info *raw;
|
|
+ int i, written;
|
|
|
|
if (!tty)
|
|
return 0;
|
|
raw = (struct raw3215_info *) tty->driver_data;
|
|
- raw3215_write(raw, buf, count);
|
|
- return count;
|
|
+ written = count;
|
|
+ while (count > 0) {
|
|
+ for (i = 0; i < count; i++)
|
|
+ if (buf[i] == '\t' || buf[i] == '\n')
|
|
+ break;
|
|
+ raw3215_write(raw, buf, i);
|
|
+ count -= i;
|
|
+ buf += i;
|
|
+ if (count > 0) {
|
|
+ raw3215_putchar(raw, *buf);
|
|
+ count--;
|
|
+ buf++;
|
|
+ }
|
|
+ }
|
|
+ return written;
|
|
}
|
|
|
|
/*
|
|
@@ -1149,7 +1163,7 @@ static int __init tty3215_init(void)
|
|
driver->subtype = SYSTEM_TYPE_TTY;
|
|
driver->init_termios = tty_std_termios;
|
|
driver->init_termios.c_iflag = IGNBRK | IGNPAR;
|
|
- driver->init_termios.c_oflag = ONLCR | XTABS;
|
|
+ driver->init_termios.c_oflag = ONLCR;
|
|
driver->init_termios.c_lflag = ISIG;
|
|
driver->flags = TTY_DRIVER_REAL_RAW;
|
|
tty_set_operations(driver, &tty3215_ops);
|
|
diff --git a/drivers/scsi/NCR5380.c b/drivers/scsi/NCR5380.c
|
|
index 165e4dd86..a57f85a 100644
|
|
--- a/drivers/scsi/NCR5380.c
|
|
+++ b/drivers/scsi/NCR5380.c
|
|
@@ -2662,14 +2662,14 @@ static void NCR5380_dma_complete(NCR5380_instance * instance) {
|
|
*
|
|
* Purpose : abort a command
|
|
*
|
|
- * Inputs : cmd - the Scsi_Cmnd to abort, code - code to set the
|
|
- * host byte of the result field to, if zero DID_ABORTED is
|
|
+ * Inputs : cmd - the Scsi_Cmnd to abort, code - code to set the
|
|
+ * host byte of the result field to, if zero DID_ABORTED is
|
|
* used.
|
|
*
|
|
- * Returns : 0 - success, -1 on failure.
|
|
+ * Returns : SUCCESS - success, FAILED on failure.
|
|
*
|
|
- * XXX - there is no way to abort the command that is currently
|
|
- * connected, you have to wait for it to complete. If this is
|
|
+ * XXX - there is no way to abort the command that is currently
|
|
+ * connected, you have to wait for it to complete. If this is
|
|
* a problem, we could implement longjmp() / setjmp(), setjmp()
|
|
* called where the loop started in NCR5380_main().
|
|
*
|
|
@@ -2719,7 +2719,7 @@ static int NCR5380_abort(Scsi_Cmnd * cmd) {
|
|
* aborted flag and get back into our main loop.
|
|
*/
|
|
|
|
- return 0;
|
|
+ return SUCCESS;
|
|
}
|
|
#endif
|
|
|
|
diff --git a/drivers/scsi/aha1740.c b/drivers/scsi/aha1740.c
|
|
index a3e6ed3..d0fa3e7 100644
|
|
--- a/drivers/scsi/aha1740.c
|
|
+++ b/drivers/scsi/aha1740.c
|
|
@@ -550,7 +550,7 @@ static int aha1740_eh_abort_handler (Scsi_Cmnd *dummy)
|
|
* quiet as possible...
|
|
*/
|
|
|
|
- return 0;
|
|
+ return SUCCESS;
|
|
}
|
|
|
|
static struct scsi_host_template aha1740_template = {
|
|
diff --git a/drivers/scsi/atari_NCR5380.c b/drivers/scsi/atari_NCR5380.c
|
|
index 2db79b4..589c2a3 100644
|
|
--- a/drivers/scsi/atari_NCR5380.c
|
|
+++ b/drivers/scsi/atari_NCR5380.c
|
|
@@ -2638,7 +2638,7 @@ static void NCR5380_reselect(struct Scsi_Host *instance)
|
|
* host byte of the result field to, if zero DID_ABORTED is
|
|
* used.
|
|
*
|
|
- * Returns : 0 - success, -1 on failure.
|
|
+ * Returns : SUCCESS - success, FAILED on failure.
|
|
*
|
|
* XXX - there is no way to abort the command that is currently
|
|
* connected, you have to wait for it to complete. If this is
|
|
diff --git a/drivers/scsi/bnx2fc/bnx2fc_fcoe.c b/drivers/scsi/bnx2fc/bnx2fc_fcoe.c
|
|
index c1c6a92..cabfbf3 100644
|
|
--- a/drivers/scsi/bnx2fc/bnx2fc_fcoe.c
|
|
+++ b/drivers/scsi/bnx2fc/bnx2fc_fcoe.c
|
|
@@ -406,6 +406,7 @@ static int bnx2fc_rcv(struct sk_buff *skb, struct net_device *dev,
|
|
struct fc_frame_header *fh;
|
|
struct fcoe_rcv_info *fr;
|
|
struct fcoe_percpu_s *bg;
|
|
+ struct sk_buff *tmp_skb;
|
|
unsigned short oxid;
|
|
|
|
interface = container_of(ptype, struct bnx2fc_interface,
|
|
@@ -417,6 +418,12 @@ static int bnx2fc_rcv(struct sk_buff *skb, struct net_device *dev,
|
|
goto err;
|
|
}
|
|
|
|
+ tmp_skb = skb_share_check(skb, GFP_ATOMIC);
|
|
+ if (!tmp_skb)
|
|
+ goto err;
|
|
+
|
|
+ skb = tmp_skb;
|
|
+
|
|
if (unlikely(eth_hdr(skb)->h_proto != htons(ETH_P_FCOE))) {
|
|
printk(KERN_ERR PFX "bnx2fc_rcv: Wrong FC type frame\n");
|
|
goto err;
|
|
diff --git a/drivers/scsi/megaraid.c b/drivers/scsi/megaraid.c
|
|
index 4d39a9f..152fe62 100644
|
|
--- a/drivers/scsi/megaraid.c
|
|
+++ b/drivers/scsi/megaraid.c
|
|
@@ -1967,7 +1967,7 @@ megaraid_abort_and_reset(adapter_t *adapter, Scsi_Cmnd *cmd, int aor)
|
|
cmd->device->id, cmd->device->lun);
|
|
|
|
if(list_empty(&adapter->pending_list))
|
|
- return FALSE;
|
|
+ return FAILED;
|
|
|
|
list_for_each_safe(pos, next, &adapter->pending_list) {
|
|
|
|
@@ -1990,7 +1990,7 @@ megaraid_abort_and_reset(adapter_t *adapter, Scsi_Cmnd *cmd, int aor)
|
|
(aor==SCB_ABORT) ? "ABORTING":"RESET",
|
|
scb->idx);
|
|
|
|
- return FALSE;
|
|
+ return FAILED;
|
|
}
|
|
else {
|
|
|
|
@@ -2015,12 +2015,12 @@ megaraid_abort_and_reset(adapter_t *adapter, Scsi_Cmnd *cmd, int aor)
|
|
list_add_tail(SCSI_LIST(cmd),
|
|
&adapter->completed_list);
|
|
|
|
- return TRUE;
|
|
+ return SUCCESS;
|
|
}
|
|
}
|
|
}
|
|
|
|
- return FALSE;
|
|
+ return FAILED;
|
|
}
|
|
|
|
static inline int
|
|
diff --git a/drivers/scsi/megaraid/megaraid_sas_base.c b/drivers/scsi/megaraid/megaraid_sas_base.c
|
|
index 6188700..bacd344 100644
|
|
--- a/drivers/scsi/megaraid/megaraid_sas_base.c
|
|
+++ b/drivers/scsi/megaraid/megaraid_sas_base.c
|
|
@@ -919,7 +919,7 @@ megasas_issue_blocked_abort_cmd(struct megasas_instance *instance,
|
|
abort_fr->abort_mfi_phys_addr_hi = 0;
|
|
|
|
cmd->sync_cmd = 1;
|
|
- cmd->cmd_status = 0xFF;
|
|
+ cmd->cmd_status = ENODATA;
|
|
|
|
instance->instancet->issue_dcmd(instance, cmd);
|
|
|
|
diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c
|
|
index 71459d5..e127ceb 100644
|
|
--- a/drivers/scsi/sd.c
|
|
+++ b/drivers/scsi/sd.c
|
|
@@ -2227,7 +2227,10 @@ sd_read_cache_type(struct scsi_disk *sdkp, unsigned char *buffer)
|
|
}
|
|
|
|
sdkp->DPOFUA = (data.device_specific & 0x10) != 0;
|
|
- if (sdkp->DPOFUA && !sdkp->device->use_10_for_rw) {
|
|
+ if (sdp->broken_fua) {
|
|
+ sd_printk(KERN_NOTICE, sdkp, "Disabling FUA\n");
|
|
+ sdkp->DPOFUA = 0;
|
|
+ } else if (sdkp->DPOFUA && !sdkp->device->use_10_for_rw) {
|
|
sd_printk(KERN_NOTICE, sdkp,
|
|
"Uses READ/WRITE(6), disabling FUA\n");
|
|
sdkp->DPOFUA = 0;
|
|
diff --git a/drivers/scsi/storvsc_drv.c b/drivers/scsi/storvsc_drv.c
|
|
index 446c023..a0df0fb 100644
|
|
--- a/drivers/scsi/storvsc_drv.c
|
|
+++ b/drivers/scsi/storvsc_drv.c
|
|
@@ -1359,13 +1359,12 @@ static int storvsc_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *scmnd)
|
|
if (ret == -EAGAIN) {
|
|
/* no more space */
|
|
|
|
- if (cmd_request->bounce_sgl_count) {
|
|
+ if (cmd_request->bounce_sgl_count)
|
|
destroy_bounce_buffer(cmd_request->bounce_sgl,
|
|
cmd_request->bounce_sgl_count);
|
|
|
|
- ret = SCSI_MLQUEUE_DEVICE_BUSY;
|
|
- goto queue_error;
|
|
- }
|
|
+ ret = SCSI_MLQUEUE_DEVICE_BUSY;
|
|
+ goto queue_error;
|
|
}
|
|
|
|
return 0;
|
|
diff --git a/drivers/scsi/sun3_NCR5380.c b/drivers/scsi/sun3_NCR5380.c
|
|
index 7e12a2e..9aaf084 100644
|
|
--- a/drivers/scsi/sun3_NCR5380.c
|
|
+++ b/drivers/scsi/sun3_NCR5380.c
|
|
@@ -2624,15 +2624,15 @@ static void NCR5380_reselect (struct Scsi_Host *instance)
|
|
* Purpose : abort a command
|
|
*
|
|
* Inputs : cmd - the struct scsi_cmnd to abort, code - code to set the
|
|
- * host byte of the result field to, if zero DID_ABORTED is
|
|
+ * host byte of the result field to, if zero DID_ABORTED is
|
|
* used.
|
|
*
|
|
- * Returns : 0 - success, -1 on failure.
|
|
+ * Returns : SUCCESS - success, FAILED on failure.
|
|
*
|
|
- * XXX - there is no way to abort the command that is currently
|
|
- * connected, you have to wait for it to complete. If this is
|
|
+ * XXX - there is no way to abort the command that is currently
|
|
+ * connected, you have to wait for it to complete. If this is
|
|
* a problem, we could implement longjmp() / setjmp(), setjmp()
|
|
- * called where the loop started in NCR5380_main().
|
|
+ * called where the loop started in NCR5380_main().
|
|
*/
|
|
|
|
static int NCR5380_abort(struct scsi_cmnd *cmd)
|
|
diff --git a/drivers/spi/spi-dw-mid.c b/drivers/spi/spi-dw-mid.c
|
|
index efc494a..f15f624 100644
|
|
--- a/drivers/spi/spi-dw-mid.c
|
|
+++ b/drivers/spi/spi-dw-mid.c
|
|
@@ -219,7 +219,6 @@ int dw_spi_mid_init(struct dw_spi *dws)
|
|
iounmap(clk_reg);
|
|
|
|
dws->num_cs = 16;
|
|
- dws->fifo_len = 40; /* FIFO has 40 words buffer */
|
|
|
|
#ifdef CONFIG_SPI_DW_MID_DMA
|
|
dws->dma_priv = kzalloc(sizeof(struct mid_dma), GFP_KERNEL);
|
|
diff --git a/drivers/spi/spi-dw.c b/drivers/spi/spi-dw.c
|
|
index d1a495f..cce2d7b 100644
|
|
--- a/drivers/spi/spi-dw.c
|
|
+++ b/drivers/spi/spi-dw.c
|
|
@@ -394,9 +394,6 @@ static void pump_transfers(unsigned long data)
|
|
chip = dws->cur_chip;
|
|
spi = message->spi;
|
|
|
|
- if (unlikely(!chip->clk_div))
|
|
- chip->clk_div = dws->max_freq / chip->speed_hz;
|
|
-
|
|
if (message->state == ERROR_STATE) {
|
|
message->status = -EIO;
|
|
goto early_exit;
|
|
@@ -438,7 +435,7 @@ static void pump_transfers(unsigned long data)
|
|
if (transfer->speed_hz) {
|
|
speed = chip->speed_hz;
|
|
|
|
- if (transfer->speed_hz != speed) {
|
|
+ if ((transfer->speed_hz != speed) || (!chip->clk_div)) {
|
|
speed = transfer->speed_hz;
|
|
if (speed > dws->max_freq) {
|
|
printk(KERN_ERR "MRST SPI0: unsupported"
|
|
@@ -677,7 +674,6 @@ static int dw_spi_setup(struct spi_device *spi)
|
|
dev_err(&spi->dev, "No max speed HZ parameter\n");
|
|
return -EINVAL;
|
|
}
|
|
- chip->speed_hz = spi->max_speed_hz;
|
|
|
|
chip->tmode = 0; /* Tx & Rx */
|
|
/* Default SPI mode is SCPOL = 0, SCPH = 0 */
|
|
@@ -784,13 +780,13 @@ static void spi_hw_init(struct dw_spi *dws)
|
|
*/
|
|
if (!dws->fifo_len) {
|
|
u32 fifo;
|
|
- for (fifo = 2; fifo <= 257; fifo++) {
|
|
+ for (fifo = 1; fifo < 256; fifo++) {
|
|
dw_writew(dws, DW_SPI_TXFLTR, fifo);
|
|
if (fifo != dw_readw(dws, DW_SPI_TXFLTR))
|
|
break;
|
|
}
|
|
|
|
- dws->fifo_len = (fifo == 257) ? 0 : fifo;
|
|
+ dws->fifo_len = (fifo == 1) ? 0 : fifo;
|
|
dw_writew(dws, DW_SPI_TXFLTR, 0);
|
|
}
|
|
}
|
|
diff --git a/drivers/staging/comedi/drivers/cb_pcidas64.c b/drivers/staging/comedi/drivers/cb_pcidas64.c
|
|
index 915157d..6f743df 100644
|
|
--- a/drivers/staging/comedi/drivers/cb_pcidas64.c
|
|
+++ b/drivers/staging/comedi/drivers/cb_pcidas64.c
|
|
@@ -423,6 +423,29 @@ static const struct comedi_lrange ai_ranges_64xx = {
|
|
}
|
|
};
|
|
|
|
+static const uint8_t ai_range_code_64xx[8] = {
|
|
+ 0x0, 0x1, 0x2, 0x3, /* bipolar 10, 5, 2,5, 1.25 */
|
|
+ 0x8, 0x9, 0xa, 0xb /* unipolar 10, 5, 2.5, 1.25 */
|
|
+};
|
|
+
|
|
+/* analog input ranges for 64-Mx boards */
|
|
+static const struct comedi_lrange ai_ranges_64_mx = {
|
|
+ 7, {
|
|
+ BIP_RANGE(5),
|
|
+ BIP_RANGE(2.5),
|
|
+ BIP_RANGE(1.25),
|
|
+ BIP_RANGE(0.625),
|
|
+ UNI_RANGE(5),
|
|
+ UNI_RANGE(2.5),
|
|
+ UNI_RANGE(1.25)
|
|
+ }
|
|
+};
|
|
+
|
|
+static const uint8_t ai_range_code_64_mx[7] = {
|
|
+ 0x0, 0x1, 0x2, 0x3, /* bipolar 5, 2.5, 1.25, 0.625 */
|
|
+ 0x9, 0xa, 0xb /* unipolar 5, 2.5, 1.25 */
|
|
+};
|
|
+
|
|
/* analog input ranges for 60xx boards */
|
|
static const struct comedi_lrange ai_ranges_60xx = {
|
|
4,
|
|
@@ -434,6 +457,10 @@ static const struct comedi_lrange ai_ranges_60xx = {
|
|
}
|
|
};
|
|
|
|
+static const uint8_t ai_range_code_60xx[4] = {
|
|
+ 0x0, 0x1, 0x4, 0x7 /* bipolar 10, 5, 0.5, 0.05 */
|
|
+};
|
|
+
|
|
/* analog input ranges for 6030, etc boards */
|
|
static const struct comedi_lrange ai_ranges_6030 = {
|
|
14,
|
|
@@ -455,6 +482,11 @@ static const struct comedi_lrange ai_ranges_6030 = {
|
|
}
|
|
};
|
|
|
|
+static const uint8_t ai_range_code_6030[14] = {
|
|
+ 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, /* bip 10, 5, 2, 1, 0.5, 0.2, 0.1 */
|
|
+ 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf /* uni 10, 5, 2, 1, 0.5, 0.2, 0.1 */
|
|
+};
|
|
+
|
|
/* analog input ranges for 6052, etc boards */
|
|
static const struct comedi_lrange ai_ranges_6052 = {
|
|
15,
|
|
@@ -477,6 +509,11 @@ static const struct comedi_lrange ai_ranges_6052 = {
|
|
}
|
|
};
|
|
|
|
+static const uint8_t ai_range_code_6052[15] = {
|
|
+ 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, /* bipolar 10 ... 0.05 */
|
|
+ 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf /* unipolar 10 ... 0.1 */
|
|
+};
|
|
+
|
|
/* analog input ranges for 4020 board */
|
|
static const struct comedi_lrange ai_ranges_4020 = {
|
|
2,
|
|
@@ -561,6 +598,7 @@ struct pcidas64_board {
|
|
int ai_bits; /* analog input resolution */
|
|
int ai_speed; /* fastest conversion period in ns */
|
|
const struct comedi_lrange *ai_range_table;
|
|
+ const uint8_t *ai_range_code;
|
|
int ao_nchan; /* number of analog out channels */
|
|
int ao_bits; /* analog output resolution */
|
|
int ao_scan_speed; /* analog output speed (for a scan, not conversion) */
|
|
@@ -619,6 +657,7 @@ static const struct pcidas64_board pcidas64_boards[] = {
|
|
.ao_scan_speed = 10000,
|
|
.layout = LAYOUT_64XX,
|
|
.ai_range_table = &ai_ranges_64xx,
|
|
+ .ai_range_code = ai_range_code_64xx,
|
|
.ao_range_table = &ao_ranges_64xx,
|
|
.ao_range_code = ao_range_code_64xx,
|
|
.ai_fifo = &ai_fifo_64xx,
|
|
@@ -635,6 +674,7 @@ static const struct pcidas64_board pcidas64_boards[] = {
|
|
.ao_scan_speed = 10000,
|
|
.layout = LAYOUT_64XX,
|
|
.ai_range_table = &ai_ranges_64xx,
|
|
+ .ai_range_code = ai_range_code_64xx,
|
|
.ao_range_table = &ao_ranges_64xx,
|
|
.ao_range_code = ao_range_code_64xx,
|
|
.ai_fifo = &ai_fifo_64xx,
|
|
@@ -650,7 +690,8 @@ static const struct pcidas64_board pcidas64_boards[] = {
|
|
.ao_bits = 16,
|
|
.ao_scan_speed = 10000,
|
|
.layout = LAYOUT_64XX,
|
|
- .ai_range_table = &ai_ranges_64xx,
|
|
+ .ai_range_table = &ai_ranges_64_mx,
|
|
+ .ai_range_code = ai_range_code_64_mx,
|
|
.ao_range_table = &ao_ranges_64xx,
|
|
.ao_range_code = ao_range_code_64xx,
|
|
.ai_fifo = &ai_fifo_64xx,
|
|
@@ -666,7 +707,8 @@ static const struct pcidas64_board pcidas64_boards[] = {
|
|
.ao_bits = 16,
|
|
.ao_scan_speed = 10000,
|
|
.layout = LAYOUT_64XX,
|
|
- .ai_range_table = &ai_ranges_64xx,
|
|
+ .ai_range_table = &ai_ranges_64_mx,
|
|
+ .ai_range_code = ai_range_code_64_mx,
|
|
.ao_range_table = &ao_ranges_64xx,
|
|
.ao_range_code = ao_range_code_64xx,
|
|
.ai_fifo = &ai_fifo_64xx,
|
|
@@ -682,7 +724,8 @@ static const struct pcidas64_board pcidas64_boards[] = {
|
|
.ao_bits = 16,
|
|
.ao_scan_speed = 10000,
|
|
.layout = LAYOUT_64XX,
|
|
- .ai_range_table = &ai_ranges_64xx,
|
|
+ .ai_range_table = &ai_ranges_64_mx,
|
|
+ .ai_range_code = ai_range_code_64_mx,
|
|
.ao_range_table = &ao_ranges_64xx,
|
|
.ao_range_code = ao_range_code_64xx,
|
|
.ai_fifo = &ai_fifo_64xx,
|
|
@@ -698,6 +741,7 @@ static const struct pcidas64_board pcidas64_boards[] = {
|
|
.ao_bits = 16,
|
|
.layout = LAYOUT_60XX,
|
|
.ai_range_table = &ai_ranges_60xx,
|
|
+ .ai_range_code = ai_range_code_60xx,
|
|
.ao_range_table = &ao_ranges_60xx,
|
|
.ao_range_code = ao_range_code_60xx,
|
|
.ai_fifo = &ai_fifo_60xx,
|
|
@@ -714,6 +758,7 @@ static const struct pcidas64_board pcidas64_boards[] = {
|
|
.ao_scan_speed = 100000,
|
|
.layout = LAYOUT_60XX,
|
|
.ai_range_table = &ai_ranges_60xx,
|
|
+ .ai_range_code = ai_range_code_60xx,
|
|
.ao_range_table = &ao_ranges_60xx,
|
|
.ao_range_code = ao_range_code_60xx,
|
|
.ai_fifo = &ai_fifo_60xx,
|
|
@@ -729,6 +774,7 @@ static const struct pcidas64_board pcidas64_boards[] = {
|
|
.ao_scan_speed = 100000,
|
|
.layout = LAYOUT_60XX,
|
|
.ai_range_table = &ai_ranges_60xx,
|
|
+ .ai_range_code = ai_range_code_60xx,
|
|
.ao_range_table = &ao_ranges_60xx,
|
|
.ao_range_code = ao_range_code_60xx,
|
|
.ai_fifo = &ai_fifo_60xx,
|
|
@@ -745,6 +791,7 @@ static const struct pcidas64_board pcidas64_boards[] = {
|
|
.ao_scan_speed = 100000,
|
|
.layout = LAYOUT_60XX,
|
|
.ai_range_table = &ai_ranges_60xx,
|
|
+ .ai_range_code = ai_range_code_60xx,
|
|
.ao_range_table = &ao_ranges_60xx,
|
|
.ao_range_code = ao_range_code_60xx,
|
|
.ai_fifo = &ai_fifo_60xx,
|
|
@@ -761,6 +808,7 @@ static const struct pcidas64_board pcidas64_boards[] = {
|
|
.ao_scan_speed = 10000,
|
|
.layout = LAYOUT_60XX,
|
|
.ai_range_table = &ai_ranges_6030,
|
|
+ .ai_range_code = ai_range_code_6030,
|
|
.ao_range_table = &ao_ranges_6030,
|
|
.ao_range_code = ao_range_code_6030,
|
|
.ai_fifo = &ai_fifo_60xx,
|
|
@@ -777,6 +825,7 @@ static const struct pcidas64_board pcidas64_boards[] = {
|
|
.ao_scan_speed = 10000,
|
|
.layout = LAYOUT_60XX,
|
|
.ai_range_table = &ai_ranges_6030,
|
|
+ .ai_range_code = ai_range_code_6030,
|
|
.ao_range_table = &ao_ranges_6030,
|
|
.ao_range_code = ao_range_code_6030,
|
|
.ai_fifo = &ai_fifo_60xx,
|
|
@@ -791,6 +840,7 @@ static const struct pcidas64_board pcidas64_boards[] = {
|
|
.ao_nchan = 0,
|
|
.layout = LAYOUT_60XX,
|
|
.ai_range_table = &ai_ranges_6030,
|
|
+ .ai_range_code = ai_range_code_6030,
|
|
.ai_fifo = &ai_fifo_60xx,
|
|
.has_8255 = 0,
|
|
},
|
|
@@ -803,6 +853,7 @@ static const struct pcidas64_board pcidas64_boards[] = {
|
|
.ao_nchan = 0,
|
|
.layout = LAYOUT_60XX,
|
|
.ai_range_table = &ai_ranges_6030,
|
|
+ .ai_range_code = ai_range_code_6030,
|
|
.ai_fifo = &ai_fifo_60xx,
|
|
.has_8255 = 0,
|
|
},
|
|
@@ -816,6 +867,7 @@ static const struct pcidas64_board pcidas64_boards[] = {
|
|
.ao_scan_speed = 0,
|
|
.layout = LAYOUT_60XX,
|
|
.ai_range_table = &ai_ranges_60xx,
|
|
+ .ai_range_code = ai_range_code_60xx,
|
|
.ai_fifo = &ai_fifo_60xx,
|
|
.has_8255 = 0,
|
|
},
|
|
@@ -830,6 +882,7 @@ static const struct pcidas64_board pcidas64_boards[] = {
|
|
.ao_scan_speed = 100000,
|
|
.layout = LAYOUT_60XX,
|
|
.ai_range_table = &ai_ranges_60xx,
|
|
+ .ai_range_code = ai_range_code_60xx,
|
|
.ao_range_table = &ao_ranges_60xx,
|
|
.ao_range_code = ao_range_code_60xx,
|
|
.ai_fifo = &ai_fifo_60xx,
|
|
@@ -846,6 +899,7 @@ static const struct pcidas64_board pcidas64_boards[] = {
|
|
.ao_scan_speed = 100000,
|
|
.layout = LAYOUT_60XX,
|
|
.ai_range_table = &ai_ranges_60xx,
|
|
+ .ai_range_code = ai_range_code_60xx,
|
|
.ao_range_table = &ao_ranges_60xx,
|
|
.ao_range_code = ao_range_code_60xx,
|
|
.ai_fifo = &ai_fifo_60xx,
|
|
@@ -862,6 +916,7 @@ static const struct pcidas64_board pcidas64_boards[] = {
|
|
.ao_scan_speed = 1000,
|
|
.layout = LAYOUT_60XX,
|
|
.ai_range_table = &ai_ranges_6052,
|
|
+ .ai_range_code = ai_range_code_6052,
|
|
.ao_range_table = &ao_ranges_6030,
|
|
.ao_range_code = ao_range_code_6030,
|
|
.ai_fifo = &ai_fifo_60xx,
|
|
@@ -878,6 +933,7 @@ static const struct pcidas64_board pcidas64_boards[] = {
|
|
.ao_scan_speed = 3333,
|
|
.layout = LAYOUT_60XX,
|
|
.ai_range_table = &ai_ranges_6052,
|
|
+ .ai_range_code = ai_range_code_6052,
|
|
.ao_range_table = &ao_ranges_6030,
|
|
.ao_range_code = ao_range_code_6030,
|
|
.ai_fifo = &ai_fifo_60xx,
|
|
@@ -894,6 +950,7 @@ static const struct pcidas64_board pcidas64_boards[] = {
|
|
.ao_scan_speed = 1000,
|
|
.layout = LAYOUT_60XX,
|
|
.ai_range_table = &ai_ranges_6052,
|
|
+ .ai_range_code = ai_range_code_6052,
|
|
.ao_range_table = &ao_ranges_6030,
|
|
.ao_range_code = ao_range_code_6030,
|
|
.ai_fifo = &ai_fifo_60xx,
|
|
@@ -910,6 +967,7 @@ static const struct pcidas64_board pcidas64_boards[] = {
|
|
.ao_scan_speed = 1000,
|
|
.layout = LAYOUT_60XX,
|
|
.ai_range_table = &ai_ranges_6052,
|
|
+ .ai_range_code = ai_range_code_6052,
|
|
.ao_range_table = &ao_ranges_6030,
|
|
.ao_range_code = ao_range_code_6030,
|
|
.ai_fifo = &ai_fifo_60xx,
|
|
@@ -942,6 +1000,7 @@ static const struct pcidas64_board pcidas64_boards[] = {
|
|
.ao_scan_speed = 10000,
|
|
.layout = LAYOUT_64XX,
|
|
.ai_range_table = &ai_ranges_64xx,
|
|
+ .ai_range_code = ai_range_code_64xx,
|
|
.ai_fifo = ai_fifo_64xx,
|
|
.has_8255 = 1,
|
|
},
|
|
@@ -954,7 +1013,8 @@ static const struct pcidas64_board pcidas64_boards[] = {
|
|
.ao_nchan = 0,
|
|
.ao_scan_speed = 10000,
|
|
.layout = LAYOUT_64XX,
|
|
- .ai_range_table = &ai_ranges_64xx,
|
|
+ .ai_range_table = &ai_ranges_64_mx,
|
|
+ .ai_range_code = ai_range_code_64_mx,
|
|
.ai_fifo = ai_fifo_64xx,
|
|
.has_8255 = 1,
|
|
},
|
|
@@ -967,7 +1027,8 @@ static const struct pcidas64_board pcidas64_boards[] = {
|
|
.ao_nchan = 0,
|
|
.ao_scan_speed = 10000,
|
|
.layout = LAYOUT_64XX,
|
|
- .ai_range_table = &ai_ranges_64xx,
|
|
+ .ai_range_table = &ai_ranges_64_mx,
|
|
+ .ai_range_code = ai_range_code_64_mx,
|
|
.ai_fifo = ai_fifo_64xx,
|
|
.has_8255 = 1,
|
|
},
|
|
@@ -980,7 +1041,8 @@ static const struct pcidas64_board pcidas64_boards[] = {
|
|
.ao_nchan = 0,
|
|
.ao_scan_speed = 10000,
|
|
.layout = LAYOUT_64XX,
|
|
- .ai_range_table = &ai_ranges_64xx,
|
|
+ .ai_range_table = &ai_ranges_64_mx,
|
|
+ .ai_range_code = ai_range_code_64_mx,
|
|
.ai_fifo = ai_fifo_64xx,
|
|
.has_8255 = 1,
|
|
},
|
|
@@ -993,7 +1055,8 @@ static const struct pcidas64_board pcidas64_boards[] = {
|
|
.ao_nchan = 2,
|
|
.ao_scan_speed = 10000,
|
|
.layout = LAYOUT_64XX,
|
|
- .ai_range_table = &ai_ranges_64xx,
|
|
+ .ai_range_table = &ai_ranges_64_mx,
|
|
+ .ai_range_code = ai_range_code_64_mx,
|
|
.ai_fifo = ai_fifo_64xx,
|
|
.has_8255 = 1,
|
|
},
|
|
@@ -1006,7 +1069,8 @@ static const struct pcidas64_board pcidas64_boards[] = {
|
|
.ao_nchan = 2,
|
|
.ao_scan_speed = 10000,
|
|
.layout = LAYOUT_64XX,
|
|
- .ai_range_table = &ai_ranges_64xx,
|
|
+ .ai_range_table = &ai_ranges_64_mx,
|
|
+ .ai_range_code = ai_range_code_64_mx,
|
|
.ai_fifo = ai_fifo_64xx,
|
|
.has_8255 = 1,
|
|
},
|
|
@@ -1019,7 +1083,8 @@ static const struct pcidas64_board pcidas64_boards[] = {
|
|
.ao_nchan = 2,
|
|
.ao_scan_speed = 10000,
|
|
.layout = LAYOUT_64XX,
|
|
- .ai_range_table = &ai_ranges_64xx,
|
|
+ .ai_range_table = &ai_ranges_64_mx,
|
|
+ .ai_range_code = ai_range_code_64_mx,
|
|
.ai_fifo = ai_fifo_64xx,
|
|
.has_8255 = 1,
|
|
},
|
|
@@ -1257,45 +1322,7 @@ module_exit(driver_cb_pcidas_cleanup_module);
|
|
static unsigned int ai_range_bits_6xxx(const struct comedi_device *dev,
|
|
unsigned int range_index)
|
|
{
|
|
- const struct comedi_krange *range =
|
|
- &board(dev)->ai_range_table->range[range_index];
|
|
- unsigned int bits = 0;
|
|
-
|
|
- switch (range->max) {
|
|
- case 10000000:
|
|
- bits = 0x000;
|
|
- break;
|
|
- case 5000000:
|
|
- bits = 0x100;
|
|
- break;
|
|
- case 2000000:
|
|
- case 2500000:
|
|
- bits = 0x200;
|
|
- break;
|
|
- case 1000000:
|
|
- case 1250000:
|
|
- bits = 0x300;
|
|
- break;
|
|
- case 500000:
|
|
- bits = 0x400;
|
|
- break;
|
|
- case 200000:
|
|
- case 250000:
|
|
- bits = 0x500;
|
|
- break;
|
|
- case 100000:
|
|
- bits = 0x600;
|
|
- break;
|
|
- case 50000:
|
|
- bits = 0x700;
|
|
- break;
|
|
- default:
|
|
- comedi_error(dev, "bug! in ai_range_bits_6xxx");
|
|
- break;
|
|
- }
|
|
- if (range->min == 0)
|
|
- bits += 0x900;
|
|
- return bits;
|
|
+ return board(dev)->ai_range_code[range_index] << 8;
|
|
}
|
|
|
|
static unsigned int hw_revision(const struct comedi_device *dev,
|
|
diff --git a/drivers/staging/iio/events.h b/drivers/staging/iio/events.h
|
|
index c25f0e3..a6f999c 100644
|
|
--- a/drivers/staging/iio/events.h
|
|
+++ b/drivers/staging/iio/events.h
|
|
@@ -90,7 +90,7 @@ enum iio_event_direction {
|
|
|
|
#define IIO_EVENT_CODE_EXTRACT_TYPE(mask) ((mask >> 56) & 0xFF)
|
|
|
|
-#define IIO_EVENT_CODE_EXTRACT_DIR(mask) ((mask >> 48) & 0xCF)
|
|
+#define IIO_EVENT_CODE_EXTRACT_DIR(mask) ((mask >> 48) & 0x7F)
|
|
|
|
#define IIO_EVENT_CODE_EXTRACT_CHAN_TYPE(mask) ((mask >> 32) & 0xFF)
|
|
|
|
diff --git a/drivers/target/iscsi/iscsi_target_util.c b/drivers/target/iscsi/iscsi_target_util.c
|
|
index 4c05ed6..8d57ab3 100644
|
|
--- a/drivers/target/iscsi/iscsi_target_util.c
|
|
+++ b/drivers/target/iscsi/iscsi_target_util.c
|
|
@@ -1480,15 +1480,15 @@ static int iscsit_do_tx_data(
|
|
struct iscsi_conn *conn,
|
|
struct iscsi_data_count *count)
|
|
{
|
|
- int data = count->data_length, total_tx = 0, tx_loop = 0, iov_len;
|
|
+ int ret, iov_len;
|
|
struct kvec *iov_p;
|
|
struct msghdr msg;
|
|
|
|
if (!conn || !conn->sock || !conn->conn_ops)
|
|
return -1;
|
|
|
|
- if (data <= 0) {
|
|
- pr_err("Data length is: %d\n", data);
|
|
+ if (count->data_length <= 0) {
|
|
+ pr_err("Data length is: %d\n", count->data_length);
|
|
return -1;
|
|
}
|
|
|
|
@@ -1497,20 +1497,16 @@ static int iscsit_do_tx_data(
|
|
iov_p = count->iov;
|
|
iov_len = count->iov_count;
|
|
|
|
- while (total_tx < data) {
|
|
- tx_loop = kernel_sendmsg(conn->sock, &msg, iov_p, iov_len,
|
|
- (data - total_tx));
|
|
- if (tx_loop <= 0) {
|
|
- pr_debug("tx_loop: %d total_tx %d\n",
|
|
- tx_loop, total_tx);
|
|
- return tx_loop;
|
|
- }
|
|
- total_tx += tx_loop;
|
|
- pr_debug("tx_loop: %d, total_tx: %d, data: %d\n",
|
|
- tx_loop, total_tx, data);
|
|
+ ret = kernel_sendmsg(conn->sock, &msg, iov_p, iov_len,
|
|
+ count->data_length);
|
|
+ if (ret != count->data_length) {
|
|
+ pr_err("Unexpected ret: %d send data %d\n",
|
|
+ ret, count->data_length);
|
|
+ return -EPIPE;
|
|
}
|
|
+ pr_debug("ret: %d, sent data: %d\n", ret, count->data_length);
|
|
|
|
- return total_tx;
|
|
+ return ret;
|
|
}
|
|
|
|
int rx_data(
|
|
diff --git a/drivers/tty/serial/samsung.c b/drivers/tty/serial/samsung.c
|
|
index c49f3bf..8b409d4 100644
|
|
--- a/drivers/tty/serial/samsung.c
|
|
+++ b/drivers/tty/serial/samsung.c
|
|
@@ -528,11 +528,15 @@ static void s3c24xx_serial_pm(struct uart_port *port, unsigned int level,
|
|
unsigned int old)
|
|
{
|
|
struct s3c24xx_uart_port *ourport = to_ourport(port);
|
|
+ int timeout = 10000;
|
|
|
|
ourport->pm_level = level;
|
|
|
|
switch (level) {
|
|
case 3:
|
|
+ while (--timeout && !s3c24xx_serial_txempty_nofifo(port))
|
|
+ udelay(100);
|
|
+
|
|
if (!IS_ERR(ourport->baudclk) && ourport->baudclk != NULL)
|
|
clk_disable(ourport->baudclk);
|
|
|
|
diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c
|
|
index 8f4a628..0532577 100644
|
|
--- a/drivers/usb/class/cdc-acm.c
|
|
+++ b/drivers/usb/class/cdc-acm.c
|
|
@@ -1108,10 +1108,11 @@ static int acm_probe(struct usb_interface *intf,
|
|
} else {
|
|
control_interface = usb_ifnum_to_if(usb_dev, union_header->bMasterInterface0);
|
|
data_interface = usb_ifnum_to_if(usb_dev, (data_interface_num = union_header->bSlaveInterface0));
|
|
- if (!control_interface || !data_interface) {
|
|
- dev_dbg(&intf->dev, "no interfaces\n");
|
|
- return -ENODEV;
|
|
- }
|
|
+ }
|
|
+
|
|
+ if (!control_interface || !data_interface) {
|
|
+ dev_dbg(&intf->dev, "no interfaces\n");
|
|
+ return -ENODEV;
|
|
}
|
|
|
|
if (data_interface_num != call_interface_num)
|
|
@@ -1429,6 +1430,7 @@ static void acm_disconnect(struct usb_interface *intf)
|
|
&dev_attr_wCountryCodes);
|
|
device_remove_file(&acm->control->dev,
|
|
&dev_attr_iCountryCodeRelDate);
|
|
+ kfree(acm->country_codes);
|
|
}
|
|
device_remove_file(&acm->control->dev, &dev_attr_bmCapabilities);
|
|
usb_set_intfdata(acm->control, NULL);
|
|
diff --git a/drivers/usb/core/config.c b/drivers/usb/core/config.c
|
|
index 6ed7e7c..cc1004a 100644
|
|
--- a/drivers/usb/core/config.c
|
|
+++ b/drivers/usb/core/config.c
|
|
@@ -201,6 +201,17 @@ static int usb_parse_endpoint(struct device *ddev, int cfgno, int inum,
|
|
if (n == 0)
|
|
n = 9; /* 32 ms = 2^(9-1) uframes */
|
|
j = 16;
|
|
+
|
|
+ /*
|
|
+ * Adjust bInterval for quirked devices.
|
|
+ * This quirk fixes bIntervals reported in
|
|
+ * linear microframes.
|
|
+ */
|
|
+ if (to_usb_device(ddev)->quirks &
|
|
+ USB_QUIRK_LINEAR_UFRAME_INTR_BINTERVAL) {
|
|
+ n = clamp(fls(d->bInterval), i, j);
|
|
+ i = j = n;
|
|
+ }
|
|
break;
|
|
default: /* USB_SPEED_FULL or _LOW */
|
|
/* For low-speed, 10 ms is the official minimum.
|
|
diff --git a/drivers/usb/core/quirks.c b/drivers/usb/core/quirks.c
|
|
index d482141..95f60d0 100644
|
|
--- a/drivers/usb/core/quirks.c
|
|
+++ b/drivers/usb/core/quirks.c
|
|
@@ -38,6 +38,9 @@ static const struct usb_device_id usb_quirk_list[] = {
|
|
/* Creative SB Audigy 2 NX */
|
|
{ USB_DEVICE(0x041e, 0x3020), .driver_info = USB_QUIRK_RESET_RESUME },
|
|
|
|
+ /* Microsoft Wireless Laser Mouse 6000 Receiver */
|
|
+ { USB_DEVICE(0x045e, 0x00e1), .driver_info = USB_QUIRK_RESET_RESUME },
|
|
+
|
|
/* Microsoft LifeCam-VX700 v2.0 */
|
|
{ USB_DEVICE(0x045e, 0x0770), .driver_info = USB_QUIRK_RESET_RESUME },
|
|
|
|
@@ -174,6 +177,10 @@ static const struct usb_device_id usb_quirk_list[] = {
|
|
/* SKYMEDI USB_DRIVE */
|
|
{ USB_DEVICE(0x1516, 0x8628), .driver_info = USB_QUIRK_RESET_RESUME },
|
|
|
|
+ /* Razer - Razer Blade Keyboard */
|
|
+ { USB_DEVICE(0x1532, 0x0116), .driver_info =
|
|
+ USB_QUIRK_LINEAR_UFRAME_INTR_BINTERVAL },
|
|
+
|
|
/* BUILDWIN Photo Frame */
|
|
{ USB_DEVICE(0x1908, 0x1315), .driver_info =
|
|
USB_QUIRK_HONOR_BNUMINTERFACES },
|
|
@@ -184,6 +191,10 @@ static const struct usb_device_id usb_quirk_list[] = {
|
|
/* Protocol and OTG Electrical Test Device */
|
|
{ USB_DEVICE(0x1a0a, 0x0200), .driver_info = USB_QUIRK_OTG_PET },
|
|
|
|
+ /* Protocol and OTG Electrical Test Device */
|
|
+ { USB_DEVICE(0x1a0a, 0x0200), .driver_info =
|
|
+ USB_QUIRK_LINEAR_UFRAME_INTR_BINTERVAL },
|
|
+
|
|
{ } /* terminating entry must be last */
|
|
};
|
|
|
|
diff --git a/drivers/usb/host/pci-quirks.c b/drivers/usb/host/pci-quirks.c
|
|
index 90dcf54..1f230ed 100644
|
|
--- a/drivers/usb/host/pci-quirks.c
|
|
+++ b/drivers/usb/host/pci-quirks.c
|
|
@@ -470,7 +470,8 @@ static void __devinit quirk_usb_handoff_ohci(struct pci_dev *pdev)
|
|
{
|
|
void __iomem *base;
|
|
u32 control;
|
|
- u32 fminterval;
|
|
+ u32 fminterval = 0;
|
|
+ bool no_fminterval = false;
|
|
int cnt;
|
|
|
|
if (!mmio_resource_enabled(pdev, 0))
|
|
@@ -480,6 +481,13 @@ static void __devinit quirk_usb_handoff_ohci(struct pci_dev *pdev)
|
|
if (base == NULL)
|
|
return;
|
|
|
|
+ /*
|
|
+ * ULi M5237 OHCI controller locks the whole system when accessing
|
|
+ * the OHCI_FMINTERVAL offset.
|
|
+ */
|
|
+ if (pdev->vendor == PCI_VENDOR_ID_AL && pdev->device == 0x5237)
|
|
+ no_fminterval = true;
|
|
+
|
|
control = readl(base + OHCI_CONTROL);
|
|
|
|
/* On PA-RISC, PDC can leave IR set incorrectly; ignore it there. */
|
|
@@ -518,7 +526,9 @@ static void __devinit quirk_usb_handoff_ohci(struct pci_dev *pdev)
|
|
}
|
|
|
|
/* software reset of the controller, preserving HcFmInterval */
|
|
- fminterval = readl(base + OHCI_FMINTERVAL);
|
|
+ if (!no_fminterval)
|
|
+ fminterval = readl(base + OHCI_FMINTERVAL);
|
|
+
|
|
writel(OHCI_HCR, base + OHCI_CMDSTATUS);
|
|
|
|
/* reset requires max 10 us delay */
|
|
@@ -527,7 +537,9 @@ static void __devinit quirk_usb_handoff_ohci(struct pci_dev *pdev)
|
|
break;
|
|
udelay(1);
|
|
}
|
|
- writel(fminterval, base + OHCI_FMINTERVAL);
|
|
+
|
|
+ if (!no_fminterval)
|
|
+ writel(fminterval, base + OHCI_FMINTERVAL);
|
|
|
|
/* Now the controller is safely in SUSPEND and nothing can wake it up */
|
|
iounmap(base);
|
|
diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c
|
|
index 0e1f1f0..7d1a99dd 100644
|
|
--- a/drivers/usb/host/xhci-pci.c
|
|
+++ b/drivers/usb/host/xhci-pci.c
|
|
@@ -222,7 +222,7 @@ static int xhci_pci_suspend(struct usb_hcd *hcd, bool do_wakeup)
|
|
xhci->shared_hcd->state != HC_STATE_SUSPENDED)
|
|
return -EINVAL;
|
|
|
|
- retval = xhci_suspend(xhci);
|
|
+ retval = xhci_suspend(xhci, do_wakeup);
|
|
|
|
return retval;
|
|
}
|
|
diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c
|
|
index 5cdb965..7a10a49 100644
|
|
--- a/drivers/usb/host/xhci-ring.c
|
|
+++ b/drivers/usb/host/xhci-ring.c
|
|
@@ -1182,9 +1182,8 @@ static void handle_reset_ep_completion(struct xhci_hcd *xhci,
|
|
false);
|
|
xhci_ring_cmd_db(xhci);
|
|
} else {
|
|
- /* Clear our internal halted state and restart the ring(s) */
|
|
+ /* Clear our internal halted state */
|
|
xhci->devs[slot_id]->eps[ep_index].ep_state &= ~EP_HALTED;
|
|
- ring_doorbell_for_active_rings(xhci, slot_id, ep_index);
|
|
}
|
|
}
|
|
|
|
@@ -1922,23 +1921,12 @@ static int finish_td(struct xhci_hcd *xhci, struct xhci_td *td,
|
|
ep->stopped_trb = event_trb;
|
|
return 0;
|
|
} else {
|
|
- if (trb_comp_code == COMP_STALL) {
|
|
- /* The transfer is completed from the driver's
|
|
- * perspective, but we need to issue a set dequeue
|
|
- * command for this stalled endpoint to move the dequeue
|
|
- * pointer past the TD. We can't do that here because
|
|
- * the halt condition must be cleared first. Let the
|
|
- * USB class driver clear the stall later.
|
|
- */
|
|
- ep->stopped_td = td;
|
|
- ep->stopped_trb = event_trb;
|
|
- ep->stopped_stream = ep_ring->stream_id;
|
|
- } else if (xhci_requires_manual_halt_cleanup(xhci,
|
|
- ep_ctx, trb_comp_code)) {
|
|
- /* Other types of errors halt the endpoint, but the
|
|
- * class driver doesn't call usb_reset_endpoint() unless
|
|
- * the error is -EPIPE. Clear the halted status in the
|
|
- * xHCI hardware manually.
|
|
+ if (trb_comp_code == COMP_STALL ||
|
|
+ xhci_requires_manual_halt_cleanup(xhci, ep_ctx,
|
|
+ trb_comp_code)) {
|
|
+ /* Issue a reset endpoint command to clear the host side * halt, followed by a set dequeue command to move the
|
|
+ * dequeue pointer past the TD.
|
|
+ * The class driver clears the device side halt later.
|
|
*/
|
|
xhci_cleanup_halted_endpoint(xhci,
|
|
slot_id, ep_index, ep_ring->stream_id,
|
|
@@ -2058,9 +2046,7 @@ static int process_ctrl_td(struct xhci_hcd *xhci, struct xhci_td *td,
|
|
else
|
|
td->urb->actual_length = 0;
|
|
|
|
- xhci_cleanup_halted_endpoint(xhci,
|
|
- slot_id, ep_index, 0, td, event_trb);
|
|
- return finish_td(xhci, td, event_trb, event, ep, status, true);
|
|
+ return finish_td(xhci, td, event_trb, event, ep, status, false);
|
|
}
|
|
/*
|
|
* Did we transfer any data, despite the errors that might have
|
|
@@ -2612,17 +2598,8 @@ static int handle_tx_event(struct xhci_hcd *xhci,
|
|
if (ret) {
|
|
urb = td->urb;
|
|
urb_priv = urb->hcpriv;
|
|
- /* Leave the TD around for the reset endpoint function
|
|
- * to use(but only if it's not a control endpoint,
|
|
- * since we already queued the Set TR dequeue pointer
|
|
- * command for stalled control endpoints).
|
|
- */
|
|
- if (usb_endpoint_xfer_control(&urb->ep->desc) ||
|
|
- (trb_comp_code != COMP_STALL &&
|
|
- trb_comp_code != COMP_BABBLE))
|
|
- xhci_urb_free_priv(xhci, urb_priv);
|
|
- else
|
|
- kfree(urb_priv);
|
|
+
|
|
+ xhci_urb_free_priv(xhci, urb_priv);
|
|
|
|
usb_hcd_unlink_urb_from_ep(bus_to_hcd(urb->dev->bus), urb);
|
|
if ((urb->actual_length != urb->transfer_buffer_length &&
|
|
diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c
|
|
index 1bef534..b20962d 100644
|
|
--- a/drivers/usb/host/xhci.c
|
|
+++ b/drivers/usb/host/xhci.c
|
|
@@ -33,6 +33,8 @@
|
|
#define DRIVER_AUTHOR "Sarah Sharp"
|
|
#define DRIVER_DESC "'eXtensible' Host Controller (xHC) Driver"
|
|
|
|
+#define PORT_WAKE_BITS (PORT_WKOC_E | PORT_WKDISC_E | PORT_WKCONN_E)
|
|
+
|
|
/* Some 0.95 hardware can't handle the chain bit on a Link TRB being cleared */
|
|
static int link_quirk;
|
|
module_param(link_quirk, int, S_IRUGO | S_IWUSR);
|
|
@@ -887,18 +889,56 @@ static void xhci_clear_command_ring(struct xhci_hcd *xhci)
|
|
xhci_set_cmd_ring_deq(xhci);
|
|
}
|
|
|
|
+static void xhci_disable_port_wake_on_bits(struct xhci_hcd *xhci)
|
|
+{
|
|
+ int port_index;
|
|
+ __le32 __iomem **port_array;
|
|
+ unsigned long flags;
|
|
+ u32 t1, t2;
|
|
+
|
|
+ spin_lock_irqsave(&xhci->lock, flags);
|
|
+
|
|
+ /* disble usb3 ports Wake bits*/
|
|
+ port_index = xhci->num_usb3_ports;
|
|
+ port_array = xhci->usb3_ports;
|
|
+ while (port_index--) {
|
|
+ t1 = readl(port_array[port_index]);
|
|
+ t1 = xhci_port_state_to_neutral(t1);
|
|
+ t2 = t1 & ~PORT_WAKE_BITS;
|
|
+ if (t1 != t2)
|
|
+ writel(t2, port_array[port_index]);
|
|
+ }
|
|
+
|
|
+ /* disble usb2 ports Wake bits*/
|
|
+ port_index = xhci->num_usb2_ports;
|
|
+ port_array = xhci->usb2_ports;
|
|
+ while (port_index--) {
|
|
+ t1 = readl(port_array[port_index]);
|
|
+ t1 = xhci_port_state_to_neutral(t1);
|
|
+ t2 = t1 & ~PORT_WAKE_BITS;
|
|
+ if (t1 != t2)
|
|
+ writel(t2, port_array[port_index]);
|
|
+ }
|
|
+
|
|
+ spin_unlock_irqrestore(&xhci->lock, flags);
|
|
+}
|
|
+
|
|
/*
|
|
* Stop HC (not bus-specific)
|
|
*
|
|
* This is called when the machine transition into S3/S4 mode.
|
|
*
|
|
*/
|
|
-int xhci_suspend(struct xhci_hcd *xhci)
|
|
+int xhci_suspend(struct xhci_hcd *xhci, bool do_wakeup)
|
|
{
|
|
int rc = 0;
|
|
struct usb_hcd *hcd = xhci_to_hcd(xhci);
|
|
u32 command;
|
|
|
|
+ /* Clear root port wake on bits if wakeup not allowed. */
|
|
+ if (!do_wakeup)
|
|
+ xhci_disable_port_wake_on_bits(xhci);
|
|
+
|
|
/* Don't poll the roothubs on bus suspend. */
|
|
xhci_dbg(xhci, "%s: stopping port polling.\n", __func__);
|
|
clear_bit(HCD_FLAG_POLL_RH, &hcd->flags);
|
|
@@ -2851,61 +2891,31 @@ void xhci_cleanup_stalled_ring(struct xhci_hcd *xhci,
|
|
}
|
|
}
|
|
|
|
-/* Deal with stalled endpoints. The core should have sent the control message
|
|
- * to clear the halt condition. However, we need to make the xHCI hardware
|
|
- * reset its sequence number, since a device will expect a sequence number of
|
|
- * zero after the halt condition is cleared.
|
|
+/* Called when clearing halted device. The core should have sent the control
|
|
+ * message to clear the device halt condition. The host side of the halt should
|
|
+ * already be cleared with a reset endpoint command issued when the STALL tx
|
|
+ * event was received.
|
|
+ *
|
|
* Context: in_interrupt
|
|
*/
|
|
+
|
|
void xhci_endpoint_reset(struct usb_hcd *hcd,
|
|
struct usb_host_endpoint *ep)
|
|
{
|
|
struct xhci_hcd *xhci;
|
|
- struct usb_device *udev;
|
|
- unsigned int ep_index;
|
|
- unsigned long flags;
|
|
- int ret;
|
|
- struct xhci_virt_ep *virt_ep;
|
|
|
|
xhci = hcd_to_xhci(hcd);
|
|
- udev = (struct usb_device *) ep->hcpriv;
|
|
- /* Called with a root hub endpoint (or an endpoint that wasn't added
|
|
- * with xhci_add_endpoint()
|
|
- */
|
|
- if (!ep->hcpriv)
|
|
- return;
|
|
- ep_index = xhci_get_endpoint_index(&ep->desc);
|
|
- virt_ep = &xhci->devs[udev->slot_id]->eps[ep_index];
|
|
- if (!virt_ep->stopped_td) {
|
|
- xhci_dbg(xhci, "Endpoint 0x%x not halted, refusing to reset.\n",
|
|
- ep->desc.bEndpointAddress);
|
|
- return;
|
|
- }
|
|
- if (usb_endpoint_xfer_control(&ep->desc)) {
|
|
- xhci_dbg(xhci, "Control endpoint stall already handled.\n");
|
|
- return;
|
|
- }
|
|
-
|
|
- xhci_dbg(xhci, "Queueing reset endpoint command\n");
|
|
- spin_lock_irqsave(&xhci->lock, flags);
|
|
- ret = xhci_queue_reset_ep(xhci, udev->slot_id, ep_index);
|
|
/*
|
|
- * Can't change the ring dequeue pointer until it's transitioned to the
|
|
- * stopped state, which is only upon a successful reset endpoint
|
|
- * command. Better hope that last command worked!
|
|
+ * We might need to implement the config ep cmd in xhci 4.8.1 note:
|
|
+ * The Reset Endpoint Command may only be issued to endpoints in the
|
|
+ * Halted state. If software wishes reset the Data Toggle or Sequence
|
|
+ * Number of an endpoint that isn't in the Halted state, then software
|
|
+ * may issue a Configure Endpoint Command with the Drop and Add bits set
|
|
+ * for the target endpoint. that is in the Stopped state.
|
|
*/
|
|
- if (!ret) {
|
|
- xhci_cleanup_stalled_ring(xhci, udev, ep_index);
|
|
- kfree(virt_ep->stopped_td);
|
|
- xhci_ring_cmd_db(xhci);
|
|
- }
|
|
- virt_ep->stopped_td = NULL;
|
|
- virt_ep->stopped_trb = NULL;
|
|
- virt_ep->stopped_stream = 0;
|
|
- spin_unlock_irqrestore(&xhci->lock, flags);
|
|
-
|
|
- if (ret)
|
|
- xhci_warn(xhci, "FIXME allocate a new ring segment\n");
|
|
+ /* For now just print debug to follow the situation */
|
|
+ xhci_dbg(xhci, "Endpoint 0x%x ep reset callback called\n",
|
|
+ ep->desc.bEndpointAddress);
|
|
}
|
|
|
|
static int xhci_check_streams_endpoint(struct xhci_hcd *xhci,
|
|
diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h
|
|
index d643c1a..16cc569 100644
|
|
--- a/drivers/usb/host/xhci.h
|
|
+++ b/drivers/usb/host/xhci.h
|
|
@@ -1755,7 +1755,7 @@ void xhci_shutdown(struct usb_hcd *hcd);
|
|
int xhci_gen_setup(struct usb_hcd *hcd, xhci_get_quirks_t get_quirks);
|
|
|
|
#ifdef CONFIG_PM
|
|
-int xhci_suspend(struct xhci_hcd *xhci);
|
|
+int xhci_suspend(struct xhci_hcd *xhci, bool do_wakeup);
|
|
int xhci_resume(struct xhci_hcd *xhci, bool hibernated);
|
|
#else
|
|
#define xhci_suspend NULL
|
|
diff --git a/drivers/usb/renesas_usbhs/mod_gadget.c b/drivers/usb/renesas_usbhs/mod_gadget.c
|
|
index 00bd2a5..056dc6e 100644
|
|
--- a/drivers/usb/renesas_usbhs/mod_gadget.c
|
|
+++ b/drivers/usb/renesas_usbhs/mod_gadget.c
|
|
@@ -672,6 +672,9 @@ static int __usbhsg_ep_set_halt_wedge(struct usb_ep *ep, int halt, int wedge)
|
|
struct device *dev = usbhsg_gpriv_to_dev(gpriv);
|
|
unsigned long flags;
|
|
|
|
+ if (!pipe)
|
|
+ return -EINVAL;
|
|
+
|
|
usbhsg_pipe_disable(uep);
|
|
|
|
dev_dbg(dev, "set halt %d (pipe %d)\n",
|
|
diff --git a/drivers/usb/serial/console.c b/drivers/usb/serial/console.c
|
|
index 1ee6b2a..87302dd 100644
|
|
--- a/drivers/usb/serial/console.c
|
|
+++ b/drivers/usb/serial/console.c
|
|
@@ -47,6 +47,8 @@ static struct console usbcons;
|
|
* ------------------------------------------------------------
|
|
*/
|
|
|
|
+static const struct tty_operations usb_console_fake_tty_ops = {
|
|
+};
|
|
|
|
/*
|
|
* The parsing of the command line works exactly like the
|
|
@@ -141,14 +143,17 @@ static int usb_console_setup(struct console *co, char *options)
|
|
goto reset_open_count;
|
|
}
|
|
kref_init(&tty->kref);
|
|
- tty_port_tty_set(&port->port, tty);
|
|
tty->driver = usb_serial_tty_driver;
|
|
tty->index = co->index;
|
|
+ INIT_LIST_HEAD(&tty->tty_files);
|
|
+ kref_get(&tty->driver->kref);
|
|
+ tty->ops = &usb_console_fake_tty_ops;
|
|
if (tty_init_termios(tty)) {
|
|
retval = -ENOMEM;
|
|
err("no more memory");
|
|
- goto free_tty;
|
|
+ goto put_tty;
|
|
}
|
|
+ tty_port_tty_set(&port->port, tty);
|
|
}
|
|
|
|
/* only call the device specific open if this
|
|
@@ -170,7 +175,7 @@ static int usb_console_setup(struct console *co, char *options)
|
|
serial->type->set_termios(tty, port, &dummy);
|
|
|
|
tty_port_tty_set(&port->port, NULL);
|
|
- kfree(tty);
|
|
+ tty_kref_put(tty);
|
|
}
|
|
set_bit(ASYNCB_INITIALIZED, &port->port.flags);
|
|
}
|
|
@@ -186,8 +191,8 @@ static int usb_console_setup(struct console *co, char *options)
|
|
|
|
fail:
|
|
tty_port_tty_set(&port->port, NULL);
|
|
- free_tty:
|
|
- kfree(tty);
|
|
+ put_tty:
|
|
+ tty_kref_put(tty);
|
|
reset_open_count:
|
|
port->port.count = 0;
|
|
usb_autopm_put_interface(serial->interface);
|
|
diff --git a/drivers/usb/serial/cp210x.c b/drivers/usb/serial/cp210x.c
|
|
index 19074db..8137937 100644
|
|
--- a/drivers/usb/serial/cp210x.c
|
|
+++ b/drivers/usb/serial/cp210x.c
|
|
@@ -126,9 +126,12 @@ static const struct usb_device_id id_table[] = {
|
|
{ USB_DEVICE(0x10C4, 0x85F8) }, /* Virtenio Preon32 */
|
|
{ USB_DEVICE(0x10C4, 0x8664) }, /* AC-Services CAN-IF */
|
|
{ USB_DEVICE(0x10C4, 0x8665) }, /* AC-Services OBD-IF */
|
|
+ { USB_DEVICE(0x10C4, 0x8856) }, /* CEL EM357 ZigBee USB Stick - LR */
|
|
+ { USB_DEVICE(0x10C4, 0x8857) }, /* CEL EM357 ZigBee USB Stick */
|
|
{ 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, 0x8977) }, /* CEL MeshWorks DevKit Device */
|
|
{ USB_DEVICE(0x10C4, 0xEA60) }, /* Silicon Labs factory default */
|
|
{ USB_DEVICE(0x10C4, 0xEA61) }, /* Silicon Labs factory default */
|
|
{ USB_DEVICE(0x10C4, 0xEA70) }, /* Silicon Labs factory default */
|
|
diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c
|
|
index a89433b..4bfcfa7 100644
|
|
--- a/drivers/usb/serial/ftdi_sio.c
|
|
+++ b/drivers/usb/serial/ftdi_sio.c
|
|
@@ -494,6 +494,39 @@ static struct usb_device_id id_table_combined [] = {
|
|
{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01FD_PID) },
|
|
{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01FE_PID) },
|
|
{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01FF_PID) },
|
|
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_4701_PID) },
|
|
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_9300_PID) },
|
|
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_9301_PID) },
|
|
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_9302_PID) },
|
|
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_9303_PID) },
|
|
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_9304_PID) },
|
|
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_9305_PID) },
|
|
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_9306_PID) },
|
|
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_9307_PID) },
|
|
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_9308_PID) },
|
|
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_9309_PID) },
|
|
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_930A_PID) },
|
|
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_930B_PID) },
|
|
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_930C_PID) },
|
|
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_930D_PID) },
|
|
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_930E_PID) },
|
|
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_930F_PID) },
|
|
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_9310_PID) },
|
|
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_9311_PID) },
|
|
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_9312_PID) },
|
|
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_9313_PID) },
|
|
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_9314_PID) },
|
|
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_9315_PID) },
|
|
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_9316_PID) },
|
|
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_9317_PID) },
|
|
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_9318_PID) },
|
|
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_9319_PID) },
|
|
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_931A_PID) },
|
|
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_931B_PID) },
|
|
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_931C_PID) },
|
|
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_931D_PID) },
|
|
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_931E_PID) },
|
|
+ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_931F_PID) },
|
|
{ USB_DEVICE(FTDI_VID, FTDI_PERLE_ULTRAPORT_PID) },
|
|
{ USB_DEVICE(FTDI_VID, FTDI_PIEGROUP_PID) },
|
|
{ USB_DEVICE(FTDI_VID, FTDI_TNC_X_PID) },
|
|
diff --git a/drivers/usb/serial/ftdi_sio_ids.h b/drivers/usb/serial/ftdi_sio_ids.h
|
|
index 64ee791..ecb4dee 100644
|
|
--- a/drivers/usb/serial/ftdi_sio_ids.h
|
|
+++ b/drivers/usb/serial/ftdi_sio_ids.h
|
|
@@ -920,8 +920,8 @@
|
|
#define BAYER_CONTOUR_CABLE_PID 0x6001
|
|
|
|
/*
|
|
- * The following are the values for the Matrix Orbital FTDI Range
|
|
- * Anything in this range will use an FT232RL.
|
|
+ * Matrix Orbital Intelligent USB displays.
|
|
+ * http://www.matrixorbital.com
|
|
*/
|
|
#define MTXORB_VID 0x1B3D
|
|
#define MTXORB_FTDI_RANGE_0100_PID 0x0100
|
|
@@ -1180,8 +1180,39 @@
|
|
#define MTXORB_FTDI_RANGE_01FD_PID 0x01FD
|
|
#define MTXORB_FTDI_RANGE_01FE_PID 0x01FE
|
|
#define MTXORB_FTDI_RANGE_01FF_PID 0x01FF
|
|
-
|
|
-
|
|
+#define MTXORB_FTDI_RANGE_4701_PID 0x4701
|
|
+#define MTXORB_FTDI_RANGE_9300_PID 0x9300
|
|
+#define MTXORB_FTDI_RANGE_9301_PID 0x9301
|
|
+#define MTXORB_FTDI_RANGE_9302_PID 0x9302
|
|
+#define MTXORB_FTDI_RANGE_9303_PID 0x9303
|
|
+#define MTXORB_FTDI_RANGE_9304_PID 0x9304
|
|
+#define MTXORB_FTDI_RANGE_9305_PID 0x9305
|
|
+#define MTXORB_FTDI_RANGE_9306_PID 0x9306
|
|
+#define MTXORB_FTDI_RANGE_9307_PID 0x9307
|
|
+#define MTXORB_FTDI_RANGE_9308_PID 0x9308
|
|
+#define MTXORB_FTDI_RANGE_9309_PID 0x9309
|
|
+#define MTXORB_FTDI_RANGE_930A_PID 0x930A
|
|
+#define MTXORB_FTDI_RANGE_930B_PID 0x930B
|
|
+#define MTXORB_FTDI_RANGE_930C_PID 0x930C
|
|
+#define MTXORB_FTDI_RANGE_930D_PID 0x930D
|
|
+#define MTXORB_FTDI_RANGE_930E_PID 0x930E
|
|
+#define MTXORB_FTDI_RANGE_930F_PID 0x930F
|
|
+#define MTXORB_FTDI_RANGE_9310_PID 0x9310
|
|
+#define MTXORB_FTDI_RANGE_9311_PID 0x9311
|
|
+#define MTXORB_FTDI_RANGE_9312_PID 0x9312
|
|
+#define MTXORB_FTDI_RANGE_9313_PID 0x9313
|
|
+#define MTXORB_FTDI_RANGE_9314_PID 0x9314
|
|
+#define MTXORB_FTDI_RANGE_9315_PID 0x9315
|
|
+#define MTXORB_FTDI_RANGE_9316_PID 0x9316
|
|
+#define MTXORB_FTDI_RANGE_9317_PID 0x9317
|
|
+#define MTXORB_FTDI_RANGE_9318_PID 0x9318
|
|
+#define MTXORB_FTDI_RANGE_9319_PID 0x9319
|
|
+#define MTXORB_FTDI_RANGE_931A_PID 0x931A
|
|
+#define MTXORB_FTDI_RANGE_931B_PID 0x931B
|
|
+#define MTXORB_FTDI_RANGE_931C_PID 0x931C
|
|
+#define MTXORB_FTDI_RANGE_931D_PID 0x931D
|
|
+#define MTXORB_FTDI_RANGE_931E_PID 0x931E
|
|
+#define MTXORB_FTDI_RANGE_931F_PID 0x931F
|
|
|
|
/*
|
|
* The Mobility Lab (TML)
|
|
diff --git a/drivers/usb/serial/keyspan.c b/drivers/usb/serial/keyspan.c
|
|
index 66d806e..0879ac7 100644
|
|
--- a/drivers/usb/serial/keyspan.c
|
|
+++ b/drivers/usb/serial/keyspan.c
|
|
@@ -323,24 +323,28 @@ static void usa26_indat_callback(struct urb *urb)
|
|
if ((data[0] & 0x80) == 0) {
|
|
/* no errors on individual bytes, only
|
|
possible overrun err */
|
|
- if (data[0] & RXERROR_OVERRUN)
|
|
- err = TTY_OVERRUN;
|
|
- else
|
|
- err = 0;
|
|
+ if (data[0] & RXERROR_OVERRUN) {
|
|
+ tty_insert_flip_char(tty, 0, TTY_OVERRUN);
|
|
+ }
|
|
for (i = 1; i < urb->actual_length ; ++i)
|
|
- tty_insert_flip_char(tty, data[i], err);
|
|
+ tty_insert_flip_char(tty, data[i], TTY_NORMAL);
|
|
} else {
|
|
/* some bytes had errors, every byte has status */
|
|
dbg("%s - RX error!!!!", __func__);
|
|
for (i = 0; i + 1 < urb->actual_length; i += 2) {
|
|
- int stat = data[i], flag = 0;
|
|
- if (stat & RXERROR_OVERRUN)
|
|
- flag |= TTY_OVERRUN;
|
|
- if (stat & RXERROR_FRAMING)
|
|
- flag |= TTY_FRAME;
|
|
- if (stat & RXERROR_PARITY)
|
|
- flag |= TTY_PARITY;
|
|
+ int stat = data[i];
|
|
+ int flag = TTY_NORMAL;
|
|
+
|
|
+ if (stat & RXERROR_OVERRUN) {
|
|
+ tty_insert_flip_char(tty, 0,
|
|
+ TTY_OVERRUN);
|
|
+ }
|
|
/* XXX should handle break (0x10) */
|
|
+ if (stat & RXERROR_PARITY)
|
|
+ flag = TTY_PARITY;
|
|
+ else if (stat & RXERROR_FRAMING)
|
|
+ flag = TTY_FRAME;
|
|
+
|
|
tty_insert_flip_char(tty, data[i+1], flag);
|
|
}
|
|
}
|
|
@@ -712,14 +716,19 @@ static void usa49_indat_callback(struct urb *urb)
|
|
} else {
|
|
/* some bytes had errors, every byte has status */
|
|
for (i = 0; i + 1 < urb->actual_length; i += 2) {
|
|
- int stat = data[i], flag = 0;
|
|
- if (stat & RXERROR_OVERRUN)
|
|
- flag |= TTY_OVERRUN;
|
|
- if (stat & RXERROR_FRAMING)
|
|
- flag |= TTY_FRAME;
|
|
- if (stat & RXERROR_PARITY)
|
|
- flag |= TTY_PARITY;
|
|
+ int stat = data[i];
|
|
+ int flag = TTY_NORMAL;
|
|
+
|
|
+ if (stat & RXERROR_OVERRUN) {
|
|
+ tty_insert_flip_char(tty, 0,
|
|
+ TTY_OVERRUN);
|
|
+ }
|
|
/* XXX should handle break (0x10) */
|
|
+ if (stat & RXERROR_PARITY)
|
|
+ flag = TTY_PARITY;
|
|
+ else if (stat & RXERROR_FRAMING)
|
|
+ flag = TTY_FRAME;
|
|
+
|
|
tty_insert_flip_char(tty, data[i+1], flag);
|
|
}
|
|
}
|
|
@@ -779,14 +788,19 @@ static void usa49wg_indat_callback(struct urb *urb)
|
|
* some bytes had errors, every byte has status
|
|
*/
|
|
for (x = 0; x + 1 < len; x += 2) {
|
|
- int stat = data[i], flag = 0;
|
|
- if (stat & RXERROR_OVERRUN)
|
|
- flag |= TTY_OVERRUN;
|
|
- if (stat & RXERROR_FRAMING)
|
|
- flag |= TTY_FRAME;
|
|
- if (stat & RXERROR_PARITY)
|
|
- flag |= TTY_PARITY;
|
|
+ int stat = data[i];
|
|
+ int flag = TTY_NORMAL;
|
|
+
|
|
+ if (stat & RXERROR_OVERRUN) {
|
|
+ tty_insert_flip_char(tty, 0,
|
|
+ TTY_OVERRUN);
|
|
+ }
|
|
/* XXX should handle break (0x10) */
|
|
+ if (stat & RXERROR_PARITY)
|
|
+ flag = TTY_PARITY;
|
|
+ else if (stat & RXERROR_FRAMING)
|
|
+ flag = TTY_FRAME;
|
|
+
|
|
tty_insert_flip_char(tty,
|
|
data[i+1], flag);
|
|
i += 2;
|
|
@@ -844,25 +858,32 @@ static void usa90_indat_callback(struct urb *urb)
|
|
if ((data[0] & 0x80) == 0) {
|
|
/* no errors on individual bytes, only
|
|
possible overrun err*/
|
|
- if (data[0] & RXERROR_OVERRUN)
|
|
- err = TTY_OVERRUN;
|
|
- else
|
|
- err = 0;
|
|
+ if (data[0] & RXERROR_OVERRUN) {
|
|
+ tty_insert_flip_char(tty, 0,
|
|
+ TTY_OVERRUN);
|
|
+ }
|
|
for (i = 1; i < urb->actual_length ; ++i)
|
|
tty_insert_flip_char(tty, data[i],
|
|
- err);
|
|
+ TTY_NORMAL);
|
|
} else {
|
|
/* some bytes had errors, every byte has status */
|
|
dbg("%s - RX error!!!!", __func__);
|
|
for (i = 0; i + 1 < urb->actual_length; i += 2) {
|
|
- int stat = data[i], flag = 0;
|
|
- if (stat & RXERROR_OVERRUN)
|
|
- flag |= TTY_OVERRUN;
|
|
- if (stat & RXERROR_FRAMING)
|
|
- flag |= TTY_FRAME;
|
|
- if (stat & RXERROR_PARITY)
|
|
- flag |= TTY_PARITY;
|
|
+ int stat = data[i];
|
|
+ int flag = TTY_NORMAL;
|
|
+
|
|
+ if (stat & RXERROR_OVERRUN) {
|
|
+ tty_insert_flip_char(
|
|
+ tty, 0,
|
|
+ TTY_OVERRUN);
|
|
+ }
|
|
+
|
|
/* XXX should handle break (0x10) */
|
|
+ if (stat & RXERROR_PARITY)
|
|
+ flag = TTY_PARITY;
|
|
+ else if (stat & RXERROR_FRAMING)
|
|
+ flag = TTY_FRAME;
|
|
+
|
|
tty_insert_flip_char(tty, data[i+1],
|
|
flag);
|
|
}
|
|
diff --git a/drivers/usb/serial/ssu100.c b/drivers/usb/serial/ssu100.c
|
|
index d19fa6a..f425507 100644
|
|
--- a/drivers/usb/serial/ssu100.c
|
|
+++ b/drivers/usb/serial/ssu100.c
|
|
@@ -598,10 +598,10 @@ static void ssu100_update_lsr(struct usb_serial_port *port, u8 lsr,
|
|
if (*tty_flag == TTY_NORMAL)
|
|
*tty_flag = TTY_FRAME;
|
|
}
|
|
- if (lsr & UART_LSR_OE){
|
|
+ if (lsr & UART_LSR_OE) {
|
|
priv->icount.overrun++;
|
|
- if (*tty_flag == TTY_NORMAL)
|
|
- *tty_flag = TTY_OVERRUN;
|
|
+ tty_insert_flip_char(tty_port_tty_get(&port->port),
|
|
+ 0, TTY_OVERRUN);
|
|
}
|
|
}
|
|
|
|
@@ -622,11 +622,8 @@ static int ssu100_process_packet(struct urb *urb,
|
|
if ((len >= 4) &&
|
|
(packet[0] == 0x1b) && (packet[1] == 0x1b) &&
|
|
((packet[2] == 0x00) || (packet[2] == 0x01))) {
|
|
- if (packet[2] == 0x00) {
|
|
+ if (packet[2] == 0x00)
|
|
ssu100_update_lsr(port, packet[3], &flag);
|
|
- if (flag == TTY_OVERRUN)
|
|
- tty_insert_flip_char(tty, 0, TTY_OVERRUN);
|
|
- }
|
|
if (packet[2] == 0x01)
|
|
ssu100_update_msr(port, packet[3]);
|
|
|
|
diff --git a/drivers/usb/storage/scsiglue.c b/drivers/usb/storage/scsiglue.c
|
|
index a4f033b..b987c53 100644
|
|
--- a/drivers/usb/storage/scsiglue.c
|
|
+++ b/drivers/usb/storage/scsiglue.c
|
|
@@ -247,6 +247,10 @@ static int slave_configure(struct scsi_device *sdev)
|
|
sdev->use_rpm_auto = 1;
|
|
sdev->autosuspend_delay = us->sdev_autosuspend_delay;
|
|
}
|
|
+
|
|
+ /* A few buggy USB-ATA bridges don't understand FUA */
|
|
+ if (us->fflags & US_FL_BROKEN_FUA)
|
|
+ sdev->broken_fua = 1;
|
|
} else {
|
|
|
|
/* Non-disk-type devices don't need to blacklist any pages
|
|
diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h
|
|
index a280945..25174be 100644
|
|
--- a/drivers/usb/storage/unusual_devs.h
|
|
+++ b/drivers/usb/storage/unusual_devs.h
|
|
@@ -1940,6 +1940,13 @@ UNUSUAL_DEV( 0x14cd, 0x6600, 0x0201, 0x0201,
|
|
USB_SC_DEVICE, USB_PR_DEVICE, NULL,
|
|
US_FL_IGNORE_RESIDUE ),
|
|
|
|
+/* Reported by Michael Büsch <m@bues.ch> */
|
|
+UNUSUAL_DEV( 0x152d, 0x0567, 0x0114, 0x0114,
|
|
+ "JMicron",
|
|
+ "USB to ATA/ATAPI Bridge",
|
|
+ USB_SC_DEVICE, USB_PR_DEVICE, NULL,
|
|
+ US_FL_BROKEN_FUA ),
|
|
+
|
|
/* Reported by Alexandre Oliva <oliva@lsd.ic.unicamp.br>
|
|
* JMicron responds to USN and several other SCSI ioctls with a
|
|
* residue that causes subsequent I/O requests to fail. */
|
|
@@ -1949,6 +1956,13 @@ UNUSUAL_DEV( 0x152d, 0x2329, 0x0100, 0x0100,
|
|
USB_SC_DEVICE, USB_PR_DEVICE, NULL,
|
|
US_FL_IGNORE_RESIDUE | US_FL_SANE_SENSE ),
|
|
|
|
+/* Reported by Dmitry Nezhevenko <dion@dion.org.ua> */
|
|
+UNUSUAL_DEV( 0x152d, 0x2566, 0x0114, 0x0114,
|
|
+ "JMicron",
|
|
+ "USB to ATA/ATAPI Bridge",
|
|
+ USB_SC_DEVICE, USB_PR_DEVICE, NULL,
|
|
+ US_FL_BROKEN_FUA ),
|
|
+
|
|
/* Entrega Technologies U1-SC25 (later Xircom PortGear PGSCSI)
|
|
* and Mac USB Dock USB-SCSI */
|
|
UNUSUAL_DEV( 0x1645, 0x0007, 0x0100, 0x0133,
|
|
diff --git a/drivers/video/logo/logo.c b/drivers/video/logo/logo.c
|
|
index 080c35b..cc5dbb5 100644
|
|
--- a/drivers/video/logo/logo.c
|
|
+++ b/drivers/video/logo/logo.c
|
|
@@ -25,6 +25,21 @@ static bool nologo;
|
|
module_param(nologo, bool, 0);
|
|
MODULE_PARM_DESC(nologo, "Disables startup logo");
|
|
|
|
+/*
|
|
+ * Logos are located in the initdata, and will be freed in kernel_init.
|
|
+ * Use late_init to mark the logos as freed to prevent any further use.
|
|
+ */
|
|
+
|
|
+static bool logos_freed;
|
|
+
|
|
+static int __init fb_logo_late_init(void)
|
|
+{
|
|
+ logos_freed = true;
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+late_initcall(fb_logo_late_init);
|
|
+
|
|
/* logo's are marked __initdata. Use __init_refok to tell
|
|
* modpost that it is intended that this function uses data
|
|
* marked __initdata.
|
|
@@ -33,7 +48,7 @@ const struct linux_logo * __init_refok fb_find_logo(int depth)
|
|
{
|
|
const struct linux_logo *logo = NULL;
|
|
|
|
- if (nologo)
|
|
+ if (nologo || logos_freed)
|
|
return NULL;
|
|
|
|
if (depth >= 1) {
|
|
diff --git a/drivers/virtio/virtio.c b/drivers/virtio/virtio.c
|
|
index 984c501..cc02a9b 100644
|
|
--- a/drivers/virtio/virtio.c
|
|
+++ b/drivers/virtio/virtio.c
|
|
@@ -9,33 +9,32 @@ static unsigned int dev_index;
|
|
static ssize_t device_show(struct device *_d,
|
|
struct device_attribute *attr, char *buf)
|
|
{
|
|
- struct virtio_device *dev = container_of(_d,struct virtio_device,dev);
|
|
+ struct virtio_device *dev = dev_to_virtio(_d);
|
|
return sprintf(buf, "0x%04x\n", dev->id.device);
|
|
}
|
|
static ssize_t vendor_show(struct device *_d,
|
|
struct device_attribute *attr, char *buf)
|
|
{
|
|
- struct virtio_device *dev = container_of(_d,struct virtio_device,dev);
|
|
+ struct virtio_device *dev = dev_to_virtio(_d);
|
|
return sprintf(buf, "0x%04x\n", dev->id.vendor);
|
|
}
|
|
static ssize_t status_show(struct device *_d,
|
|
struct device_attribute *attr, char *buf)
|
|
{
|
|
- struct virtio_device *dev = container_of(_d,struct virtio_device,dev);
|
|
+ struct virtio_device *dev = dev_to_virtio(_d);
|
|
return sprintf(buf, "0x%08x\n", dev->config->get_status(dev));
|
|
}
|
|
static ssize_t modalias_show(struct device *_d,
|
|
struct device_attribute *attr, char *buf)
|
|
{
|
|
- struct virtio_device *dev = container_of(_d,struct virtio_device,dev);
|
|
-
|
|
+ struct virtio_device *dev = dev_to_virtio(_d);
|
|
return sprintf(buf, "virtio:d%08Xv%08X\n",
|
|
dev->id.device, dev->id.vendor);
|
|
}
|
|
static ssize_t features_show(struct device *_d,
|
|
struct device_attribute *attr, char *buf)
|
|
{
|
|
- struct virtio_device *dev = container_of(_d, struct virtio_device, dev);
|
|
+ struct virtio_device *dev = dev_to_virtio(_d);
|
|
unsigned int i;
|
|
ssize_t len = 0;
|
|
|
|
@@ -70,7 +69,7 @@ static inline int virtio_id_match(const struct virtio_device *dev,
|
|
static int virtio_dev_match(struct device *_dv, struct device_driver *_dr)
|
|
{
|
|
unsigned int i;
|
|
- struct virtio_device *dev = container_of(_dv,struct virtio_device,dev);
|
|
+ struct virtio_device *dev = dev_to_virtio(_dv);
|
|
const struct virtio_device_id *ids;
|
|
|
|
ids = container_of(_dr, struct virtio_driver, driver)->id_table;
|
|
@@ -82,7 +81,7 @@ static int virtio_dev_match(struct device *_dv, struct device_driver *_dr)
|
|
|
|
static int virtio_uevent(struct device *_dv, struct kobj_uevent_env *env)
|
|
{
|
|
- struct virtio_device *dev = container_of(_dv,struct virtio_device,dev);
|
|
+ struct virtio_device *dev = dev_to_virtio(_dv);
|
|
|
|
return add_uevent_var(env, "MODALIAS=virtio:d%08Xv%08X",
|
|
dev->id.device, dev->id.vendor);
|
|
@@ -110,7 +109,7 @@ EXPORT_SYMBOL_GPL(virtio_check_driver_offered_feature);
|
|
static int virtio_dev_probe(struct device *_d)
|
|
{
|
|
int err, i;
|
|
- struct virtio_device *dev = container_of(_d,struct virtio_device,dev);
|
|
+ struct virtio_device *dev = dev_to_virtio(_d);
|
|
struct virtio_driver *drv = container_of(dev->dev.driver,
|
|
struct virtio_driver, driver);
|
|
u32 device_features;
|
|
@@ -148,7 +147,7 @@ static int virtio_dev_probe(struct device *_d)
|
|
|
|
static int virtio_dev_remove(struct device *_d)
|
|
{
|
|
- struct virtio_device *dev = container_of(_d,struct virtio_device,dev);
|
|
+ struct virtio_device *dev = dev_to_virtio(_d);
|
|
struct virtio_driver *drv = container_of(dev->dev.driver,
|
|
struct virtio_driver, driver);
|
|
|
|
diff --git a/drivers/virtio/virtio_pci.c b/drivers/virtio/virtio_pci.c
|
|
index a41f264..cc56763 100644
|
|
--- a/drivers/virtio/virtio_pci.c
|
|
+++ b/drivers/virtio/virtio_pci.c
|
|
@@ -624,11 +624,13 @@ static struct virtio_config_ops virtio_pci_config_ops = {
|
|
|
|
static void virtio_pci_release_dev(struct device *_d)
|
|
{
|
|
- /*
|
|
- * No need for a release method as we allocate/free
|
|
- * all devices together with the pci devices.
|
|
- * Provide an empty one to avoid getting a warning from core.
|
|
- */
|
|
+ struct virtio_device *vdev = dev_to_virtio(_d);
|
|
+ struct virtio_pci_device *vp_dev = to_vp_device(vdev);
|
|
+
|
|
+ /* As struct device is a kobject, it's not safe to
|
|
+ * free the memory (including the reference counter itself)
|
|
+ * until it's release callback. */
|
|
+ kfree(vp_dev);
|
|
}
|
|
|
|
/* the PCI probing function */
|
|
@@ -716,7 +718,6 @@ static void __devexit virtio_pci_remove(struct pci_dev *pci_dev)
|
|
pci_iounmap(pci_dev, vp_dev->ioaddr);
|
|
pci_release_regions(pci_dev);
|
|
pci_disable_device(pci_dev);
|
|
- kfree(vp_dev);
|
|
}
|
|
|
|
#ifdef CONFIG_PM
|
|
diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c
|
|
index a009b9e..6dacccef 100644
|
|
--- a/fs/binfmt_elf.c
|
|
+++ b/fs/binfmt_elf.c
|
|
@@ -539,11 +539,12 @@ static unsigned long load_elf_interp(struct elfhdr *interp_elf_ex,
|
|
|
|
static unsigned long randomize_stack_top(unsigned long stack_top)
|
|
{
|
|
- unsigned int random_variable = 0;
|
|
+ unsigned long random_variable = 0;
|
|
|
|
if ((current->flags & PF_RANDOMIZE) &&
|
|
!(current->personality & ADDR_NO_RANDOMIZE)) {
|
|
- random_variable = get_random_int() & STACK_RND_MASK;
|
|
+ random_variable = (unsigned long) get_random_int();
|
|
+ random_variable &= STACK_RND_MASK;
|
|
random_variable <<= PAGE_SHIFT;
|
|
}
|
|
#ifdef CONFIG_STACK_GROWSUP
|
|
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c
|
|
index a7ffc88..7c23cd9 100644
|
|
--- a/fs/btrfs/disk-io.c
|
|
+++ b/fs/btrfs/disk-io.c
|
|
@@ -3556,12 +3556,6 @@ static int btrfs_destroy_pinned_extent(struct btrfs_root *root,
|
|
if (ret)
|
|
break;
|
|
|
|
- /* opt_discard */
|
|
- if (btrfs_test_opt(root, DISCARD))
|
|
- ret = btrfs_error_discard_extent(root, start,
|
|
- end + 1 - start,
|
|
- NULL);
|
|
-
|
|
clear_extent_dirty(unpin, start, end, GFP_NOFS);
|
|
btrfs_error_unpin_extent_range(root, start, end);
|
|
cond_resched();
|
|
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c
|
|
index 224ce21..cf6e7f4 100644
|
|
--- a/fs/btrfs/extent-tree.c
|
|
+++ b/fs/btrfs/extent-tree.c
|
|
@@ -4892,7 +4892,8 @@ void btrfs_prepare_extent_commit(struct btrfs_trans_handle *trans,
|
|
update_global_block_rsv(fs_info);
|
|
}
|
|
|
|
-static int unpin_extent_range(struct btrfs_root *root, u64 start, u64 end)
|
|
+static int unpin_extent_range(struct btrfs_root *root, u64 start, u64 end,
|
|
+ const bool return_free_space)
|
|
{
|
|
struct btrfs_fs_info *fs_info = root->fs_info;
|
|
struct btrfs_block_group_cache *cache = NULL;
|
|
@@ -4912,7 +4913,8 @@ static int unpin_extent_range(struct btrfs_root *root, u64 start, u64 end)
|
|
|
|
if (start < cache->last_byte_to_unpin) {
|
|
len = min(len, cache->last_byte_to_unpin - start);
|
|
- btrfs_add_free_space(cache, start, len);
|
|
+ if (return_free_space)
|
|
+ btrfs_add_free_space(cache, start, len);
|
|
}
|
|
|
|
start += len;
|
|
@@ -4960,7 +4962,7 @@ int btrfs_finish_extent_commit(struct btrfs_trans_handle *trans,
|
|
end + 1 - start, NULL);
|
|
|
|
clear_extent_dirty(unpin, start, end, GFP_NOFS);
|
|
- unpin_extent_range(root, start, end);
|
|
+ unpin_extent_range(root, start, end, true);
|
|
cond_resched();
|
|
}
|
|
|
|
@@ -8008,7 +8010,7 @@ int btrfs_init_space_info(struct btrfs_fs_info *fs_info)
|
|
|
|
int btrfs_error_unpin_extent_range(struct btrfs_root *root, u64 start, u64 end)
|
|
{
|
|
- return unpin_extent_range(root, start, end);
|
|
+ return unpin_extent_range(root, start, end, false);
|
|
}
|
|
|
|
int btrfs_error_discard_extent(struct btrfs_root *root, u64 bytenr,
|
|
diff --git a/fs/ecryptfs/file.c b/fs/ecryptfs/file.c
|
|
index d45ba45..f04aa33 100644
|
|
--- a/fs/ecryptfs/file.c
|
|
+++ b/fs/ecryptfs/file.c
|
|
@@ -195,24 +195,12 @@ static int ecryptfs_open(struct inode *inode, struct file *file)
|
|
{
|
|
int rc = 0;
|
|
struct ecryptfs_crypt_stat *crypt_stat = NULL;
|
|
- struct ecryptfs_mount_crypt_stat *mount_crypt_stat;
|
|
struct dentry *ecryptfs_dentry = file->f_path.dentry;
|
|
/* Private value of ecryptfs_dentry allocated in
|
|
* ecryptfs_lookup() */
|
|
struct dentry *lower_dentry;
|
|
struct ecryptfs_file_info *file_info;
|
|
|
|
- mount_crypt_stat = &ecryptfs_superblock_to_private(
|
|
- ecryptfs_dentry->d_sb)->mount_crypt_stat;
|
|
- if ((mount_crypt_stat->flags & ECRYPTFS_ENCRYPTED_VIEW_ENABLED)
|
|
- && ((file->f_flags & O_WRONLY) || (file->f_flags & O_RDWR)
|
|
- || (file->f_flags & O_CREAT) || (file->f_flags & O_TRUNC)
|
|
- || (file->f_flags & O_APPEND))) {
|
|
- printk(KERN_WARNING "Mount has encrypted view enabled; "
|
|
- "files may only be read\n");
|
|
- rc = -EPERM;
|
|
- goto out;
|
|
- }
|
|
/* Released in ecryptfs_release or end of function if failure */
|
|
file_info = kmem_cache_zalloc(ecryptfs_file_info_cache, GFP_KERNEL);
|
|
ecryptfs_set_file_private(file, file_info);
|
|
diff --git a/fs/ecryptfs/main.c b/fs/ecryptfs/main.c
|
|
index 240832e..93b7bec 100644
|
|
--- a/fs/ecryptfs/main.c
|
|
+++ b/fs/ecryptfs/main.c
|
|
@@ -494,6 +494,7 @@ static struct dentry *ecryptfs_mount(struct file_system_type *fs_type, int flags
|
|
{
|
|
struct super_block *s;
|
|
struct ecryptfs_sb_info *sbi;
|
|
+ struct ecryptfs_mount_crypt_stat *mount_crypt_stat;
|
|
struct ecryptfs_dentry_info *root_info;
|
|
const char *err = "Getting sb failed";
|
|
struct inode *inode;
|
|
@@ -512,6 +513,7 @@ static struct dentry *ecryptfs_mount(struct file_system_type *fs_type, int flags
|
|
err = "Error parsing options";
|
|
goto out;
|
|
}
|
|
+ mount_crypt_stat = &sbi->mount_crypt_stat;
|
|
|
|
s = sget(fs_type, NULL, set_anon_super, NULL);
|
|
if (IS_ERR(s)) {
|
|
@@ -557,11 +559,19 @@ static struct dentry *ecryptfs_mount(struct file_system_type *fs_type, int flags
|
|
|
|
/**
|
|
* Set the POSIX ACL flag based on whether they're enabled in the lower
|
|
- * mount. Force a read-only eCryptfs mount if the lower mount is ro.
|
|
- * Allow a ro eCryptfs mount even when the lower mount is rw.
|
|
+ * mount.
|
|
*/
|
|
s->s_flags = flags & ~MS_POSIXACL;
|
|
- s->s_flags |= path.dentry->d_sb->s_flags & (MS_RDONLY | MS_POSIXACL);
|
|
+ s->s_flags |= path.dentry->d_sb->s_flags & MS_POSIXACL;
|
|
+
|
|
+ /**
|
|
+ * Force a read-only eCryptfs mount when:
|
|
+ * 1) The lower mount is ro
|
|
+ * 2) The ecryptfs_encrypted_view mount option is specified
|
|
+ */
|
|
+ if (path.dentry->d_sb->s_flags & MS_RDONLY ||
|
|
+ mount_crypt_stat->flags & ECRYPTFS_ENCRYPTED_VIEW_ENABLED)
|
|
+ s->s_flags |= MS_RDONLY;
|
|
|
|
s->s_maxbytes = path.dentry->d_sb->s_maxbytes;
|
|
s->s_blocksize = path.dentry->d_sb->s_blocksize;
|
|
diff --git a/fs/fs-writeback.c b/fs/fs-writeback.c
|
|
index e4926e5..6e748b1 100644
|
|
--- a/fs/fs-writeback.c
|
|
+++ b/fs/fs-writeback.c
|
|
@@ -403,7 +403,6 @@ writeback_single_inode(struct inode *inode, struct bdi_writeback *wb,
|
|
|
|
/* Set I_SYNC, reset I_DIRTY_PAGES */
|
|
inode->i_state |= I_SYNC;
|
|
- inode->i_state &= ~I_DIRTY_PAGES;
|
|
spin_unlock(&inode->i_lock);
|
|
spin_unlock(&wb->list_lock);
|
|
|
|
@@ -428,9 +427,28 @@ writeback_single_inode(struct inode *inode, struct bdi_writeback *wb,
|
|
* write_inode()
|
|
*/
|
|
spin_lock(&inode->i_lock);
|
|
+
|
|
dirty = inode->i_state & I_DIRTY;
|
|
- inode->i_state &= ~(I_DIRTY_SYNC | I_DIRTY_DATASYNC);
|
|
+ inode->i_state &= ~I_DIRTY;
|
|
+
|
|
+ /*
|
|
+ * Paired with smp_mb() in __mark_inode_dirty(). This allows
|
|
+ * __mark_inode_dirty() to test i_state without grabbing i_lock -
|
|
+ * either they see the I_DIRTY bits cleared or we see the dirtied
|
|
+ * inode.
|
|
+ *
|
|
+ * I_DIRTY_PAGES is always cleared together above even if @mapping
|
|
+ * still has dirty pages. The flag is reinstated after smp_mb() if
|
|
+ * necessary. This guarantees that either __mark_inode_dirty()
|
|
+ * sees clear I_DIRTY_PAGES or we see PAGECACHE_TAG_DIRTY.
|
|
+ */
|
|
+ smp_mb();
|
|
+
|
|
+ if (mapping_tagged(mapping, PAGECACHE_TAG_DIRTY))
|
|
+ inode->i_state |= I_DIRTY_PAGES;
|
|
+
|
|
spin_unlock(&inode->i_lock);
|
|
+
|
|
/* Don't write the inode if only I_DIRTY_PAGES was set */
|
|
if (dirty & (I_DIRTY_SYNC | I_DIRTY_DATASYNC)) {
|
|
int err = write_inode(inode, wbc);
|
|
@@ -456,7 +474,6 @@ writeback_single_inode(struct inode *inode, struct bdi_writeback *wb,
|
|
* We didn't write back all the pages. nfs_writepages()
|
|
* sometimes bales out without doing anything.
|
|
*/
|
|
- inode->i_state |= I_DIRTY_PAGES;
|
|
if (wbc->nr_to_write <= 0) {
|
|
/*
|
|
* slice used up: queue for next turn
|
|
@@ -1076,12 +1093,11 @@ void __mark_inode_dirty(struct inode *inode, int flags)
|
|
}
|
|
|
|
/*
|
|
- * make sure that changes are seen by all cpus before we test i_state
|
|
- * -- mikulas
|
|
+ * Paired with smp_mb() in __writeback_single_inode() for the
|
|
+ * following lockless i_state test. See there for details.
|
|
*/
|
|
smp_mb();
|
|
|
|
- /* avoid the locking if we can */
|
|
if ((inode->i_state & flags) == flags)
|
|
return;
|
|
|
|
diff --git a/fs/isofs/rock.c b/fs/isofs/rock.c
|
|
index ee62cc0..1780949 100644
|
|
--- a/fs/isofs/rock.c
|
|
+++ b/fs/isofs/rock.c
|
|
@@ -30,6 +30,7 @@ struct rock_state {
|
|
int cont_size;
|
|
int cont_extent;
|
|
int cont_offset;
|
|
+ int cont_loops;
|
|
struct inode *inode;
|
|
};
|
|
|
|
@@ -73,6 +74,9 @@ static void init_rock_state(struct rock_state *rs, struct inode *inode)
|
|
rs->inode = inode;
|
|
}
|
|
|
|
+/* Maximum number of Rock Ridge continuation entries */
|
|
+#define RR_MAX_CE_ENTRIES 32
|
|
+
|
|
/*
|
|
* Returns 0 if the caller should continue scanning, 1 if the scan must end
|
|
* and -ve on error.
|
|
@@ -105,6 +109,8 @@ static int rock_continue(struct rock_state *rs)
|
|
goto out;
|
|
}
|
|
ret = -EIO;
|
|
+ if (++rs->cont_loops >= RR_MAX_CE_ENTRIES)
|
|
+ goto out;
|
|
bh = sb_bread(rs->inode->i_sb, rs->cont_extent);
|
|
if (bh) {
|
|
memcpy(rs->buffer, bh->b_data + rs->cont_offset,
|
|
@@ -356,6 +362,9 @@ parse_rock_ridge_inode_internal(struct iso_directory_record *de,
|
|
rs.cont_size = isonum_733(rr->u.CE.size);
|
|
break;
|
|
case SIG('E', 'R'):
|
|
+ /* Invalid length of ER tag id? */
|
|
+ if (rr->u.ER.len_id + offsetof(struct rock_ridge, u.ER.data) > rr->len)
|
|
+ goto out;
|
|
ISOFS_SB(inode->i_sb)->s_rock = 1;
|
|
printk(KERN_DEBUG "ISO 9660 Extensions: ");
|
|
{
|
|
diff --git a/fs/jfs/jfs_dtree.c b/fs/jfs/jfs_dtree.c
|
|
index b6f17c0..33c8624 100644
|
|
--- a/fs/jfs/jfs_dtree.c
|
|
+++ b/fs/jfs/jfs_dtree.c
|
|
@@ -3103,7 +3103,7 @@ int jfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
|
|
* self "."
|
|
*/
|
|
filp->f_pos = 1;
|
|
- if (filldir(dirent, ".", 1, 0, ip->i_ino,
|
|
+ if (filldir(dirent, ".", 1, 1, ip->i_ino,
|
|
DT_DIR))
|
|
return 0;
|
|
}
|
|
@@ -3111,7 +3111,7 @@ int jfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
|
|
* parent ".."
|
|
*/
|
|
filp->f_pos = 2;
|
|
- if (filldir(dirent, "..", 2, 1, PARENT(ip), DT_DIR))
|
|
+ if (filldir(dirent, "..", 2, 2, PARENT(ip), DT_DIR))
|
|
return 0;
|
|
|
|
/*
|
|
diff --git a/fs/ncpfs/ioctl.c b/fs/ncpfs/ioctl.c
|
|
index 6958adf..0a76def 100644
|
|
--- a/fs/ncpfs/ioctl.c
|
|
+++ b/fs/ncpfs/ioctl.c
|
|
@@ -445,7 +445,6 @@ static long __ncp_ioctl(struct inode *inode, unsigned int cmd, unsigned long arg
|
|
result = -EIO;
|
|
}
|
|
}
|
|
- result = 0;
|
|
}
|
|
mutex_unlock(&server->root_setup_lock);
|
|
|
|
diff --git a/fs/nfsd/nfs4callback.c b/fs/nfsd/nfs4callback.c
|
|
index c8e9f63..ebf3f59 100644
|
|
--- a/fs/nfsd/nfs4callback.c
|
|
+++ b/fs/nfsd/nfs4callback.c
|
|
@@ -784,8 +784,12 @@ static bool nfsd41_cb_get_slot(struct nfs4_client *clp, struct rpc_task *task)
|
|
{
|
|
if (test_and_set_bit(0, &clp->cl_cb_slot_busy) != 0) {
|
|
rpc_sleep_on(&clp->cl_cb_waitq, task, NULL);
|
|
- dprintk("%s slot is busy\n", __func__);
|
|
- return false;
|
|
+ /* Race breaker */
|
|
+ if (test_and_set_bit(0, &clp->cl_cb_slot_busy) != 0) {
|
|
+ dprintk("%s slot is busy\n", __func__);
|
|
+ return false;
|
|
+ }
|
|
+ rpc_wake_up_queued_task(&clp->cl_cb_waitq, task);
|
|
}
|
|
return true;
|
|
}
|
|
diff --git a/fs/nilfs2/nilfs.h b/fs/nilfs2/nilfs.h
|
|
index 250add8..161a10c 100644
|
|
--- a/fs/nilfs2/nilfs.h
|
|
+++ b/fs/nilfs2/nilfs.h
|
|
@@ -128,7 +128,6 @@ enum {
|
|
* @ti_save: Backup of journal_info field of task_struct
|
|
* @ti_flags: Flags
|
|
* @ti_count: Nest level
|
|
- * @ti_garbage: List of inode to be put when releasing semaphore
|
|
*/
|
|
struct nilfs_transaction_info {
|
|
u32 ti_magic;
|
|
@@ -137,7 +136,6 @@ struct nilfs_transaction_info {
|
|
one of other filesystems has a bug. */
|
|
unsigned short ti_flags;
|
|
unsigned short ti_count;
|
|
- struct list_head ti_garbage;
|
|
};
|
|
|
|
/* ti_magic */
|
|
diff --git a/fs/nilfs2/segment.c b/fs/nilfs2/segment.c
|
|
index e0a5a18..7bb866c 100644
|
|
--- a/fs/nilfs2/segment.c
|
|
+++ b/fs/nilfs2/segment.c
|
|
@@ -302,7 +302,6 @@ static void nilfs_transaction_lock(struct super_block *sb,
|
|
ti->ti_count = 0;
|
|
ti->ti_save = cur_ti;
|
|
ti->ti_magic = NILFS_TI_MAGIC;
|
|
- INIT_LIST_HEAD(&ti->ti_garbage);
|
|
current->journal_info = ti;
|
|
|
|
for (;;) {
|
|
@@ -329,8 +328,6 @@ static void nilfs_transaction_unlock(struct super_block *sb)
|
|
|
|
up_write(&nilfs->ns_segctor_sem);
|
|
current->journal_info = ti->ti_save;
|
|
- if (!list_empty(&ti->ti_garbage))
|
|
- nilfs_dispose_list(nilfs, &ti->ti_garbage, 0);
|
|
}
|
|
|
|
static void *nilfs_segctor_map_segsum_entry(struct nilfs_sc_info *sci,
|
|
@@ -743,6 +740,15 @@ static void nilfs_dispose_list(struct the_nilfs *nilfs,
|
|
}
|
|
}
|
|
|
|
+static void nilfs_iput_work_func(struct work_struct *work)
|
|
+{
|
|
+ struct nilfs_sc_info *sci = container_of(work, struct nilfs_sc_info,
|
|
+ sc_iput_work);
|
|
+ struct the_nilfs *nilfs = sci->sc_super->s_fs_info;
|
|
+
|
|
+ nilfs_dispose_list(nilfs, &sci->sc_iput_queue, 0);
|
|
+}
|
|
+
|
|
static int nilfs_test_metadata_dirty(struct the_nilfs *nilfs,
|
|
struct nilfs_root *root)
|
|
{
|
|
@@ -1896,8 +1902,9 @@ static int nilfs_segctor_collect_dirty_files(struct nilfs_sc_info *sci,
|
|
static void nilfs_segctor_drop_written_files(struct nilfs_sc_info *sci,
|
|
struct the_nilfs *nilfs)
|
|
{
|
|
- struct nilfs_transaction_info *ti = current->journal_info;
|
|
struct nilfs_inode_info *ii, *n;
|
|
+ int during_mount = !(sci->sc_super->s_flags & MS_ACTIVE);
|
|
+ int defer_iput = false;
|
|
|
|
spin_lock(&nilfs->ns_inode_lock);
|
|
list_for_each_entry_safe(ii, n, &sci->sc_dirty_files, i_dirty) {
|
|
@@ -1908,9 +1915,24 @@ static void nilfs_segctor_drop_written_files(struct nilfs_sc_info *sci,
|
|
clear_bit(NILFS_I_BUSY, &ii->i_state);
|
|
brelse(ii->i_bh);
|
|
ii->i_bh = NULL;
|
|
- list_move_tail(&ii->i_dirty, &ti->ti_garbage);
|
|
+ list_del_init(&ii->i_dirty);
|
|
+ if (!ii->vfs_inode.i_nlink || during_mount) {
|
|
+ /*
|
|
+ * Defer calling iput() to avoid deadlocks if
|
|
+ * i_nlink == 0 or mount is not yet finished.
|
|
+ */
|
|
+ list_add_tail(&ii->i_dirty, &sci->sc_iput_queue);
|
|
+ defer_iput = true;
|
|
+ } else {
|
|
+ spin_unlock(&nilfs->ns_inode_lock);
|
|
+ iput(&ii->vfs_inode);
|
|
+ spin_lock(&nilfs->ns_inode_lock);
|
|
+ }
|
|
}
|
|
spin_unlock(&nilfs->ns_inode_lock);
|
|
+
|
|
+ if (defer_iput)
|
|
+ schedule_work(&sci->sc_iput_work);
|
|
}
|
|
|
|
/*
|
|
@@ -2577,6 +2599,8 @@ static struct nilfs_sc_info *nilfs_segctor_new(struct super_block *sb,
|
|
INIT_LIST_HEAD(&sci->sc_segbufs);
|
|
INIT_LIST_HEAD(&sci->sc_write_logs);
|
|
INIT_LIST_HEAD(&sci->sc_gc_inodes);
|
|
+ INIT_LIST_HEAD(&sci->sc_iput_queue);
|
|
+ INIT_WORK(&sci->sc_iput_work, nilfs_iput_work_func);
|
|
init_timer(&sci->sc_timer);
|
|
|
|
sci->sc_interval = HZ * NILFS_SC_DEFAULT_TIMEOUT;
|
|
@@ -2603,6 +2627,8 @@ static void nilfs_segctor_write_out(struct nilfs_sc_info *sci)
|
|
ret = nilfs_segctor_construct(sci, SC_LSEG_SR);
|
|
nilfs_transaction_unlock(sci->sc_super);
|
|
|
|
+ flush_work(&sci->sc_iput_work);
|
|
+
|
|
} while (ret && retrycount-- > 0);
|
|
}
|
|
|
|
@@ -2627,6 +2653,9 @@ static void nilfs_segctor_destroy(struct nilfs_sc_info *sci)
|
|
|| sci->sc_seq_request != sci->sc_seq_done);
|
|
spin_unlock(&sci->sc_state_lock);
|
|
|
|
+ if (flush_work(&sci->sc_iput_work))
|
|
+ flag = true;
|
|
+
|
|
if (flag || !nilfs_segctor_confirm(sci))
|
|
nilfs_segctor_write_out(sci);
|
|
|
|
@@ -2636,6 +2665,12 @@ static void nilfs_segctor_destroy(struct nilfs_sc_info *sci)
|
|
nilfs_dispose_list(nilfs, &sci->sc_dirty_files, 1);
|
|
}
|
|
|
|
+ if (!list_empty(&sci->sc_iput_queue)) {
|
|
+ nilfs_warning(sci->sc_super, __func__,
|
|
+ "iput queue is not empty\n");
|
|
+ nilfs_dispose_list(nilfs, &sci->sc_iput_queue, 1);
|
|
+ }
|
|
+
|
|
WARN_ON(!list_empty(&sci->sc_segbufs));
|
|
WARN_ON(!list_empty(&sci->sc_write_logs));
|
|
|
|
diff --git a/fs/nilfs2/segment.h b/fs/nilfs2/segment.h
|
|
index 38a1d00..a48d6de 100644
|
|
--- a/fs/nilfs2/segment.h
|
|
+++ b/fs/nilfs2/segment.h
|
|
@@ -26,6 +26,7 @@
|
|
#include <linux/types.h>
|
|
#include <linux/fs.h>
|
|
#include <linux/buffer_head.h>
|
|
+#include <linux/workqueue.h>
|
|
#include <linux/nilfs2_fs.h>
|
|
#include "nilfs.h"
|
|
|
|
@@ -92,6 +93,8 @@ struct nilfs_segsum_pointer {
|
|
* @sc_nblk_inc: Block count of current generation
|
|
* @sc_dirty_files: List of files to be written
|
|
* @sc_gc_inodes: List of GC inodes having blocks to be written
|
|
+ * @sc_iput_queue: list of inodes for which iput should be done
|
|
+ * @sc_iput_work: work struct to defer iput call
|
|
* @sc_freesegs: array of segment numbers to be freed
|
|
* @sc_nfreesegs: number of segments on @sc_freesegs
|
|
* @sc_dsync_inode: inode whose data pages are written for a sync operation
|
|
@@ -135,6 +138,8 @@ struct nilfs_sc_info {
|
|
|
|
struct list_head sc_dirty_files;
|
|
struct list_head sc_gc_inodes;
|
|
+ struct list_head sc_iput_queue;
|
|
+ struct work_struct sc_iput_work;
|
|
|
|
__u64 *sc_freesegs;
|
|
size_t sc_nfreesegs;
|
|
diff --git a/fs/notify/inode_mark.c b/fs/notify/inode_mark.c
|
|
index b13c00a..df6dacc 100644
|
|
--- a/fs/notify/inode_mark.c
|
|
+++ b/fs/notify/inode_mark.c
|
|
@@ -282,20 +282,25 @@ void fsnotify_unmount_inodes(struct list_head *list)
|
|
spin_unlock(&inode->i_lock);
|
|
|
|
/* In case the dropping of a reference would nuke next_i. */
|
|
- if ((&next_i->i_sb_list != list) &&
|
|
- atomic_read(&next_i->i_count)) {
|
|
+ while (&next_i->i_sb_list != list) {
|
|
spin_lock(&next_i->i_lock);
|
|
- if (!(next_i->i_state & (I_FREEING | I_WILL_FREE))) {
|
|
+ if (!(next_i->i_state & (I_FREEING | I_WILL_FREE)) &&
|
|
+ atomic_read(&next_i->i_count)) {
|
|
__iget(next_i);
|
|
need_iput = next_i;
|
|
+ spin_unlock(&next_i->i_lock);
|
|
+ break;
|
|
}
|
|
spin_unlock(&next_i->i_lock);
|
|
+ next_i = list_entry(next_i->i_sb_list.next,
|
|
+ struct inode, i_sb_list);
|
|
}
|
|
|
|
/*
|
|
- * We can safely drop inode_sb_list_lock here because we hold
|
|
- * references on both inode and next_i. Also no new inodes
|
|
- * will be added since the umount has begun.
|
|
+ * We can safely drop inode_sb_list_lock here because either
|
|
+ * we actually hold references on both inode and next_i or
|
|
+ * end of list. Also no new inodes will be added since the
|
|
+ * umount has begun.
|
|
*/
|
|
spin_unlock(&inode_sb_list_lock);
|
|
|
|
diff --git a/fs/ocfs2/aops.c b/fs/ocfs2/aops.c
|
|
index 340bd02..e9829ca 100644
|
|
--- a/fs/ocfs2/aops.c
|
|
+++ b/fs/ocfs2/aops.c
|
|
@@ -917,7 +917,7 @@ void ocfs2_unlock_and_free_pages(struct page **pages, int num_pages)
|
|
}
|
|
}
|
|
|
|
-static void ocfs2_free_write_ctxt(struct ocfs2_write_ctxt *wc)
|
|
+static void ocfs2_unlock_pages(struct ocfs2_write_ctxt *wc)
|
|
{
|
|
int i;
|
|
|
|
@@ -938,7 +938,11 @@ static void ocfs2_free_write_ctxt(struct ocfs2_write_ctxt *wc)
|
|
page_cache_release(wc->w_target_page);
|
|
}
|
|
ocfs2_unlock_and_free_pages(wc->w_pages, wc->w_num_pages);
|
|
+}
|
|
|
|
+static void ocfs2_free_write_ctxt(struct ocfs2_write_ctxt *wc)
|
|
+{
|
|
+ ocfs2_unlock_pages(wc);
|
|
brelse(wc->w_di_bh);
|
|
kfree(wc);
|
|
}
|
|
@@ -2059,11 +2063,19 @@ int ocfs2_write_end_nolock(struct address_space *mapping,
|
|
di->i_mtime_nsec = di->i_ctime_nsec = cpu_to_le32(inode->i_mtime.tv_nsec);
|
|
ocfs2_journal_dirty(handle, wc->w_di_bh);
|
|
|
|
+ /* unlock pages before dealloc since it needs acquiring j_trans_barrier
|
|
+ * lock, or it will cause a deadlock since journal commit threads holds
|
|
+ * this lock and will ask for the page lock when flushing the data.
|
|
+ * put it here to preserve the unlock order.
|
|
+ */
|
|
+ ocfs2_unlock_pages(wc);
|
|
+
|
|
ocfs2_commit_trans(osb, handle);
|
|
|
|
ocfs2_run_deallocs(osb, &wc->w_dealloc);
|
|
|
|
- ocfs2_free_write_ctxt(wc);
|
|
+ brelse(wc->w_di_bh);
|
|
+ kfree(wc);
|
|
|
|
return copied;
|
|
}
|
|
diff --git a/fs/proc/stat.c b/fs/proc/stat.c
|
|
index a1ca9bc..95f2e25 100644
|
|
--- a/fs/proc/stat.c
|
|
+++ b/fs/proc/stat.c
|
|
@@ -159,7 +159,7 @@ static int show_stat(struct seq_file *p, void *v)
|
|
|
|
/* sum again ? it could be updated? */
|
|
for_each_irq_nr(j)
|
|
- seq_put_decimal_ull(p, ' ', kstat_irqs(j));
|
|
+ seq_put_decimal_ull(p, ' ', kstat_irqs_usr(j));
|
|
|
|
seq_printf(p,
|
|
"\nctxt %llu\n"
|
|
diff --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c
|
|
index e4e423a..324eb57 100644
|
|
--- a/fs/proc/task_mmu.c
|
|
+++ b/fs/proc/task_mmu.c
|
|
@@ -1054,9 +1054,19 @@ static ssize_t pagemap_read(struct file *file, char __user *buf,
|
|
return ret;
|
|
}
|
|
|
|
+static int pagemap_open(struct inode *inode, struct file *file)
|
|
+{
|
|
+ /* do not disclose physical addresses to unprivileged
|
|
+ userspace (closes a rowhammer attack vector) */
|
|
+ if (!capable(CAP_SYS_ADMIN))
|
|
+ return -EPERM;
|
|
+ return 0;
|
|
+}
|
|
+
|
|
const struct file_operations proc_pagemap_operations = {
|
|
.llseek = mem_lseek, /* borrow this */
|
|
.read = pagemap_read,
|
|
+ .open = pagemap_open,
|
|
};
|
|
#endif /* CONFIG_PROC_PAGE_MONITOR */
|
|
|
|
diff --git a/fs/udf/dir.c b/fs/udf/dir.c
|
|
index eb8bfe2..56341af 100644
|
|
--- a/fs/udf/dir.c
|
|
+++ b/fs/udf/dir.c
|
|
@@ -163,7 +163,8 @@ static int do_udf_readdir(struct inode *dir, struct file *filp,
|
|
struct kernel_lb_addr tloc = lelb_to_cpu(cfi.icb.extLocation);
|
|
|
|
iblock = udf_get_lb_pblock(dir->i_sb, &tloc, 0);
|
|
- flen = udf_get_filename(dir->i_sb, nameptr, fname, lfi);
|
|
+ flen = udf_get_filename(dir->i_sb, nameptr, lfi, fname,
|
|
+ UDF_NAME_LEN);
|
|
dt_type = DT_UNKNOWN;
|
|
}
|
|
|
|
diff --git a/fs/udf/inode.c b/fs/udf/inode.c
|
|
index aa70035..8053ee7 100644
|
|
--- a/fs/udf/inode.c
|
|
+++ b/fs/udf/inode.c
|
|
@@ -1392,6 +1392,20 @@ static void udf_fill_inode(struct inode *inode, struct buffer_head *bh)
|
|
iinfo->i_lenEAttr;
|
|
}
|
|
|
|
+ /* Sanity checks for files in ICB so that we don't get confused later */
|
|
+ if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB) {
|
|
+ /*
|
|
+ * For file in ICB data is stored in allocation descriptor
|
|
+ * so sizes should match
|
|
+ */
|
|
+ if (iinfo->i_lenAlloc != inode->i_size)
|
|
+ return;
|
|
+ /* File in ICB has to fit in there... */
|
|
+ if (inode->i_size > inode->i_sb->s_blocksize -
|
|
+ udf_file_entry_alloc_offset(inode))
|
|
+ return;
|
|
+ }
|
|
+
|
|
switch (fe->icbTag.fileType) {
|
|
case ICBTAG_FILE_TYPE_DIRECTORY:
|
|
inode->i_op = &udf_dir_inode_operations;
|
|
diff --git a/fs/udf/namei.c b/fs/udf/namei.c
|
|
index 78bff11..407c129 100644
|
|
--- a/fs/udf/namei.c
|
|
+++ b/fs/udf/namei.c
|
|
@@ -233,7 +233,8 @@ static struct fileIdentDesc *udf_find_entry(struct inode *dir,
|
|
if (!lfi)
|
|
continue;
|
|
|
|
- flen = udf_get_filename(dir->i_sb, nameptr, fname, lfi);
|
|
+ flen = udf_get_filename(dir->i_sb, nameptr, lfi, fname,
|
|
+ UDF_NAME_LEN);
|
|
if (flen && udf_match(flen, fname, child->len, child->name))
|
|
goto out_ok;
|
|
}
|
|
diff --git a/fs/udf/symlink.c b/fs/udf/symlink.c
|
|
index d7c6dbe..0422b7b 100644
|
|
--- a/fs/udf/symlink.c
|
|
+++ b/fs/udf/symlink.c
|
|
@@ -30,49 +30,73 @@
|
|
#include <linux/buffer_head.h>
|
|
#include "udf_i.h"
|
|
|
|
-static void udf_pc_to_char(struct super_block *sb, unsigned char *from,
|
|
- int fromlen, unsigned char *to)
|
|
+static int udf_pc_to_char(struct super_block *sb, unsigned char *from,
|
|
+ int fromlen, unsigned char *to, int tolen)
|
|
{
|
|
struct pathComponent *pc;
|
|
int elen = 0;
|
|
+ int comp_len;
|
|
unsigned char *p = to;
|
|
|
|
+ /* Reserve one byte for terminating \0 */
|
|
+ tolen--;
|
|
while (elen < fromlen) {
|
|
pc = (struct pathComponent *)(from + elen);
|
|
+ elen += sizeof(struct pathComponent);
|
|
switch (pc->componentType) {
|
|
case 1:
|
|
/*
|
|
* Symlink points to some place which should be agreed
|
|
* upon between originator and receiver of the media. Ignore.
|
|
*/
|
|
- if (pc->lengthComponentIdent > 0)
|
|
+ if (pc->lengthComponentIdent > 0) {
|
|
+ elen += pc->lengthComponentIdent;
|
|
break;
|
|
+ }
|
|
/* Fall through */
|
|
case 2:
|
|
+ if (tolen == 0)
|
|
+ return -ENAMETOOLONG;
|
|
p = to;
|
|
*p++ = '/';
|
|
+ tolen--;
|
|
break;
|
|
case 3:
|
|
+ if (tolen < 3)
|
|
+ return -ENAMETOOLONG;
|
|
memcpy(p, "../", 3);
|
|
p += 3;
|
|
+ tolen -= 3;
|
|
break;
|
|
case 4:
|
|
+ if (tolen < 2)
|
|
+ return -ENAMETOOLONG;
|
|
memcpy(p, "./", 2);
|
|
p += 2;
|
|
+ tolen -= 2;
|
|
/* that would be . - just ignore */
|
|
break;
|
|
case 5:
|
|
- p += udf_get_filename(sb, pc->componentIdent, p,
|
|
- pc->lengthComponentIdent);
|
|
+ elen += pc->lengthComponentIdent;
|
|
+ if (elen > fromlen)
|
|
+ return -EIO;
|
|
+ comp_len = udf_get_filename(sb, pc->componentIdent,
|
|
+ pc->lengthComponentIdent,
|
|
+ p, tolen);
|
|
+ p += comp_len;
|
|
+ tolen -= comp_len;
|
|
+ if (tolen == 0)
|
|
+ return -ENAMETOOLONG;
|
|
*p++ = '/';
|
|
+ tolen--;
|
|
break;
|
|
}
|
|
- elen += sizeof(struct pathComponent) + pc->lengthComponentIdent;
|
|
}
|
|
if (p > to + 1)
|
|
p[-1] = '\0';
|
|
else
|
|
p[0] = '\0';
|
|
+ return 0;
|
|
}
|
|
|
|
static int udf_symlink_filler(struct file *file, struct page *page)
|
|
@@ -80,11 +104,17 @@ static int udf_symlink_filler(struct file *file, struct page *page)
|
|
struct inode *inode = page->mapping->host;
|
|
struct buffer_head *bh = NULL;
|
|
unsigned char *symlink;
|
|
- int err = -EIO;
|
|
+ int err;
|
|
unsigned char *p = kmap(page);
|
|
struct udf_inode_info *iinfo;
|
|
uint32_t pos;
|
|
|
|
+ /* We don't support symlinks longer than one block */
|
|
+ if (inode->i_size > inode->i_sb->s_blocksize) {
|
|
+ err = -ENAMETOOLONG;
|
|
+ goto out_unmap;
|
|
+ }
|
|
+
|
|
iinfo = UDF_I(inode);
|
|
pos = udf_block_map(inode, 0);
|
|
|
|
@@ -94,14 +124,18 @@ static int udf_symlink_filler(struct file *file, struct page *page)
|
|
} else {
|
|
bh = sb_bread(inode->i_sb, pos);
|
|
|
|
- if (!bh)
|
|
- goto out;
|
|
+ if (!bh) {
|
|
+ err = -EIO;
|
|
+ goto out_unlock_inode;
|
|
+ }
|
|
|
|
symlink = bh->b_data;
|
|
}
|
|
|
|
- udf_pc_to_char(inode->i_sb, symlink, inode->i_size, p);
|
|
+ err = udf_pc_to_char(inode->i_sb, symlink, inode->i_size, p, PAGE_SIZE);
|
|
brelse(bh);
|
|
+ if (err)
|
|
+ goto out_unlock_inode;
|
|
|
|
up_read(&iinfo->i_data_sem);
|
|
SetPageUptodate(page);
|
|
@@ -109,9 +143,10 @@ static int udf_symlink_filler(struct file *file, struct page *page)
|
|
unlock_page(page);
|
|
return 0;
|
|
|
|
-out:
|
|
+out_unlock_inode:
|
|
up_read(&iinfo->i_data_sem);
|
|
SetPageError(page);
|
|
+out_unmap:
|
|
kunmap(page);
|
|
unlock_page(page);
|
|
return err;
|
|
diff --git a/fs/udf/udfdecl.h b/fs/udf/udfdecl.h
|
|
index ebe1031..375f648 100644
|
|
--- a/fs/udf/udfdecl.h
|
|
+++ b/fs/udf/udfdecl.h
|
|
@@ -207,7 +207,8 @@ udf_get_lb_pblock(struct super_block *sb, struct kernel_lb_addr *loc,
|
|
}
|
|
|
|
/* unicode.c */
|
|
-extern int udf_get_filename(struct super_block *, uint8_t *, uint8_t *, int);
|
|
+extern int udf_get_filename(struct super_block *, uint8_t *, int, uint8_t *,
|
|
+ int);
|
|
extern int udf_put_filename(struct super_block *, const uint8_t *, uint8_t *,
|
|
int);
|
|
extern int udf_build_ustr(struct ustr *, dstring *, int);
|
|
diff --git a/fs/udf/unicode.c b/fs/udf/unicode.c
|
|
index 44b815e..d29c06f 100644
|
|
--- a/fs/udf/unicode.c
|
|
+++ b/fs/udf/unicode.c
|
|
@@ -28,7 +28,8 @@
|
|
|
|
#include "udf_sb.h"
|
|
|
|
-static int udf_translate_to_linux(uint8_t *, uint8_t *, int, uint8_t *, int);
|
|
+static int udf_translate_to_linux(uint8_t *, int, uint8_t *, int, uint8_t *,
|
|
+ int);
|
|
|
|
static int udf_char_to_ustr(struct ustr *dest, const uint8_t *src, int strlen)
|
|
{
|
|
@@ -333,8 +334,8 @@ static int udf_NLStoCS0(struct nls_table *nls, dstring *ocu, struct ustr *uni,
|
|
return u_len + 1;
|
|
}
|
|
|
|
-int udf_get_filename(struct super_block *sb, uint8_t *sname, uint8_t *dname,
|
|
- int flen)
|
|
+int udf_get_filename(struct super_block *sb, uint8_t *sname, int slen,
|
|
+ uint8_t *dname, int dlen)
|
|
{
|
|
struct ustr *filename, *unifilename;
|
|
int len = 0;
|
|
@@ -347,7 +348,7 @@ int udf_get_filename(struct super_block *sb, uint8_t *sname, uint8_t *dname,
|
|
if (!unifilename)
|
|
goto out1;
|
|
|
|
- if (udf_build_ustr_exact(unifilename, sname, flen))
|
|
+ if (udf_build_ustr_exact(unifilename, sname, slen))
|
|
goto out2;
|
|
|
|
if (UDF_QUERY_FLAG(sb, UDF_FLAG_UTF8)) {
|
|
@@ -366,7 +367,8 @@ int udf_get_filename(struct super_block *sb, uint8_t *sname, uint8_t *dname,
|
|
} else
|
|
goto out2;
|
|
|
|
- len = udf_translate_to_linux(dname, filename->u_name, filename->u_len,
|
|
+ len = udf_translate_to_linux(dname, dlen,
|
|
+ filename->u_name, filename->u_len,
|
|
unifilename->u_name, unifilename->u_len);
|
|
out2:
|
|
kfree(unifilename);
|
|
@@ -403,10 +405,12 @@ int udf_put_filename(struct super_block *sb, const uint8_t *sname,
|
|
#define EXT_MARK '.'
|
|
#define CRC_MARK '#'
|
|
#define EXT_SIZE 5
|
|
+/* Number of chars we need to store generated CRC to make filename unique */
|
|
+#define CRC_LEN 5
|
|
|
|
-static int udf_translate_to_linux(uint8_t *newName, uint8_t *udfName,
|
|
- int udfLen, uint8_t *fidName,
|
|
- int fidNameLen)
|
|
+static int udf_translate_to_linux(uint8_t *newName, int newLen,
|
|
+ uint8_t *udfName, int udfLen,
|
|
+ uint8_t *fidName, int fidNameLen)
|
|
{
|
|
int index, newIndex = 0, needsCRC = 0;
|
|
int extIndex = 0, newExtIndex = 0, hasExt = 0;
|
|
@@ -440,7 +444,7 @@ static int udf_translate_to_linux(uint8_t *newName, uint8_t *udfName,
|
|
newExtIndex = newIndex;
|
|
}
|
|
}
|
|
- if (newIndex < 256)
|
|
+ if (newIndex < newLen)
|
|
newName[newIndex++] = curr;
|
|
else
|
|
needsCRC = 1;
|
|
@@ -468,13 +472,13 @@ static int udf_translate_to_linux(uint8_t *newName, uint8_t *udfName,
|
|
}
|
|
ext[localExtIndex++] = curr;
|
|
}
|
|
- maxFilenameLen = 250 - localExtIndex;
|
|
+ maxFilenameLen = newLen - CRC_LEN - localExtIndex;
|
|
if (newIndex > maxFilenameLen)
|
|
newIndex = maxFilenameLen;
|
|
else
|
|
newIndex = newExtIndex;
|
|
- } else if (newIndex > 250)
|
|
- newIndex = 250;
|
|
+ } else if (newIndex > newLen - CRC_LEN)
|
|
+ newIndex = newLen - CRC_LEN;
|
|
newName[newIndex++] = CRC_MARK;
|
|
valueCRC = crc_itu_t(0, fidName, fidNameLen);
|
|
newName[newIndex++] = hexChar[(valueCRC & 0xf000) >> 12];
|
|
diff --git a/include/linux/device.h b/include/linux/device.h
|
|
index c297f25..5bf8909 100644
|
|
--- a/include/linux/device.h
|
|
+++ b/include/linux/device.h
|
|
@@ -849,6 +849,11 @@ extern __printf(5, 6)
|
|
struct device *device_create(struct class *cls, struct device *parent,
|
|
dev_t devt, void *drvdata,
|
|
const char *fmt, ...);
|
|
+extern __printf(6, 7)
|
|
+struct device *device_create_with_groups(struct class *cls,
|
|
+ struct device *parent, dev_t devt, void *drvdata,
|
|
+ const struct attribute_group **groups,
|
|
+ const char *fmt, ...);
|
|
extern void device_destroy(struct class *cls, dev_t devt);
|
|
|
|
/*
|
|
diff --git a/include/linux/kernel_stat.h b/include/linux/kernel_stat.h
|
|
index 2fbd905..8e62498 100644
|
|
--- a/include/linux/kernel_stat.h
|
|
+++ b/include/linux/kernel_stat.h
|
|
@@ -104,8 +104,13 @@ static inline unsigned int kstat_irqs(unsigned int irq)
|
|
|
|
return sum;
|
|
}
|
|
+static inline unsigned int kstat_irqs_usr(unsigned int irq)
|
|
+{
|
|
+ return kstat_irqs(irq);
|
|
+}
|
|
#else
|
|
extern unsigned int kstat_irqs(unsigned int irq);
|
|
+extern unsigned int kstat_irqs_usr(unsigned int irq);
|
|
#endif
|
|
|
|
/*
|
|
diff --git a/include/linux/libata.h b/include/linux/libata.h
|
|
index dd16deb..764cd54 100644
|
|
--- a/include/linux/libata.h
|
|
+++ b/include/linux/libata.h
|
|
@@ -207,6 +207,7 @@ enum {
|
|
ATA_FLAG_SW_ACTIVITY = (1 << 22), /* driver supports sw activity
|
|
* led */
|
|
ATA_FLAG_NO_DIPM = (1 << 23), /* host not happy with DIPM */
|
|
+ ATA_FLAG_LOWTAG = (1 << 24), /* host wants lowest available tag */
|
|
|
|
/* bits 24:31 of ap->flags are reserved for LLD specific flags */
|
|
|
|
diff --git a/include/linux/mm.h b/include/linux/mm.h
|
|
index dcff232..e2309a7 100644
|
|
--- a/include/linux/mm.h
|
|
+++ b/include/linux/mm.h
|
|
@@ -871,6 +871,7 @@ static inline int page_mapped(struct page *page)
|
|
#define VM_FAULT_WRITE 0x0008 /* Special case for get_user_pages */
|
|
#define VM_FAULT_HWPOISON 0x0010 /* Hit poisoned small page */
|
|
#define VM_FAULT_HWPOISON_LARGE 0x0020 /* Hit poisoned large page. Index encoded in upper bits */
|
|
+#define VM_FAULT_SIGSEGV 0x0040
|
|
|
|
#define VM_FAULT_NOPAGE 0x0100 /* ->fault installed the pte, not return page */
|
|
#define VM_FAULT_LOCKED 0x0200 /* ->fault locked the returned page */
|
|
@@ -878,8 +879,8 @@ static inline int page_mapped(struct page *page)
|
|
|
|
#define VM_FAULT_HWPOISON_LARGE_MASK 0xf000 /* encodes hpage index for large hwpoison */
|
|
|
|
-#define VM_FAULT_ERROR (VM_FAULT_OOM | VM_FAULT_SIGBUS | VM_FAULT_HWPOISON | \
|
|
- VM_FAULT_HWPOISON_LARGE)
|
|
+#define VM_FAULT_ERROR (VM_FAULT_OOM | VM_FAULT_SIGBUS | VM_FAULT_SIGSEGV | \
|
|
+ VM_FAULT_HWPOISON | VM_FAULT_HWPOISON_LARGE)
|
|
|
|
/* Encode hstate index for a hwpoisoned large page */
|
|
#define VM_FAULT_SET_HINDEX(x) ((x) << 12)
|
|
@@ -1492,7 +1493,7 @@ extern int expand_downwards(struct vm_area_struct *vma,
|
|
#if VM_GROWSUP
|
|
extern int expand_upwards(struct vm_area_struct *vma, unsigned long address);
|
|
#else
|
|
- #define expand_upwards(vma, address) do { } while (0)
|
|
+ #define expand_upwards(vma, address) (0)
|
|
#endif
|
|
|
|
/* Look up the first VMA which satisfies addr < vm_end, NULL if none. */
|
|
diff --git a/include/linux/rmap.h b/include/linux/rmap.h
|
|
index a5ddc60..2f69ff4 100644
|
|
--- a/include/linux/rmap.h
|
|
+++ b/include/linux/rmap.h
|
|
@@ -37,6 +37,16 @@ struct anon_vma {
|
|
atomic_t refcount;
|
|
|
|
/*
|
|
+ * Count of child anon_vmas and VMAs which points to this anon_vma.
|
|
+ *
|
|
+ * This counter is used for making decision about reusing anon_vma
|
|
+ * instead of forking new one. See comments in function anon_vma_clone.
|
|
+ */
|
|
+ unsigned degree;
|
|
+
|
|
+ struct anon_vma *parent; /* Parent of this anon_vma */
|
|
+
|
|
+ /*
|
|
* NOTE: the LSB of the head.next is set by
|
|
* mm_take_all_locks() _after_ taking the above lock. So the
|
|
* head must only be read/written after taking the above lock
|
|
diff --git a/include/linux/sysfs.h b/include/linux/sysfs.h
|
|
index 0010009..caf2e56 100644
|
|
--- a/include/linux/sysfs.h
|
|
+++ b/include/linux/sysfs.h
|
|
@@ -80,6 +80,15 @@ struct attribute_group {
|
|
|
|
#define __ATTR_NULL { .attr = { .name = NULL } }
|
|
|
|
+#define ATTRIBUTE_GROUPS(name) \
|
|
+static const struct attribute_group name##_group = { \
|
|
+ .attrs = name##_attrs, \
|
|
+}; \
|
|
+static const struct attribute_group *name##_groups[] = { \
|
|
+ &name##_group, \
|
|
+ NULL, \
|
|
+}
|
|
+
|
|
#define attr_name(_attr) (_attr).attr.name
|
|
|
|
struct file;
|
|
diff --git a/include/linux/time.h b/include/linux/time.h
|
|
index af224eb..577e465 100644
|
|
--- a/include/linux/time.h
|
|
+++ b/include/linux/time.h
|
|
@@ -195,6 +195,19 @@ extern void getboottime(struct timespec *ts);
|
|
extern void monotonic_to_bootbased(struct timespec *ts);
|
|
extern void get_monotonic_boottime(struct timespec *ts);
|
|
|
|
+static inline bool timeval_valid(const struct timeval *tv)
|
|
+{
|
|
+ /* Dates before 1970 are bogus */
|
|
+ if (tv->tv_sec < 0)
|
|
+ return false;
|
|
+
|
|
+ /* Can't have more microseconds then a second */
|
|
+ if (tv->tv_usec < 0 || tv->tv_usec >= USEC_PER_SEC)
|
|
+ return false;
|
|
+
|
|
+ return true;
|
|
+}
|
|
+
|
|
extern struct timespec timespec_trunc(struct timespec t, unsigned gran);
|
|
extern int timekeeping_valid_for_hres(void);
|
|
extern u64 timekeeping_max_deferment(void);
|
|
diff --git a/include/linux/usb/quirks.h b/include/linux/usb/quirks.h
|
|
index b1a7654..4bfff7a 100644
|
|
--- a/include/linux/usb/quirks.h
|
|
+++ b/include/linux/usb/quirks.h
|
|
@@ -35,4 +35,15 @@
|
|
/* device can't handle device_qualifier descriptor requests */
|
|
#define USB_QUIRK_DEVICE_QUALIFIER 0x00000100
|
|
|
|
+/*
|
|
+ * For high speed and super speed interupt endpoints, the USB 2.0 and
|
|
+ * USB 3.0 spec require the interval in microframes
|
|
+ * (1 microframe = 125 microseconds) to be calculated as
|
|
+ * interval = 2 ^ (bInterval-1).
|
|
+ *
|
|
+ * Devices with this quirk report their bInterval as the result of this
|
|
+ * calculation instead of the exponent variable used in the calculation.
|
|
+ */
|
|
+#define USB_QUIRK_LINEAR_UFRAME_INTR_BINTERVAL 0x00000080
|
|
+
|
|
#endif /* __LINUX_USB_QUIRKS_H */
|
|
diff --git a/include/linux/usb_usual.h b/include/linux/usb_usual.h
|
|
index 17df360..f2000e9 100644
|
|
--- a/include/linux/usb_usual.h
|
|
+++ b/include/linux/usb_usual.h
|
|
@@ -64,7 +64,9 @@
|
|
US_FLAG(NO_READ_CAPACITY_16, 0x00080000) \
|
|
/* cannot handle READ_CAPACITY_16 */ \
|
|
US_FLAG(INITIAL_READ10, 0x00100000) \
|
|
- /* Initial READ(10) (and others) must be retried */
|
|
+ /* Initial READ(10) (and others) must be retried */ \
|
|
+ US_FLAG(BROKEN_FUA, 0x01000000) \
|
|
+ /* Cannot handle FUA in WRITE or READ CDBs */ \
|
|
|
|
#define US_FLAG(name, value) US_FL_##name = value ,
|
|
enum { US_DO_ALL_FLAGS };
|
|
diff --git a/include/linux/virtio.h b/include/linux/virtio.h
|
|
index c2814ab..eba97bf 100644
|
|
--- a/include/linux/virtio.h
|
|
+++ b/include/linux/virtio.h
|
|
@@ -280,7 +280,11 @@ struct virtio_device {
|
|
void *priv;
|
|
};
|
|
|
|
-#define dev_to_virtio(dev) container_of(dev, struct virtio_device, dev)
|
|
+static inline struct virtio_device *dev_to_virtio(struct device *_dev)
|
|
+{
|
|
+ return container_of(_dev, struct virtio_device, dev);
|
|
+}
|
|
+
|
|
int register_virtio_device(struct virtio_device *dev);
|
|
void unregister_virtio_device(struct virtio_device *dev);
|
|
|
|
diff --git a/include/linux/writeback.h b/include/linux/writeback.h
|
|
index 57b3695..4c5950c 100644
|
|
--- a/include/linux/writeback.h
|
|
+++ b/include/linux/writeback.h
|
|
@@ -187,7 +187,6 @@ int write_cache_pages(struct address_space *mapping,
|
|
struct writeback_control *wbc, writepage_t writepage,
|
|
void *data);
|
|
int do_writepages(struct address_space *mapping, struct writeback_control *wbc);
|
|
-void set_page_dirty_balance(struct page *page, int page_mkwrite);
|
|
void writeback_set_ratelimit(void);
|
|
void tag_pages_for_writeback(struct address_space *mapping,
|
|
pgoff_t start, pgoff_t end);
|
|
diff --git a/include/net/sctp/sctp.h b/include/net/sctp/sctp.h
|
|
index a2ef814..43c8bbcdb 100644
|
|
--- a/include/net/sctp/sctp.h
|
|
+++ b/include/net/sctp/sctp.h
|
|
@@ -524,6 +524,11 @@ static inline void sctp_assoc_pending_pmtu(struct sctp_association *asoc)
|
|
asoc->pmtu_pending = 0;
|
|
}
|
|
|
|
+static inline bool sctp_chunk_pending(const struct sctp_chunk *chunk)
|
|
+{
|
|
+ return !list_empty(&chunk->list);
|
|
+}
|
|
+
|
|
/* Walk through a list of TLV parameters. Don't trust the
|
|
* individual parameter lengths and instead depend on
|
|
* the chunk length to indicate when to stop. Make sure
|
|
diff --git a/include/net/sctp/sm.h b/include/net/sctp/sm.h
|
|
index 9148632..4d1be75 100644
|
|
--- a/include/net/sctp/sm.h
|
|
+++ b/include/net/sctp/sm.h
|
|
@@ -251,9 +251,9 @@ struct sctp_chunk *sctp_make_asconf_update_ip(struct sctp_association *,
|
|
int, __be16);
|
|
struct sctp_chunk *sctp_make_asconf_set_prim(struct sctp_association *asoc,
|
|
union sctp_addr *addr);
|
|
-int sctp_verify_asconf(const struct sctp_association *asoc,
|
|
- struct sctp_paramhdr *param_hdr, void *chunk_end,
|
|
- struct sctp_paramhdr **errp);
|
|
+bool sctp_verify_asconf(const struct sctp_association *asoc,
|
|
+ struct sctp_chunk *chunk, bool addr_param_needed,
|
|
+ struct sctp_paramhdr **errp);
|
|
struct sctp_chunk *sctp_process_asconf(struct sctp_association *asoc,
|
|
struct sctp_chunk *asconf);
|
|
int sctp_process_asconf_ack(struct sctp_association *asoc,
|
|
diff --git a/include/scsi/scsi_device.h b/include/scsi/scsi_device.h
|
|
index 0564655..ef54805 100644
|
|
--- a/include/scsi/scsi_device.h
|
|
+++ b/include/scsi/scsi_device.h
|
|
@@ -154,6 +154,7 @@ struct scsi_device {
|
|
unsigned try_rc_10_first:1; /* Try READ_CAPACACITY_10 first */
|
|
unsigned is_visible:1; /* is the device visible in sysfs */
|
|
unsigned use_rpm_auto:1; /* Enable runtime PM auto suspend */
|
|
+ unsigned broken_fua:1; /* Don't set FUA bit */
|
|
|
|
#define SCSI_DEFAULT_AUTOSUSPEND_DELAY -1
|
|
int autosuspend_delay;
|
|
diff --git a/include/sound/ak4113.h b/include/sound/ak4113.h
|
|
index 2609048..3a34f6e 100644
|
|
--- a/include/sound/ak4113.h
|
|
+++ b/include/sound/ak4113.h
|
|
@@ -286,7 +286,7 @@ struct ak4113 {
|
|
ak4113_write_t *write;
|
|
ak4113_read_t *read;
|
|
void *private_data;
|
|
- unsigned int init:1;
|
|
+ atomic_t wq_processing;
|
|
spinlock_t lock;
|
|
unsigned char regmap[AK4113_WRITABLE_REGS];
|
|
struct snd_kcontrol *kctls[AK4113_CONTROLS];
|
|
diff --git a/include/sound/ak4114.h b/include/sound/ak4114.h
|
|
index 3ce69fd..6944116 100644
|
|
--- a/include/sound/ak4114.h
|
|
+++ b/include/sound/ak4114.h
|
|
@@ -168,7 +168,7 @@ struct ak4114 {
|
|
ak4114_write_t * write;
|
|
ak4114_read_t * read;
|
|
void * private_data;
|
|
- unsigned int init: 1;
|
|
+ atomic_t wq_processing;
|
|
spinlock_t lock;
|
|
unsigned char regmap[7];
|
|
unsigned char txcsb[5];
|
|
diff --git a/kernel/irq/internals.h b/kernel/irq/internals.h
|
|
index 001fa5b..8a160e8 100644
|
|
--- a/kernel/irq/internals.h
|
|
+++ b/kernel/irq/internals.h
|
|
@@ -74,6 +74,14 @@ extern void irq_percpu_disable(struct irq_desc *desc, unsigned int cpu);
|
|
extern void mask_irq(struct irq_desc *desc);
|
|
extern void unmask_irq(struct irq_desc *desc);
|
|
|
|
+#ifdef CONFIG_SPARSE_IRQ
|
|
+extern void irq_lock_sparse(void);
|
|
+extern void irq_unlock_sparse(void);
|
|
+#else
|
|
+static inline void irq_lock_sparse(void) { }
|
|
+static inline void irq_unlock_sparse(void) { }
|
|
+#endif
|
|
+
|
|
extern void init_kstat_irqs(struct irq_desc *desc, int node, int nr);
|
|
|
|
irqreturn_t handle_irq_event_percpu(struct irq_desc *desc, struct irqaction *action);
|
|
diff --git a/kernel/irq/irqdesc.c b/kernel/irq/irqdesc.c
|
|
index 5413064..69772e5 100644
|
|
--- a/kernel/irq/irqdesc.c
|
|
+++ b/kernel/irq/irqdesc.c
|
|
@@ -132,6 +132,16 @@ static void free_masks(struct irq_desc *desc)
|
|
static inline void free_masks(struct irq_desc *desc) { }
|
|
#endif
|
|
|
|
+void irq_lock_sparse(void)
|
|
+{
|
|
+ mutex_lock(&sparse_irq_lock);
|
|
+}
|
|
+
|
|
+void irq_unlock_sparse(void)
|
|
+{
|
|
+ mutex_unlock(&sparse_irq_lock);
|
|
+}
|
|
+
|
|
static struct irq_desc *alloc_desc(int irq, int node, struct module *owner)
|
|
{
|
|
struct irq_desc *desc;
|
|
@@ -168,6 +178,12 @@ static void free_desc(unsigned int irq)
|
|
|
|
unregister_irq_proc(irq, desc);
|
|
|
|
+ /*
|
|
+ * sparse_irq_lock protects also show_interrupts() and
|
|
+ * kstat_irq_usr(). Once we deleted the descriptor from the
|
|
+ * sparse tree we can free it. Access in proc will fail to
|
|
+ * lookup the descriptor.
|
|
+ */
|
|
mutex_lock(&sparse_irq_lock);
|
|
delete_irq_desc(irq);
|
|
mutex_unlock(&sparse_irq_lock);
|
|
@@ -499,6 +515,15 @@ void dynamic_irq_cleanup(unsigned int irq)
|
|
raw_spin_unlock_irqrestore(&desc->lock, flags);
|
|
}
|
|
|
|
+/**
|
|
+ * kstat_irqs_cpu - Get the statistics for an interrupt on a cpu
|
|
+ * @irq: The interrupt number
|
|
+ * @cpu: The cpu number
|
|
+ *
|
|
+ * Returns the sum of interrupt counts on @cpu since boot for
|
|
+ * @irq. The caller must ensure that the interrupt is not removed
|
|
+ * concurrently.
|
|
+ */
|
|
unsigned int kstat_irqs_cpu(unsigned int irq, int cpu)
|
|
{
|
|
struct irq_desc *desc = irq_to_desc(irq);
|
|
@@ -507,6 +532,14 @@ unsigned int kstat_irqs_cpu(unsigned int irq, int cpu)
|
|
*per_cpu_ptr(desc->kstat_irqs, cpu) : 0;
|
|
}
|
|
|
|
+/**
|
|
+ * kstat_irqs - Get the statistics for an interrupt
|
|
+ * @irq: The interrupt number
|
|
+ *
|
|
+ * Returns the sum of interrupt counts on all cpus since boot for
|
|
+ * @irq. The caller must ensure that the interrupt is not removed
|
|
+ * concurrently.
|
|
+ */
|
|
unsigned int kstat_irqs(unsigned int irq)
|
|
{
|
|
struct irq_desc *desc = irq_to_desc(irq);
|
|
@@ -519,3 +552,22 @@ unsigned int kstat_irqs(unsigned int irq)
|
|
sum += *per_cpu_ptr(desc->kstat_irqs, cpu);
|
|
return sum;
|
|
}
|
|
+
|
|
+/**
|
|
+ * kstat_irqs_usr - Get the statistics for an interrupt
|
|
+ * @irq: The interrupt number
|
|
+ *
|
|
+ * Returns the sum of interrupt counts on all cpus since boot for
|
|
+ * @irq. Contrary to kstat_irqs() this can be called from any
|
|
+ * preemptible context. It's protected against concurrent removal of
|
|
+ * an interrupt descriptor when sparse irqs are enabled.
|
|
+ */
|
|
+unsigned int kstat_irqs_usr(unsigned int irq)
|
|
+{
|
|
+ int sum;
|
|
+
|
|
+ irq_lock_sparse();
|
|
+ sum = kstat_irqs(irq);
|
|
+ irq_unlock_sparse();
|
|
+ return sum;
|
|
+}
|
|
diff --git a/kernel/irq/proc.c b/kernel/irq/proc.c
|
|
index 4bd4faa..fb655f5f 100644
|
|
--- a/kernel/irq/proc.c
|
|
+++ b/kernel/irq/proc.c
|
|
@@ -15,6 +15,23 @@
|
|
|
|
#include "internals.h"
|
|
|
|
+/*
|
|
+ * Access rules:
|
|
+ *
|
|
+ * procfs protects read/write of /proc/irq/N/ files against a
|
|
+ * concurrent free of the interrupt descriptor. remove_proc_entry()
|
|
+ * immediately prevents new read/writes to happen and waits for
|
|
+ * already running read/write functions to complete.
|
|
+ *
|
|
+ * We remove the proc entries first and then delete the interrupt
|
|
+ * descriptor from the radix tree and free it. So it is guaranteed
|
|
+ * that irq_to_desc(N) is valid as long as the read/writes are
|
|
+ * permitted by procfs.
|
|
+ *
|
|
+ * The read from /proc/interrupts is a different problem because there
|
|
+ * is no protection. So the lookup and the access to irqdesc
|
|
+ * information must be protected by sparse_irq_lock.
|
|
+ */
|
|
static struct proc_dir_entry *root_irq_dir;
|
|
|
|
#ifdef CONFIG_SMP
|
|
@@ -441,9 +458,10 @@ int show_interrupts(struct seq_file *p, void *v)
|
|
seq_putc(p, '\n');
|
|
}
|
|
|
|
+ irq_lock_sparse();
|
|
desc = irq_to_desc(i);
|
|
if (!desc)
|
|
- return 0;
|
|
+ goto outsparse;
|
|
|
|
raw_spin_lock_irqsave(&desc->lock, flags);
|
|
for_each_online_cpu(j)
|
|
@@ -481,6 +499,8 @@ int show_interrupts(struct seq_file *p, void *v)
|
|
seq_putc(p, '\n');
|
|
out:
|
|
raw_spin_unlock_irqrestore(&desc->lock, flags);
|
|
+outsparse:
|
|
+ irq_unlock_sparse();
|
|
return 0;
|
|
}
|
|
#endif
|
|
diff --git a/kernel/sched/rt.c b/kernel/sched/rt.c
|
|
index 526c77d..71429db 100644
|
|
--- a/kernel/sched/rt.c
|
|
+++ b/kernel/sched/rt.c
|
|
@@ -1293,7 +1293,12 @@ select_task_rq_rt(struct task_struct *p, int sd_flag, int flags)
|
|
(p->rt.nr_cpus_allowed > 1)) {
|
|
int target = find_lowest_rq(p);
|
|
|
|
- if (target != -1)
|
|
+ /*
|
|
+ * Don't bother moving it if the destination CPU is
|
|
+ * not running a lower priority task.
|
|
+ */
|
|
+ if (target != -1 &&
|
|
+ p->prio < cpu_rq(target)->rt.highest_prio.curr)
|
|
cpu = target;
|
|
}
|
|
rcu_read_unlock();
|
|
@@ -1570,6 +1575,16 @@ static struct rq *find_lock_lowest_rq(struct task_struct *task, struct rq *rq)
|
|
|
|
lowest_rq = cpu_rq(cpu);
|
|
|
|
+ if (lowest_rq->rt.highest_prio.curr <= task->prio) {
|
|
+ /*
|
|
+ * Target rq has tasks of equal or higher priority,
|
|
+ * retrying does not release any lock and is unlikely
|
|
+ * to yield a different result.
|
|
+ */
|
|
+ lowest_rq = NULL;
|
|
+ break;
|
|
+ }
|
|
+
|
|
/* if the prio of this runqueue changed, try again */
|
|
if (double_lock_balance(rq, lowest_rq)) {
|
|
/*
|
|
diff --git a/kernel/time.c b/kernel/time.c
|
|
index a095290..0864d70 100644
|
|
--- a/kernel/time.c
|
|
+++ b/kernel/time.c
|
|
@@ -186,6 +186,10 @@ SYSCALL_DEFINE2(settimeofday, struct timeval __user *, tv,
|
|
if (tv) {
|
|
if (copy_from_user(&user_tv, tv, sizeof(*tv)))
|
|
return -EFAULT;
|
|
+
|
|
+ if (!timeval_valid(&user_tv))
|
|
+ return -EINVAL;
|
|
+
|
|
new_ts.tv_sec = user_tv.tv_sec;
|
|
new_ts.tv_nsec = user_tv.tv_usec * NSEC_PER_USEC;
|
|
}
|
|
diff --git a/kernel/time/ntp.c b/kernel/time/ntp.c
|
|
index 8b70710..e32587e 100644
|
|
--- a/kernel/time/ntp.c
|
|
+++ b/kernel/time/ntp.c
|
|
@@ -660,6 +660,17 @@ int do_adjtimex(struct timex *txc)
|
|
return result;
|
|
}
|
|
|
|
+ /*
|
|
+ * Check for potential multiplication overflows that can
|
|
+ * only happen on 64-bit systems:
|
|
+ */
|
|
+ if ((txc->modes & ADJ_FREQUENCY) && (BITS_PER_LONG == 64)) {
|
|
+ if (LLONG_MIN / PPM_SCALE > txc->freq)
|
|
+ return -EINVAL;
|
|
+ if (LLONG_MAX / PPM_SCALE < txc->freq)
|
|
+ return -EINVAL;
|
|
+ }
|
|
+
|
|
getnstimeofday(&ts);
|
|
|
|
spin_lock_irq(&ntp_lock);
|
|
diff --git a/lib/checksum.c b/lib/checksum.c
|
|
index 12dceb2..33f29f0 100644
|
|
--- a/lib/checksum.c
|
|
+++ b/lib/checksum.c
|
|
@@ -179,6 +179,15 @@ csum_partial_copy(const void *src, void *dst, int len, __wsum sum)
|
|
EXPORT_SYMBOL(csum_partial_copy);
|
|
|
|
#ifndef csum_tcpudp_nofold
|
|
+static inline u32 from64to32(u64 x)
|
|
+{
|
|
+ /* add up 32-bit and 32-bit for 32+c bit */
|
|
+ x = (x & 0xffffffff) + (x >> 32);
|
|
+ /* add up carry.. */
|
|
+ x = (x & 0xffffffff) + (x >> 32);
|
|
+ return (u32)x;
|
|
+}
|
|
+
|
|
__wsum csum_tcpudp_nofold(__be32 saddr, __be32 daddr,
|
|
unsigned short len,
|
|
unsigned short proto,
|
|
@@ -193,8 +202,7 @@ __wsum csum_tcpudp_nofold(__be32 saddr, __be32 daddr,
|
|
#else
|
|
s += (proto + len) << 8;
|
|
#endif
|
|
- s += (s >> 32);
|
|
- return (__force __wsum)s;
|
|
+ return (__force __wsum)from64to32(s);
|
|
}
|
|
EXPORT_SYMBOL(csum_tcpudp_nofold);
|
|
#endif
|
|
diff --git a/mm/ksm.c b/mm/ksm.c
|
|
index fa73fc6..c9a2934 100644
|
|
--- a/mm/ksm.c
|
|
+++ b/mm/ksm.c
|
|
@@ -345,7 +345,7 @@ static int break_ksm(struct vm_area_struct *vma, unsigned long addr)
|
|
else
|
|
ret = VM_FAULT_WRITE;
|
|
put_page(page);
|
|
- } while (!(ret & (VM_FAULT_WRITE | VM_FAULT_SIGBUS | VM_FAULT_OOM)));
|
|
+ } while (!(ret & (VM_FAULT_WRITE | VM_FAULT_SIGBUS | VM_FAULT_SIGSEGV | VM_FAULT_OOM)));
|
|
/*
|
|
* We must loop because handle_mm_fault() may back out if there's
|
|
* any difficulty e.g. if pte accessed bit gets updated concurrently.
|
|
diff --git a/mm/memory.c b/mm/memory.c
|
|
index 6d5e635..0e4c5fe 100644
|
|
--- a/mm/memory.c
|
|
+++ b/mm/memory.c
|
|
@@ -852,20 +852,20 @@ copy_one_pte(struct mm_struct *dst_mm, struct mm_struct *src_mm,
|
|
if (!pte_file(pte)) {
|
|
swp_entry_t entry = pte_to_swp_entry(pte);
|
|
|
|
- if (swap_duplicate(entry) < 0)
|
|
- return entry.val;
|
|
-
|
|
- /* make sure dst_mm is on swapoff's mmlist. */
|
|
- if (unlikely(list_empty(&dst_mm->mmlist))) {
|
|
- spin_lock(&mmlist_lock);
|
|
- if (list_empty(&dst_mm->mmlist))
|
|
- list_add(&dst_mm->mmlist,
|
|
- &src_mm->mmlist);
|
|
- spin_unlock(&mmlist_lock);
|
|
- }
|
|
- if (likely(!non_swap_entry(entry)))
|
|
+ if (likely(!non_swap_entry(entry))) {
|
|
+ if (swap_duplicate(entry) < 0)
|
|
+ return entry.val;
|
|
+
|
|
+ /* make sure dst_mm is on swapoff's mmlist. */
|
|
+ if (unlikely(list_empty(&dst_mm->mmlist))) {
|
|
+ spin_lock(&mmlist_lock);
|
|
+ if (list_empty(&dst_mm->mmlist))
|
|
+ list_add(&dst_mm->mmlist,
|
|
+ &src_mm->mmlist);
|
|
+ spin_unlock(&mmlist_lock);
|
|
+ }
|
|
rss[MM_SWAPENTS]++;
|
|
- else if (is_migration_entry(entry)) {
|
|
+ } else if (is_migration_entry(entry)) {
|
|
page = migration_entry_to_page(entry);
|
|
|
|
if (PageAnon(page))
|
|
@@ -1805,7 +1805,7 @@ int __get_user_pages(struct task_struct *tsk, struct mm_struct *mm,
|
|
else
|
|
return -EFAULT;
|
|
}
|
|
- if (ret & VM_FAULT_SIGBUS)
|
|
+ if (ret & (VM_FAULT_SIGBUS | VM_FAULT_SIGSEGV))
|
|
return i ? i : -EFAULT;
|
|
BUG();
|
|
}
|
|
@@ -1909,7 +1909,7 @@ int fixup_user_fault(struct task_struct *tsk, struct mm_struct *mm,
|
|
return -ENOMEM;
|
|
if (ret & (VM_FAULT_HWPOISON | VM_FAULT_HWPOISON_LARGE))
|
|
return -EHWPOISON;
|
|
- if (ret & VM_FAULT_SIGBUS)
|
|
+ if (ret & (VM_FAULT_SIGBUS | VM_FAULT_SIGSEGV))
|
|
return -EFAULT;
|
|
BUG();
|
|
}
|
|
@@ -2699,18 +2699,25 @@ static int do_wp_page(struct mm_struct *mm, struct vm_area_struct *vma,
|
|
if (!dirty_page)
|
|
return ret;
|
|
|
|
- /*
|
|
- * Yes, Virginia, this is actually required to prevent a race
|
|
- * with clear_page_dirty_for_io() from clearing the page dirty
|
|
- * bit after it clear all dirty ptes, but before a racing
|
|
- * do_wp_page installs a dirty pte.
|
|
- *
|
|
- * __do_fault is protected similarly.
|
|
- */
|
|
if (!page_mkwrite) {
|
|
- wait_on_page_locked(dirty_page);
|
|
- set_page_dirty_balance(dirty_page, page_mkwrite);
|
|
+ struct address_space *mapping;
|
|
+ int dirtied;
|
|
+
|
|
+ lock_page(dirty_page);
|
|
+ dirtied = set_page_dirty(dirty_page);
|
|
+ VM_BUG_ON(dirty_page);
|
|
+ mapping = dirty_page->mapping;
|
|
+ unlock_page(dirty_page);
|
|
+
|
|
+ if (dirtied && mapping) {
|
|
+ /*
|
|
+ * Some device drivers do not set page.mapping
|
|
+ * but still dirty their pages
|
|
+ */
|
|
+ balance_dirty_pages_ratelimited(mapping);
|
|
+ }
|
|
}
|
|
+
|
|
put_page(dirty_page);
|
|
if (page_mkwrite) {
|
|
struct address_space *mapping = dirty_page->mapping;
|
|
@@ -3165,7 +3172,7 @@ static inline int check_stack_guard_page(struct vm_area_struct *vma, unsigned lo
|
|
if (prev && prev->vm_end == address)
|
|
return prev->vm_flags & VM_GROWSDOWN ? 0 : -ENOMEM;
|
|
|
|
- expand_downwards(vma, address - PAGE_SIZE);
|
|
+ return expand_downwards(vma, address - PAGE_SIZE);
|
|
}
|
|
if ((vma->vm_flags & VM_GROWSUP) && address + PAGE_SIZE == vma->vm_end) {
|
|
struct vm_area_struct *next = vma->vm_next;
|
|
@@ -3174,7 +3181,7 @@ static inline int check_stack_guard_page(struct vm_area_struct *vma, unsigned lo
|
|
if (next && next->vm_start == address + PAGE_SIZE)
|
|
return next->vm_flags & VM_GROWSUP ? 0 : -ENOMEM;
|
|
|
|
- expand_upwards(vma, address + PAGE_SIZE);
|
|
+ return expand_upwards(vma, address + PAGE_SIZE);
|
|
}
|
|
return 0;
|
|
}
|
|
@@ -3196,7 +3203,7 @@ static int do_anonymous_page(struct mm_struct *mm, struct vm_area_struct *vma,
|
|
|
|
/* Check if we need to add a guard page to the stack */
|
|
if (check_stack_guard_page(vma, address) < 0)
|
|
- return VM_FAULT_SIGBUS;
|
|
+ return VM_FAULT_SIGSEGV;
|
|
|
|
/* Use the zero-page for reads */
|
|
if (!(flags & FAULT_FLAG_WRITE)) {
|
|
diff --git a/mm/mmap.c b/mm/mmap.c
|
|
index eadef99..4cef37e 100644
|
|
--- a/mm/mmap.c
|
|
+++ b/mm/mmap.c
|
|
@@ -567,9 +567,12 @@ again: remove_next = 1 + (end > next->vm_end);
|
|
* shrinking vma had, to cover any anon pages imported.
|
|
*/
|
|
if (exporter && exporter->anon_vma && !importer->anon_vma) {
|
|
- if (anon_vma_clone(importer, exporter))
|
|
- return -ENOMEM;
|
|
+ int error;
|
|
+
|
|
importer->anon_vma = exporter->anon_vma;
|
|
+ error = anon_vma_clone(importer, exporter);
|
|
+ if (error)
|
|
+ return error;
|
|
}
|
|
}
|
|
|
|
@@ -1734,14 +1737,17 @@ static int acct_stack_growth(struct vm_area_struct *vma, unsigned long size, uns
|
|
{
|
|
struct mm_struct *mm = vma->vm_mm;
|
|
struct rlimit *rlim = current->signal->rlim;
|
|
- unsigned long new_start;
|
|
+ unsigned long new_start, actual_size;
|
|
|
|
/* address space limit tests */
|
|
if (!may_expand_vm(mm, grow))
|
|
return -ENOMEM;
|
|
|
|
/* Stack limit test */
|
|
- if (size > ACCESS_ONCE(rlim[RLIMIT_STACK].rlim_cur))
|
|
+ actual_size = size;
|
|
+ if (size && (vma->vm_flags & (VM_GROWSUP | VM_GROWSDOWN)))
|
|
+ actual_size -= PAGE_SIZE;
|
|
+ if (actual_size > ACCESS_ONCE(rlim[RLIMIT_STACK].rlim_cur))
|
|
return -ENOMEM;
|
|
|
|
/* mlock limit tests */
|
|
diff --git a/mm/page-writeback.c b/mm/page-writeback.c
|
|
index e696d5e..0a49a2f 100644
|
|
--- a/mm/page-writeback.c
|
|
+++ b/mm/page-writeback.c
|
|
@@ -1397,16 +1397,6 @@ static void balance_dirty_pages(struct address_space *mapping,
|
|
bdi_start_background_writeback(bdi);
|
|
}
|
|
|
|
-void set_page_dirty_balance(struct page *page, int page_mkwrite)
|
|
-{
|
|
- if (set_page_dirty(page) || page_mkwrite) {
|
|
- struct address_space *mapping = page_mapping(page);
|
|
-
|
|
- if (mapping)
|
|
- balance_dirty_pages_ratelimited(mapping);
|
|
- }
|
|
-}
|
|
-
|
|
static DEFINE_PER_CPU(int, bdp_ratelimits);
|
|
|
|
/*
|
|
@@ -1984,32 +1974,25 @@ EXPORT_SYMBOL(account_page_writeback);
|
|
* page dirty in that case, but not all the buffers. This is a "bottom-up"
|
|
* dirtying, whereas __set_page_dirty_buffers() is a "top-down" dirtying.
|
|
*
|
|
- * Most callers have locked the page, which pins the address_space in memory.
|
|
- * But zap_pte_range() does not lock the page, however in that case the
|
|
- * mapping is pinned by the vma's ->vm_file reference.
|
|
- *
|
|
- * We take care to handle the case where the page was truncated from the
|
|
- * mapping by re-checking page_mapping() inside tree_lock.
|
|
+ * The caller must ensure this doesn't race with truncation. Most will simply
|
|
+ * hold the page lock, but e.g. zap_pte_range() calls with the page mapped and
|
|
+ * the pte lock held, which also locks out truncat
|
|
*/
|
|
int __set_page_dirty_nobuffers(struct page *page)
|
|
{
|
|
if (!TestSetPageDirty(page)) {
|
|
struct address_space *mapping = page_mapping(page);
|
|
- struct address_space *mapping2;
|
|
unsigned long flags;
|
|
|
|
if (!mapping)
|
|
return 1;
|
|
|
|
spin_lock_irqsave(&mapping->tree_lock, flags);
|
|
- mapping2 = page_mapping(page);
|
|
- if (mapping2) { /* Race with truncate? */
|
|
- BUG_ON(mapping2 != mapping);
|
|
- WARN_ON_ONCE(!PagePrivate(page) && !PageUptodate(page));
|
|
- account_page_dirtied(page, mapping);
|
|
- radix_tree_tag_set(&mapping->page_tree,
|
|
- page_index(page), PAGECACHE_TAG_DIRTY);
|
|
- }
|
|
+ BUG_ON(page_mapping(page) != mapping);
|
|
+ WARN_ON_ONCE(!PagePrivate(page) && !PageUptodate(page));
|
|
+ account_page_dirtied(page, mapping);
|
|
+ radix_tree_tag_set(&mapping->page_tree, page_index(page),
|
|
+ PAGECACHE_TAG_DIRTY);
|
|
spin_unlock_irqrestore(&mapping->tree_lock, flags);
|
|
if (mapping->host) {
|
|
/* !PageAnon && !swapper_space */
|
|
@@ -2166,12 +2149,10 @@ int clear_page_dirty_for_io(struct page *page)
|
|
/*
|
|
* We carefully synchronise fault handlers against
|
|
* installing a dirty pte and marking the page dirty
|
|
- * at this point. We do this by having them hold the
|
|
- * page lock at some point after installing their
|
|
- * pte, but before marking the page dirty.
|
|
- * Pages are always locked coming in here, so we get
|
|
- * the desired exclusion. See mm/memory.c:do_wp_page()
|
|
- * for more comments.
|
|
+ * at this point. We do this by having them hold the
|
|
+ * page lock while dirtying the page, and pages are
|
|
+ * always locked coming in here, so we get the desired
|
|
+ * exclusion.
|
|
*/
|
|
if (TestClearPageDirty(page)) {
|
|
dec_zone_page_state(page, NR_FILE_DIRTY);
|
|
diff --git a/mm/rmap.c b/mm/rmap.c
|
|
index ecce3ec..46dfc4e 100644
|
|
--- a/mm/rmap.c
|
|
+++ b/mm/rmap.c
|
|
@@ -72,6 +72,8 @@ static inline struct anon_vma *anon_vma_alloc(void)
|
|
anon_vma = kmem_cache_alloc(anon_vma_cachep, GFP_KERNEL);
|
|
if (anon_vma) {
|
|
atomic_set(&anon_vma->refcount, 1);
|
|
+ anon_vma->degree = 1; /* Reference for first vma */
|
|
+ anon_vma->parent = anon_vma;
|
|
/*
|
|
* Initialise the anon_vma root to point to itself. If called
|
|
* from fork, the root will be reset to the parents anon_vma.
|
|
@@ -193,6 +195,8 @@ int anon_vma_prepare(struct vm_area_struct *vma)
|
|
if (likely(!vma->anon_vma)) {
|
|
vma->anon_vma = anon_vma;
|
|
anon_vma_chain_link(vma, avc, anon_vma);
|
|
+ /* vma reference or self-parent link for new root */
|
|
+ anon_vma->degree++;
|
|
allocated = NULL;
|
|
avc = NULL;
|
|
}
|
|
@@ -241,6 +245,14 @@ static inline void unlock_anon_vma_root(struct anon_vma *root)
|
|
/*
|
|
* Attach the anon_vmas from src to dst.
|
|
* Returns 0 on success, -ENOMEM on failure.
|
|
+ *
|
|
+ * If dst->anon_vma is NULL this function tries to find and reuse existing
|
|
+ * anon_vma which has no vmas and only one child anon_vma. This prevents
|
|
+ * degradation of anon_vma hierarchy to endless linear chain in case of
|
|
+ * constantly forking task. On the other hand, an anon_vma with more than one
|
|
+ * child isn't reused even if there was no alive vma, thus rmap walker has a
|
|
+ * good chance of avoiding scanning the whole hierarchy when it searches where
|
|
+ * page is mapped.
|
|
*/
|
|
int anon_vma_clone(struct vm_area_struct *dst, struct vm_area_struct *src)
|
|
{
|
|
@@ -261,11 +273,32 @@ int anon_vma_clone(struct vm_area_struct *dst, struct vm_area_struct *src)
|
|
anon_vma = pavc->anon_vma;
|
|
root = lock_anon_vma_root(root, anon_vma);
|
|
anon_vma_chain_link(dst, avc, anon_vma);
|
|
+
|
|
+ /*
|
|
+ * Reuse existing anon_vma if its degree lower than two,
|
|
+ * that means it has no vma and only one anon_vma child.
|
|
+ *
|
|
+ * Do not chose parent anon_vma, otherwise first child
|
|
+ * will always reuse it. Root anon_vma is never reused:
|
|
+ * it has self-parent reference and at least one child.
|
|
+ */
|
|
+ if (!dst->anon_vma && anon_vma != src->anon_vma &&
|
|
+ anon_vma->degree < 2)
|
|
+ dst->anon_vma = anon_vma;
|
|
}
|
|
+ if (dst->anon_vma)
|
|
+ dst->anon_vma->degree++;
|
|
unlock_anon_vma_root(root);
|
|
return 0;
|
|
|
|
enomem_failure:
|
|
+ /*
|
|
+ * dst->anon_vma is dropped here otherwise its degree can be incorrectly
|
|
+ * decremented in unlink_anon_vmas().
|
|
+ * We can safely do this because callers of anon_vma_clone() don't care
|
|
+ * about dst->anon_vma if anon_vma_clone() failed.
|
|
+ */
|
|
+ dst->anon_vma = NULL;
|
|
unlink_anon_vmas(dst);
|
|
return -ENOMEM;
|
|
}
|
|
@@ -329,6 +362,9 @@ int anon_vma_fork(struct vm_area_struct *vma, struct vm_area_struct *pvma)
|
|
if (!pvma->anon_vma)
|
|
return 0;
|
|
|
|
+ /* Drop inherited anon_vma, we'll reuse existing or allocate new. */
|
|
+ vma->anon_vma = NULL;
|
|
+
|
|
/*
|
|
* First, attach the new VMA to the parent VMA's anon_vmas,
|
|
* so rmap can find non-COWed pages in child processes.
|
|
@@ -336,6 +372,10 @@ int anon_vma_fork(struct vm_area_struct *vma, struct vm_area_struct *pvma)
|
|
if (anon_vma_clone(vma, pvma))
|
|
return -ENOMEM;
|
|
|
|
+ /* An existing anon_vma has been reused, all done then. */
|
|
+ if (vma->anon_vma)
|
|
+ return 0;
|
|
+
|
|
/* Then add our own anon_vma. */
|
|
anon_vma = anon_vma_alloc();
|
|
if (!anon_vma)
|
|
@@ -349,6 +389,7 @@ int anon_vma_fork(struct vm_area_struct *vma, struct vm_area_struct *pvma)
|
|
* lock any of the anon_vmas in this anon_vma tree.
|
|
*/
|
|
anon_vma->root = pvma->anon_vma->root;
|
|
+ anon_vma->parent = pvma->anon_vma;
|
|
/*
|
|
* With refcounts, an anon_vma can stay around longer than the
|
|
* process it belongs to. The root anon_vma needs to be pinned until
|
|
@@ -359,6 +400,7 @@ int anon_vma_fork(struct vm_area_struct *vma, struct vm_area_struct *pvma)
|
|
vma->anon_vma = anon_vma;
|
|
anon_vma_lock(anon_vma);
|
|
anon_vma_chain_link(vma, avc, anon_vma);
|
|
+ anon_vma->parent->degree++;
|
|
anon_vma_unlock(anon_vma);
|
|
|
|
return 0;
|
|
@@ -389,12 +431,16 @@ void unlink_anon_vmas(struct vm_area_struct *vma)
|
|
* Leave empty anon_vmas on the list - we'll need
|
|
* to free them outside the lock.
|
|
*/
|
|
- if (list_empty(&anon_vma->head))
|
|
+ if (list_empty(&anon_vma->head)) {
|
|
+ anon_vma->parent->degree--;
|
|
continue;
|
|
+ }
|
|
|
|
list_del(&avc->same_vma);
|
|
anon_vma_chain_free(avc);
|
|
}
|
|
+ if (vma->anon_vma)
|
|
+ vma->anon_vma->degree--;
|
|
unlock_anon_vma_root(root);
|
|
|
|
/*
|
|
@@ -405,6 +451,7 @@ void unlink_anon_vmas(struct vm_area_struct *vma)
|
|
list_for_each_entry_safe(avc, next, &vma->anon_vma_chain, same_vma) {
|
|
struct anon_vma *anon_vma = avc->anon_vma;
|
|
|
|
+ BUG_ON(anon_vma->degree);
|
|
put_anon_vma(anon_vma);
|
|
|
|
list_del(&avc->same_vma);
|
|
diff --git a/net/caif/chnl_net.c b/net/caif/chnl_net.c
|
|
index d09340e..b8d9403 100644
|
|
--- a/net/caif/chnl_net.c
|
|
+++ b/net/caif/chnl_net.c
|
|
@@ -467,7 +467,6 @@ static int ipcaif_newlink(struct net *src_net, struct net_device *dev,
|
|
ASSERT_RTNL();
|
|
caifdev = netdev_priv(dev);
|
|
caif_netlink_parms(data, &caifdev->conn_req);
|
|
- dev_net_set(caifdev->netdev, src_net);
|
|
|
|
ret = register_netdevice(dev);
|
|
if (ret)
|
|
diff --git a/net/compat.c b/net/compat.c
|
|
index f7f82ba..618ad24 100644
|
|
--- a/net/compat.c
|
|
+++ b/net/compat.c
|
|
@@ -71,6 +71,13 @@ int get_compat_msghdr(struct msghdr *kmsg, struct compat_msghdr __user *umsg)
|
|
__get_user(kmsg->msg_controllen, &umsg->msg_controllen) ||
|
|
__get_user(kmsg->msg_flags, &umsg->msg_flags))
|
|
return -EFAULT;
|
|
+
|
|
+ if (!tmp1)
|
|
+ kmsg->msg_namelen = 0;
|
|
+
|
|
+ if (kmsg->msg_namelen < 0)
|
|
+ return -EINVAL;
|
|
+
|
|
if (kmsg->msg_namelen > sizeof(struct sockaddr_storage))
|
|
kmsg->msg_namelen = sizeof(struct sockaddr_storage);
|
|
kmsg->msg_name = compat_ptr(tmp1);
|
|
diff --git a/net/core/dev.c b/net/core/dev.c
|
|
index 634f56d..06ea934 100644
|
|
--- a/net/core/dev.c
|
|
+++ b/net/core/dev.c
|
|
@@ -2143,12 +2143,14 @@ netdev_features_t netif_skb_features(struct sk_buff *skb)
|
|
if (skb_shinfo(skb)->gso_segs > skb->dev->gso_max_segs)
|
|
features &= ~NETIF_F_GSO_MASK;
|
|
|
|
- if (protocol == htons(ETH_P_8021Q)) {
|
|
- struct vlan_ethhdr *veh = (struct vlan_ethhdr *)skb->data;
|
|
- protocol = veh->h_vlan_encapsulated_proto;
|
|
- } else if (!vlan_tx_tag_present(skb)) {
|
|
- return harmonize_features(skb, protocol, features);
|
|
- }
|
|
+ if (!vlan_tx_tag_present(skb)) {
|
|
+ if (unlikely(protocol == htons(ETH_P_8021Q))) {
|
|
+ struct vlan_ethhdr *veh = (struct vlan_ethhdr *)skb->data;
|
|
+ protocol = veh->h_vlan_encapsulated_proto;
|
|
+ } else {
|
|
+ return harmonize_features(skb, protocol, features);
|
|
+ }
|
|
+ }
|
|
|
|
features &= (skb->dev->vlan_features | NETIF_F_HW_VLAN_TX);
|
|
|
|
diff --git a/net/ipv6/ip6_fib.c b/net/ipv6/ip6_fib.c
|
|
index 5bb77a6..2cfcfb7 100644
|
|
--- a/net/ipv6/ip6_fib.c
|
|
+++ b/net/ipv6/ip6_fib.c
|
|
@@ -633,6 +633,29 @@ static struct fib6_node * fib6_add_1(struct fib6_node *root, void *addr,
|
|
return ln;
|
|
}
|
|
|
|
+static void fib6_purge_rt(struct rt6_info *rt, struct fib6_node *fn,
|
|
+ struct net *net)
|
|
+{
|
|
+ if (atomic_read(&rt->rt6i_ref) != 1) {
|
|
+ /* This route is used as dummy address holder in some split
|
|
+ * nodes. It is not leaked, but it still holds other resources,
|
|
+ * which must be released in time. So, scan ascendant nodes
|
|
+ * and replace dummy references to this route with references
|
|
+ * to still alive ones.
|
|
+ */
|
|
+ while (fn) {
|
|
+ if (!(fn->fn_flags & RTN_RTINFO) && fn->leaf == rt) {
|
|
+ fn->leaf = fib6_find_prefix(net, fn);
|
|
+ atomic_inc(&fn->leaf->rt6i_ref);
|
|
+ rt6_release(rt);
|
|
+ }
|
|
+ fn = fn->parent;
|
|
+ }
|
|
+ /* No more references are possible at this point. */
|
|
+ BUG_ON(atomic_read(&rt->rt6i_ref) != 1);
|
|
+ }
|
|
+}
|
|
+
|
|
/*
|
|
* Insert routing information in a node.
|
|
*/
|
|
@@ -723,11 +746,12 @@ static int fib6_add_rt2node(struct fib6_node *fn, struct rt6_info *rt,
|
|
rt->dst.rt6_next = iter->dst.rt6_next;
|
|
atomic_inc(&rt->rt6i_ref);
|
|
inet6_rt_notify(RTM_NEWROUTE, rt, info);
|
|
- rt6_release(iter);
|
|
if (!(fn->fn_flags & RTN_RTINFO)) {
|
|
info->nl_net->ipv6.rt6_stats->fib_route_nodes++;
|
|
fn->fn_flags |= RTN_RTINFO;
|
|
}
|
|
+ fib6_purge_rt(iter, fn, info->nl_net);
|
|
+ rt6_release(iter);
|
|
}
|
|
|
|
return 0;
|
|
@@ -1229,24 +1253,7 @@ static void fib6_del_route(struct fib6_node *fn, struct rt6_info **rtp,
|
|
fn = fib6_repair_tree(net, fn);
|
|
}
|
|
|
|
- if (atomic_read(&rt->rt6i_ref) != 1) {
|
|
- /* This route is used as dummy address holder in some split
|
|
- * nodes. It is not leaked, but it still holds other resources,
|
|
- * which must be released in time. So, scan ascendant nodes
|
|
- * and replace dummy references to this route with references
|
|
- * to still alive ones.
|
|
- */
|
|
- while (fn) {
|
|
- if (!(fn->fn_flags & RTN_RTINFO) && fn->leaf == rt) {
|
|
- fn->leaf = fib6_find_prefix(net, fn);
|
|
- atomic_inc(&fn->leaf->rt6i_ref);
|
|
- rt6_release(rt);
|
|
- }
|
|
- fn = fn->parent;
|
|
- }
|
|
- /* No more references are possible at this point. */
|
|
- BUG_ON(atomic_read(&rt->rt6i_ref) != 1);
|
|
- }
|
|
+ fib6_purge_rt(rt, fn, net);
|
|
|
|
inet6_rt_notify(RTM_DELROUTE, rt, info);
|
|
rt6_release(rt);
|
|
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
|
|
index 32929b0..24f2a41 100644
|
|
--- a/net/mac80211/rx.c
|
|
+++ b/net/mac80211/rx.c
|
|
@@ -1486,14 +1486,14 @@ ieee80211_rx_h_defragment(struct ieee80211_rx_data *rx)
|
|
sc = le16_to_cpu(hdr->seq_ctrl);
|
|
frag = sc & IEEE80211_SCTL_FRAG;
|
|
|
|
- if (likely(!ieee80211_has_morefrags(fc) && frag == 0))
|
|
- goto out;
|
|
-
|
|
if (is_multicast_ether_addr(hdr->addr1)) {
|
|
rx->local->dot11MulticastReceivedFrameCount++;
|
|
- goto out;
|
|
+ goto out_no_led;
|
|
}
|
|
|
|
+ if (likely(!ieee80211_has_morefrags(fc) && frag == 0))
|
|
+ goto out;
|
|
+
|
|
I802_DEBUG_INC(rx->local->rx_handlers_fragments);
|
|
|
|
if (skb_linearize(rx->skb))
|
|
@@ -1584,9 +1584,10 @@ ieee80211_rx_h_defragment(struct ieee80211_rx_data *rx)
|
|
status->rx_flags |= IEEE80211_RX_FRAGMENTED;
|
|
|
|
out:
|
|
+ ieee80211_led_rx(rx->local);
|
|
+ out_no_led:
|
|
if (rx->sta)
|
|
rx->sta->rx_packets++;
|
|
- ieee80211_led_rx(rx->local);
|
|
return RX_CONTINUE;
|
|
}
|
|
|
|
diff --git a/net/netfilter/ipvs/ip_vs_core.c b/net/netfilter/ipvs/ip_vs_core.c
|
|
index 00bdb1d..abdb475 100644
|
|
--- a/net/netfilter/ipvs/ip_vs_core.c
|
|
+++ b/net/netfilter/ipvs/ip_vs_core.c
|
|
@@ -662,16 +662,24 @@ static inline int ip_vs_gather_frags_v6(struct sk_buff *skb, u_int32_t user)
|
|
}
|
|
#endif
|
|
|
|
-static int ip_vs_route_me_harder(int af, struct sk_buff *skb)
|
|
+static int ip_vs_route_me_harder(int af, struct sk_buff *skb,
|
|
+ unsigned int hooknum)
|
|
{
|
|
+ if (!sysctl_snat_reroute(skb))
|
|
+ return 0;
|
|
+ /* Reroute replies only to remote clients (FORWARD and LOCAL_OUT) */
|
|
+ if (NF_INET_LOCAL_IN == hooknum)
|
|
+ return 0;
|
|
#ifdef CONFIG_IP_VS_IPV6
|
|
if (af == AF_INET6) {
|
|
- if (sysctl_snat_reroute(skb) && ip6_route_me_harder(skb) != 0)
|
|
+ struct dst_entry *dst = skb_dst(skb);
|
|
+
|
|
+ if (dst->dev && !(dst->dev->flags & IFF_LOOPBACK) &&
|
|
+ ip6_route_me_harder(skb) != 0)
|
|
return 1;
|
|
} else
|
|
#endif
|
|
- if ((sysctl_snat_reroute(skb) ||
|
|
- skb_rtable(skb)->rt_flags & RTCF_LOCAL) &&
|
|
+ if (!(skb_rtable(skb)->rt_flags & RTCF_LOCAL) &&
|
|
ip_route_me_harder(skb, RTN_LOCAL) != 0)
|
|
return 1;
|
|
|
|
@@ -782,7 +790,8 @@ static int handle_response_icmp(int af, struct sk_buff *skb,
|
|
union nf_inet_addr *snet,
|
|
__u8 protocol, struct ip_vs_conn *cp,
|
|
struct ip_vs_protocol *pp,
|
|
- unsigned int offset, unsigned int ihl)
|
|
+ unsigned int offset, unsigned int ihl,
|
|
+ unsigned int hooknum)
|
|
{
|
|
unsigned int verdict = NF_DROP;
|
|
|
|
@@ -812,7 +821,7 @@ static int handle_response_icmp(int af, struct sk_buff *skb,
|
|
#endif
|
|
ip_vs_nat_icmp(skb, pp, cp, 1);
|
|
|
|
- if (ip_vs_route_me_harder(af, skb))
|
|
+ if (ip_vs_route_me_harder(af, skb, hooknum))
|
|
goto out;
|
|
|
|
/* do the statistics and put it back */
|
|
@@ -908,7 +917,7 @@ static int ip_vs_out_icmp(struct sk_buff *skb, int *related,
|
|
|
|
snet.ip = iph->saddr;
|
|
return handle_response_icmp(AF_INET, skb, &snet, cih->protocol, cp,
|
|
- pp, offset, ihl);
|
|
+ pp, offset, ihl, hooknum);
|
|
}
|
|
|
|
#ifdef CONFIG_IP_VS_IPV6
|
|
@@ -985,7 +994,8 @@ static int ip_vs_out_icmp_v6(struct sk_buff *skb, int *related,
|
|
|
|
snet.in6 = iph->saddr;
|
|
return handle_response_icmp(AF_INET6, skb, &snet, cih->nexthdr, cp,
|
|
- pp, offset, sizeof(struct ipv6hdr));
|
|
+ pp, offset, sizeof(struct ipv6hdr),
|
|
+ hooknum);
|
|
}
|
|
#endif
|
|
|
|
@@ -1018,7 +1028,7 @@ static inline int is_tcp_reset(const struct sk_buff *skb, int nh_len)
|
|
*/
|
|
static unsigned int
|
|
handle_response(int af, struct sk_buff *skb, struct ip_vs_proto_data *pd,
|
|
- struct ip_vs_conn *cp, int ihl)
|
|
+ struct ip_vs_conn *cp, int ihl, unsigned int hooknum)
|
|
{
|
|
struct ip_vs_protocol *pp = pd->pp;
|
|
|
|
@@ -1056,7 +1066,7 @@ handle_response(int af, struct sk_buff *skb, struct ip_vs_proto_data *pd,
|
|
* if it came from this machine itself. So re-compute
|
|
* the routing information.
|
|
*/
|
|
- if (ip_vs_route_me_harder(af, skb))
|
|
+ if (ip_vs_route_me_harder(af, skb, hooknum))
|
|
goto drop;
|
|
|
|
IP_VS_DBG_PKT(10, af, pp, skb, 0, "After SNAT");
|
|
@@ -1169,7 +1179,7 @@ ip_vs_out(unsigned int hooknum, struct sk_buff *skb, int af)
|
|
cp = pp->conn_out_get(af, skb, &iph, iph.len, 0);
|
|
|
|
if (likely(cp))
|
|
- return handle_response(af, skb, pd, cp, iph.len);
|
|
+ return handle_response(af, skb, pd, cp, iph.len, hooknum);
|
|
if (sysctl_nat_icmp_send(net) &&
|
|
(pp->protocol == IPPROTO_TCP ||
|
|
pp->protocol == IPPROTO_UDP ||
|
|
diff --git a/net/sctp/associola.c b/net/sctp/associola.c
|
|
index da54d29..d014b05 100644
|
|
--- a/net/sctp/associola.c
|
|
+++ b/net/sctp/associola.c
|
|
@@ -1272,7 +1272,6 @@ void sctp_assoc_update(struct sctp_association *asoc,
|
|
asoc->peer.peer_hmacs = new->peer.peer_hmacs;
|
|
new->peer.peer_hmacs = NULL;
|
|
|
|
- sctp_auth_key_put(asoc->asoc_shared_key);
|
|
sctp_auth_asoc_init_active_key(asoc, GFP_ATOMIC);
|
|
}
|
|
|
|
@@ -1638,6 +1637,8 @@ struct sctp_chunk *sctp_assoc_lookup_asconf_ack(
|
|
* ack chunk whose serial number matches that of the request.
|
|
*/
|
|
list_for_each_entry(ack, &asoc->asconf_ack_list, transmitted_list) {
|
|
+ if (sctp_chunk_pending(ack))
|
|
+ continue;
|
|
if (ack->subh.addip_hdr->serial == serial) {
|
|
sctp_chunk_hold(ack);
|
|
return ack;
|
|
diff --git a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c
|
|
index adb0287..f1249b3 100644
|
|
--- a/net/sctp/sm_make_chunk.c
|
|
+++ b/net/sctp/sm_make_chunk.c
|
|
@@ -2569,7 +2569,10 @@ static int sctp_process_param(struct sctp_association *asoc,
|
|
|
|
addr_param = param.v + sizeof(sctp_addip_param_t);
|
|
|
|
- af = sctp_get_af_specific(param_type2af(param.p->type));
|
|
+ af = sctp_get_af_specific(param_type2af(addr_param->p.type));
|
|
+ if (af == NULL)
|
|
+ break;
|
|
+
|
|
af->from_addr_param(&addr, addr_param,
|
|
htons(asoc->peer.port), 0);
|
|
|
|
@@ -3068,50 +3071,63 @@ static __be16 sctp_process_asconf_param(struct sctp_association *asoc,
|
|
return SCTP_ERROR_NO_ERROR;
|
|
}
|
|
|
|
-/* Verify the ASCONF packet before we process it. */
|
|
-int sctp_verify_asconf(const struct sctp_association *asoc,
|
|
- struct sctp_paramhdr *param_hdr, void *chunk_end,
|
|
- struct sctp_paramhdr **errp) {
|
|
- sctp_addip_param_t *asconf_param;
|
|
+/* Verify the ASCONF packet before we process it. */
|
|
+bool sctp_verify_asconf(const struct sctp_association *asoc,
|
|
+ struct sctp_chunk *chunk, bool addr_param_needed,
|
|
+ struct sctp_paramhdr **errp)
|
|
+{
|
|
+ sctp_addip_chunk_t *addip = (sctp_addip_chunk_t *) chunk->chunk_hdr;
|
|
union sctp_params param;
|
|
- int length, plen;
|
|
+ bool addr_param_seen = false;
|
|
|
|
- param.v = (sctp_paramhdr_t *) param_hdr;
|
|
- while (param.v <= chunk_end - sizeof(sctp_paramhdr_t)) {
|
|
- length = ntohs(param.p->length);
|
|
- *errp = param.p;
|
|
-
|
|
- if (param.v > chunk_end - length ||
|
|
- length < sizeof(sctp_paramhdr_t))
|
|
- return 0;
|
|
+ sctp_walk_params(param, addip, addip_hdr.params) {
|
|
+ size_t length = ntohs(param.p->length);
|
|
|
|
+ *errp = param.p;
|
|
switch (param.p->type) {
|
|
+ case SCTP_PARAM_ERR_CAUSE:
|
|
+ break;
|
|
+ case SCTP_PARAM_IPV4_ADDRESS:
|
|
+ if (length != sizeof(sctp_ipv4addr_param_t))
|
|
+ return false;
|
|
+ addr_param_seen = true;
|
|
+ break;
|
|
+ case SCTP_PARAM_IPV6_ADDRESS:
|
|
+ if (length != sizeof(sctp_ipv6addr_param_t))
|
|
+ return false;
|
|
+ addr_param_seen = true;
|
|
+ break;
|
|
case SCTP_PARAM_ADD_IP:
|
|
case SCTP_PARAM_DEL_IP:
|
|
case SCTP_PARAM_SET_PRIMARY:
|
|
- asconf_param = (sctp_addip_param_t *)param.v;
|
|
- plen = ntohs(asconf_param->param_hdr.length);
|
|
- if (plen < sizeof(sctp_addip_param_t) +
|
|
- sizeof(sctp_paramhdr_t))
|
|
- return 0;
|
|
+ /* In ASCONF chunks, these need to be first. */
|
|
+ if (addr_param_needed && !addr_param_seen)
|
|
+ return false;
|
|
+ length = ntohs(param.addip->param_hdr.length);
|
|
+ if (length < sizeof(sctp_addip_param_t) +
|
|
+ sizeof(sctp_paramhdr_t))
|
|
+ return false;
|
|
break;
|
|
case SCTP_PARAM_SUCCESS_REPORT:
|
|
case SCTP_PARAM_ADAPTATION_LAYER_IND:
|
|
if (length != sizeof(sctp_addip_param_t))
|
|
- return 0;
|
|
-
|
|
+ return false;
|
|
break;
|
|
default:
|
|
- break;
|
|
+ /* This is unkown to us, reject! */
|
|
+ return false;
|
|
}
|
|
-
|
|
- param.v += WORD_ROUND(length);
|
|
}
|
|
|
|
- if (param.v != chunk_end)
|
|
- return 0;
|
|
+ /* Remaining sanity checks. */
|
|
+ if (addr_param_needed && !addr_param_seen)
|
|
+ return false;
|
|
+ if (!addr_param_needed && addr_param_seen)
|
|
+ return false;
|
|
+ if (param.v != chunk->chunk_end)
|
|
+ return false;
|
|
|
|
- return 1;
|
|
+ return true;
|
|
}
|
|
|
|
/* Process an incoming ASCONF chunk with the next expected serial no. and
|
|
@@ -3120,16 +3136,17 @@ int sctp_verify_asconf(const struct sctp_association *asoc,
|
|
struct sctp_chunk *sctp_process_asconf(struct sctp_association *asoc,
|
|
struct sctp_chunk *asconf)
|
|
{
|
|
+ sctp_addip_chunk_t *addip = (sctp_addip_chunk_t *) asconf->chunk_hdr;
|
|
+ bool all_param_pass = true;
|
|
+ union sctp_params param;
|
|
sctp_addiphdr_t *hdr;
|
|
union sctp_addr_param *addr_param;
|
|
sctp_addip_param_t *asconf_param;
|
|
struct sctp_chunk *asconf_ack;
|
|
-
|
|
__be16 err_code;
|
|
int length = 0;
|
|
int chunk_len;
|
|
__u32 serial;
|
|
- int all_param_pass = 1;
|
|
|
|
chunk_len = ntohs(asconf->chunk_hdr->length) - sizeof(sctp_chunkhdr_t);
|
|
hdr = (sctp_addiphdr_t *)asconf->skb->data;
|
|
@@ -3157,9 +3174,14 @@ struct sctp_chunk *sctp_process_asconf(struct sctp_association *asoc,
|
|
goto done;
|
|
|
|
/* Process the TLVs contained within the ASCONF chunk. */
|
|
- while (chunk_len > 0) {
|
|
+ sctp_walk_params(param, addip, addip_hdr.params) {
|
|
+ /* Skip preceeding address parameters. */
|
|
+ if (param.p->type == SCTP_PARAM_IPV4_ADDRESS ||
|
|
+ param.p->type == SCTP_PARAM_IPV6_ADDRESS)
|
|
+ continue;
|
|
+
|
|
err_code = sctp_process_asconf_param(asoc, asconf,
|
|
- asconf_param);
|
|
+ param.addip);
|
|
/* ADDIP 4.1 A7)
|
|
* If an error response is received for a TLV parameter,
|
|
* all TLVs with no response before the failed TLV are
|
|
@@ -3167,28 +3189,20 @@ struct sctp_chunk *sctp_process_asconf(struct sctp_association *asoc,
|
|
* the failed response are considered unsuccessful unless
|
|
* a specific success indication is present for the parameter.
|
|
*/
|
|
- if (SCTP_ERROR_NO_ERROR != err_code)
|
|
- all_param_pass = 0;
|
|
-
|
|
+ if (err_code != SCTP_ERROR_NO_ERROR)
|
|
+ all_param_pass = false;
|
|
if (!all_param_pass)
|
|
- sctp_add_asconf_response(asconf_ack,
|
|
- asconf_param->crr_id, err_code,
|
|
- asconf_param);
|
|
+ sctp_add_asconf_response(asconf_ack, param.addip->crr_id,
|
|
+ err_code, param.addip);
|
|
|
|
/* ADDIP 4.3 D11) When an endpoint receiving an ASCONF to add
|
|
* an IP address sends an 'Out of Resource' in its response, it
|
|
* MUST also fail any subsequent add or delete requests bundled
|
|
* in the ASCONF.
|
|
*/
|
|
- if (SCTP_ERROR_RSRC_LOW == err_code)
|
|
+ if (err_code == SCTP_ERROR_RSRC_LOW)
|
|
goto done;
|
|
-
|
|
- /* Move to the next ASCONF param. */
|
|
- length = ntohs(asconf_param->param_hdr.length);
|
|
- asconf_param = (void *)asconf_param + length;
|
|
- chunk_len -= length;
|
|
}
|
|
-
|
|
done:
|
|
asoc->peer.addip_serial++;
|
|
|
|
diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c
|
|
index 5ac33b6..a6a3006 100644
|
|
--- a/net/sctp/sm_statefuns.c
|
|
+++ b/net/sctp/sm_statefuns.c
|
|
@@ -3516,9 +3516,7 @@ sctp_disposition_t sctp_sf_do_asconf(const struct sctp_endpoint *ep,
|
|
struct sctp_chunk *asconf_ack = NULL;
|
|
struct sctp_paramhdr *err_param = NULL;
|
|
sctp_addiphdr_t *hdr;
|
|
- union sctp_addr_param *addr_param;
|
|
__u32 serial;
|
|
- int length;
|
|
|
|
if (!sctp_vtag_verify(chunk, asoc)) {
|
|
sctp_add_cmd_sf(commands, SCTP_CMD_REPORT_BAD_TAG,
|
|
@@ -3543,17 +3541,8 @@ sctp_disposition_t sctp_sf_do_asconf(const struct sctp_endpoint *ep,
|
|
hdr = (sctp_addiphdr_t *)chunk->skb->data;
|
|
serial = ntohl(hdr->serial);
|
|
|
|
- addr_param = (union sctp_addr_param *)hdr->params;
|
|
- length = ntohs(addr_param->p.length);
|
|
- if (length < sizeof(sctp_paramhdr_t))
|
|
- return sctp_sf_violation_paramlen(ep, asoc, type, arg,
|
|
- (void *)addr_param, commands);
|
|
-
|
|
/* Verify the ASCONF chunk before processing it. */
|
|
- if (!sctp_verify_asconf(asoc,
|
|
- (sctp_paramhdr_t *)((void *)addr_param + length),
|
|
- (void *)chunk->chunk_end,
|
|
- &err_param))
|
|
+ if (!sctp_verify_asconf(asoc, chunk, true, &err_param))
|
|
return sctp_sf_violation_paramlen(ep, asoc, type, arg,
|
|
(void *)err_param, commands);
|
|
|
|
@@ -3670,10 +3659,7 @@ sctp_disposition_t sctp_sf_do_asconf_ack(const struct sctp_endpoint *ep,
|
|
rcvd_serial = ntohl(addip_hdr->serial);
|
|
|
|
/* Verify the ASCONF-ACK chunk before processing it. */
|
|
- if (!sctp_verify_asconf(asoc,
|
|
- (sctp_paramhdr_t *)addip_hdr->params,
|
|
- (void *)asconf_ack->chunk_end,
|
|
- &err_param))
|
|
+ if (!sctp_verify_asconf(asoc, asconf_ack, false, &err_param))
|
|
return sctp_sf_violation_paramlen(ep, asoc, type, arg,
|
|
(void *)err_param, commands);
|
|
|
|
diff --git a/net/socket.c b/net/socket.c
|
|
index 7e13992..efcf863 100644
|
|
--- a/net/socket.c
|
|
+++ b/net/socket.c
|
|
@@ -1929,6 +1929,9 @@ static int copy_msghdr_from_user(struct msghdr *kmsg,
|
|
if (copy_from_user(kmsg, umsg, sizeof(struct msghdr)))
|
|
return -EFAULT;
|
|
|
|
+ if (kmsg->msg_name == NULL)
|
|
+ kmsg->msg_namelen = 0;
|
|
+
|
|
if (kmsg->msg_namelen < 0)
|
|
return -EINVAL;
|
|
|
|
diff --git a/net/sunrpc/svcsock.c b/net/sunrpc/svcsock.c
|
|
index 4c23cfc..a0769e1 100644
|
|
--- a/net/sunrpc/svcsock.c
|
|
+++ b/net/sunrpc/svcsock.c
|
|
@@ -1055,17 +1055,12 @@ static int receive_cb_reply(struct svc_sock *svsk, struct svc_rqst *rqstp)
|
|
xid = *p++;
|
|
calldir = *p;
|
|
|
|
- if (bc_xprt)
|
|
- req = xprt_lookup_rqst(bc_xprt, xid);
|
|
-
|
|
- if (!req) {
|
|
- printk(KERN_NOTICE
|
|
- "%s: Got unrecognized reply: "
|
|
- "calldir 0x%x xpt_bc_xprt %p xid %08x\n",
|
|
- __func__, ntohl(calldir),
|
|
- bc_xprt, xid);
|
|
+ if (!bc_xprt)
|
|
return -EAGAIN;
|
|
- }
|
|
+ spin_lock_bh(&bc_xprt->transport_lock);
|
|
+ req = xprt_lookup_rqst(bc_xprt, xid);
|
|
+ if (!req)
|
|
+ goto unlock_notfound;
|
|
|
|
memcpy(&req->rq_private_buf, &req->rq_rcv_buf, sizeof(struct xdr_buf));
|
|
/*
|
|
@@ -1076,11 +1071,21 @@ static int receive_cb_reply(struct svc_sock *svsk, struct svc_rqst *rqstp)
|
|
dst = &req->rq_private_buf.head[0];
|
|
src = &rqstp->rq_arg.head[0];
|
|
if (dst->iov_len < src->iov_len)
|
|
- return -EAGAIN; /* whatever; just giving up. */
|
|
+ goto unlock_eagain; /* whatever; just giving up. */
|
|
memcpy(dst->iov_base, src->iov_base, src->iov_len);
|
|
xprt_complete_rqst(req->rq_task, svsk->sk_reclen);
|
|
rqstp->rq_arg.len = 0;
|
|
+ spin_unlock_bh(&bc_xprt->transport_lock);
|
|
return 0;
|
|
+unlock_notfound:
|
|
+ printk(KERN_NOTICE
|
|
+ "%s: Got unrecognized reply: "
|
|
+ "calldir 0x%x xpt_bc_xprt %p xid %08x\n",
|
|
+ __func__, ntohl(calldir),
|
|
+ bc_xprt, ntohl(xid));
|
|
+unlock_eagain:
|
|
+ spin_unlock_bh(&bc_xprt->transport_lock);
|
|
+ return -EAGAIN;
|
|
}
|
|
|
|
static int copy_pages_to_kvecs(struct kvec *vec, struct page **pages, int len)
|
|
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
|
|
index be8244d..1bab426 100644
|
|
--- a/net/wireless/nl80211.c
|
|
+++ b/net/wireless/nl80211.c
|
|
@@ -1957,6 +1957,9 @@ static int nl80211_get_key(struct sk_buff *skb, struct genl_info *info)
|
|
if (!rdev->ops->get_key)
|
|
return -EOPNOTSUPP;
|
|
|
|
+ if (!pairwise && mac_addr && !(rdev->wiphy.flags & WIPHY_FLAG_IBSS_RSN))
|
|
+ return -ENOENT;
|
|
+
|
|
msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
|
|
if (!msg)
|
|
return -ENOMEM;
|
|
@@ -1974,10 +1977,6 @@ static int nl80211_get_key(struct sk_buff *skb, struct genl_info *info)
|
|
if (mac_addr)
|
|
NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, mac_addr);
|
|
|
|
- if (pairwise && mac_addr &&
|
|
- !(rdev->wiphy.flags & WIPHY_FLAG_IBSS_RSN))
|
|
- return -ENOENT;
|
|
-
|
|
err = rdev->ops->get_key(&rdev->wiphy, dev, key_idx, pairwise,
|
|
mac_addr, &cookie, get_key_callback);
|
|
|
|
@@ -2149,7 +2148,7 @@ static int nl80211_del_key(struct sk_buff *skb, struct genl_info *info)
|
|
wdev_lock(dev->ieee80211_ptr);
|
|
err = nl80211_key_allowed(dev->ieee80211_ptr);
|
|
|
|
- if (key.type == NL80211_KEYTYPE_PAIRWISE && mac_addr &&
|
|
+ if (key.type == NL80211_KEYTYPE_GROUP && mac_addr &&
|
|
!(rdev->wiphy.flags & WIPHY_FLAG_IBSS_RSN))
|
|
err = -ENOENT;
|
|
|
|
diff --git a/scripts/recordmcount.pl b/scripts/recordmcount.pl
|
|
index 858966a..679218b 100755
|
|
--- a/scripts/recordmcount.pl
|
|
+++ b/scripts/recordmcount.pl
|
|
@@ -262,7 +262,6 @@ sub check_objcopy
|
|
# force flags for this arch
|
|
$ld .= " -m shlelf_linux";
|
|
$objcopy .= " -O elf32-sh-linux";
|
|
- $cc .= " -m32";
|
|
|
|
} elsif ($arch eq "powerpc") {
|
|
$local_regex = "^[0-9a-fA-F]+\\s+t\\s+(\\.?\\S+)";
|
|
diff --git a/security/keys/encrypted-keys/encrypted.c b/security/keys/encrypted-keys/encrypted.c
|
|
index 2d1bb8a..a02f923 100644
|
|
--- a/security/keys/encrypted-keys/encrypted.c
|
|
+++ b/security/keys/encrypted-keys/encrypted.c
|
|
@@ -1016,10 +1016,13 @@ static int __init init_encrypted(void)
|
|
ret = encrypted_shash_alloc();
|
|
if (ret < 0)
|
|
return ret;
|
|
+ ret = aes_get_sizes();
|
|
+ if (ret < 0)
|
|
+ goto out;
|
|
ret = register_key_type(&key_type_encrypted);
|
|
if (ret < 0)
|
|
goto out;
|
|
- return aes_get_sizes();
|
|
+ return 0;
|
|
out:
|
|
encrypted_shash_release();
|
|
return ret;
|
|
diff --git a/sound/core/seq/seq_dummy.c b/sound/core/seq/seq_dummy.c
|
|
index dbc5507..f60d814 100644
|
|
--- a/sound/core/seq/seq_dummy.c
|
|
+++ b/sound/core/seq/seq_dummy.c
|
|
@@ -82,36 +82,6 @@ struct snd_seq_dummy_port {
|
|
static int my_client = -1;
|
|
|
|
/*
|
|
- * unuse callback - send ALL_SOUNDS_OFF and RESET_CONTROLLERS events
|
|
- * to subscribers.
|
|
- * Note: this callback is called only after all subscribers are removed.
|
|
- */
|
|
-static int
|
|
-dummy_unuse(void *private_data, struct snd_seq_port_subscribe *info)
|
|
-{
|
|
- struct snd_seq_dummy_port *p;
|
|
- int i;
|
|
- struct snd_seq_event ev;
|
|
-
|
|
- p = private_data;
|
|
- memset(&ev, 0, sizeof(ev));
|
|
- if (p->duplex)
|
|
- ev.source.port = p->connect;
|
|
- else
|
|
- ev.source.port = p->port;
|
|
- ev.dest.client = SNDRV_SEQ_ADDRESS_SUBSCRIBERS;
|
|
- ev.type = SNDRV_SEQ_EVENT_CONTROLLER;
|
|
- for (i = 0; i < 16; i++) {
|
|
- ev.data.control.channel = i;
|
|
- ev.data.control.param = MIDI_CTL_ALL_SOUNDS_OFF;
|
|
- snd_seq_kernel_client_dispatch(p->client, &ev, 0, 0);
|
|
- ev.data.control.param = MIDI_CTL_RESET_CONTROLLERS;
|
|
- snd_seq_kernel_client_dispatch(p->client, &ev, 0, 0);
|
|
- }
|
|
- return 0;
|
|
-}
|
|
-
|
|
-/*
|
|
* event input callback - just redirect events to subscribers
|
|
*/
|
|
static int
|
|
@@ -175,7 +145,6 @@ create_port(int idx, int type)
|
|
| SNDRV_SEQ_PORT_TYPE_PORT;
|
|
memset(&pcb, 0, sizeof(pcb));
|
|
pcb.owner = THIS_MODULE;
|
|
- pcb.unuse = dummy_unuse;
|
|
pcb.event_input = dummy_input;
|
|
pcb.private_free = dummy_free;
|
|
pcb.private_data = rec;
|
|
diff --git a/sound/i2c/other/ak4113.c b/sound/i2c/other/ak4113.c
|
|
index dde5c9c..e1ab3ad 100644
|
|
--- a/sound/i2c/other/ak4113.c
|
|
+++ b/sound/i2c/other/ak4113.c
|
|
@@ -56,8 +56,7 @@ static inline unsigned char reg_read(struct ak4113 *ak4113, unsigned char reg)
|
|
|
|
static void snd_ak4113_free(struct ak4113 *chip)
|
|
{
|
|
- chip->init = 1; /* don't schedule new work */
|
|
- mb();
|
|
+ atomic_inc(&chip->wq_processing); /* don't schedule new work */
|
|
cancel_delayed_work_sync(&chip->work);
|
|
kfree(chip);
|
|
}
|
|
@@ -89,6 +88,7 @@ int snd_ak4113_create(struct snd_card *card, ak4113_read_t *read,
|
|
chip->write = write;
|
|
chip->private_data = private_data;
|
|
INIT_DELAYED_WORK(&chip->work, ak4113_stats);
|
|
+ atomic_set(&chip->wq_processing, 0);
|
|
|
|
for (reg = 0; reg < AK4113_WRITABLE_REGS ; reg++)
|
|
chip->regmap[reg] = pgm[reg];
|
|
@@ -139,13 +139,11 @@ static void ak4113_init_regs(struct ak4113 *chip)
|
|
|
|
void snd_ak4113_reinit(struct ak4113 *chip)
|
|
{
|
|
- chip->init = 1;
|
|
- mb();
|
|
- flush_delayed_work_sync(&chip->work);
|
|
+ if (atomic_inc_return(&chip->wq_processing) == 1)
|
|
+ cancel_delayed_work_sync(&chip->work);
|
|
ak4113_init_regs(chip);
|
|
/* bring up statistics / event queing */
|
|
- chip->init = 0;
|
|
- if (chip->kctls[0])
|
|
+ if (atomic_dec_and_test(&chip->wq_processing))
|
|
schedule_delayed_work(&chip->work, HZ / 10);
|
|
}
|
|
EXPORT_SYMBOL_GPL(snd_ak4113_reinit);
|
|
@@ -632,8 +630,9 @@ static void ak4113_stats(struct work_struct *work)
|
|
{
|
|
struct ak4113 *chip = container_of(work, struct ak4113, work.work);
|
|
|
|
- if (!chip->init)
|
|
+ if (atomic_inc_return(&chip->wq_processing) == 1)
|
|
snd_ak4113_check_rate_and_errors(chip, chip->check_flags);
|
|
|
|
- schedule_delayed_work(&chip->work, HZ / 10);
|
|
+ if (atomic_dec_and_test(&chip->wq_processing))
|
|
+ schedule_delayed_work(&chip->work, HZ / 10);
|
|
}
|
|
diff --git a/sound/i2c/other/ak4114.c b/sound/i2c/other/ak4114.c
|
|
index fdf3c1b..4c6b379 100644
|
|
--- a/sound/i2c/other/ak4114.c
|
|
+++ b/sound/i2c/other/ak4114.c
|
|
@@ -66,8 +66,7 @@ static void reg_dump(struct ak4114 *ak4114)
|
|
|
|
static void snd_ak4114_free(struct ak4114 *chip)
|
|
{
|
|
- chip->init = 1; /* don't schedule new work */
|
|
- mb();
|
|
+ atomic_inc(&chip->wq_processing); /* don't schedule new work */
|
|
cancel_delayed_work_sync(&chip->work);
|
|
kfree(chip);
|
|
}
|
|
@@ -100,6 +99,7 @@ int snd_ak4114_create(struct snd_card *card,
|
|
chip->write = write;
|
|
chip->private_data = private_data;
|
|
INIT_DELAYED_WORK(&chip->work, ak4114_stats);
|
|
+ atomic_set(&chip->wq_processing, 0);
|
|
|
|
for (reg = 0; reg < 7; reg++)
|
|
chip->regmap[reg] = pgm[reg];
|
|
@@ -152,13 +152,11 @@ static void ak4114_init_regs(struct ak4114 *chip)
|
|
|
|
void snd_ak4114_reinit(struct ak4114 *chip)
|
|
{
|
|
- chip->init = 1;
|
|
- mb();
|
|
- flush_delayed_work_sync(&chip->work);
|
|
+ if (atomic_inc_return(&chip->wq_processing) == 1)
|
|
+ cancel_delayed_work_sync(&chip->work);
|
|
ak4114_init_regs(chip);
|
|
/* bring up statistics / event queing */
|
|
- chip->init = 0;
|
|
- if (chip->kctls[0])
|
|
+ if (atomic_dec_and_test(&chip->wq_processing))
|
|
schedule_delayed_work(&chip->work, HZ / 10);
|
|
}
|
|
|
|
@@ -612,10 +610,10 @@ static void ak4114_stats(struct work_struct *work)
|
|
{
|
|
struct ak4114 *chip = container_of(work, struct ak4114, work.work);
|
|
|
|
- if (!chip->init)
|
|
+ if (atomic_inc_return(&chip->wq_processing) == 1)
|
|
snd_ak4114_check_rate_and_errors(chip, chip->check_flags);
|
|
-
|
|
- schedule_delayed_work(&chip->work, HZ / 10);
|
|
+ if (atomic_dec_and_test(&chip->wq_processing))
|
|
+ schedule_delayed_work(&chip->work, HZ / 10);
|
|
}
|
|
|
|
EXPORT_SYMBOL(snd_ak4114_create);
|
|
diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c
|
|
index 33e538f..f461737 100644
|
|
--- a/sound/pci/hda/hda_intel.c
|
|
+++ b/sound/pci/hda/hda_intel.c
|
|
@@ -2685,6 +2685,7 @@ static int __devinit azx_create(struct snd_card *card, struct pci_dev *pci,
|
|
struct azx *chip;
|
|
int i, err;
|
|
unsigned short gcap;
|
|
+ unsigned int dma_bits = 64;
|
|
static struct snd_device_ops ops = {
|
|
.dev_free = azx_dev_free,
|
|
};
|
|
@@ -2780,9 +2781,14 @@ static int __devinit azx_create(struct snd_card *card, struct pci_dev *pci,
|
|
gcap = azx_readw(chip, GCAP);
|
|
snd_printdd(SFX "chipset global capabilities = 0x%x\n", gcap);
|
|
|
|
+ /* AMD devices support 40 or 48bit DMA, take the safe one */
|
|
+ if (chip->pci->vendor == PCI_VENDOR_ID_AMD)
|
|
+ dma_bits = 40;
|
|
+
|
|
/* disable SB600 64bit support for safety */
|
|
if (chip->pci->vendor == PCI_VENDOR_ID_ATI) {
|
|
struct pci_dev *p_smbus;
|
|
+ dma_bits = 40;
|
|
p_smbus = pci_get_device(PCI_VENDOR_ID_ATI,
|
|
PCI_DEVICE_ID_ATI_SBX00_SMBUS,
|
|
NULL);
|
|
@@ -2812,9 +2818,11 @@ static int __devinit azx_create(struct snd_card *card, struct pci_dev *pci,
|
|
}
|
|
|
|
/* allow 64bit DMA address if supported by H/W */
|
|
- if ((gcap & ICH6_GCAP_64OK) && !pci_set_dma_mask(pci, DMA_BIT_MASK(64)))
|
|
- pci_set_consistent_dma_mask(pci, DMA_BIT_MASK(64));
|
|
- else {
|
|
+ if (!(gcap & ICH6_GCAP_64OK))
|
|
+ dma_bits = 32;
|
|
+ if (!pci_set_dma_mask(pci, DMA_BIT_MASK(dma_bits))) {
|
|
+ pci_set_consistent_dma_mask(pci, DMA_BIT_MASK(dma_bits));
|
|
+ } else {
|
|
pci_set_dma_mask(pci, DMA_BIT_MASK(32));
|
|
pci_set_consistent_dma_mask(pci, DMA_BIT_MASK(32));
|
|
}
|
|
diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c
|
|
index 137b67f..606f87a 100644
|
|
--- a/sound/pci/hda/patch_sigmatel.c
|
|
+++ b/sound/pci/hda/patch_sigmatel.c
|
|
@@ -4246,9 +4246,9 @@ static void stac_store_hints(struct hda_codec *codec)
|
|
spec->gpio_mask;
|
|
}
|
|
if (get_int_hint(codec, "gpio_dir", &spec->gpio_dir))
|
|
- spec->gpio_mask &= spec->gpio_mask;
|
|
- if (get_int_hint(codec, "gpio_data", &spec->gpio_data))
|
|
spec->gpio_dir &= spec->gpio_mask;
|
|
+ if (get_int_hint(codec, "gpio_data", &spec->gpio_data))
|
|
+ spec->gpio_data &= spec->gpio_mask;
|
|
if (get_int_hint(codec, "eapd_mask", &spec->eapd_mask))
|
|
spec->eapd_mask &= spec->gpio_mask;
|
|
if (get_int_hint(codec, "gpio_mute", &spec->gpio_mute))
|
|
diff --git a/sound/soc/atmel/atmel_ssc_dai.c b/sound/soc/atmel/atmel_ssc_dai.c
|
|
index 354341e..8d7d29c 100644
|
|
--- a/sound/soc/atmel/atmel_ssc_dai.c
|
|
+++ b/sound/soc/atmel/atmel_ssc_dai.c
|
|
@@ -341,7 +341,6 @@ static int atmel_ssc_hw_params(struct snd_pcm_substream *substream,
|
|
struct atmel_pcm_dma_params *dma_params;
|
|
int dir, channels, bits;
|
|
u32 tfmr, rfmr, tcmr, rcmr;
|
|
- int start_event;
|
|
int ret;
|
|
|
|
/*
|
|
@@ -460,19 +459,10 @@ static int atmel_ssc_hw_params(struct snd_pcm_substream *substream,
|
|
* The SSC transmit clock is obtained from the BCLK signal on
|
|
* on the TK line, and the SSC receive clock is
|
|
* generated from the transmit clock.
|
|
- *
|
|
- * For single channel data, one sample is transferred
|
|
- * on the falling edge of the LRC clock.
|
|
- * For two channel data, one sample is
|
|
- * transferred on both edges of the LRC clock.
|
|
*/
|
|
- start_event = ((channels == 1)
|
|
- ? SSC_START_FALLING_RF
|
|
- : SSC_START_EDGE_RF);
|
|
-
|
|
rcmr = SSC_BF(RCMR_PERIOD, 0)
|
|
| SSC_BF(RCMR_STTDLY, START_DELAY)
|
|
- | SSC_BF(RCMR_START, start_event)
|
|
+ | SSC_BF(RCMR_START, SSC_START_FALLING_RF)
|
|
| SSC_BF(RCMR_CKI, SSC_CKI_RISING)
|
|
| SSC_BF(RCMR_CKO, SSC_CKO_NONE)
|
|
| SSC_BF(RCMR_CKS, SSC_CKS_CLOCK);
|
|
@@ -480,14 +470,14 @@ static int atmel_ssc_hw_params(struct snd_pcm_substream *substream,
|
|
rfmr = SSC_BF(RFMR_FSEDGE, SSC_FSEDGE_POSITIVE)
|
|
| SSC_BF(RFMR_FSOS, SSC_FSOS_NONE)
|
|
| SSC_BF(RFMR_FSLEN, 0)
|
|
- | SSC_BF(RFMR_DATNB, 0)
|
|
+ | SSC_BF(RFMR_DATNB, (channels - 1))
|
|
| SSC_BIT(RFMR_MSBF)
|
|
| SSC_BF(RFMR_LOOP, 0)
|
|
| SSC_BF(RFMR_DATLEN, (bits - 1));
|
|
|
|
tcmr = SSC_BF(TCMR_PERIOD, 0)
|
|
| SSC_BF(TCMR_STTDLY, START_DELAY)
|
|
- | SSC_BF(TCMR_START, start_event)
|
|
+ | SSC_BF(TCMR_START, SSC_START_FALLING_RF)
|
|
| SSC_BF(TCMR_CKI, SSC_CKI_FALLING)
|
|
| SSC_BF(TCMR_CKO, SSC_CKO_NONE)
|
|
| SSC_BF(TCMR_CKS, SSC_CKS_PIN);
|
|
@@ -496,7 +486,7 @@ static int atmel_ssc_hw_params(struct snd_pcm_substream *substream,
|
|
| SSC_BF(TFMR_FSDEN, 0)
|
|
| SSC_BF(TFMR_FSOS, SSC_FSOS_NONE)
|
|
| SSC_BF(TFMR_FSLEN, 0)
|
|
- | SSC_BF(TFMR_DATNB, 0)
|
|
+ | SSC_BF(TFMR_DATNB, (channels - 1))
|
|
| SSC_BIT(TFMR_MSBF)
|
|
| SSC_BF(TFMR_DATDEF, 0)
|
|
| SSC_BF(TFMR_DATLEN, (bits - 1));
|
|
diff --git a/sound/soc/codecs/sgtl5000.c b/sound/soc/codecs/sgtl5000.c
|
|
index c40b7ca..87cbf14 100644
|
|
--- a/sound/soc/codecs/sgtl5000.c
|
|
+++ b/sound/soc/codecs/sgtl5000.c
|
|
@@ -1238,6 +1238,9 @@ static int sgtl5000_enable_regulators(struct snd_soc_codec *codec)
|
|
/* wait for all power rails bring up */
|
|
udelay(10);
|
|
|
|
+ /* Need 8 clocks before I2C accesses */
|
|
+ udelay(1);
|
|
+
|
|
/* read chip information */
|
|
reg = snd_soc_read(codec, SGTL5000_CHIP_ID);
|
|
if (((reg & SGTL5000_PARTID_MASK) >> SGTL5000_PARTID_SHIFT) !=
|
|
diff --git a/sound/soc/codecs/sigmadsp.c b/sound/soc/codecs/sigmadsp.c
|
|
index 4068f24..bb3878c 100644
|
|
--- a/sound/soc/codecs/sigmadsp.c
|
|
+++ b/sound/soc/codecs/sigmadsp.c
|
|
@@ -176,6 +176,13 @@ static int _process_sigma_firmware(struct device *dev,
|
|
goto done;
|
|
}
|
|
|
|
+ if (ssfw_head->version != 1) {
|
|
+ dev_err(dev,
|
|
+ "Failed to load firmware: Invalid version %d. Supported firmware versions: 1\n",
|
|
+ ssfw_head->version);
|
|
+ goto done;
|
|
+ }
|
|
+
|
|
crc = crc32(0, fw->data + sizeof(*ssfw_head),
|
|
fw->size - sizeof(*ssfw_head));
|
|
pr_debug("%s: crc=%x\n", __func__, crc);
|
|
diff --git a/sound/soc/codecs/wm8960.c b/sound/soc/codecs/wm8960.c
|
|
index ddb0d90..a09d7eb 100644
|
|
--- a/sound/soc/codecs/wm8960.c
|
|
+++ b/sound/soc/codecs/wm8960.c
|
|
@@ -496,7 +496,7 @@ static struct {
|
|
{ 22050, 2 },
|
|
{ 24000, 2 },
|
|
{ 16000, 3 },
|
|
- { 11250, 4 },
|
|
+ { 11025, 4 },
|
|
{ 12000, 4 },
|
|
{ 8000, 5 },
|
|
};
|
|
diff --git a/sound/usb/midi.c b/sound/usb/midi.c
|
|
index 2778815..c6ded49 100644
|
|
--- a/sound/usb/midi.c
|
|
+++ b/sound/usb/midi.c
|
|
@@ -365,6 +365,8 @@ static void snd_usbmidi_error_timer(unsigned long data)
|
|
if (in && in->error_resubmit) {
|
|
in->error_resubmit = 0;
|
|
for (j = 0; j < INPUT_URBS; ++j) {
|
|
+ if (atomic_read(&in->urbs[j]->use_count))
|
|
+ continue;
|
|
in->urbs[j]->dev = umidi->dev;
|
|
snd_usbmidi_submit_urb(in->urbs[j], GFP_ATOMIC);
|
|
}
|
|
diff --git a/sound/usb/mixer.c b/sound/usb/mixer.c
|
|
index 42d34c3..c44f605 100644
|
|
--- a/sound/usb/mixer.c
|
|
+++ b/sound/usb/mixer.c
|
|
@@ -909,6 +909,7 @@ static void volume_control_quirks(struct usb_mixer_elem_info *cval,
|
|
case USB_ID(0x046d, 0x0807): /* Logitech Webcam C500 */
|
|
case USB_ID(0x046d, 0x0808):
|
|
case USB_ID(0x046d, 0x0809):
|
|
+ case USB_ID(0x046d, 0x0819): /* Logitech Webcam C210 */
|
|
case USB_ID(0x046d, 0x081d): /* HD Webcam c510 */
|
|
case USB_ID(0x046d, 0x0991):
|
|
/* Most audio usb devices lie about volume resolution.
|
|
diff --git a/sound/usb/mixer_maps.c b/sound/usb/mixer_maps.c
|
|
index d1d72ff..621bc9e 100644
|
|
--- a/sound/usb/mixer_maps.c
|
|
+++ b/sound/usb/mixer_maps.c
|
|
@@ -328,8 +328,11 @@ static struct usbmix_name_map gamecom780_map[] = {
|
|
{}
|
|
};
|
|
|
|
-static const struct usbmix_name_map kef_x300a_map[] = {
|
|
- { 10, NULL }, /* firmware locks up (?) when we try to access this FU */
|
|
+/* some (all?) SCMS USB3318 devices are affected by a firmware lock up
|
|
+ * when anything attempts to access FU 10 (control)
|
|
+ */
|
|
+static const struct usbmix_name_map scms_usb3318_map[] = {
|
|
+ { 10, NULL },
|
|
{ 0 }
|
|
};
|
|
|
|
@@ -425,8 +428,14 @@ static struct usbmix_ctl_map usbmix_ctl_maps[] = {
|
|
.map = ebox44_map,
|
|
},
|
|
{
|
|
+ /* KEF X300A */
|
|
.id = USB_ID(0x27ac, 0x1000),
|
|
- .map = kef_x300a_map,
|
|
+ .map = scms_usb3318_map,
|
|
+ },
|
|
+ {
|
|
+ /* Arcam rPAC */
|
|
+ .id = USB_ID(0x25c4, 0x0003),
|
|
+ .map = scms_usb3318_map,
|
|
},
|
|
{ 0 } /* terminator */
|
|
};
|