2586 lines
82 KiB
Diff
2586 lines
82 KiB
Diff
|
diff --git a/Documentation/connector/cn_test.c b/Documentation/connector/cn_test.c
|
||
|
index 6a5be5d..473c589 100644
|
||
|
--- a/Documentation/connector/cn_test.c
|
||
|
+++ b/Documentation/connector/cn_test.c
|
||
|
@@ -32,10 +32,8 @@ static char cn_test_name[] = "cn_test";
|
||
|
static struct sock *nls;
|
||
|
static struct timer_list cn_test_timer;
|
||
|
|
||
|
-void cn_test_callback(void *data)
|
||
|
+static void cn_test_callback(struct cn_msg *msg, struct netlink_skb_parms *nsp)
|
||
|
{
|
||
|
- struct cn_msg *msg = (struct cn_msg *)data;
|
||
|
-
|
||
|
printk("%s: %lu: idx=%x, val=%x, seq=%u, ack=%u, len=%d: %s.\n",
|
||
|
__func__, jiffies, msg->id.idx, msg->id.val,
|
||
|
msg->seq, msg->ack, msg->len, (char *)msg->data);
|
||
|
diff --git a/Documentation/connector/connector.txt b/Documentation/connector/connector.txt
|
||
|
index ad6e0ba..3e6dcc7 100644
|
||
|
--- a/Documentation/connector/connector.txt
|
||
|
+++ b/Documentation/connector/connector.txt
|
||
|
@@ -23,7 +23,7 @@ handling... Connector allows any kernelspace agents to use netlink
|
||
|
based networking for inter-process communication in a significantly
|
||
|
easier way:
|
||
|
|
||
|
-int cn_add_callback(struct cb_id *id, char *name, void (*callback) (void *));
|
||
|
+int cn_add_callback(struct cb_id *id, char *name, void (*callback) (struct cn_msg *, struct netlink_skb_parms *));
|
||
|
void cn_netlink_send(struct cn_msg *msg, u32 __group, int gfp_mask);
|
||
|
|
||
|
struct cb_id
|
||
|
@@ -53,15 +53,15 @@ struct cn_msg
|
||
|
Connector interfaces.
|
||
|
/*****************************************/
|
||
|
|
||
|
-int cn_add_callback(struct cb_id *id, char *name, void (*callback) (void *));
|
||
|
+int cn_add_callback(struct cb_id *id, char *name, void (*callback) (struct cn_msg *, struct netlink_skb_parms *));
|
||
|
|
||
|
Registers new callback with connector core.
|
||
|
|
||
|
struct cb_id *id - unique connector's user identifier.
|
||
|
It must be registered in connector.h for legal in-kernel users.
|
||
|
char *name - connector's callback symbolic name.
|
||
|
-void (*callback) (void *) - connector's callback.
|
||
|
- Argument must be dereferenced to struct cn_msg *.
|
||
|
+void (*callback) (struct cn..) - connector's callback.
|
||
|
+ cn_msg and the sender's credentials
|
||
|
|
||
|
void cn_del_callback(struct cb_id *id);
|
||
|
|
||
|
diff --git a/MAINTAINERS b/MAINTAINERS
|
||
|
index 2ccc21c..94138c4 100644
|
||
|
--- a/MAINTAINERS
|
||
|
+++ b/MAINTAINERS
|
||
|
@@ -1992,7 +1992,7 @@ S: Maintained
|
||
|
F: fs/*
|
||
|
|
||
|
FINTEK F75375S HARDWARE MONITOR AND FAN CONTROLLER DRIVER
|
||
|
-M: Riku Voipio <riku.vipio@iki.fi>
|
||
|
+M: Riku Voipio <riku.voipio@iki.fi>
|
||
|
L: lm-sensors@lm-sensors.org
|
||
|
S: Maintained
|
||
|
F: drivers/hwmon/f75375s.c
|
||
|
diff --git a/Makefile b/Makefile
|
||
|
index 314a3aa..8190a1c 100644
|
||
|
diff --git a/arch/arm/Makefile b/arch/arm/Makefile
|
||
|
index c877d6d..41edaf2 100644
|
||
|
--- a/arch/arm/Makefile
|
||
|
+++ b/arch/arm/Makefile
|
||
|
@@ -14,7 +14,7 @@ LDFLAGS_vmlinux :=-p --no-undefined -X
|
||
|
ifeq ($(CONFIG_CPU_ENDIAN_BE8),y)
|
||
|
LDFLAGS_vmlinux += --be8
|
||
|
endif
|
||
|
-CPPFLAGS_vmlinux.lds = -DTEXT_OFFSET=$(TEXT_OFFSET)
|
||
|
+
|
||
|
OBJCOPYFLAGS :=-O binary -R .note -R .note.gnu.build-id -R .comment -S
|
||
|
GZFLAGS :=-9
|
||
|
#KBUILD_CFLAGS +=-pipe
|
||
|
diff --git a/arch/arm/kernel/Makefile b/arch/arm/kernel/Makefile
|
||
|
index ff89d0b..60be28d 100644
|
||
|
--- a/arch/arm/kernel/Makefile
|
||
|
+++ b/arch/arm/kernel/Makefile
|
||
|
@@ -2,7 +2,8 @@
|
||
|
# Makefile for the linux kernel.
|
||
|
#
|
||
|
|
||
|
-AFLAGS_head.o := -DTEXT_OFFSET=$(TEXT_OFFSET)
|
||
|
+CPPFLAGS_vmlinux.lds := -DTEXT_OFFSET=$(TEXT_OFFSET)
|
||
|
+AFLAGS_head.o := -DTEXT_OFFSET=$(TEXT_OFFSET)
|
||
|
|
||
|
ifdef CONFIG_DYNAMIC_FTRACE
|
||
|
CFLAGS_REMOVE_ftrace.o = -pg
|
||
|
diff --git a/arch/arm/mach-pxa/cpufreq-pxa2xx.c b/arch/arm/mach-pxa/cpufreq-pxa2xx.c
|
||
|
index 3a8ee22..983cc8c 100644
|
||
|
--- a/arch/arm/mach-pxa/cpufreq-pxa2xx.c
|
||
|
+++ b/arch/arm/mach-pxa/cpufreq-pxa2xx.c
|
||
|
@@ -155,7 +155,7 @@ MODULE_PARM_DESC(pxa255_turbo_table, "Selects the frequency table (0 = run table
|
||
|
|
||
|
static pxa_freqs_t pxa27x_freqs[] = {
|
||
|
{104000, 104000, PXA27x_CCCR(1, 8, 2), 0, CCLKCFG2(1, 0, 1), 900000, 1705000 },
|
||
|
- {156000, 104000, PXA27x_CCCR(1, 8, 6), 0, CCLKCFG2(1, 1, 1), 1000000, 1705000 },
|
||
|
+ {156000, 104000, PXA27x_CCCR(1, 8, 3), 0, CCLKCFG2(1, 0, 1), 1000000, 1705000 },
|
||
|
{208000, 208000, PXA27x_CCCR(0, 16, 2), 1, CCLKCFG2(0, 0, 1), 1180000, 1705000 },
|
||
|
{312000, 208000, PXA27x_CCCR(1, 16, 3), 1, CCLKCFG2(1, 0, 1), 1250000, 1705000 },
|
||
|
{416000, 208000, PXA27x_CCCR(1, 16, 4), 1, CCLKCFG2(1, 0, 1), 1350000, 1705000 },
|
||
|
diff --git a/arch/cris/Makefile b/arch/cris/Makefile
|
||
|
index 71e17d3..29c2ceb 100644
|
||
|
--- a/arch/cris/Makefile
|
||
|
+++ b/arch/cris/Makefile
|
||
|
@@ -42,8 +42,6 @@ LD = $(CROSS_COMPILE)ld -mcrislinux
|
||
|
|
||
|
OBJCOPYFLAGS := -O binary -R .note -R .comment -S
|
||
|
|
||
|
-CPPFLAGS_vmlinux.lds = -DDRAM_VIRTUAL_BASE=0x$(CONFIG_ETRAX_DRAM_VIRTUAL_BASE)
|
||
|
-
|
||
|
KBUILD_AFLAGS += -mlinux -march=$(arch-y) $(inc)
|
||
|
KBUILD_CFLAGS += -mlinux -march=$(arch-y) -pipe $(inc)
|
||
|
KBUILD_CPPFLAGS += $(inc)
|
||
|
diff --git a/arch/cris/kernel/Makefile b/arch/cris/kernel/Makefile
|
||
|
index ee7bcd4..b45640b 100644
|
||
|
--- a/arch/cris/kernel/Makefile
|
||
|
+++ b/arch/cris/kernel/Makefile
|
||
|
@@ -3,6 +3,7 @@
|
||
|
# Makefile for the linux kernel.
|
||
|
#
|
||
|
|
||
|
+CPPFLAGS_vmlinux.lds := -DDRAM_VIRTUAL_BASE=0x$(CONFIG_ETRAX_DRAM_VIRTUAL_BASE)
|
||
|
extra-y := vmlinux.lds
|
||
|
|
||
|
obj-y := process.o traps.o irq.o ptrace.o setup.o time.o sys_cris.o
|
||
|
diff --git a/arch/mips/Makefile b/arch/mips/Makefile
|
||
|
index 861da51..7d651d5 100644
|
||
|
--- a/arch/mips/Makefile
|
||
|
+++ b/arch/mips/Makefile
|
||
|
@@ -615,16 +615,6 @@ endif
|
||
|
cflags-y += -I$(srctree)/arch/mips/include/asm/mach-generic
|
||
|
drivers-$(CONFIG_PCI) += arch/mips/pci/
|
||
|
|
||
|
-ifdef CONFIG_32BIT
|
||
|
-ifdef CONFIG_CPU_LITTLE_ENDIAN
|
||
|
-JIFFIES = jiffies_64
|
||
|
-else
|
||
|
-JIFFIES = jiffies_64 + 4
|
||
|
-endif
|
||
|
-else
|
||
|
-JIFFIES = jiffies_64
|
||
|
-endif
|
||
|
-
|
||
|
#
|
||
|
# Automatically detect the build format. By default we choose
|
||
|
# the elf format according to the load address.
|
||
|
@@ -648,8 +638,9 @@ ifdef CONFIG_64BIT
|
||
|
endif
|
||
|
|
||
|
KBUILD_AFLAGS += $(cflags-y)
|
||
|
-KBUILD_CFLAGS += $(cflags-y) \
|
||
|
- -D"VMLINUX_LOAD_ADDRESS=$(load-y)"
|
||
|
+KBUILD_CFLAGS += $(cflags-y)
|
||
|
+KBUILD_CPPFLAGS += -D"VMLINUX_LOAD_ADDRESS=$(load-y)"
|
||
|
+KBUILD_CPPFLAGS += -D"DATAOFFSET=$(if $(dataoffset-y),$(dataoffset-y),0)"
|
||
|
|
||
|
LDFLAGS += -m $(ld-emul)
|
||
|
|
||
|
@@ -664,18 +655,6 @@ endif
|
||
|
|
||
|
OBJCOPYFLAGS += --remove-section=.reginfo
|
||
|
|
||
|
-#
|
||
|
-# Choosing incompatible machines durings configuration will result in
|
||
|
-# error messages during linking. Select a default linkscript if
|
||
|
-# none has been choosen above.
|
||
|
-#
|
||
|
-
|
||
|
-CPPFLAGS_vmlinux.lds := \
|
||
|
- $(KBUILD_CFLAGS) \
|
||
|
- -D"LOADADDR=$(load-y)" \
|
||
|
- -D"JIFFIES=$(JIFFIES)" \
|
||
|
- -D"DATAOFFSET=$(if $(dataoffset-y),$(dataoffset-y),0)"
|
||
|
-
|
||
|
head-y := arch/mips/kernel/head.o arch/mips/kernel/init_task.o
|
||
|
|
||
|
libs-y += arch/mips/lib/
|
||
|
diff --git a/arch/mips/kernel/vmlinux.lds.S b/arch/mips/kernel/vmlinux.lds.S
|
||
|
index 58738c8..576f8fb 100644
|
||
|
--- a/arch/mips/kernel/vmlinux.lds.S
|
||
|
+++ b/arch/mips/kernel/vmlinux.lds.S
|
||
|
@@ -9,7 +9,16 @@ PHDRS {
|
||
|
text PT_LOAD FLAGS(7); /* RWX */
|
||
|
note PT_NOTE FLAGS(4); /* R__ */
|
||
|
}
|
||
|
-jiffies = JIFFIES;
|
||
|
+
|
||
|
+ifdef CONFIG_32BIT
|
||
|
+ ifdef CONFIG_CPU_LITTLE_ENDIAN
|
||
|
+ jiffies = jiffies_64;
|
||
|
+ else
|
||
|
+ jiffies = jiffies_64 + 4;
|
||
|
+ endif
|
||
|
+else
|
||
|
+ jiffies = jiffies_64;
|
||
|
+endif
|
||
|
|
||
|
SECTIONS
|
||
|
{
|
||
|
@@ -28,7 +37,7 @@ SECTIONS
|
||
|
/* . = 0xa800000000300000; */
|
||
|
. = 0xffffffff80300000;
|
||
|
#endif
|
||
|
- . = LOADADDR;
|
||
|
+ . = VMLINUX_LOAD_ADDRESS;
|
||
|
/* read-only */
|
||
|
_text = .; /* Text and read-only data */
|
||
|
.text : {
|
||
|
diff --git a/arch/powerpc/Makefile b/arch/powerpc/Makefile
|
||
|
index bc35f4e..39d44f7 100644
|
||
|
--- a/arch/powerpc/Makefile
|
||
|
+++ b/arch/powerpc/Makefile
|
||
|
@@ -158,8 +158,6 @@ drivers-$(CONFIG_OPROFILE) += arch/powerpc/oprofile/
|
||
|
# Default to zImage, override when needed
|
||
|
all: zImage
|
||
|
|
||
|
-CPPFLAGS_vmlinux.lds := -Upowerpc
|
||
|
-
|
||
|
BOOT_TARGETS = zImage zImage.initrd uImage zImage% dtbImage% treeImage.% cuImage.% simpleImage.%
|
||
|
|
||
|
PHONY += $(BOOT_TARGETS)
|
||
|
diff --git a/arch/sparc/Makefile b/arch/sparc/Makefile
|
||
|
index 2003ded..6c21179 100644
|
||
|
--- a/arch/sparc/Makefile
|
||
|
+++ b/arch/sparc/Makefile
|
||
|
@@ -31,7 +31,6 @@ export BITS := 32
|
||
|
#KBUILD_CFLAGS += -g -pipe -fcall-used-g5 -fcall-used-g7
|
||
|
KBUILD_CFLAGS += -m32 -pipe -mno-fpu -fcall-used-g5 -fcall-used-g7
|
||
|
KBUILD_AFLAGS += -m32
|
||
|
-CPPFLAGS_vmlinux.lds += -m32
|
||
|
|
||
|
#LDFLAGS_vmlinux = -N -Ttext 0xf0004000
|
||
|
# Since 2.5.40, the first stage is left not btfix-ed.
|
||
|
@@ -49,9 +48,6 @@ else
|
||
|
|
||
|
CHECKFLAGS += -D__sparc__ -D__sparc_v9__ -D__arch64__ -m64
|
||
|
|
||
|
-# Undefine sparc when processing vmlinux.lds - it is used
|
||
|
-# And teach CPP we are doing 64 bit builds (for this case)
|
||
|
-CPPFLAGS_vmlinux.lds += -m64 -Usparc
|
||
|
LDFLAGS := -m elf64_sparc
|
||
|
export BITS := 64
|
||
|
|
||
|
diff --git a/arch/sparc/kernel/Makefile b/arch/sparc/kernel/Makefile
|
||
|
index 475ce46..cbf5d0b 100644
|
||
|
--- a/arch/sparc/kernel/Makefile
|
||
|
+++ b/arch/sparc/kernel/Makefile
|
||
|
@@ -7,7 +7,11 @@ ccflags-y := -Werror
|
||
|
|
||
|
extra-y := head_$(BITS).o
|
||
|
extra-y += init_task.o
|
||
|
-extra-y += vmlinux.lds
|
||
|
+
|
||
|
+# Undefine sparc when processing vmlinux.lds - it is used
|
||
|
+# And teach CPP we are doing $(BITS) builds (for this case)
|
||
|
+CPPFLAGS_vmlinux.lds := -Usparc -m$(BITS)
|
||
|
+extra-y += vmlinux.lds
|
||
|
|
||
|
obj-$(CONFIG_SPARC32) += entry.o wof.o wuf.o
|
||
|
obj-$(CONFIG_SPARC32) += etrap_32.o
|
||
|
diff --git a/arch/um/Makefile b/arch/um/Makefile
|
||
|
index 0728def..fc633db 100644
|
||
|
--- a/arch/um/Makefile
|
||
|
+++ b/arch/um/Makefile
|
||
|
@@ -96,11 +96,10 @@ CFLAGS_NO_HARDENING := $(call cc-option, -fno-PIC,) $(call cc-option, -fno-pic,)
|
||
|
$(call cc-option, -fno-stack-protector,) \
|
||
|
$(call cc-option, -fno-stack-protector-all,)
|
||
|
|
||
|
-CONFIG_KERNEL_STACK_ORDER ?= 2
|
||
|
-STACK_SIZE := $(shell echo $$[ 4096 * (1 << $(CONFIG_KERNEL_STACK_ORDER)) ] )
|
||
|
-
|
||
|
-CPPFLAGS_vmlinux.lds = -U$(SUBARCH) -DSTART=$(START) -DELF_ARCH=$(ELF_ARCH) \
|
||
|
- -DELF_FORMAT="$(ELF_FORMAT)" -DKERNEL_STACK_SIZE=$(STACK_SIZE)
|
||
|
+# Options used by linker script
|
||
|
+export LDS_START := $(START)
|
||
|
+export LDS_ELF_ARCH := $(ELF_ARCH)
|
||
|
+export LDS_ELF_FORMAT := $(ELF_FORMAT)
|
||
|
|
||
|
# The wrappers will select whether using "malloc" or the kernel allocator.
|
||
|
LINK_WRAPS = -Wl,--wrap,malloc -Wl,--wrap,free -Wl,--wrap,calloc
|
||
|
diff --git a/arch/um/kernel/Makefile b/arch/um/kernel/Makefile
|
||
|
index 388ec0a..1119233 100644
|
||
|
--- a/arch/um/kernel/Makefile
|
||
|
+++ b/arch/um/kernel/Makefile
|
||
|
@@ -3,6 +3,9 @@
|
||
|
# Licensed under the GPL
|
||
|
#
|
||
|
|
||
|
+CPPFLAGS_vmlinux.lds := -U$(SUBARCH) -DSTART=$(LDS_START) \
|
||
|
+ -DELF_ARCH=$(LDS_ELF_ARCH) \
|
||
|
+ -DELF_FORMAT=$(LDS_ELF_FORMAT)
|
||
|
extra-y := vmlinux.lds
|
||
|
clean-files :=
|
||
|
|
||
|
diff --git a/arch/um/kernel/vmlinux.lds.S b/arch/um/kernel/vmlinux.lds.S
|
||
|
index f8aeb44..16e49bf 100644
|
||
|
--- a/arch/um/kernel/vmlinux.lds.S
|
||
|
+++ b/arch/um/kernel/vmlinux.lds.S
|
||
|
@@ -1,3 +1,6 @@
|
||
|
+
|
||
|
+KERNEL_STACK_SIZE = 4096 * (1 << CONFIG_KERNEL_STACK_ORDER);
|
||
|
+
|
||
|
#ifdef CONFIG_LD_SCRIPT_STATIC
|
||
|
#include "uml.lds.S"
|
||
|
#else
|
||
|
diff --git a/arch/x86/include/asm/paravirt.h b/arch/x86/include/asm/paravirt.h
|
||
|
index 4fb37c8..43b8adb 100644
|
||
|
--- a/arch/x86/include/asm/paravirt.h
|
||
|
+++ b/arch/x86/include/asm/paravirt.h
|
||
|
@@ -528,10 +528,11 @@ int paravirt_disable_iospace(void);
|
||
|
#define EXTRA_CLOBBERS
|
||
|
#define VEXTRA_CLOBBERS
|
||
|
#else /* CONFIG_X86_64 */
|
||
|
+/* [re]ax isn't an arg, but the return val */
|
||
|
#define PVOP_VCALL_ARGS \
|
||
|
unsigned long __edi = __edi, __esi = __esi, \
|
||
|
- __edx = __edx, __ecx = __ecx
|
||
|
-#define PVOP_CALL_ARGS PVOP_VCALL_ARGS, __eax
|
||
|
+ __edx = __edx, __ecx = __ecx, __eax = __eax
|
||
|
+#define PVOP_CALL_ARGS PVOP_VCALL_ARGS
|
||
|
|
||
|
#define PVOP_CALL_ARG1(x) "D" ((unsigned long)(x))
|
||
|
#define PVOP_CALL_ARG2(x) "S" ((unsigned long)(x))
|
||
|
@@ -543,6 +544,7 @@ int paravirt_disable_iospace(void);
|
||
|
"=c" (__ecx)
|
||
|
#define PVOP_CALL_CLOBBERS PVOP_VCALL_CLOBBERS, "=a" (__eax)
|
||
|
|
||
|
+/* void functions are still allowed [re]ax for scratch */
|
||
|
#define PVOP_VCALLEE_CLOBBERS "=a" (__eax)
|
||
|
#define PVOP_CALLEE_CLOBBERS PVOP_VCALLEE_CLOBBERS
|
||
|
|
||
|
@@ -617,8 +619,8 @@ int paravirt_disable_iospace(void);
|
||
|
VEXTRA_CLOBBERS, \
|
||
|
pre, post, ##__VA_ARGS__)
|
||
|
|
||
|
-#define __PVOP_VCALLEESAVE(rettype, op, pre, post, ...) \
|
||
|
- ____PVOP_CALL(rettype, op.func, CLBR_RET_REG, \
|
||
|
+#define __PVOP_VCALLEESAVE(op, pre, post, ...) \
|
||
|
+ ____PVOP_VCALL(op.func, CLBR_RET_REG, \
|
||
|
PVOP_VCALLEE_CLOBBERS, , \
|
||
|
pre, post, ##__VA_ARGS__)
|
||
|
|
||
|
@@ -1565,42 +1567,22 @@ extern struct paravirt_patch_site __parainstructions[],
|
||
|
|
||
|
static inline unsigned long __raw_local_save_flags(void)
|
||
|
{
|
||
|
- unsigned long f;
|
||
|
-
|
||
|
- asm volatile(paravirt_alt(PARAVIRT_CALL)
|
||
|
- : "=a"(f)
|
||
|
- : paravirt_type(pv_irq_ops.save_fl),
|
||
|
- paravirt_clobber(CLBR_EAX)
|
||
|
- : "memory", "cc");
|
||
|
- return f;
|
||
|
+ return PVOP_CALLEE0(unsigned long, pv_irq_ops.save_fl);
|
||
|
}
|
||
|
|
||
|
static inline void raw_local_irq_restore(unsigned long f)
|
||
|
{
|
||
|
- asm volatile(paravirt_alt(PARAVIRT_CALL)
|
||
|
- : "=a"(f)
|
||
|
- : PV_FLAGS_ARG(f),
|
||
|
- paravirt_type(pv_irq_ops.restore_fl),
|
||
|
- paravirt_clobber(CLBR_EAX)
|
||
|
- : "memory", "cc");
|
||
|
+ PVOP_VCALLEE1(pv_irq_ops.restore_fl, f);
|
||
|
}
|
||
|
|
||
|
static inline void raw_local_irq_disable(void)
|
||
|
{
|
||
|
- asm volatile(paravirt_alt(PARAVIRT_CALL)
|
||
|
- :
|
||
|
- : paravirt_type(pv_irq_ops.irq_disable),
|
||
|
- paravirt_clobber(CLBR_EAX)
|
||
|
- : "memory", "eax", "cc");
|
||
|
+ PVOP_VCALLEE0(pv_irq_ops.irq_disable);
|
||
|
}
|
||
|
|
||
|
static inline void raw_local_irq_enable(void)
|
||
|
{
|
||
|
- asm volatile(paravirt_alt(PARAVIRT_CALL)
|
||
|
- :
|
||
|
- : paravirt_type(pv_irq_ops.irq_enable),
|
||
|
- paravirt_clobber(CLBR_EAX)
|
||
|
- : "memory", "eax", "cc");
|
||
|
+ PVOP_VCALLEE0(pv_irq_ops.irq_enable);
|
||
|
}
|
||
|
|
||
|
static inline unsigned long __raw_local_irq_save(void)
|
||
|
diff --git a/arch/xtensa/kernel/Makefile b/arch/xtensa/kernel/Makefile
|
||
|
index fe3186d..6f56d95 100644
|
||
|
--- a/arch/xtensa/kernel/Makefile
|
||
|
+++ b/arch/xtensa/kernel/Makefile
|
||
|
@@ -27,7 +27,8 @@ sed-y = -e 's/(\(\.[a-z]*it\|\.ref\|\)\.text)/(\1.literal \1.text)/g' \
|
||
|
-e 's/(\(\.text\.[a-z]*\))/(\1.literal \1)/g'
|
||
|
|
||
|
quiet_cmd__cpp_lds_S = LDS $@
|
||
|
- cmd__cpp_lds_S = $(CPP) $(cpp_flags) -D__ASSEMBLY__ $< | sed $(sed-y) >$@
|
||
|
+ cmd__cpp_lds_S = $(CPP) $(cpp_flags) -P -C -Uxtensa -D__ASSEMBLY__ $< \
|
||
|
+ | sed $(sed-y) >$@
|
||
|
|
||
|
$(obj)/vmlinux.lds: $(src)/vmlinux.lds.S FORCE
|
||
|
$(call if_changed_dep,_cpp_lds_S)
|
||
|
diff --git a/drivers/char/tpm/tpm.c b/drivers/char/tpm/tpm.c
|
||
|
index b0603b2..47c2d27 100644
|
||
|
--- a/drivers/char/tpm/tpm.c
|
||
|
+++ b/drivers/char/tpm/tpm.c
|
||
|
@@ -696,8 +696,7 @@ int __tpm_pcr_read(struct tpm_chip *chip, int pcr_idx, u8 *res_buf)
|
||
|
|
||
|
cmd.header.in = pcrread_header;
|
||
|
cmd.params.pcrread_in.pcr_idx = cpu_to_be32(pcr_idx);
|
||
|
- BUILD_BUG_ON(cmd.header.in.length > READ_PCR_RESULT_SIZE);
|
||
|
- rc = transmit_cmd(chip, &cmd, cmd.header.in.length,
|
||
|
+ rc = transmit_cmd(chip, &cmd, READ_PCR_RESULT_SIZE,
|
||
|
"attempting to read a pcr value");
|
||
|
|
||
|
if (rc == 0)
|
||
|
@@ -742,7 +741,7 @@ EXPORT_SYMBOL_GPL(tpm_pcr_read);
|
||
|
* the module usage count.
|
||
|
*/
|
||
|
#define TPM_ORD_PCR_EXTEND cpu_to_be32(20)
|
||
|
-#define EXTEND_PCR_SIZE 34
|
||
|
+#define EXTEND_PCR_RESULT_SIZE 34
|
||
|
static struct tpm_input_header pcrextend_header = {
|
||
|
.tag = TPM_TAG_RQU_COMMAND,
|
||
|
.length = cpu_to_be32(34),
|
||
|
@@ -760,10 +759,9 @@ int tpm_pcr_extend(u32 chip_num, int pcr_idx, const u8 *hash)
|
||
|
return -ENODEV;
|
||
|
|
||
|
cmd.header.in = pcrextend_header;
|
||
|
- BUILD_BUG_ON(be32_to_cpu(cmd.header.in.length) > EXTEND_PCR_SIZE);
|
||
|
cmd.params.pcrextend_in.pcr_idx = cpu_to_be32(pcr_idx);
|
||
|
memcpy(cmd.params.pcrextend_in.hash, hash, TPM_DIGEST_SIZE);
|
||
|
- rc = transmit_cmd(chip, &cmd, cmd.header.in.length,
|
||
|
+ rc = transmit_cmd(chip, &cmd, EXTEND_PCR_RESULT_SIZE,
|
||
|
"attempting extend a PCR value");
|
||
|
|
||
|
module_put(chip->dev->driver->owner);
|
||
|
diff --git a/drivers/char/tty_buffer.c b/drivers/char/tty_buffer.c
|
||
|
index 3108991..0296612 100644
|
||
|
--- a/drivers/char/tty_buffer.c
|
||
|
+++ b/drivers/char/tty_buffer.c
|
||
|
@@ -402,28 +402,26 @@ static void flush_to_ldisc(struct work_struct *work)
|
||
|
container_of(work, struct tty_struct, buf.work.work);
|
||
|
unsigned long flags;
|
||
|
struct tty_ldisc *disc;
|
||
|
- struct tty_buffer *tbuf, *head;
|
||
|
- char *char_buf;
|
||
|
- unsigned char *flag_buf;
|
||
|
|
||
|
disc = tty_ldisc_ref(tty);
|
||
|
if (disc == NULL) /* !TTY_LDISC */
|
||
|
return;
|
||
|
|
||
|
spin_lock_irqsave(&tty->buf.lock, flags);
|
||
|
- /* So we know a flush is running */
|
||
|
- set_bit(TTY_FLUSHING, &tty->flags);
|
||
|
- head = tty->buf.head;
|
||
|
- if (head != NULL) {
|
||
|
- tty->buf.head = NULL;
|
||
|
- for (;;) {
|
||
|
- int count = head->commit - head->read;
|
||
|
+
|
||
|
+ if (!test_and_set_bit(TTY_FLUSHING, &tty->flags)) {
|
||
|
+ struct tty_buffer *head;
|
||
|
+ while ((head = tty->buf.head) != NULL) {
|
||
|
+ int count;
|
||
|
+ char *char_buf;
|
||
|
+ unsigned char *flag_buf;
|
||
|
+
|
||
|
+ count = head->commit - head->read;
|
||
|
if (!count) {
|
||
|
if (head->next == NULL)
|
||
|
break;
|
||
|
- tbuf = head;
|
||
|
- head = head->next;
|
||
|
- tty_buffer_free(tty, tbuf);
|
||
|
+ tty->buf.head = head->next;
|
||
|
+ tty_buffer_free(tty, head);
|
||
|
continue;
|
||
|
}
|
||
|
/* Ldisc or user is trying to flush the buffers
|
||
|
@@ -445,9 +443,9 @@ static void flush_to_ldisc(struct work_struct *work)
|
||
|
flag_buf, count);
|
||
|
spin_lock_irqsave(&tty->buf.lock, flags);
|
||
|
}
|
||
|
- /* Restore the queue head */
|
||
|
- tty->buf.head = head;
|
||
|
+ clear_bit(TTY_FLUSHING, &tty->flags);
|
||
|
}
|
||
|
+
|
||
|
/* We may have a deferred request to flush the input buffer,
|
||
|
if so pull the chain under the lock and empty the queue */
|
||
|
if (test_bit(TTY_FLUSHPENDING, &tty->flags)) {
|
||
|
@@ -455,7 +453,6 @@ static void flush_to_ldisc(struct work_struct *work)
|
||
|
clear_bit(TTY_FLUSHPENDING, &tty->flags);
|
||
|
wake_up(&tty->read_wait);
|
||
|
}
|
||
|
- clear_bit(TTY_FLUSHING, &tty->flags);
|
||
|
spin_unlock_irqrestore(&tty->buf.lock, flags);
|
||
|
|
||
|
tty_ldisc_deref(disc);
|
||
|
diff --git a/drivers/connector/cn_proc.c b/drivers/connector/cn_proc.c
|
||
|
index c5afc98..9ca20d0 100644
|
||
|
--- a/drivers/connector/cn_proc.c
|
||
|
+++ b/drivers/connector/cn_proc.c
|
||
|
@@ -202,9 +202,8 @@ static void cn_proc_ack(int err, int rcvd_seq, int rcvd_ack)
|
||
|
* cn_proc_mcast_ctl
|
||
|
* @data: message sent from userspace via the connector
|
||
|
*/
|
||
|
-static void cn_proc_mcast_ctl(void *data)
|
||
|
+static void cn_proc_mcast_ctl(struct cn_msg *msg, struct netlink_skb_parms *nsp)
|
||
|
{
|
||
|
- struct cn_msg *msg = data;
|
||
|
enum proc_cn_mcast_op *mc_op = NULL;
|
||
|
int err = 0;
|
||
|
|
||
|
diff --git a/drivers/connector/cn_queue.c b/drivers/connector/cn_queue.c
|
||
|
index 408c2af..210338e 100644
|
||
|
--- a/drivers/connector/cn_queue.c
|
||
|
+++ b/drivers/connector/cn_queue.c
|
||
|
@@ -78,16 +78,20 @@ void cn_queue_wrapper(struct work_struct *work)
|
||
|
struct cn_callback_entry *cbq =
|
||
|
container_of(work, struct cn_callback_entry, work);
|
||
|
struct cn_callback_data *d = &cbq->data;
|
||
|
+ struct cn_msg *msg = NLMSG_DATA(nlmsg_hdr(d->skb));
|
||
|
+ struct netlink_skb_parms *nsp = &NETLINK_CB(d->skb);
|
||
|
|
||
|
- d->callback(d->callback_priv);
|
||
|
+ d->callback(msg, nsp);
|
||
|
|
||
|
- d->destruct_data(d->ddata);
|
||
|
- d->ddata = NULL;
|
||
|
+ kfree_skb(d->skb);
|
||
|
+ d->skb = NULL;
|
||
|
|
||
|
kfree(d->free);
|
||
|
}
|
||
|
|
||
|
-static struct cn_callback_entry *cn_queue_alloc_callback_entry(char *name, struct cb_id *id, void (*callback)(void *))
|
||
|
+static struct cn_callback_entry *
|
||
|
+cn_queue_alloc_callback_entry(char *name, struct cb_id *id,
|
||
|
+ void (*callback)(struct cn_msg *, struct netlink_skb_parms *))
|
||
|
{
|
||
|
struct cn_callback_entry *cbq;
|
||
|
|
||
|
@@ -120,7 +124,8 @@ int cn_cb_equal(struct cb_id *i1, struct cb_id *i2)
|
||
|
return ((i1->idx == i2->idx) && (i1->val == i2->val));
|
||
|
}
|
||
|
|
||
|
-int cn_queue_add_callback(struct cn_queue_dev *dev, char *name, struct cb_id *id, void (*callback)(void *))
|
||
|
+int cn_queue_add_callback(struct cn_queue_dev *dev, char *name, struct cb_id *id,
|
||
|
+ void (*callback)(struct cn_msg *, struct netlink_skb_parms *))
|
||
|
{
|
||
|
struct cn_callback_entry *cbq, *__cbq;
|
||
|
int found = 0;
|
||
|
diff --git a/drivers/connector/connector.c b/drivers/connector/connector.c
|
||
|
index 08b2500..f060246 100644
|
||
|
--- a/drivers/connector/connector.c
|
||
|
+++ b/drivers/connector/connector.c
|
||
|
@@ -129,21 +129,19 @@ EXPORT_SYMBOL_GPL(cn_netlink_send);
|
||
|
/*
|
||
|
* Callback helper - queues work and setup destructor for given data.
|
||
|
*/
|
||
|
-static int cn_call_callback(struct cn_msg *msg, void (*destruct_data)(void *), void *data)
|
||
|
+static int cn_call_callback(struct sk_buff *skb)
|
||
|
{
|
||
|
struct cn_callback_entry *__cbq, *__new_cbq;
|
||
|
struct cn_dev *dev = &cdev;
|
||
|
+ struct cn_msg *msg = NLMSG_DATA(nlmsg_hdr(skb));
|
||
|
int err = -ENODEV;
|
||
|
|
||
|
spin_lock_bh(&dev->cbdev->queue_lock);
|
||
|
list_for_each_entry(__cbq, &dev->cbdev->queue_list, callback_entry) {
|
||
|
if (cn_cb_equal(&__cbq->id.id, &msg->id)) {
|
||
|
if (likely(!work_pending(&__cbq->work) &&
|
||
|
- __cbq->data.ddata == NULL)) {
|
||
|
- __cbq->data.callback_priv = msg;
|
||
|
-
|
||
|
- __cbq->data.ddata = data;
|
||
|
- __cbq->data.destruct_data = destruct_data;
|
||
|
+ __cbq->data.skb == NULL)) {
|
||
|
+ __cbq->data.skb = skb;
|
||
|
|
||
|
if (queue_cn_work(__cbq, &__cbq->work))
|
||
|
err = 0;
|
||
|
@@ -156,10 +154,8 @@ static int cn_call_callback(struct cn_msg *msg, void (*destruct_data)(void *), v
|
||
|
__new_cbq = kzalloc(sizeof(struct cn_callback_entry), GFP_ATOMIC);
|
||
|
if (__new_cbq) {
|
||
|
d = &__new_cbq->data;
|
||
|
- d->callback_priv = msg;
|
||
|
+ d->skb = skb;
|
||
|
d->callback = __cbq->data.callback;
|
||
|
- d->ddata = data;
|
||
|
- d->destruct_data = destruct_data;
|
||
|
d->free = __new_cbq;
|
||
|
|
||
|
__new_cbq->pdev = __cbq->pdev;
|
||
|
@@ -191,7 +187,6 @@ static int cn_call_callback(struct cn_msg *msg, void (*destruct_data)(void *), v
|
||
|
*/
|
||
|
static void cn_rx_skb(struct sk_buff *__skb)
|
||
|
{
|
||
|
- struct cn_msg *msg;
|
||
|
struct nlmsghdr *nlh;
|
||
|
int err;
|
||
|
struct sk_buff *skb;
|
||
|
@@ -208,8 +203,7 @@ static void cn_rx_skb(struct sk_buff *__skb)
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
- msg = NLMSG_DATA(nlh);
|
||
|
- err = cn_call_callback(msg, (void (*)(void *))kfree_skb, skb);
|
||
|
+ err = cn_call_callback(skb);
|
||
|
if (err < 0)
|
||
|
kfree_skb(skb);
|
||
|
}
|
||
|
@@ -269,7 +263,8 @@ static void cn_notify(struct cb_id *id, u32 notify_event)
|
||
|
*
|
||
|
* May sleep.
|
||
|
*/
|
||
|
-int cn_add_callback(struct cb_id *id, char *name, void (*callback)(void *))
|
||
|
+int cn_add_callback(struct cb_id *id, char *name,
|
||
|
+ void (*callback)(struct cn_msg *, struct netlink_skb_parms *))
|
||
|
{
|
||
|
int err;
|
||
|
struct cn_dev *dev = &cdev;
|
||
|
@@ -351,9 +346,8 @@ static int cn_ctl_msg_equals(struct cn_ctl_msg *m1, struct cn_ctl_msg *m2)
|
||
|
*
|
||
|
* Used for notification of a request's processing.
|
||
|
*/
|
||
|
-static void cn_callback(void *data)
|
||
|
+static void cn_callback(struct cn_msg *msg, struct netlink_skb_parms *nsp)
|
||
|
{
|
||
|
- struct cn_msg *msg = data;
|
||
|
struct cn_ctl_msg *ctl;
|
||
|
struct cn_ctl_entry *ent;
|
||
|
u32 size;
|
||
|
diff --git a/drivers/i2c/busses/i2c-amd756.c b/drivers/i2c/busses/i2c-amd756.c
|
||
|
index f7d6fe9..8f0b90e 100644
|
||
|
--- a/drivers/i2c/busses/i2c-amd756.c
|
||
|
+++ b/drivers/i2c/busses/i2c-amd756.c
|
||
|
@@ -364,7 +364,7 @@ static int __devinit amd756_probe(struct pci_dev *pdev,
|
||
|
error = acpi_check_region(amd756_ioport, SMB_IOSIZE,
|
||
|
amd756_driver.name);
|
||
|
if (error)
|
||
|
- return error;
|
||
|
+ return -ENODEV;
|
||
|
|
||
|
if (!request_region(amd756_ioport, SMB_IOSIZE, amd756_driver.name)) {
|
||
|
dev_err(&pdev->dev, "SMB region 0x%x already in use!\n",
|
||
|
diff --git a/drivers/i2c/busses/i2c-amd8111.c b/drivers/i2c/busses/i2c-amd8111.c
|
||
|
index a7c5990..5b4ad86 100644
|
||
|
--- a/drivers/i2c/busses/i2c-amd8111.c
|
||
|
+++ b/drivers/i2c/busses/i2c-amd8111.c
|
||
|
@@ -376,8 +376,10 @@ static int __devinit amd8111_probe(struct pci_dev *dev,
|
||
|
smbus->size = pci_resource_len(dev, 0);
|
||
|
|
||
|
error = acpi_check_resource_conflict(&dev->resource[0]);
|
||
|
- if (error)
|
||
|
+ if (error) {
|
||
|
+ error = -ENODEV;
|
||
|
goto out_kfree;
|
||
|
+ }
|
||
|
|
||
|
if (!request_region(smbus->base, smbus->size, amd8111_driver.name)) {
|
||
|
error = -EBUSY;
|
||
|
diff --git a/drivers/i2c/busses/i2c-i801.c b/drivers/i2c/busses/i2c-i801.c
|
||
|
index 9d2c5ad..55edcfe 100644
|
||
|
--- a/drivers/i2c/busses/i2c-i801.c
|
||
|
+++ b/drivers/i2c/busses/i2c-i801.c
|
||
|
@@ -732,8 +732,10 @@ static int __devinit i801_probe(struct pci_dev *dev, const struct pci_device_id
|
||
|
}
|
||
|
|
||
|
err = acpi_check_resource_conflict(&dev->resource[SMBBAR]);
|
||
|
- if (err)
|
||
|
+ if (err) {
|
||
|
+ err = -ENODEV;
|
||
|
goto exit;
|
||
|
+ }
|
||
|
|
||
|
err = pci_request_region(dev, SMBBAR, i801_driver.name);
|
||
|
if (err) {
|
||
|
diff --git a/drivers/i2c/busses/i2c-isch.c b/drivers/i2c/busses/i2c-isch.c
|
||
|
index 9f6b8e0..dba6eb0 100644
|
||
|
--- a/drivers/i2c/busses/i2c-isch.c
|
||
|
+++ b/drivers/i2c/busses/i2c-isch.c
|
||
|
@@ -281,7 +281,7 @@ static int __devinit sch_probe(struct pci_dev *dev,
|
||
|
return -ENODEV;
|
||
|
}
|
||
|
if (acpi_check_region(sch_smba, SMBIOSIZE, sch_driver.name))
|
||
|
- return -EBUSY;
|
||
|
+ return -ENODEV;
|
||
|
if (!request_region(sch_smba, SMBIOSIZE, sch_driver.name)) {
|
||
|
dev_err(&dev->dev, "SMBus region 0x%x already in use!\n",
|
||
|
sch_smba);
|
||
|
diff --git a/drivers/i2c/busses/i2c-piix4.c b/drivers/i2c/busses/i2c-piix4.c
|
||
|
index 0249a7d..808e49e 100644
|
||
|
--- a/drivers/i2c/busses/i2c-piix4.c
|
||
|
+++ b/drivers/i2c/busses/i2c-piix4.c
|
||
|
@@ -168,7 +168,7 @@ static int __devinit piix4_setup(struct pci_dev *PIIX4_dev,
|
||
|
}
|
||
|
|
||
|
if (acpi_check_region(piix4_smba, SMBIOSIZE, piix4_driver.name))
|
||
|
- return -EBUSY;
|
||
|
+ return -ENODEV;
|
||
|
|
||
|
if (!request_region(piix4_smba, SMBIOSIZE, piix4_driver.name)) {
|
||
|
dev_err(&PIIX4_dev->dev, "SMBus region 0x%x already in use!\n",
|
||
|
@@ -259,7 +259,7 @@ static int __devinit piix4_setup_sb800(struct pci_dev *PIIX4_dev,
|
||
|
|
||
|
piix4_smba = ((smba_en_hi << 8) | smba_en_lo) & 0xffe0;
|
||
|
if (acpi_check_region(piix4_smba, SMBIOSIZE, piix4_driver.name))
|
||
|
- return -EBUSY;
|
||
|
+ return -ENODEV;
|
||
|
|
||
|
if (!request_region(piix4_smba, SMBIOSIZE, piix4_driver.name)) {
|
||
|
dev_err(&PIIX4_dev->dev, "SMBus region 0x%x already in use!\n",
|
||
|
diff --git a/drivers/i2c/busses/i2c-sis96x.c b/drivers/i2c/busses/i2c-sis96x.c
|
||
|
index 8295885..1649963 100644
|
||
|
--- a/drivers/i2c/busses/i2c-sis96x.c
|
||
|
+++ b/drivers/i2c/busses/i2c-sis96x.c
|
||
|
@@ -280,7 +280,7 @@ static int __devinit sis96x_probe(struct pci_dev *dev,
|
||
|
|
||
|
retval = acpi_check_resource_conflict(&dev->resource[SIS96x_BAR]);
|
||
|
if (retval)
|
||
|
- return retval;
|
||
|
+ return -ENODEV;
|
||
|
|
||
|
/* Everything is happy, let's grab the memory and set things up. */
|
||
|
if (!request_region(sis96x_smbus_base, SMB_IOSIZE,
|
||
|
diff --git a/drivers/i2c/busses/i2c-viapro.c b/drivers/i2c/busses/i2c-viapro.c
|
||
|
index 54d810a..e4b1543 100644
|
||
|
--- a/drivers/i2c/busses/i2c-viapro.c
|
||
|
+++ b/drivers/i2c/busses/i2c-viapro.c
|
||
|
@@ -365,7 +365,7 @@ static int __devinit vt596_probe(struct pci_dev *pdev,
|
||
|
found:
|
||
|
error = acpi_check_region(vt596_smba, 8, vt596_driver.name);
|
||
|
if (error)
|
||
|
- return error;
|
||
|
+ return -ENODEV;
|
||
|
|
||
|
if (!request_region(vt596_smba, 8, vt596_driver.name)) {
|
||
|
dev_err(&pdev->dev, "SMBus region 0x%x already in use!\n",
|
||
|
diff --git a/drivers/macintosh/therm_adt746x.c b/drivers/macintosh/therm_adt746x.c
|
||
|
index fde377c..556f0fe 100644
|
||
|
--- a/drivers/macintosh/therm_adt746x.c
|
||
|
+++ b/drivers/macintosh/therm_adt746x.c
|
||
|
@@ -124,6 +124,8 @@ read_reg(struct thermostat* th, int reg)
|
||
|
return data;
|
||
|
}
|
||
|
|
||
|
+static struct i2c_driver thermostat_driver;
|
||
|
+
|
||
|
static int
|
||
|
attach_thermostat(struct i2c_adapter *adapter)
|
||
|
{
|
||
|
@@ -148,7 +150,7 @@ attach_thermostat(struct i2c_adapter *adapter)
|
||
|
* Let i2c-core delete that device on driver removal.
|
||
|
* This is safe because i2c-core holds the core_lock mutex for us.
|
||
|
*/
|
||
|
- list_add_tail(&client->detected, &client->driver->clients);
|
||
|
+ list_add_tail(&client->detected, &thermostat_driver.clients);
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
diff --git a/drivers/macintosh/therm_pm72.c b/drivers/macintosh/therm_pm72.c
|
||
|
index a028598..ea32c7e 100644
|
||
|
--- a/drivers/macintosh/therm_pm72.c
|
||
|
+++ b/drivers/macintosh/therm_pm72.c
|
||
|
@@ -286,6 +286,8 @@ struct fcu_fan_table fcu_fans[] = {
|
||
|
},
|
||
|
};
|
||
|
|
||
|
+static struct i2c_driver therm_pm72_driver;
|
||
|
+
|
||
|
/*
|
||
|
* Utility function to create an i2c_client structure and
|
||
|
* attach it to one of u3 adapters
|
||
|
@@ -318,7 +320,7 @@ static struct i2c_client *attach_i2c_chip(int id, const char *name)
|
||
|
* Let i2c-core delete that device on driver removal.
|
||
|
* This is safe because i2c-core holds the core_lock mutex for us.
|
||
|
*/
|
||
|
- list_add_tail(&clt->detected, &clt->driver->clients);
|
||
|
+ list_add_tail(&clt->detected, &therm_pm72_driver.clients);
|
||
|
return clt;
|
||
|
}
|
||
|
|
||
|
diff --git a/drivers/macintosh/windfarm_lm75_sensor.c b/drivers/macintosh/windfarm_lm75_sensor.c
|
||
|
index 529886c..ed6426a 100644
|
||
|
--- a/drivers/macintosh/windfarm_lm75_sensor.c
|
||
|
+++ b/drivers/macintosh/windfarm_lm75_sensor.c
|
||
|
@@ -115,6 +115,8 @@ static int wf_lm75_probe(struct i2c_client *client,
|
||
|
return rc;
|
||
|
}
|
||
|
|
||
|
+static struct i2c_driver wf_lm75_driver;
|
||
|
+
|
||
|
static struct i2c_client *wf_lm75_create(struct i2c_adapter *adapter,
|
||
|
u8 addr, int ds1775,
|
||
|
const char *loc)
|
||
|
@@ -157,7 +159,7 @@ static struct i2c_client *wf_lm75_create(struct i2c_adapter *adapter,
|
||
|
* Let i2c-core delete that device on driver removal.
|
||
|
* This is safe because i2c-core holds the core_lock mutex for us.
|
||
|
*/
|
||
|
- list_add_tail(&client->detected, &client->driver->clients);
|
||
|
+ list_add_tail(&client->detected, &wf_lm75_driver.clients);
|
||
|
return client;
|
||
|
fail:
|
||
|
return NULL;
|
||
|
diff --git a/drivers/macintosh/windfarm_max6690_sensor.c b/drivers/macintosh/windfarm_max6690_sensor.c
|
||
|
index e2a55ec..a67b349 100644
|
||
|
--- a/drivers/macintosh/windfarm_max6690_sensor.c
|
||
|
+++ b/drivers/macintosh/windfarm_max6690_sensor.c
|
||
|
@@ -88,6 +88,8 @@ static int wf_max6690_probe(struct i2c_client *client,
|
||
|
return rc;
|
||
|
}
|
||
|
|
||
|
+static struct i2c_driver wf_max6690_driver;
|
||
|
+
|
||
|
static struct i2c_client *wf_max6690_create(struct i2c_adapter *adapter,
|
||
|
u8 addr, const char *loc)
|
||
|
{
|
||
|
@@ -119,7 +121,7 @@ static struct i2c_client *wf_max6690_create(struct i2c_adapter *adapter,
|
||
|
* Let i2c-core delete that device on driver removal.
|
||
|
* This is safe because i2c-core holds the core_lock mutex for us.
|
||
|
*/
|
||
|
- list_add_tail(&client->detected, &client->driver->clients);
|
||
|
+ list_add_tail(&client->detected, &wf_max6690_driver.clients);
|
||
|
return client;
|
||
|
|
||
|
fail:
|
||
|
diff --git a/drivers/macintosh/windfarm_smu_sat.c b/drivers/macintosh/windfarm_smu_sat.c
|
||
|
index 5da729e..e20330a 100644
|
||
|
--- a/drivers/macintosh/windfarm_smu_sat.c
|
||
|
+++ b/drivers/macintosh/windfarm_smu_sat.c
|
||
|
@@ -194,6 +194,8 @@ static struct wf_sensor_ops wf_sat_ops = {
|
||
|
.owner = THIS_MODULE,
|
||
|
};
|
||
|
|
||
|
+static struct i2c_driver wf_sat_driver;
|
||
|
+
|
||
|
static void wf_sat_create(struct i2c_adapter *adapter, struct device_node *dev)
|
||
|
{
|
||
|
struct i2c_board_info info;
|
||
|
@@ -222,7 +224,7 @@ static void wf_sat_create(struct i2c_adapter *adapter, struct device_node *dev)
|
||
|
* Let i2c-core delete that device on driver removal.
|
||
|
* This is safe because i2c-core holds the core_lock mutex for us.
|
||
|
*/
|
||
|
- list_add_tail(&client->detected, &client->driver->clients);
|
||
|
+ list_add_tail(&client->detected, &wf_sat_driver.clients);
|
||
|
}
|
||
|
|
||
|
static int wf_sat_probe(struct i2c_client *client,
|
||
|
diff --git a/drivers/md/dm-log-userspace-transfer.c b/drivers/md/dm-log-userspace-transfer.c
|
||
|
index ba0edad..54abf9e 100644
|
||
|
--- a/drivers/md/dm-log-userspace-transfer.c
|
||
|
+++ b/drivers/md/dm-log-userspace-transfer.c
|
||
|
@@ -129,11 +129,13 @@ static int fill_pkg(struct cn_msg *msg, struct dm_ulog_request *tfr)
|
||
|
* This is the connector callback that delivers data
|
||
|
* that was sent from userspace.
|
||
|
*/
|
||
|
-static void cn_ulog_callback(void *data)
|
||
|
+static void cn_ulog_callback(struct cn_msg *msg, struct netlink_skb_parms *nsp)
|
||
|
{
|
||
|
- struct cn_msg *msg = (struct cn_msg *)data;
|
||
|
struct dm_ulog_request *tfr = (struct dm_ulog_request *)(msg + 1);
|
||
|
|
||
|
+ if (!cap_raised(nsp->eff_cap, CAP_SYS_ADMIN))
|
||
|
+ return;
|
||
|
+
|
||
|
spin_lock(&receiving_list_lock);
|
||
|
if (msg->len == 0)
|
||
|
fill_pkg(msg, NULL);
|
||
|
diff --git a/drivers/net/e1000e/82571.c b/drivers/net/e1000e/82571.c
|
||
|
index b53b40b..d1e0563 100644
|
||
|
--- a/drivers/net/e1000e/82571.c
|
||
|
+++ b/drivers/net/e1000e/82571.c
|
||
|
@@ -1803,7 +1803,7 @@ struct e1000_info e1000_82574_info = {
|
||
|
| FLAG_HAS_AMT
|
||
|
| FLAG_HAS_CTRLEXT_ON_LOAD,
|
||
|
.pba = 20,
|
||
|
- .max_hw_frame_size = ETH_FRAME_LEN + ETH_FCS_LEN,
|
||
|
+ .max_hw_frame_size = DEFAULT_JUMBO,
|
||
|
.get_variants = e1000_get_variants_82571,
|
||
|
.mac_ops = &e82571_mac_ops,
|
||
|
.phy_ops = &e82_phy_ops_bm,
|
||
|
@@ -1820,7 +1820,7 @@ struct e1000_info e1000_82583_info = {
|
||
|
| FLAG_HAS_AMT
|
||
|
| FLAG_HAS_CTRLEXT_ON_LOAD,
|
||
|
.pba = 20,
|
||
|
- .max_hw_frame_size = DEFAULT_JUMBO,
|
||
|
+ .max_hw_frame_size = ETH_FRAME_LEN + ETH_FCS_LEN,
|
||
|
.get_variants = e1000_get_variants_82571,
|
||
|
.mac_ops = &e82571_mac_ops,
|
||
|
.phy_ops = &e82_phy_ops_bm,
|
||
|
diff --git a/drivers/net/wireless/iwlwifi/iwl-eeprom.c b/drivers/net/wireless/iwlwifi/iwl-eeprom.c
|
||
|
index e8c0e82..eabe48a 100644
|
||
|
--- a/drivers/net/wireless/iwlwifi/iwl-eeprom.c
|
||
|
+++ b/drivers/net/wireless/iwlwifi/iwl-eeprom.c
|
||
|
@@ -335,7 +335,6 @@ static int iwl_find_otp_image(struct iwl_priv *priv,
|
||
|
u16 *validblockaddr)
|
||
|
{
|
||
|
u16 next_link_addr = 0, link_value = 0, valid_addr;
|
||
|
- int ret = 0;
|
||
|
int usedblocks = 0;
|
||
|
|
||
|
/* set addressing mode to absolute to traverse the link list */
|
||
|
@@ -355,29 +354,29 @@ static int iwl_find_otp_image(struct iwl_priv *priv,
|
||
|
* check for more block on the link list
|
||
|
*/
|
||
|
valid_addr = next_link_addr;
|
||
|
- next_link_addr = link_value;
|
||
|
+ next_link_addr = link_value * sizeof(u16);
|
||
|
IWL_DEBUG_INFO(priv, "OTP blocks %d addr 0x%x\n",
|
||
|
usedblocks, next_link_addr);
|
||
|
if (iwl_read_otp_word(priv, next_link_addr, &link_value))
|
||
|
return -EINVAL;
|
||
|
if (!link_value) {
|
||
|
/*
|
||
|
- * reach the end of link list,
|
||
|
+ * reach the end of link list, return success and
|
||
|
* set address point to the starting address
|
||
|
* of the image
|
||
|
*/
|
||
|
- goto done;
|
||
|
+ *validblockaddr = valid_addr;
|
||
|
+ /* skip first 2 bytes (link list pointer) */
|
||
|
+ *validblockaddr += 2;
|
||
|
+ return 0;
|
||
|
}
|
||
|
/* more in the link list, continue */
|
||
|
usedblocks++;
|
||
|
- } while (usedblocks < priv->cfg->max_ll_items);
|
||
|
- /* OTP full, use last block */
|
||
|
- IWL_DEBUG_INFO(priv, "OTP is full, use last block\n");
|
||
|
-done:
|
||
|
- *validblockaddr = valid_addr;
|
||
|
- /* skip first 2 bytes (link list pointer) */
|
||
|
- *validblockaddr += 2;
|
||
|
- return ret;
|
||
|
+ } while (usedblocks <= priv->cfg->max_ll_items);
|
||
|
+
|
||
|
+ /* OTP has no valid blocks */
|
||
|
+ IWL_DEBUG_INFO(priv, "OTP has no valid blocks\n");
|
||
|
+ return -EINVAL;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
diff --git a/drivers/pci/dmar.c b/drivers/pci/dmar.c
|
||
|
index 7b287cb..380b60e 100644
|
||
|
--- a/drivers/pci/dmar.c
|
||
|
+++ b/drivers/pci/dmar.c
|
||
|
@@ -632,20 +632,31 @@ int alloc_iommu(struct dmar_drhd_unit *drhd)
|
||
|
iommu->cap = dmar_readq(iommu->reg + DMAR_CAP_REG);
|
||
|
iommu->ecap = dmar_readq(iommu->reg + DMAR_ECAP_REG);
|
||
|
|
||
|
+ if (iommu->cap == (uint64_t)-1 && iommu->ecap == (uint64_t)-1) {
|
||
|
+ /* Promote an attitude of violence to a BIOS engineer today */
|
||
|
+ WARN(1, "Your BIOS is broken; DMAR reported at address %llx returns all ones!\n"
|
||
|
+ "BIOS vendor: %s; Ver: %s; Product Version: %s\n",
|
||
|
+ drhd->reg_base_addr,
|
||
|
+ dmi_get_system_info(DMI_BIOS_VENDOR),
|
||
|
+ dmi_get_system_info(DMI_BIOS_VERSION),
|
||
|
+ dmi_get_system_info(DMI_PRODUCT_VERSION));
|
||
|
+ goto err_unmap;
|
||
|
+ }
|
||
|
+
|
||
|
#ifdef CONFIG_DMAR
|
||
|
agaw = iommu_calculate_agaw(iommu);
|
||
|
if (agaw < 0) {
|
||
|
printk(KERN_ERR
|
||
|
"Cannot get a valid agaw for iommu (seq_id = %d)\n",
|
||
|
iommu->seq_id);
|
||
|
- goto error;
|
||
|
+ goto err_unmap;
|
||
|
}
|
||
|
msagaw = iommu_calculate_max_sagaw(iommu);
|
||
|
if (msagaw < 0) {
|
||
|
printk(KERN_ERR
|
||
|
"Cannot get a valid max agaw for iommu (seq_id = %d)\n",
|
||
|
iommu->seq_id);
|
||
|
- goto error;
|
||
|
+ goto err_unmap;
|
||
|
}
|
||
|
#endif
|
||
|
iommu->agaw = agaw;
|
||
|
@@ -665,7 +676,7 @@ int alloc_iommu(struct dmar_drhd_unit *drhd)
|
||
|
}
|
||
|
|
||
|
ver = readl(iommu->reg + DMAR_VER_REG);
|
||
|
- pr_debug("IOMMU %llx: ver %d:%d cap %llx ecap %llx\n",
|
||
|
+ pr_info("IOMMU %llx: ver %d:%d cap %llx ecap %llx\n",
|
||
|
(unsigned long long)drhd->reg_base_addr,
|
||
|
DMAR_VER_MAJOR(ver), DMAR_VER_MINOR(ver),
|
||
|
(unsigned long long)iommu->cap,
|
||
|
@@ -675,7 +686,10 @@ int alloc_iommu(struct dmar_drhd_unit *drhd)
|
||
|
|
||
|
drhd->iommu = iommu;
|
||
|
return 0;
|
||
|
-error:
|
||
|
+
|
||
|
+ err_unmap:
|
||
|
+ iounmap(iommu->reg);
|
||
|
+ error:
|
||
|
kfree(iommu);
|
||
|
return -1;
|
||
|
}
|
||
|
diff --git a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c
|
||
|
index 2de5f3a..69397bb 100644
|
||
|
--- a/drivers/scsi/scsi.c
|
||
|
+++ b/drivers/scsi/scsi.c
|
||
|
@@ -241,10 +241,7 @@ scsi_host_alloc_command(struct Scsi_Host *shost, gfp_t gfp_mask)
|
||
|
*/
|
||
|
struct scsi_cmnd *__scsi_get_command(struct Scsi_Host *shost, gfp_t gfp_mask)
|
||
|
{
|
||
|
- struct scsi_cmnd *cmd;
|
||
|
- unsigned char *buf;
|
||
|
-
|
||
|
- cmd = scsi_host_alloc_command(shost, gfp_mask);
|
||
|
+ struct scsi_cmnd *cmd = scsi_host_alloc_command(shost, gfp_mask);
|
||
|
|
||
|
if (unlikely(!cmd)) {
|
||
|
unsigned long flags;
|
||
|
@@ -258,9 +255,15 @@ struct scsi_cmnd *__scsi_get_command(struct Scsi_Host *shost, gfp_t gfp_mask)
|
||
|
spin_unlock_irqrestore(&shost->free_list_lock, flags);
|
||
|
|
||
|
if (cmd) {
|
||
|
+ void *buf, *prot;
|
||
|
+
|
||
|
buf = cmd->sense_buffer;
|
||
|
+ prot = cmd->prot_sdb;
|
||
|
+
|
||
|
memset(cmd, 0, sizeof(*cmd));
|
||
|
+
|
||
|
cmd->sense_buffer = buf;
|
||
|
+ cmd->prot_sdb = prot;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c
|
||
|
index a168935..c253e9c 100644
|
||
|
--- a/drivers/scsi/scsi_error.c
|
||
|
+++ b/drivers/scsi/scsi_error.c
|
||
|
@@ -721,6 +721,9 @@ static int scsi_send_eh_cmnd(struct scsi_cmnd *scmd, unsigned char *cmnd,
|
||
|
case NEEDS_RETRY:
|
||
|
case FAILED:
|
||
|
break;
|
||
|
+ case ADD_TO_MLQUEUE:
|
||
|
+ rtn = NEEDS_RETRY;
|
||
|
+ break;
|
||
|
default:
|
||
|
rtn = FAILED;
|
||
|
break;
|
||
|
diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c
|
||
|
index 4968c4c..dc0e3d4 100644
|
||
|
--- a/drivers/scsi/sg.c
|
||
|
+++ b/drivers/scsi/sg.c
|
||
|
@@ -1708,11 +1708,6 @@ static int sg_finish_rem_req(Sg_request * srp)
|
||
|
Sg_scatter_hold *req_schp = &srp->data;
|
||
|
|
||
|
SCSI_LOG_TIMEOUT(4, printk("sg_finish_rem_req: res_used=%d\n", (int) srp->res_used));
|
||
|
- if (srp->res_used)
|
||
|
- sg_unlink_reserve(sfp, srp);
|
||
|
- else
|
||
|
- sg_remove_scat(req_schp);
|
||
|
-
|
||
|
if (srp->rq) {
|
||
|
if (srp->bio)
|
||
|
ret = blk_rq_unmap_user(srp->bio);
|
||
|
@@ -1720,6 +1715,11 @@ static int sg_finish_rem_req(Sg_request * srp)
|
||
|
blk_put_request(srp->rq);
|
||
|
}
|
||
|
|
||
|
+ if (srp->res_used)
|
||
|
+ sg_unlink_reserve(sfp, srp);
|
||
|
+ else
|
||
|
+ sg_remove_scat(req_schp);
|
||
|
+
|
||
|
sg_remove_request(sfp, srp);
|
||
|
|
||
|
return ret;
|
||
|
diff --git a/drivers/staging/dst/dcore.c b/drivers/staging/dst/dcore.c
|
||
|
index fad25b7..5546898 100644
|
||
|
--- a/drivers/staging/dst/dcore.c
|
||
|
+++ b/drivers/staging/dst/dcore.c
|
||
|
@@ -846,15 +846,19 @@ static dst_command_func dst_commands[] = {
|
||
|
/*
|
||
|
* Configuration parser.
|
||
|
*/
|
||
|
-static void cn_dst_callback(void *data)
|
||
|
+static void cn_dst_callback(struct cn_msg *msg, struct netlink_skb_parms *nsp)
|
||
|
{
|
||
|
struct dst_ctl *ctl;
|
||
|
- struct cn_msg *msg = data;
|
||
|
int err;
|
||
|
struct dst_ctl_ack ack;
|
||
|
struct dst_node *n = NULL, *tmp;
|
||
|
unsigned int hash;
|
||
|
|
||
|
+ if (!cap_raised(nsp->eff_cap, CAP_SYS_ADMIN)) {
|
||
|
+ err = -EPERM;
|
||
|
+ goto out;
|
||
|
+ }
|
||
|
+
|
||
|
if (msg->len < sizeof(struct dst_ctl)) {
|
||
|
err = -EBADMSG;
|
||
|
goto out;
|
||
|
diff --git a/drivers/staging/pohmelfs/config.c b/drivers/staging/pohmelfs/config.c
|
||
|
index a6eaa42..d8ec47a 100644
|
||
|
--- a/drivers/staging/pohmelfs/config.c
|
||
|
+++ b/drivers/staging/pohmelfs/config.c
|
||
|
@@ -446,11 +446,13 @@ out_unlock:
|
||
|
return err;
|
||
|
}
|
||
|
|
||
|
-static void pohmelfs_cn_callback(void *data)
|
||
|
+static void pohmelfs_cn_callback(struct cn_msg *msg, struct netlink_skb_parms *nsp)
|
||
|
{
|
||
|
- struct cn_msg *msg = data;
|
||
|
int err;
|
||
|
|
||
|
+ if (!cap_raised(nsp->eff_cap, CAP_SYS_ADMIN))
|
||
|
+ return;
|
||
|
+
|
||
|
switch (msg->flags) {
|
||
|
case POHMELFS_FLAGS_ADD:
|
||
|
case POHMELFS_FLAGS_DEL:
|
||
|
diff --git a/drivers/staging/rt2860/common/cmm_data_2860.c b/drivers/staging/rt2860/common/cmm_data_2860.c
|
||
|
index fb17355..857ff45 100644
|
||
|
--- a/drivers/staging/rt2860/common/cmm_data_2860.c
|
||
|
+++ b/drivers/staging/rt2860/common/cmm_data_2860.c
|
||
|
@@ -363,6 +363,8 @@ int RtmpPCIMgmtKickOut(
|
||
|
ULONG SwIdx = pAd->MgmtRing.TxCpuIdx;
|
||
|
|
||
|
pTxD = (PTXD_STRUC) pAd->MgmtRing.Cell[SwIdx].AllocVa;
|
||
|
+ if (!pTxD)
|
||
|
+ return 0;
|
||
|
|
||
|
pAd->MgmtRing.Cell[SwIdx].pNdisPacket = pPacket;
|
||
|
pAd->MgmtRing.Cell[SwIdx].pNextNdisPacket = NULL;
|
||
|
diff --git a/drivers/usb/serial/cp210x.c b/drivers/usb/serial/cp210x.c
|
||
|
index b5275c4..a69457f 100644
|
||
|
--- a/drivers/usb/serial/cp210x.c
|
||
|
+++ b/drivers/usb/serial/cp210x.c
|
||
|
@@ -114,6 +114,7 @@ static struct usb_device_id id_table [] = {
|
||
|
{ USB_DEVICE(0x166A, 0x0303) }, /* Clipsal 5500PCU C-Bus USB interface */
|
||
|
{ USB_DEVICE(0x16D6, 0x0001) }, /* Jablotron serial interface */
|
||
|
{ USB_DEVICE(0x18EF, 0xE00F) }, /* ELV USB-I2C-Interface */
|
||
|
+ { USB_DEVICE(0x413C, 0x9500) }, /* DW700 GPS USB interface */
|
||
|
{ } /* Terminating Entry */
|
||
|
};
|
||
|
|
||
|
diff --git a/drivers/usb/serial/digi_acceleport.c b/drivers/usb/serial/digi_acceleport.c
|
||
|
index f480809..9bd82b4 100644
|
||
|
--- a/drivers/usb/serial/digi_acceleport.c
|
||
|
+++ b/drivers/usb/serial/digi_acceleport.c
|
||
|
@@ -899,16 +899,16 @@ static void digi_rx_unthrottle(struct tty_struct *tty)
|
||
|
|
||
|
spin_lock_irqsave(&priv->dp_port_lock, flags);
|
||
|
|
||
|
- /* turn throttle off */
|
||
|
- priv->dp_throttled = 0;
|
||
|
- priv->dp_throttle_restart = 0;
|
||
|
-
|
||
|
/* restart read chain */
|
||
|
if (priv->dp_throttle_restart) {
|
||
|
port->read_urb->dev = port->serial->dev;
|
||
|
ret = usb_submit_urb(port->read_urb, GFP_ATOMIC);
|
||
|
}
|
||
|
|
||
|
+ /* turn throttle off */
|
||
|
+ priv->dp_throttled = 0;
|
||
|
+ priv->dp_throttle_restart = 0;
|
||
|
+
|
||
|
spin_unlock_irqrestore(&priv->dp_port_lock, flags);
|
||
|
|
||
|
if (ret)
|
||
|
diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c
|
||
|
index 0cc78f9..048b563 100644
|
||
|
--- a/drivers/usb/serial/ftdi_sio.c
|
||
|
+++ b/drivers/usb/serial/ftdi_sio.c
|
||
|
@@ -76,13 +76,7 @@ struct ftdi_private {
|
||
|
unsigned long last_dtr_rts; /* saved modem control outputs */
|
||
|
wait_queue_head_t delta_msr_wait; /* Used for TIOCMIWAIT */
|
||
|
char prev_status, diff_status; /* Used for TIOCMIWAIT */
|
||
|
- __u8 rx_flags; /* receive state flags (throttling) */
|
||
|
- spinlock_t rx_lock; /* spinlock for receive state */
|
||
|
- struct delayed_work rx_work;
|
||
|
struct usb_serial_port *port;
|
||
|
- int rx_processed;
|
||
|
- unsigned long rx_bytes;
|
||
|
-
|
||
|
__u16 interface; /* FT2232C, FT2232H or FT4232H port interface
|
||
|
(0 for FT232/245) */
|
||
|
|
||
|
@@ -737,10 +731,6 @@ static const char *ftdi_chip_name[] = {
|
||
|
/* Constants for read urb and write urb */
|
||
|
#define BUFSZ 512
|
||
|
|
||
|
-/* rx_flags */
|
||
|
-#define THROTTLED 0x01
|
||
|
-#define ACTUALLY_THROTTLED 0x02
|
||
|
-
|
||
|
/* Used for TIOCMIWAIT */
|
||
|
#define FTDI_STATUS_B0_MASK (FTDI_RS0_CTS | FTDI_RS0_DSR | FTDI_RS0_RI | FTDI_RS0_RLSD)
|
||
|
#define FTDI_STATUS_B1_MASK (FTDI_RS_BI)
|
||
|
@@ -764,7 +754,7 @@ static int ftdi_write_room(struct tty_struct *tty);
|
||
|
static int ftdi_chars_in_buffer(struct tty_struct *tty);
|
||
|
static void ftdi_write_bulk_callback(struct urb *urb);
|
||
|
static void ftdi_read_bulk_callback(struct urb *urb);
|
||
|
-static void ftdi_process_read(struct work_struct *work);
|
||
|
+static void ftdi_process_read(struct usb_serial_port *port);
|
||
|
static void ftdi_set_termios(struct tty_struct *tty,
|
||
|
struct usb_serial_port *port, struct ktermios *old);
|
||
|
static int ftdi_tiocmget(struct tty_struct *tty, struct file *file);
|
||
|
@@ -1235,7 +1225,6 @@ static int set_serial_info(struct tty_struct *tty,
|
||
|
(new_serial.flags & ASYNC_FLAGS));
|
||
|
priv->custom_divisor = new_serial.custom_divisor;
|
||
|
|
||
|
- tty->low_latency = (priv->flags & ASYNC_LOW_LATENCY) ? 1 : 0;
|
||
|
write_latency_timer(port);
|
||
|
|
||
|
check_and_exit:
|
||
|
@@ -1528,7 +1517,6 @@ static int ftdi_sio_port_probe(struct usb_serial_port *port)
|
||
|
}
|
||
|
|
||
|
kref_init(&priv->kref);
|
||
|
- spin_lock_init(&priv->rx_lock);
|
||
|
spin_lock_init(&priv->tx_lock);
|
||
|
init_waitqueue_head(&priv->delta_msr_wait);
|
||
|
/* This will push the characters through immediately rather
|
||
|
@@ -1550,7 +1538,6 @@ static int ftdi_sio_port_probe(struct usb_serial_port *port)
|
||
|
port->read_urb->transfer_buffer_length = BUFSZ;
|
||
|
}
|
||
|
|
||
|
- INIT_DELAYED_WORK(&priv->rx_work, ftdi_process_read);
|
||
|
priv->port = port;
|
||
|
|
||
|
/* Free port's existing write urb and transfer buffer. */
|
||
|
@@ -1687,6 +1674,26 @@ static int ftdi_sio_port_remove(struct usb_serial_port *port)
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
+static int ftdi_submit_read_urb(struct usb_serial_port *port, gfp_t mem_flags)
|
||
|
+{
|
||
|
+ struct urb *urb = port->read_urb;
|
||
|
+ struct usb_serial *serial = port->serial;
|
||
|
+ int result;
|
||
|
+
|
||
|
+ usb_fill_bulk_urb(urb, serial->dev,
|
||
|
+ usb_rcvbulkpipe(serial->dev,
|
||
|
+ port->bulk_in_endpointAddress),
|
||
|
+ urb->transfer_buffer,
|
||
|
+ urb->transfer_buffer_length,
|
||
|
+ ftdi_read_bulk_callback, port);
|
||
|
+ result = usb_submit_urb(urb, mem_flags);
|
||
|
+ if (result)
|
||
|
+ dev_err(&port->dev,
|
||
|
+ "%s - failed submitting read urb, error %d\n",
|
||
|
+ __func__, result);
|
||
|
+ return result;
|
||
|
+}
|
||
|
+
|
||
|
static int ftdi_open(struct tty_struct *tty,
|
||
|
struct usb_serial_port *port, struct file *filp)
|
||
|
{ /* ftdi_open */
|
||
|
@@ -1702,12 +1709,6 @@ static int ftdi_open(struct tty_struct *tty,
|
||
|
spin_lock_irqsave(&priv->tx_lock, flags);
|
||
|
priv->tx_bytes = 0;
|
||
|
spin_unlock_irqrestore(&priv->tx_lock, flags);
|
||
|
- spin_lock_irqsave(&priv->rx_lock, flags);
|
||
|
- priv->rx_bytes = 0;
|
||
|
- spin_unlock_irqrestore(&priv->rx_lock, flags);
|
||
|
-
|
||
|
- if (tty)
|
||
|
- tty->low_latency = (priv->flags & ASYNC_LOW_LATENCY) ? 1 : 0;
|
||
|
|
||
|
write_latency_timer(port);
|
||
|
|
||
|
@@ -1727,23 +1728,14 @@ static int ftdi_open(struct tty_struct *tty,
|
||
|
ftdi_set_termios(tty, port, tty->termios);
|
||
|
|
||
|
/* Not throttled */
|
||
|
- spin_lock_irqsave(&priv->rx_lock, flags);
|
||
|
- priv->rx_flags &= ~(THROTTLED | ACTUALLY_THROTTLED);
|
||
|
- spin_unlock_irqrestore(&priv->rx_lock, flags);
|
||
|
+ spin_lock_irqsave(&port->lock, flags);
|
||
|
+ port->throttled = 0;
|
||
|
+ port->throttle_req = 0;
|
||
|
+ spin_unlock_irqrestore(&port->lock, flags);
|
||
|
|
||
|
/* Start reading from the device */
|
||
|
- priv->rx_processed = 0;
|
||
|
- usb_fill_bulk_urb(port->read_urb, dev,
|
||
|
- usb_rcvbulkpipe(dev, port->bulk_in_endpointAddress),
|
||
|
- port->read_urb->transfer_buffer,
|
||
|
- port->read_urb->transfer_buffer_length,
|
||
|
- ftdi_read_bulk_callback, port);
|
||
|
- result = usb_submit_urb(port->read_urb, GFP_KERNEL);
|
||
|
- if (result)
|
||
|
- dev_err(&port->dev,
|
||
|
- "%s - failed submitting read urb, error %d\n",
|
||
|
- __func__, result);
|
||
|
- else
|
||
|
+ result = ftdi_submit_read_urb(port, GFP_KERNEL);
|
||
|
+ if (!result)
|
||
|
kref_get(&priv->kref);
|
||
|
|
||
|
return result;
|
||
|
@@ -1789,10 +1781,6 @@ static void ftdi_close(struct usb_serial_port *port)
|
||
|
|
||
|
dbg("%s", __func__);
|
||
|
|
||
|
-
|
||
|
- /* cancel any scheduled reading */
|
||
|
- cancel_delayed_work_sync(&priv->rx_work);
|
||
|
-
|
||
|
/* shutdown our bulk read */
|
||
|
usb_kill_urb(port->read_urb);
|
||
|
kref_put(&priv->kref, ftdi_sio_priv_release);
|
||
|
@@ -2015,271 +2003,121 @@ static int ftdi_chars_in_buffer(struct tty_struct *tty)
|
||
|
return buffered;
|
||
|
}
|
||
|
|
||
|
-static void ftdi_read_bulk_callback(struct urb *urb)
|
||
|
+static int ftdi_process_packet(struct tty_struct *tty,
|
||
|
+ struct usb_serial_port *port, struct ftdi_private *priv,
|
||
|
+ char *packet, int len)
|
||
|
{
|
||
|
- struct usb_serial_port *port = urb->context;
|
||
|
- struct tty_struct *tty;
|
||
|
- struct ftdi_private *priv;
|
||
|
- unsigned long countread;
|
||
|
- unsigned long flags;
|
||
|
- int status = urb->status;
|
||
|
-
|
||
|
- if (urb->number_of_packets > 0) {
|
||
|
- dev_err(&port->dev, "%s transfer_buffer_length %d "
|
||
|
- "actual_length %d number of packets %d\n", __func__,
|
||
|
- urb->transfer_buffer_length,
|
||
|
- urb->actual_length, urb->number_of_packets);
|
||
|
- dev_err(&port->dev, "%s transfer_flags %x\n", __func__,
|
||
|
- urb->transfer_flags);
|
||
|
- }
|
||
|
+ int i;
|
||
|
+ char status;
|
||
|
+ char flag;
|
||
|
+ char *ch;
|
||
|
|
||
|
dbg("%s - port %d", __func__, port->number);
|
||
|
|
||
|
- if (port->port.count <= 0)
|
||
|
- return;
|
||
|
-
|
||
|
- tty = tty_port_tty_get(&port->port);
|
||
|
- if (!tty) {
|
||
|
- dbg("%s - bad tty pointer - exiting", __func__);
|
||
|
- return;
|
||
|
+ if (len < 2) {
|
||
|
+ dbg("malformed packet");
|
||
|
+ return 0;
|
||
|
}
|
||
|
|
||
|
- priv = usb_get_serial_port_data(port);
|
||
|
- if (!priv) {
|
||
|
- dbg("%s - bad port private data pointer - exiting", __func__);
|
||
|
- goto out;
|
||
|
+ /* Compare new line status to the old one, signal if different/
|
||
|
+ N.B. packet may be processed more than once, but differences
|
||
|
+ are only processed once. */
|
||
|
+ status = packet[0] & FTDI_STATUS_B0_MASK;
|
||
|
+ if (status != priv->prev_status) {
|
||
|
+ priv->diff_status |= status ^ priv->prev_status;
|
||
|
+ wake_up_interruptible(&priv->delta_msr_wait);
|
||
|
+ priv->prev_status = status;
|
||
|
}
|
||
|
|
||
|
- if (urb != port->read_urb)
|
||
|
- dev_err(&port->dev, "%s - Not my urb!\n", __func__);
|
||
|
-
|
||
|
- if (status) {
|
||
|
- /* This will happen at close every time so it is a dbg not an
|
||
|
- err */
|
||
|
- dbg("(this is ok on close) nonzero read bulk status received: %d", status);
|
||
|
- goto out;
|
||
|
+ /*
|
||
|
+ * Although the device uses a bitmask and hence can have multiple
|
||
|
+ * errors on a packet - the order here sets the priority the error is
|
||
|
+ * returned to the tty layer.
|
||
|
+ */
|
||
|
+ flag = TTY_NORMAL;
|
||
|
+ if (packet[1] & FTDI_RS_OE) {
|
||
|
+ flag = TTY_OVERRUN;
|
||
|
+ dbg("OVERRRUN error");
|
||
|
+ }
|
||
|
+ if (packet[1] & FTDI_RS_BI) {
|
||
|
+ flag = TTY_BREAK;
|
||
|
+ dbg("BREAK received");
|
||
|
+ usb_serial_handle_break(port);
|
||
|
+ }
|
||
|
+ if (packet[1] & FTDI_RS_PE) {
|
||
|
+ flag = TTY_PARITY;
|
||
|
+ dbg("PARITY error");
|
||
|
+ }
|
||
|
+ if (packet[1] & FTDI_RS_FE) {
|
||
|
+ flag = TTY_FRAME;
|
||
|
+ dbg("FRAMING error");
|
||
|
}
|
||
|
|
||
|
- /* count data bytes, but not status bytes */
|
||
|
- countread = urb->actual_length;
|
||
|
- countread -= 2 * DIV_ROUND_UP(countread, priv->max_packet_size);
|
||
|
- spin_lock_irqsave(&priv->rx_lock, flags);
|
||
|
- priv->rx_bytes += countread;
|
||
|
- spin_unlock_irqrestore(&priv->rx_lock, flags);
|
||
|
-
|
||
|
- ftdi_process_read(&priv->rx_work.work);
|
||
|
-out:
|
||
|
- tty_kref_put(tty);
|
||
|
-} /* ftdi_read_bulk_callback */
|
||
|
-
|
||
|
+ len -= 2;
|
||
|
+ if (!len)
|
||
|
+ return 0; /* status only */
|
||
|
+ ch = packet + 2;
|
||
|
+
|
||
|
+ if (!(port->console && port->sysrq) && flag == TTY_NORMAL)
|
||
|
+ tty_insert_flip_string(tty, ch, len);
|
||
|
+ else {
|
||
|
+ for (i = 0; i < len; i++, ch++) {
|
||
|
+ if (!usb_serial_handle_sysrq_char(tty, port, *ch))
|
||
|
+ tty_insert_flip_char(tty, *ch, flag);
|
||
|
+ }
|
||
|
+ }
|
||
|
+ return len;
|
||
|
+}
|
||
|
|
||
|
-static void ftdi_process_read(struct work_struct *work)
|
||
|
-{ /* ftdi_process_read */
|
||
|
- struct ftdi_private *priv =
|
||
|
- container_of(work, struct ftdi_private, rx_work.work);
|
||
|
- struct usb_serial_port *port = priv->port;
|
||
|
- struct urb *urb;
|
||
|
+static void ftdi_process_read(struct usb_serial_port *port)
|
||
|
+{
|
||
|
+ struct urb *urb = port->read_urb;
|
||
|
struct tty_struct *tty;
|
||
|
- char error_flag;
|
||
|
- unsigned char *data;
|
||
|
-
|
||
|
+ struct ftdi_private *priv = usb_get_serial_port_data(port);
|
||
|
+ char *data = (char *)urb->transfer_buffer;
|
||
|
int i;
|
||
|
- int result;
|
||
|
- int need_flip;
|
||
|
- int packet_offset;
|
||
|
- unsigned long flags;
|
||
|
-
|
||
|
- dbg("%s - port %d", __func__, port->number);
|
||
|
-
|
||
|
- if (port->port.count <= 0)
|
||
|
- return;
|
||
|
+ int len;
|
||
|
+ int count = 0;
|
||
|
|
||
|
tty = tty_port_tty_get(&port->port);
|
||
|
- if (!tty) {
|
||
|
- dbg("%s - bad tty pointer - exiting", __func__);
|
||
|
+ if (!tty)
|
||
|
return;
|
||
|
- }
|
||
|
-
|
||
|
- priv = usb_get_serial_port_data(port);
|
||
|
- if (!priv) {
|
||
|
- dbg("%s - bad port private data pointer - exiting", __func__);
|
||
|
- goto out;
|
||
|
- }
|
||
|
-
|
||
|
- urb = port->read_urb;
|
||
|
- if (!urb) {
|
||
|
- dbg("%s - bad read_urb pointer - exiting", __func__);
|
||
|
- goto out;
|
||
|
- }
|
||
|
-
|
||
|
- data = urb->transfer_buffer;
|
||
|
|
||
|
- if (priv->rx_processed) {
|
||
|
- dbg("%s - already processed: %d bytes, %d remain", __func__,
|
||
|
- priv->rx_processed,
|
||
|
- urb->actual_length - priv->rx_processed);
|
||
|
- } else {
|
||
|
- /* The first two bytes of every read packet are status */
|
||
|
- if (urb->actual_length > 2)
|
||
|
- usb_serial_debug_data(debug, &port->dev, __func__,
|
||
|
- urb->actual_length, data);
|
||
|
- else
|
||
|
- dbg("Status only: %03oo %03oo", data[0], data[1]);
|
||
|
+ for (i = 0; i < urb->actual_length; i += priv->max_packet_size) {
|
||
|
+ len = min_t(int, urb->actual_length - i, priv->max_packet_size);
|
||
|
+ count += ftdi_process_packet(tty, port, priv, &data[i], len);
|
||
|
}
|
||
|
|
||
|
-
|
||
|
- /* TO DO -- check for hung up line and handle appropriately: */
|
||
|
- /* send hangup */
|
||
|
- /* See acm.c - you do a tty_hangup - eg tty_hangup(tty) */
|
||
|
- /* if CD is dropped and the line is not CLOCAL then we should hangup */
|
||
|
-
|
||
|
- need_flip = 0;
|
||
|
- for (packet_offset = priv->rx_processed;
|
||
|
- packet_offset < urb->actual_length; packet_offset += priv->max_packet_size) {
|
||
|
- int length;
|
||
|
-
|
||
|
- /* Compare new line status to the old one, signal if different/
|
||
|
- N.B. packet may be processed more than once, but differences
|
||
|
- are only processed once. */
|
||
|
- char new_status = data[packet_offset + 0] &
|
||
|
- FTDI_STATUS_B0_MASK;
|
||
|
- if (new_status != priv->prev_status) {
|
||
|
- priv->diff_status |=
|
||
|
- new_status ^ priv->prev_status;
|
||
|
- wake_up_interruptible(&priv->delta_msr_wait);
|
||
|
- priv->prev_status = new_status;
|
||
|
- }
|
||
|
-
|
||
|
- length = min_t(u32, priv->max_packet_size, urb->actual_length-packet_offset)-2;
|
||
|
- if (length < 0) {
|
||
|
- dev_err(&port->dev, "%s - bad packet length: %d\n",
|
||
|
- __func__, length+2);
|
||
|
- length = 0;
|
||
|
- }
|
||
|
-
|
||
|
- if (priv->rx_flags & THROTTLED) {
|
||
|
- dbg("%s - throttled", __func__);
|
||
|
- break;
|
||
|
- }
|
||
|
- if (tty_buffer_request_room(tty, length) < length) {
|
||
|
- /* break out & wait for throttling/unthrottling to
|
||
|
- happen */
|
||
|
- dbg("%s - receive room low", __func__);
|
||
|
- break;
|
||
|
- }
|
||
|
-
|
||
|
- /* Handle errors and break */
|
||
|
- error_flag = TTY_NORMAL;
|
||
|
- /* Although the device uses a bitmask and hence can have
|
||
|
- multiple errors on a packet - the order here sets the
|
||
|
- priority the error is returned to the tty layer */
|
||
|
-
|
||
|
- if (data[packet_offset+1] & FTDI_RS_OE) {
|
||
|
- error_flag = TTY_OVERRUN;
|
||
|
- dbg("OVERRRUN error");
|
||
|
- }
|
||
|
- if (data[packet_offset+1] & FTDI_RS_BI) {
|
||
|
- error_flag = TTY_BREAK;
|
||
|
- dbg("BREAK received");
|
||
|
- usb_serial_handle_break(port);
|
||
|
- }
|
||
|
- if (data[packet_offset+1] & FTDI_RS_PE) {
|
||
|
- error_flag = TTY_PARITY;
|
||
|
- dbg("PARITY error");
|
||
|
- }
|
||
|
- if (data[packet_offset+1] & FTDI_RS_FE) {
|
||
|
- error_flag = TTY_FRAME;
|
||
|
- dbg("FRAMING error");
|
||
|
- }
|
||
|
- if (length > 0) {
|
||
|
- for (i = 2; i < length+2; i++) {
|
||
|
- /* Note that the error flag is duplicated for
|
||
|
- every character received since we don't know
|
||
|
- which character it applied to */
|
||
|
- if (!usb_serial_handle_sysrq_char(tty, port,
|
||
|
- data[packet_offset + i]))
|
||
|
- tty_insert_flip_char(tty,
|
||
|
- data[packet_offset + i],
|
||
|
- error_flag);
|
||
|
- }
|
||
|
- need_flip = 1;
|
||
|
- }
|
||
|
-
|
||
|
-#ifdef NOT_CORRECT_BUT_KEEPING_IT_FOR_NOW
|
||
|
- /* if a parity error is detected you get status packets forever
|
||
|
- until a character is sent without a parity error.
|
||
|
- This doesn't work well since the application receives a
|
||
|
- never ending stream of bad data - even though new data
|
||
|
- hasn't been sent. Therefore I (bill) have taken this out.
|
||
|
- However - this might make sense for framing errors and so on
|
||
|
- so I am leaving the code in for now.
|
||
|
- */
|
||
|
- else {
|
||
|
- if (error_flag != TTY_NORMAL) {
|
||
|
- dbg("error_flag is not normal");
|
||
|
- /* In this case it is just status - if that is
|
||
|
- an error send a bad character */
|
||
|
- if (tty->flip.count >= TTY_FLIPBUF_SIZE)
|
||
|
- tty_flip_buffer_push(tty);
|
||
|
- tty_insert_flip_char(tty, 0xff, error_flag);
|
||
|
- need_flip = 1;
|
||
|
- }
|
||
|
- }
|
||
|
-#endif
|
||
|
- } /* "for(packet_offset=0..." */
|
||
|
-
|
||
|
- /* Low latency */
|
||
|
- if (need_flip)
|
||
|
+ if (count)
|
||
|
tty_flip_buffer_push(tty);
|
||
|
+ tty_kref_put(tty);
|
||
|
+}
|
||
|
|
||
|
- if (packet_offset < urb->actual_length) {
|
||
|
- /* not completely processed - record progress */
|
||
|
- priv->rx_processed = packet_offset;
|
||
|
- dbg("%s - incomplete, %d bytes processed, %d remain",
|
||
|
- __func__, packet_offset,
|
||
|
- urb->actual_length - packet_offset);
|
||
|
- /* check if we were throttled while processing */
|
||
|
- spin_lock_irqsave(&priv->rx_lock, flags);
|
||
|
- if (priv->rx_flags & THROTTLED) {
|
||
|
- priv->rx_flags |= ACTUALLY_THROTTLED;
|
||
|
- spin_unlock_irqrestore(&priv->rx_lock, flags);
|
||
|
- dbg("%s - deferring remainder until unthrottled",
|
||
|
- __func__);
|
||
|
- goto out;
|
||
|
- }
|
||
|
- spin_unlock_irqrestore(&priv->rx_lock, flags);
|
||
|
- /* if the port is closed stop trying to read */
|
||
|
- if (port->port.count > 0)
|
||
|
- /* delay processing of remainder */
|
||
|
- schedule_delayed_work(&priv->rx_work, 1);
|
||
|
- else
|
||
|
- dbg("%s - port is closed", __func__);
|
||
|
- goto out;
|
||
|
- }
|
||
|
-
|
||
|
- /* urb is completely processed */
|
||
|
- priv->rx_processed = 0;
|
||
|
+static void ftdi_read_bulk_callback(struct urb *urb)
|
||
|
+{
|
||
|
+ struct usb_serial_port *port = urb->context;
|
||
|
+ unsigned long flags;
|
||
|
|
||
|
- /* if the port is closed stop trying to read */
|
||
|
- if (port->port.count > 0) {
|
||
|
- /* Continue trying to always read */
|
||
|
- usb_fill_bulk_urb(port->read_urb, port->serial->dev,
|
||
|
- usb_rcvbulkpipe(port->serial->dev,
|
||
|
- port->bulk_in_endpointAddress),
|
||
|
- port->read_urb->transfer_buffer,
|
||
|
- port->read_urb->transfer_buffer_length,
|
||
|
- ftdi_read_bulk_callback, port);
|
||
|
+ dbg("%s - port %d", __func__, port->number);
|
||
|
|
||
|
- result = usb_submit_urb(port->read_urb, GFP_ATOMIC);
|
||
|
- if (result)
|
||
|
- dev_err(&port->dev,
|
||
|
- "%s - failed resubmitting read urb, error %d\n",
|
||
|
- __func__, result);
|
||
|
+ if (urb->status) {
|
||
|
+ dbg("%s - nonzero read bulk status received: %d",
|
||
|
+ __func__, urb->status);
|
||
|
+ return;
|
||
|
}
|
||
|
-out:
|
||
|
- tty_kref_put(tty);
|
||
|
-} /* ftdi_process_read */
|
||
|
|
||
|
+ usb_serial_debug_data(debug, &port->dev, __func__,
|
||
|
+ urb->actual_length, urb->transfer_buffer);
|
||
|
+ ftdi_process_read(port);
|
||
|
+
|
||
|
+ spin_lock_irqsave(&port->lock, flags);
|
||
|
+ port->throttled = port->throttle_req;
|
||
|
+ if (!port->throttled) {
|
||
|
+ spin_unlock_irqrestore(&port->lock, flags);
|
||
|
+ ftdi_submit_read_urb(port, GFP_ATOMIC);
|
||
|
+ } else
|
||
|
+ spin_unlock_irqrestore(&port->lock, flags);
|
||
|
+}
|
||
|
|
||
|
static void ftdi_break_ctl(struct tty_struct *tty, int break_state)
|
||
|
{
|
||
|
@@ -2611,33 +2449,31 @@ static int ftdi_ioctl(struct tty_struct *tty, struct file *file,
|
||
|
static void ftdi_throttle(struct tty_struct *tty)
|
||
|
{
|
||
|
struct usb_serial_port *port = tty->driver_data;
|
||
|
- struct ftdi_private *priv = usb_get_serial_port_data(port);
|
||
|
unsigned long flags;
|
||
|
|
||
|
dbg("%s - port %d", __func__, port->number);
|
||
|
|
||
|
- spin_lock_irqsave(&priv->rx_lock, flags);
|
||
|
- priv->rx_flags |= THROTTLED;
|
||
|
- spin_unlock_irqrestore(&priv->rx_lock, flags);
|
||
|
+ spin_lock_irqsave(&port->lock, flags);
|
||
|
+ port->throttle_req = 1;
|
||
|
+ spin_unlock_irqrestore(&port->lock, flags);
|
||
|
}
|
||
|
|
||
|
-
|
||
|
-static void ftdi_unthrottle(struct tty_struct *tty)
|
||
|
+void ftdi_unthrottle(struct tty_struct *tty)
|
||
|
{
|
||
|
struct usb_serial_port *port = tty->driver_data;
|
||
|
- struct ftdi_private *priv = usb_get_serial_port_data(port);
|
||
|
- int actually_throttled;
|
||
|
+ int was_throttled;
|
||
|
unsigned long flags;
|
||
|
|
||
|
dbg("%s - port %d", __func__, port->number);
|
||
|
|
||
|
- spin_lock_irqsave(&priv->rx_lock, flags);
|
||
|
- actually_throttled = priv->rx_flags & ACTUALLY_THROTTLED;
|
||
|
- priv->rx_flags &= ~(THROTTLED | ACTUALLY_THROTTLED);
|
||
|
- spin_unlock_irqrestore(&priv->rx_lock, flags);
|
||
|
+ spin_lock_irqsave(&port->lock, flags);
|
||
|
+ was_throttled = port->throttled;
|
||
|
+ port->throttled = port->throttle_req = 0;
|
||
|
+ spin_unlock_irqrestore(&port->lock, flags);
|
||
|
|
||
|
- if (actually_throttled)
|
||
|
- schedule_delayed_work(&priv->rx_work, 0);
|
||
|
+ /* Resubmit urb if throttled and open. */
|
||
|
+ if (was_throttled && test_bit(ASYNCB_INITIALIZED, &port->port.flags))
|
||
|
+ ftdi_submit_read_urb(port, GFP_KERNEL);
|
||
|
}
|
||
|
|
||
|
static int __init ftdi_init(void)
|
||
|
diff --git a/drivers/usb/serial/generic.c b/drivers/usb/serial/generic.c
|
||
|
index ce57f6a..7170b69 100644
|
||
|
--- a/drivers/usb/serial/generic.c
|
||
|
+++ b/drivers/usb/serial/generic.c
|
||
|
@@ -530,7 +530,7 @@ void usb_serial_generic_unthrottle(struct tty_struct *tty)
|
||
|
|
||
|
if (was_throttled) {
|
||
|
/* Resume reading from device */
|
||
|
- usb_serial_generic_resubmit_read_urb(port, GFP_KERNEL);
|
||
|
+ flush_and_resubmit_read_urb(port);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
diff --git a/drivers/usb/serial/ipaq.c b/drivers/usb/serial/ipaq.c
|
||
|
index 2545d45..c4d0206 100644
|
||
|
--- a/drivers/usb/serial/ipaq.c
|
||
|
+++ b/drivers/usb/serial/ipaq.c
|
||
|
@@ -971,6 +971,15 @@ static int ipaq_calc_num_ports(struct usb_serial *serial)
|
||
|
static int ipaq_startup(struct usb_serial *serial)
|
||
|
{
|
||
|
dbg("%s", __func__);
|
||
|
+
|
||
|
+ /* Some of the devices in ipaq_id_table[] are composite, and we
|
||
|
+ * shouldn't bind to all the interfaces. This test will rule out
|
||
|
+ * some obviously invalid possibilities.
|
||
|
+ */
|
||
|
+ if (serial->num_bulk_in < serial->num_ports ||
|
||
|
+ serial->num_bulk_out < serial->num_ports)
|
||
|
+ return -ENODEV;
|
||
|
+
|
||
|
if (serial->dev->actconfig->desc.bConfigurationValue != 1) {
|
||
|
/*
|
||
|
* FIXME: HP iPaq rx3715, possibly others, have 1 config that
|
||
|
diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c
|
||
|
index 0101548..20b0788 100644
|
||
|
--- a/drivers/usb/serial/option.c
|
||
|
+++ b/drivers/usb/serial/option.c
|
||
|
@@ -319,6 +319,7 @@ static int option_resume(struct usb_serial *serial);
|
||
|
/* TOSHIBA PRODUCTS */
|
||
|
#define TOSHIBA_VENDOR_ID 0x0930
|
||
|
#define TOSHIBA_PRODUCT_HSDPA_MINICARD 0x1302
|
||
|
+#define TOSHIBA_PRODUCT_G450 0x0d45
|
||
|
|
||
|
#define ALINK_VENDOR_ID 0x1e0e
|
||
|
#define ALINK_PRODUCT_3GU 0x9200
|
||
|
@@ -582,6 +583,7 @@ static struct usb_device_id option_ids[] = {
|
||
|
{ USB_DEVICE(QISDA_VENDOR_ID, QISDA_PRODUCT_H21_4523) },
|
||
|
{ USB_DEVICE(QISDA_VENDOR_ID, QISDA_PRODUCT_H20_4515) },
|
||
|
{ USB_DEVICE(QISDA_VENDOR_ID, QISDA_PRODUCT_H20_4519) },
|
||
|
+ { USB_DEVICE(TOSHIBA_VENDOR_ID, TOSHIBA_PRODUCT_G450) },
|
||
|
{ USB_DEVICE(TOSHIBA_VENDOR_ID, TOSHIBA_PRODUCT_HSDPA_MINICARD ) }, /* Toshiba 3G HSDPA == Novatel Expedite EU870D MiniCard */
|
||
|
{ USB_DEVICE(ALINK_VENDOR_ID, 0x9000) },
|
||
|
{ USB_DEVICE_AND_INTERFACE_INFO(ALINK_VENDOR_ID, ALINK_PRODUCT_3GU, 0xff, 0xff, 0xff) },
|
||
|
diff --git a/drivers/usb/serial/pl2303.c b/drivers/usb/serial/pl2303.c
|
||
|
index 124d5ae..600097d 100644
|
||
|
--- a/drivers/usb/serial/pl2303.c
|
||
|
+++ b/drivers/usb/serial/pl2303.c
|
||
|
@@ -995,13 +995,15 @@ static void pl2303_push_data(struct tty_struct *tty,
|
||
|
/* overrun is special, not associated with a char */
|
||
|
if (line_status & UART_OVERRUN_ERROR)
|
||
|
tty_insert_flip_char(tty, 0, TTY_OVERRUN);
|
||
|
- if (port->console && port->sysrq) {
|
||
|
+
|
||
|
+ if (tty_flag == TTY_NORMAL && !(port->console && port->sysrq))
|
||
|
+ tty_insert_flip_string(tty, data, urb->actual_length);
|
||
|
+ else {
|
||
|
int i;
|
||
|
for (i = 0; i < urb->actual_length; ++i)
|
||
|
if (!usb_serial_handle_sysrq_char(tty, port, data[i]))
|
||
|
tty_insert_flip_char(tty, data[i], tty_flag);
|
||
|
- } else
|
||
|
- tty_insert_flip_string(tty, data, urb->actual_length);
|
||
|
+ }
|
||
|
tty_flip_buffer_push(tty);
|
||
|
}
|
||
|
|
||
|
diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c
|
||
|
index a0702db..3292e03 100644
|
||
|
--- a/drivers/usb/serial/usb-serial.c
|
||
|
+++ b/drivers/usb/serial/usb-serial.c
|
||
|
@@ -155,7 +155,8 @@ static void destroy_serial(struct kref *kref)
|
||
|
if (serial->minor != SERIAL_TTY_NO_MINOR)
|
||
|
return_serial(serial);
|
||
|
|
||
|
- serial->type->release(serial);
|
||
|
+ if (serial->attached)
|
||
|
+ serial->type->release(serial);
|
||
|
|
||
|
/* Now that nothing is using the ports, they can be freed */
|
||
|
for (i = 0; i < serial->num_port_pointers; ++i) {
|
||
|
@@ -1060,12 +1061,15 @@ int usb_serial_probe(struct usb_interface *interface,
|
||
|
module_put(type->driver.owner);
|
||
|
if (retval < 0)
|
||
|
goto probe_error;
|
||
|
+ serial->attached = 1;
|
||
|
if (retval > 0) {
|
||
|
/* quietly accept this device, but don't bind to a
|
||
|
serial port as it's about to disappear */
|
||
|
serial->num_ports = 0;
|
||
|
goto exit;
|
||
|
}
|
||
|
+ } else {
|
||
|
+ serial->attached = 1;
|
||
|
}
|
||
|
|
||
|
if (get_free_serial(serial, num_ports, &minor) == NULL) {
|
||
|
diff --git a/drivers/usb/storage/transport.c b/drivers/usb/storage/transport.c
|
||
|
index e20dc52..589f6b4 100644
|
||
|
--- a/drivers/usb/storage/transport.c
|
||
|
+++ b/drivers/usb/storage/transport.c
|
||
|
@@ -696,7 +696,7 @@ void usb_stor_invoke_transport(struct scsi_cmnd *srb, struct us_data *us)
|
||
|
/* device supports and needs bigger sense buffer */
|
||
|
if (us->fflags & US_FL_SANE_SENSE)
|
||
|
sense_size = ~0;
|
||
|
-
|
||
|
+Retry_Sense:
|
||
|
US_DEBUGP("Issuing auto-REQUEST_SENSE\n");
|
||
|
|
||
|
scsi_eh_prep_cmnd(srb, &ses, NULL, 0, sense_size);
|
||
|
@@ -720,6 +720,21 @@ void usb_stor_invoke_transport(struct scsi_cmnd *srb, struct us_data *us)
|
||
|
srb->result = DID_ABORT << 16;
|
||
|
goto Handle_Errors;
|
||
|
}
|
||
|
+
|
||
|
+ /* Some devices claim to support larger sense but fail when
|
||
|
+ * trying to request it. When a transport failure happens
|
||
|
+ * using US_FS_SANE_SENSE, we always retry with a standard
|
||
|
+ * (small) sense request. This fixes some USB GSM modems
|
||
|
+ */
|
||
|
+ if (temp_result == USB_STOR_TRANSPORT_FAILED &&
|
||
|
+ (us->fflags & US_FL_SANE_SENSE) &&
|
||
|
+ sense_size != US_SENSE_SIZE) {
|
||
|
+ US_DEBUGP("-- auto-sense failure, retry small sense\n");
|
||
|
+ sense_size = US_SENSE_SIZE;
|
||
|
+ goto Retry_Sense;
|
||
|
+ }
|
||
|
+
|
||
|
+ /* Other failures */
|
||
|
if (temp_result != USB_STOR_TRANSPORT_GOOD) {
|
||
|
US_DEBUGP("-- auto-sense failure\n");
|
||
|
|
||
|
@@ -768,17 +783,32 @@ void usb_stor_invoke_transport(struct scsi_cmnd *srb, struct us_data *us)
|
||
|
/* set the result so the higher layers expect this data */
|
||
|
srb->result = SAM_STAT_CHECK_CONDITION;
|
||
|
|
||
|
- /* If things are really okay, then let's show that. Zero
|
||
|
- * out the sense buffer so the higher layers won't realize
|
||
|
- * we did an unsolicited auto-sense. */
|
||
|
- if (result == USB_STOR_TRANSPORT_GOOD &&
|
||
|
- /* Filemark 0, ignore EOM, ILI 0, no sense */
|
||
|
+ /* We often get empty sense data. This could indicate that
|
||
|
+ * everything worked or that there was an unspecified
|
||
|
+ * problem. We have to decide which.
|
||
|
+ */
|
||
|
+ if ( /* Filemark 0, ignore EOM, ILI 0, no sense */
|
||
|
(srb->sense_buffer[2] & 0xaf) == 0 &&
|
||
|
/* No ASC or ASCQ */
|
||
|
srb->sense_buffer[12] == 0 &&
|
||
|
srb->sense_buffer[13] == 0) {
|
||
|
- srb->result = SAM_STAT_GOOD;
|
||
|
- srb->sense_buffer[0] = 0x0;
|
||
|
+
|
||
|
+ /* If things are really okay, then let's show that.
|
||
|
+ * Zero out the sense buffer so the higher layers
|
||
|
+ * won't realize we did an unsolicited auto-sense.
|
||
|
+ */
|
||
|
+ if (result == USB_STOR_TRANSPORT_GOOD) {
|
||
|
+ srb->result = SAM_STAT_GOOD;
|
||
|
+ srb->sense_buffer[0] = 0x0;
|
||
|
+
|
||
|
+ /* If there was a problem, report an unspecified
|
||
|
+ * hardware error to prevent the higher layers from
|
||
|
+ * entering an infinite retry loop.
|
||
|
+ */
|
||
|
+ } else {
|
||
|
+ srb->result = DID_ERROR << 16;
|
||
|
+ srb->sense_buffer[2] = HARDWARE_ERROR;
|
||
|
+ }
|
||
|
}
|
||
|
}
|
||
|
|
||
|
diff --git a/drivers/video/uvesafb.c b/drivers/video/uvesafb.c
|
||
|
index ca5b464..e35232a 100644
|
||
|
--- a/drivers/video/uvesafb.c
|
||
|
+++ b/drivers/video/uvesafb.c
|
||
|
@@ -67,12 +67,14 @@ static DEFINE_MUTEX(uvfb_lock);
|
||
|
* find the kernel part of the task struct, copy the registers and
|
||
|
* the buffer contents and then complete the task.
|
||
|
*/
|
||
|
-static void uvesafb_cn_callback(void *data)
|
||
|
+static void uvesafb_cn_callback(struct cn_msg *msg, struct netlink_skb_parms *nsp)
|
||
|
{
|
||
|
- struct cn_msg *msg = data;
|
||
|
struct uvesafb_task *utask;
|
||
|
struct uvesafb_ktask *task;
|
||
|
|
||
|
+ if (!cap_raised(nsp->eff_cap, CAP_SYS_ADMIN))
|
||
|
+ return;
|
||
|
+
|
||
|
if (msg->seq >= UVESAFB_TASKS_MAX)
|
||
|
return;
|
||
|
|
||
|
diff --git a/drivers/w1/w1_netlink.c b/drivers/w1/w1_netlink.c
|
||
|
index fdf7285..45c126f 100644
|
||
|
--- a/drivers/w1/w1_netlink.c
|
||
|
+++ b/drivers/w1/w1_netlink.c
|
||
|
@@ -306,9 +306,8 @@ static int w1_netlink_send_error(struct cn_msg *rcmsg, struct w1_netlink_msg *rm
|
||
|
return error;
|
||
|
}
|
||
|
|
||
|
-static void w1_cn_callback(void *data)
|
||
|
+static void w1_cn_callback(struct cn_msg *msg, struct netlink_skb_parms *nsp)
|
||
|
{
|
||
|
- struct cn_msg *msg = data;
|
||
|
struct w1_netlink_msg *m = (struct w1_netlink_msg *)(msg + 1);
|
||
|
struct w1_netlink_cmd *cmd;
|
||
|
struct w1_slave *sl;
|
||
|
diff --git a/fs/sysfs/file.c b/fs/sysfs/file.c
|
||
|
index 561a9c0..f5ea468 100644
|
||
|
--- a/fs/sysfs/file.c
|
||
|
+++ b/fs/sysfs/file.c
|
||
|
@@ -268,7 +268,7 @@ static int sysfs_get_open_dirent(struct sysfs_dirent *sd,
|
||
|
struct sysfs_open_dirent *od, *new_od = NULL;
|
||
|
|
||
|
retry:
|
||
|
- spin_lock(&sysfs_open_dirent_lock);
|
||
|
+ spin_lock_irq(&sysfs_open_dirent_lock);
|
||
|
|
||
|
if (!sd->s_attr.open && new_od) {
|
||
|
sd->s_attr.open = new_od;
|
||
|
@@ -281,7 +281,7 @@ static int sysfs_get_open_dirent(struct sysfs_dirent *sd,
|
||
|
list_add_tail(&buffer->list, &od->buffers);
|
||
|
}
|
||
|
|
||
|
- spin_unlock(&sysfs_open_dirent_lock);
|
||
|
+ spin_unlock_irq(&sysfs_open_dirent_lock);
|
||
|
|
||
|
if (od) {
|
||
|
kfree(new_od);
|
||
|
@@ -315,8 +315,9 @@ static void sysfs_put_open_dirent(struct sysfs_dirent *sd,
|
||
|
struct sysfs_buffer *buffer)
|
||
|
{
|
||
|
struct sysfs_open_dirent *od = sd->s_attr.open;
|
||
|
+ unsigned long flags;
|
||
|
|
||
|
- spin_lock(&sysfs_open_dirent_lock);
|
||
|
+ spin_lock_irqsave(&sysfs_open_dirent_lock, flags);
|
||
|
|
||
|
list_del(&buffer->list);
|
||
|
if (atomic_dec_and_test(&od->refcnt))
|
||
|
@@ -324,7 +325,7 @@ static void sysfs_put_open_dirent(struct sysfs_dirent *sd,
|
||
|
else
|
||
|
od = NULL;
|
||
|
|
||
|
- spin_unlock(&sysfs_open_dirent_lock);
|
||
|
+ spin_unlock_irqrestore(&sysfs_open_dirent_lock, flags);
|
||
|
|
||
|
kfree(od);
|
||
|
}
|
||
|
@@ -456,8 +457,9 @@ static unsigned int sysfs_poll(struct file *filp, poll_table *wait)
|
||
|
void sysfs_notify_dirent(struct sysfs_dirent *sd)
|
||
|
{
|
||
|
struct sysfs_open_dirent *od;
|
||
|
+ unsigned long flags;
|
||
|
|
||
|
- spin_lock(&sysfs_open_dirent_lock);
|
||
|
+ spin_lock_irqsave(&sysfs_open_dirent_lock, flags);
|
||
|
|
||
|
od = sd->s_attr.open;
|
||
|
if (od) {
|
||
|
@@ -465,7 +467,7 @@ void sysfs_notify_dirent(struct sysfs_dirent *sd)
|
||
|
wake_up_interruptible(&od->poll);
|
||
|
}
|
||
|
|
||
|
- spin_unlock(&sysfs_open_dirent_lock);
|
||
|
+ spin_unlock_irqrestore(&sysfs_open_dirent_lock, flags);
|
||
|
}
|
||
|
EXPORT_SYMBOL_GPL(sysfs_notify_dirent);
|
||
|
|
||
|
diff --git a/include/linux/connector.h b/include/linux/connector.h
|
||
|
index b68d278..3a14615 100644
|
||
|
--- a/include/linux/connector.h
|
||
|
+++ b/include/linux/connector.h
|
||
|
@@ -132,11 +132,8 @@ struct cn_callback_id {
|
||
|
};
|
||
|
|
||
|
struct cn_callback_data {
|
||
|
- void (*destruct_data) (void *);
|
||
|
- void *ddata;
|
||
|
-
|
||
|
- void *callback_priv;
|
||
|
- void (*callback) (void *);
|
||
|
+ struct sk_buff *skb;
|
||
|
+ void (*callback) (struct cn_msg *, struct netlink_skb_parms *);
|
||
|
|
||
|
void *free;
|
||
|
};
|
||
|
@@ -167,11 +164,11 @@ struct cn_dev {
|
||
|
struct cn_queue_dev *cbdev;
|
||
|
};
|
||
|
|
||
|
-int cn_add_callback(struct cb_id *, char *, void (*callback) (void *));
|
||
|
+int cn_add_callback(struct cb_id *, char *, void (*callback) (struct cn_msg *, struct netlink_skb_parms *));
|
||
|
void cn_del_callback(struct cb_id *);
|
||
|
int cn_netlink_send(struct cn_msg *, u32, gfp_t);
|
||
|
|
||
|
-int cn_queue_add_callback(struct cn_queue_dev *dev, char *name, struct cb_id *id, void (*callback)(void *));
|
||
|
+int cn_queue_add_callback(struct cn_queue_dev *dev, char *name, struct cb_id *id, void (*callback)(struct cn_msg *, struct netlink_skb_parms *));
|
||
|
void cn_queue_del_callback(struct cn_queue_dev *dev, struct cb_id *id);
|
||
|
|
||
|
int queue_cn_work(struct cn_callback_entry *cbq, struct work_struct *work);
|
||
|
diff --git a/include/linux/usb/serial.h b/include/linux/usb/serial.h
|
||
|
index 73f121e..20b12f3 100644
|
||
|
--- a/include/linux/usb/serial.h
|
||
|
+++ b/include/linux/usb/serial.h
|
||
|
@@ -148,6 +148,7 @@ struct usb_serial {
|
||
|
struct usb_interface *interface;
|
||
|
unsigned char disconnected:1;
|
||
|
unsigned char suspending:1;
|
||
|
+ unsigned char attached:1;
|
||
|
unsigned char minor;
|
||
|
unsigned char num_ports;
|
||
|
unsigned char num_port_pointers;
|
||
|
diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
|
||
|
index c4ca422..25b8a03 100644
|
||
|
--- a/include/net/bluetooth/hci_core.h
|
||
|
+++ b/include/net/bluetooth/hci_core.h
|
||
|
@@ -187,6 +187,7 @@ struct hci_conn {
|
||
|
struct work_struct work_del;
|
||
|
|
||
|
struct device dev;
|
||
|
+ atomic_t devref;
|
||
|
|
||
|
struct hci_dev *hdev;
|
||
|
void *l2cap_data;
|
||
|
@@ -339,6 +340,9 @@ int hci_conn_switch_role(struct hci_conn *conn, __u8 role);
|
||
|
void hci_conn_enter_active_mode(struct hci_conn *conn);
|
||
|
void hci_conn_enter_sniff_mode(struct hci_conn *conn);
|
||
|
|
||
|
+void hci_conn_hold_device(struct hci_conn *conn);
|
||
|
+void hci_conn_put_device(struct hci_conn *conn);
|
||
|
+
|
||
|
static inline void hci_conn_hold(struct hci_conn *conn)
|
||
|
{
|
||
|
atomic_inc(&conn->refcnt);
|
||
|
diff --git a/kernel/acct.c b/kernel/acct.c
|
||
|
index 9f33910..9a4715a 100644
|
||
|
--- a/kernel/acct.c
|
||
|
+++ b/kernel/acct.c
|
||
|
@@ -491,13 +491,17 @@ static void do_acct_process(struct bsd_acct_struct *acct,
|
||
|
u64 run_time;
|
||
|
struct timespec uptime;
|
||
|
struct tty_struct *tty;
|
||
|
+ const struct cred *orig_cred;
|
||
|
+
|
||
|
+ /* Perform file operations on behalf of whoever enabled accounting */
|
||
|
+ orig_cred = override_creds(file->f_cred);
|
||
|
|
||
|
/*
|
||
|
* First check to see if there is enough free_space to continue
|
||
|
* the process accounting system.
|
||
|
*/
|
||
|
if (!check_free_space(acct, file))
|
||
|
- return;
|
||
|
+ goto out;
|
||
|
|
||
|
/*
|
||
|
* Fill the accounting struct with the needed info as recorded
|
||
|
@@ -578,6 +582,8 @@ static void do_acct_process(struct bsd_acct_struct *acct,
|
||
|
sizeof(acct_t), &file->f_pos);
|
||
|
current->signal->rlim[RLIMIT_FSIZE].rlim_cur = flim;
|
||
|
set_fs(fs);
|
||
|
+out:
|
||
|
+ revert_creds(orig_cred);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
diff --git a/kernel/futex.c b/kernel/futex.c
|
||
|
index 2362d06..59a2f4d 100644
|
||
|
--- a/kernel/futex.c
|
||
|
+++ b/kernel/futex.c
|
||
|
@@ -115,6 +115,9 @@ struct futex_q {
|
||
|
/* rt_waiter storage for requeue_pi: */
|
||
|
struct rt_mutex_waiter *rt_waiter;
|
||
|
|
||
|
+ /* The expected requeue pi target futex key: */
|
||
|
+ union futex_key *requeue_pi_key;
|
||
|
+
|
||
|
/* Bitset for the optional bitmasked wakeup */
|
||
|
u32 bitset;
|
||
|
};
|
||
|
@@ -1089,6 +1092,10 @@ static int futex_proxy_trylock_atomic(u32 __user *pifutex,
|
||
|
if (!top_waiter)
|
||
|
return 0;
|
||
|
|
||
|
+ /* Ensure we requeue to the expected futex. */
|
||
|
+ if (!match_futex(top_waiter->requeue_pi_key, key2))
|
||
|
+ return -EINVAL;
|
||
|
+
|
||
|
/*
|
||
|
* Try to take the lock for top_waiter. Set the FUTEX_WAITERS bit in
|
||
|
* the contended case or if set_waiters is 1. The pi_state is returned
|
||
|
@@ -1276,6 +1283,12 @@ retry_private:
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
+ /* Ensure we requeue to the expected futex for requeue_pi. */
|
||
|
+ if (requeue_pi && !match_futex(this->requeue_pi_key, &key2)) {
|
||
|
+ ret = -EINVAL;
|
||
|
+ break;
|
||
|
+ }
|
||
|
+
|
||
|
/*
|
||
|
* Requeue nr_requeue waiters and possibly one more in the case
|
||
|
* of requeue_pi if we couldn't acquire the lock atomically.
|
||
|
@@ -1625,17 +1638,8 @@ out:
|
||
|
static void futex_wait_queue_me(struct futex_hash_bucket *hb, struct futex_q *q,
|
||
|
struct hrtimer_sleeper *timeout)
|
||
|
{
|
||
|
- queue_me(q, hb);
|
||
|
-
|
||
|
- /*
|
||
|
- * There might have been scheduling since the queue_me(), as we
|
||
|
- * cannot hold a spinlock across the get_user() in case it
|
||
|
- * faults, and we cannot just set TASK_INTERRUPTIBLE state when
|
||
|
- * queueing ourselves into the futex hash. This code thus has to
|
||
|
- * rely on the futex_wake() code removing us from hash when it
|
||
|
- * wakes us up.
|
||
|
- */
|
||
|
set_current_state(TASK_INTERRUPTIBLE);
|
||
|
+ queue_me(q, hb);
|
||
|
|
||
|
/* Arm the timer */
|
||
|
if (timeout) {
|
||
|
@@ -1645,8 +1649,8 @@ static void futex_wait_queue_me(struct futex_hash_bucket *hb, struct futex_q *q,
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
- * !plist_node_empty() is safe here without any lock.
|
||
|
- * q.lock_ptr != 0 is not safe, because of ordering against wakeup.
|
||
|
+ * If we have been removed from the hash list, then another task
|
||
|
+ * has tried to wake us, and we can skip the call to schedule().
|
||
|
*/
|
||
|
if (likely(!plist_node_empty(&q->list))) {
|
||
|
/*
|
||
|
@@ -1751,6 +1755,7 @@ static int futex_wait(u32 __user *uaddr, int fshared,
|
||
|
q.pi_state = NULL;
|
||
|
q.bitset = bitset;
|
||
|
q.rt_waiter = NULL;
|
||
|
+ q.requeue_pi_key = NULL;
|
||
|
|
||
|
if (abs_time) {
|
||
|
to = &timeout;
|
||
|
@@ -1858,6 +1863,7 @@ static int futex_lock_pi(u32 __user *uaddr, int fshared,
|
||
|
|
||
|
q.pi_state = NULL;
|
||
|
q.rt_waiter = NULL;
|
||
|
+ q.requeue_pi_key = NULL;
|
||
|
retry:
|
||
|
q.key = FUTEX_KEY_INIT;
|
||
|
ret = get_futex_key(uaddr, fshared, &q.key, VERIFY_WRITE);
|
||
|
@@ -2168,15 +2174,16 @@ static int futex_wait_requeue_pi(u32 __user *uaddr, int fshared,
|
||
|
debug_rt_mutex_init_waiter(&rt_waiter);
|
||
|
rt_waiter.task = NULL;
|
||
|
|
||
|
- q.pi_state = NULL;
|
||
|
- q.bitset = bitset;
|
||
|
- q.rt_waiter = &rt_waiter;
|
||
|
-
|
||
|
key2 = FUTEX_KEY_INIT;
|
||
|
ret = get_futex_key(uaddr2, fshared, &key2, VERIFY_WRITE);
|
||
|
if (unlikely(ret != 0))
|
||
|
goto out;
|
||
|
|
||
|
+ q.pi_state = NULL;
|
||
|
+ q.bitset = bitset;
|
||
|
+ q.rt_waiter = &rt_waiter;
|
||
|
+ q.requeue_pi_key = &key2;
|
||
|
+
|
||
|
/* Prepare to wait on uaddr. */
|
||
|
ret = futex_wait_setup(uaddr, val, fshared, &q, &hb);
|
||
|
if (ret)
|
||
|
diff --git a/kernel/trace/trace_events_filter.c b/kernel/trace/trace_events_filter.c
|
||
|
index f32dc9d..a6b0d73 100644
|
||
|
--- a/kernel/trace/trace_events_filter.c
|
||
|
+++ b/kernel/trace/trace_events_filter.c
|
||
|
@@ -844,8 +844,9 @@ static void postfix_clear(struct filter_parse_state *ps)
|
||
|
|
||
|
while (!list_empty(&ps->postfix)) {
|
||
|
elt = list_first_entry(&ps->postfix, struct postfix_elt, list);
|
||
|
- kfree(elt->operand);
|
||
|
list_del(&elt->list);
|
||
|
+ kfree(elt->operand);
|
||
|
+ kfree(elt);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c
|
||
|
index fa47d5d..a975098 100644
|
||
|
--- a/net/bluetooth/hci_conn.c
|
||
|
+++ b/net/bluetooth/hci_conn.c
|
||
|
@@ -246,6 +246,8 @@ struct hci_conn *hci_conn_add(struct hci_dev *hdev, int type, bdaddr_t *dst)
|
||
|
if (hdev->notify)
|
||
|
hdev->notify(hdev, HCI_NOTIFY_CONN_ADD);
|
||
|
|
||
|
+ atomic_set(&conn->devref, 0);
|
||
|
+
|
||
|
hci_conn_init_sysfs(conn);
|
||
|
|
||
|
tasklet_enable(&hdev->tx_task);
|
||
|
@@ -288,7 +290,7 @@ int hci_conn_del(struct hci_conn *conn)
|
||
|
|
||
|
skb_queue_purge(&conn->data_q);
|
||
|
|
||
|
- hci_conn_del_sysfs(conn);
|
||
|
+ hci_conn_put_device(conn);
|
||
|
|
||
|
hci_dev_put(hdev);
|
||
|
|
||
|
@@ -583,6 +585,19 @@ void hci_conn_check_pending(struct hci_dev *hdev)
|
||
|
hci_dev_unlock(hdev);
|
||
|
}
|
||
|
|
||
|
+void hci_conn_hold_device(struct hci_conn *conn)
|
||
|
+{
|
||
|
+ atomic_inc(&conn->devref);
|
||
|
+}
|
||
|
+EXPORT_SYMBOL(hci_conn_hold_device);
|
||
|
+
|
||
|
+void hci_conn_put_device(struct hci_conn *conn)
|
||
|
+{
|
||
|
+ if (atomic_dec_and_test(&conn->devref))
|
||
|
+ hci_conn_del_sysfs(conn);
|
||
|
+}
|
||
|
+EXPORT_SYMBOL(hci_conn_put_device);
|
||
|
+
|
||
|
int hci_get_conn_list(void __user *arg)
|
||
|
{
|
||
|
struct hci_conn_list_req req, *cl;
|
||
|
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
|
||
|
index 184ba0a..e99fe38 100644
|
||
|
--- a/net/bluetooth/hci_event.c
|
||
|
+++ b/net/bluetooth/hci_event.c
|
||
|
@@ -887,6 +887,7 @@ static inline void hci_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *s
|
||
|
} else
|
||
|
conn->state = BT_CONNECTED;
|
||
|
|
||
|
+ hci_conn_hold_device(conn);
|
||
|
hci_conn_add_sysfs(conn);
|
||
|
|
||
|
if (test_bit(HCI_AUTH, &hdev->flags))
|
||
|
@@ -1693,6 +1694,7 @@ static inline void hci_sync_conn_complete_evt(struct hci_dev *hdev, struct sk_bu
|
||
|
conn->handle = __le16_to_cpu(ev->handle);
|
||
|
conn->state = BT_CONNECTED;
|
||
|
|
||
|
+ hci_conn_hold_device(conn);
|
||
|
hci_conn_add_sysfs(conn);
|
||
|
break;
|
||
|
|
||
|
diff --git a/net/bluetooth/hidp/core.c b/net/bluetooth/hidp/core.c
|
||
|
index b186768..9f1e765 100644
|
||
|
--- a/net/bluetooth/hidp/core.c
|
||
|
+++ b/net/bluetooth/hidp/core.c
|
||
|
@@ -40,6 +40,7 @@
|
||
|
|
||
|
#include <linux/input.h>
|
||
|
#include <linux/hid.h>
|
||
|
+#include <linux/hidraw.h>
|
||
|
|
||
|
#include <net/bluetooth/bluetooth.h>
|
||
|
#include <net/bluetooth/hci_core.h>
|
||
|
@@ -92,10 +93,14 @@ static void __hidp_link_session(struct hidp_session *session)
|
||
|
{
|
||
|
__module_get(THIS_MODULE);
|
||
|
list_add(&session->list, &hidp_session_list);
|
||
|
+
|
||
|
+ hci_conn_hold_device(session->conn);
|
||
|
}
|
||
|
|
||
|
static void __hidp_unlink_session(struct hidp_session *session)
|
||
|
{
|
||
|
+ hci_conn_put_device(session->conn);
|
||
|
+
|
||
|
list_del(&session->list);
|
||
|
module_put(THIS_MODULE);
|
||
|
}
|
||
|
@@ -573,7 +578,11 @@ static int hidp_session(void *arg)
|
||
|
if (session->hid) {
|
||
|
if (session->hid->claimed & HID_CLAIMED_INPUT)
|
||
|
hidinput_disconnect(session->hid);
|
||
|
+ if (session->hid->claimed & HID_CLAIMED_HIDRAW)
|
||
|
+ hidraw_disconnect(session->hid);
|
||
|
+
|
||
|
hid_destroy_device(session->hid);
|
||
|
+ session->hid = NULL;
|
||
|
}
|
||
|
|
||
|
/* Wakeup user-space polling for socket errors */
|
||
|
@@ -601,25 +610,27 @@ static struct device *hidp_get_device(struct hidp_session *session)
|
||
|
{
|
||
|
bdaddr_t *src = &bt_sk(session->ctrl_sock->sk)->src;
|
||
|
bdaddr_t *dst = &bt_sk(session->ctrl_sock->sk)->dst;
|
||
|
+ struct device *device = NULL;
|
||
|
struct hci_dev *hdev;
|
||
|
- struct hci_conn *conn;
|
||
|
|
||
|
hdev = hci_get_route(dst, src);
|
||
|
if (!hdev)
|
||
|
return NULL;
|
||
|
|
||
|
- conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, dst);
|
||
|
+ session->conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, dst);
|
||
|
+ if (session->conn)
|
||
|
+ device = &session->conn->dev;
|
||
|
|
||
|
hci_dev_put(hdev);
|
||
|
|
||
|
- return conn ? &conn->dev : NULL;
|
||
|
+ return device;
|
||
|
}
|
||
|
|
||
|
static int hidp_setup_input(struct hidp_session *session,
|
||
|
struct hidp_connadd_req *req)
|
||
|
{
|
||
|
struct input_dev *input;
|
||
|
- int i;
|
||
|
+ int err, i;
|
||
|
|
||
|
input = input_allocate_device();
|
||
|
if (!input)
|
||
|
@@ -666,7 +677,13 @@ static int hidp_setup_input(struct hidp_session *session,
|
||
|
|
||
|
input->event = hidp_input_event;
|
||
|
|
||
|
- return input_register_device(input);
|
||
|
+ err = input_register_device(input);
|
||
|
+ if (err < 0) {
|
||
|
+ hci_conn_put_device(session->conn);
|
||
|
+ return err;
|
||
|
+ }
|
||
|
+
|
||
|
+ return 0;
|
||
|
}
|
||
|
|
||
|
static int hidp_open(struct hid_device *hid)
|
||
|
@@ -748,13 +765,11 @@ static int hidp_setup_hid(struct hidp_session *session,
|
||
|
{
|
||
|
struct hid_device *hid;
|
||
|
bdaddr_t src, dst;
|
||
|
- int ret;
|
||
|
+ int err;
|
||
|
|
||
|
hid = hid_allocate_device();
|
||
|
- if (IS_ERR(hid)) {
|
||
|
- ret = PTR_ERR(session->hid);
|
||
|
- goto err;
|
||
|
- }
|
||
|
+ if (IS_ERR(hid))
|
||
|
+ return PTR_ERR(session->hid);
|
||
|
|
||
|
session->hid = hid;
|
||
|
session->req = req;
|
||
|
@@ -776,16 +791,17 @@ static int hidp_setup_hid(struct hidp_session *session,
|
||
|
hid->dev.parent = hidp_get_device(session);
|
||
|
hid->ll_driver = &hidp_hid_driver;
|
||
|
|
||
|
- ret = hid_add_device(hid);
|
||
|
- if (ret)
|
||
|
- goto err_hid;
|
||
|
+ err = hid_add_device(hid);
|
||
|
+ if (err < 0)
|
||
|
+ goto failed;
|
||
|
|
||
|
return 0;
|
||
|
-err_hid:
|
||
|
+
|
||
|
+failed:
|
||
|
hid_destroy_device(hid);
|
||
|
session->hid = NULL;
|
||
|
-err:
|
||
|
- return ret;
|
||
|
+
|
||
|
+ return err;
|
||
|
}
|
||
|
|
||
|
int hidp_add_connection(struct hidp_connadd_req *req, struct socket *ctrl_sock, struct socket *intr_sock)
|
||
|
@@ -835,13 +851,13 @@ int hidp_add_connection(struct hidp_connadd_req *req, struct socket *ctrl_sock,
|
||
|
if (req->rd_size > 0) {
|
||
|
err = hidp_setup_hid(session, req);
|
||
|
if (err && err != -ENODEV)
|
||
|
- goto err_skb;
|
||
|
+ goto purge;
|
||
|
}
|
||
|
|
||
|
if (!session->hid) {
|
||
|
err = hidp_setup_input(session, req);
|
||
|
if (err < 0)
|
||
|
- goto err_skb;
|
||
|
+ goto purge;
|
||
|
}
|
||
|
|
||
|
__hidp_link_session(session);
|
||
|
@@ -869,13 +885,20 @@ unlink:
|
||
|
|
||
|
__hidp_unlink_session(session);
|
||
|
|
||
|
- if (session->input)
|
||
|
+ if (session->input) {
|
||
|
input_unregister_device(session->input);
|
||
|
- if (session->hid)
|
||
|
+ session->input = NULL;
|
||
|
+ }
|
||
|
+
|
||
|
+ if (session->hid) {
|
||
|
hid_destroy_device(session->hid);
|
||
|
-err_skb:
|
||
|
+ session->hid = NULL;
|
||
|
+ }
|
||
|
+
|
||
|
+purge:
|
||
|
skb_queue_purge(&session->ctrl_transmit);
|
||
|
skb_queue_purge(&session->intr_transmit);
|
||
|
+
|
||
|
failed:
|
||
|
up_write(&hidp_session_sem);
|
||
|
|
||
|
diff --git a/net/bluetooth/hidp/hidp.h b/net/bluetooth/hidp/hidp.h
|
||
|
index e503c89..faf3d74 100644
|
||
|
--- a/net/bluetooth/hidp/hidp.h
|
||
|
+++ b/net/bluetooth/hidp/hidp.h
|
||
|
@@ -126,6 +126,8 @@ int hidp_get_conninfo(struct hidp_conninfo *ci);
|
||
|
struct hidp_session {
|
||
|
struct list_head list;
|
||
|
|
||
|
+ struct hci_conn *conn;
|
||
|
+
|
||
|
struct socket *ctrl_sock;
|
||
|
struct socket *intr_sock;
|
||
|
|
||
|
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
|
||
|
index 0936fc2..9e50fdb 100644
|
||
|
--- a/net/mac80211/rx.c
|
||
|
+++ b/net/mac80211/rx.c
|
||
|
@@ -2155,11 +2155,17 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw,
|
||
|
|
||
|
skb = rx.skb;
|
||
|
|
||
|
- list_for_each_entry_rcu(sdata, &local->interfaces, list) {
|
||
|
+ if (rx.sdata && ieee80211_is_data(hdr->frame_control)) {
|
||
|
+ rx.flags |= IEEE80211_RX_RA_MATCH;
|
||
|
+ prepares = prepare_for_handlers(rx.sdata, &rx, hdr);
|
||
|
+ if (prepares)
|
||
|
+ prev = rx.sdata;
|
||
|
+ } else list_for_each_entry_rcu(sdata, &local->interfaces, list) {
|
||
|
if (!netif_running(sdata->dev))
|
||
|
continue;
|
||
|
|
||
|
- if (sdata->vif.type == NL80211_IFTYPE_MONITOR)
|
||
|
+ if (sdata->vif.type == NL80211_IFTYPE_MONITOR ||
|
||
|
+ sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
|
||
|
continue;
|
||
|
|
||
|
rx.flags |= IEEE80211_RX_RA_MATCH;
|
||
|
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c
|
||
|
index a360bce..5ccfd10 100644
|
||
|
--- a/net/mac80211/sta_info.c
|
||
|
+++ b/net/mac80211/sta_info.c
|
||
|
@@ -360,6 +360,7 @@ int sta_info_insert(struct sta_info *sta)
|
||
|
u.ap);
|
||
|
|
||
|
drv_sta_notify(local, &sdata->vif, STA_NOTIFY_ADD, &sta->sta);
|
||
|
+ sdata = sta->sdata;
|
||
|
}
|
||
|
|
||
|
#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
|
||
|
@@ -494,6 +495,7 @@ static void __sta_info_unlink(struct sta_info **sta)
|
||
|
|
||
|
drv_sta_notify(local, &sdata->vif, STA_NOTIFY_REMOVE,
|
||
|
&(*sta)->sta);
|
||
|
+ sdata = (*sta)->sdata;
|
||
|
}
|
||
|
|
||
|
if (ieee80211_vif_is_mesh(&sdata->vif)) {
|
||
|
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
|
||
|
index 3a8922c..98576d4 100644
|
||
|
--- a/net/mac80211/tx.c
|
||
|
+++ b/net/mac80211/tx.c
|
||
|
@@ -1736,7 +1736,8 @@ int ieee80211_subif_start_xmit(struct sk_buff *skb,
|
||
|
if (!is_multicast_ether_addr(hdr.addr1)) {
|
||
|
rcu_read_lock();
|
||
|
sta = sta_info_get(local, hdr.addr1);
|
||
|
- if (sta)
|
||
|
+ /* XXX: in the future, use sdata to look up the sta */
|
||
|
+ if (sta && sta->sdata == sdata)
|
||
|
sta_flags = get_sta_flags(sta);
|
||
|
rcu_read_unlock();
|
||
|
}
|
||
|
diff --git a/scripts/Makefile.build b/scripts/Makefile.build
|
||
|
index 5c4b7a4..98112d0 100644
|
||
|
--- a/scripts/Makefile.build
|
||
|
+++ b/scripts/Makefile.build
|
||
|
@@ -269,7 +269,8 @@ targets += $(extra-y) $(MAKECMDGOALS) $(always)
|
||
|
# Linker scripts preprocessor (.lds.S -> .lds)
|
||
|
# ---------------------------------------------------------------------------
|
||
|
quiet_cmd_cpp_lds_S = LDS $@
|
||
|
- cmd_cpp_lds_S = $(CPP) $(cpp_flags) -D__ASSEMBLY__ -o $@ $<
|
||
|
+ cmd_cpp_lds_S = $(CPP) $(cpp_flags) -P -C -U$(ARCH) \
|
||
|
+ -D__ASSEMBLY__ -o $@ $<
|
||
|
|
||
|
$(obj)/%.lds: $(src)/%.lds.S FORCE
|
||
|
$(call if_changed_dep,cpp_lds_S)
|
||
|
diff --git a/sound/aoa/codecs/tas.c b/sound/aoa/codecs/tas.c
|
||
|
index f0ebc97..1dd66dd 100644
|
||
|
--- a/sound/aoa/codecs/tas.c
|
||
|
+++ b/sound/aoa/codecs/tas.c
|
||
|
@@ -897,6 +897,15 @@ static int tas_create(struct i2c_adapter *adapter,
|
||
|
client = i2c_new_device(adapter, &info);
|
||
|
if (!client)
|
||
|
return -ENODEV;
|
||
|
+ /*
|
||
|
+ * We know the driver is already loaded, so the device should be
|
||
|
+ * already bound. If not it means binding failed, and then there
|
||
|
+ * is no point in keeping the device instantiated.
|
||
|
+ */
|
||
|
+ if (!client->driver) {
|
||
|
+ i2c_unregister_device(client);
|
||
|
+ return -ENODEV;
|
||
|
+ }
|
||
|
|
||
|
/*
|
||
|
* Let i2c-core delete that device on driver removal.
|
||
|
diff --git a/sound/ppc/keywest.c b/sound/ppc/keywest.c
|
||
|
index 835fa19..bb6819a 100644
|
||
|
--- a/sound/ppc/keywest.c
|
||
|
+++ b/sound/ppc/keywest.c
|
||
|
@@ -59,6 +59,18 @@ static int keywest_attach_adapter(struct i2c_adapter *adapter)
|
||
|
strlcpy(info.type, "keywest", I2C_NAME_SIZE);
|
||
|
info.addr = keywest_ctx->addr;
|
||
|
keywest_ctx->client = i2c_new_device(adapter, &info);
|
||
|
+ if (!keywest_ctx->client)
|
||
|
+ return -ENODEV;
|
||
|
+ /*
|
||
|
+ * We know the driver is already loaded, so the device should be
|
||
|
+ * already bound. If not it means binding failed, and then there
|
||
|
+ * is no point in keeping the device instantiated.
|
||
|
+ */
|
||
|
+ if (!keywest_ctx->client->driver) {
|
||
|
+ i2c_unregister_device(keywest_ctx->client);
|
||
|
+ keywest_ctx->client = NULL;
|
||
|
+ return -ENODEV;
|
||
|
+ }
|
||
|
|
||
|
/*
|
||
|
* Let i2c-core delete that device on driver removal.
|