diff options
290 files changed, 3777 insertions, 2664 deletions
diff --git a/Documentation/devicetree/bindings/input/gpio-keys.txt b/Documentation/devicetree/bindings/input/gpio-keys.txt index a4a38fcf2ed6..44b705767aca 100644 --- a/Documentation/devicetree/bindings/input/gpio-keys.txt +++ b/Documentation/devicetree/bindings/input/gpio-keys.txt | |||
| @@ -10,12 +10,13 @@ Optional properties: | |||
| 10 | Each button (key) is represented as a sub-node of "gpio-keys": | 10 | Each button (key) is represented as a sub-node of "gpio-keys": |
| 11 | Subnode properties: | 11 | Subnode properties: |
| 12 | 12 | ||
| 13 | - gpios: OF device-tree gpio specification. | ||
| 14 | - interrupts: the interrupt line for that input. | ||
| 13 | - label: Descriptive name of the key. | 15 | - label: Descriptive name of the key. |
| 14 | - linux,code: Keycode to emit. | 16 | - linux,code: Keycode to emit. |
| 15 | 17 | ||
| 16 | Required mutual exclusive subnode-properties: | 18 | Note that either "interrupts" or "gpios" properties can be omitted, but not |
| 17 | - gpios: OF device-tree gpio specification. | 19 | both at the same time. Specifying both properties is allowed. |
| 18 | - interrupts: the interrupt line for that input | ||
| 19 | 20 | ||
| 20 | Optional subnode-properties: | 21 | Optional subnode-properties: |
| 21 | - linux,input-type: Specify event type this button/key generates. | 22 | - linux,input-type: Specify event type this button/key generates. |
| @@ -23,6 +24,9 @@ Optional subnode-properties: | |||
| 23 | - debounce-interval: Debouncing interval time in milliseconds. | 24 | - debounce-interval: Debouncing interval time in milliseconds. |
| 24 | If not specified defaults to 5. | 25 | If not specified defaults to 5. |
| 25 | - gpio-key,wakeup: Boolean, button can wake-up the system. | 26 | - gpio-key,wakeup: Boolean, button can wake-up the system. |
| 27 | - linux,can-disable: Boolean, indicates that button is connected | ||
| 28 | to dedicated (not shared) interrupt which can be disabled to | ||
| 29 | suppress events from the button. | ||
| 26 | 30 | ||
| 27 | Example nodes: | 31 | Example nodes: |
| 28 | 32 | ||
diff --git a/Documentation/devicetree/bindings/input/stmpe-keypad.txt b/Documentation/devicetree/bindings/input/stmpe-keypad.txt index 1b97222e8a0b..12bb771d66d4 100644 --- a/Documentation/devicetree/bindings/input/stmpe-keypad.txt +++ b/Documentation/devicetree/bindings/input/stmpe-keypad.txt | |||
| @@ -8,6 +8,8 @@ Optional properties: | |||
| 8 | - debounce-interval : Debouncing interval time in milliseconds | 8 | - debounce-interval : Debouncing interval time in milliseconds |
| 9 | - st,scan-count : Scanning cycles elapsed before key data is updated | 9 | - st,scan-count : Scanning cycles elapsed before key data is updated |
| 10 | - st,no-autorepeat : If specified device will not autorepeat | 10 | - st,no-autorepeat : If specified device will not autorepeat |
| 11 | - keypad,num-rows : See ./matrix-keymap.txt | ||
| 12 | - keypad,num-columns : See ./matrix-keymap.txt | ||
| 11 | 13 | ||
| 12 | Example: | 14 | Example: |
| 13 | 15 | ||
| @@ -1,7 +1,7 @@ | |||
| 1 | VERSION = 3 | 1 | VERSION = 3 |
| 2 | PATCHLEVEL = 19 | 2 | PATCHLEVEL = 19 |
| 3 | SUBLEVEL = 0 | 3 | SUBLEVEL = 0 |
| 4 | EXTRAVERSION = -rc1 | 4 | EXTRAVERSION = -rc3 |
| 5 | NAME = Diseased Newt | 5 | NAME = Diseased Newt |
| 6 | 6 | ||
| 7 | # *DOCUMENTATION* | 7 | # *DOCUMENTATION* |
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index c3a986d45125..1f5eb9aee750 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig | |||
| @@ -61,6 +61,7 @@ config ARM | |||
| 61 | select HAVE_MEMBLOCK | 61 | select HAVE_MEMBLOCK |
| 62 | select HAVE_MOD_ARCH_SPECIFIC if ARM_UNWIND | 62 | select HAVE_MOD_ARCH_SPECIFIC if ARM_UNWIND |
| 63 | select HAVE_OPROFILE if (HAVE_PERF_EVENTS) | 63 | select HAVE_OPROFILE if (HAVE_PERF_EVENTS) |
| 64 | select HAVE_OPTPROBES if !THUMB2_KERNEL | ||
| 64 | select HAVE_PERF_EVENTS | 65 | select HAVE_PERF_EVENTS |
| 65 | select HAVE_PERF_REGS | 66 | select HAVE_PERF_REGS |
| 66 | select HAVE_PERF_USER_STACK_DUMP | 67 | select HAVE_PERF_USER_STACK_DUMP |
diff --git a/arch/arm/Makefile b/arch/arm/Makefile index c1785eec2cf7..7f99cd652203 100644 --- a/arch/arm/Makefile +++ b/arch/arm/Makefile | |||
| @@ -266,6 +266,7 @@ core-$(CONFIG_KVM_ARM_HOST) += arch/arm/kvm/ | |||
| 266 | 266 | ||
| 267 | # If we have a machine-specific directory, then include it in the build. | 267 | # If we have a machine-specific directory, then include it in the build. |
| 268 | core-y += arch/arm/kernel/ arch/arm/mm/ arch/arm/common/ | 268 | core-y += arch/arm/kernel/ arch/arm/mm/ arch/arm/common/ |
| 269 | core-y += arch/arm/probes/ | ||
| 269 | core-y += arch/arm/net/ | 270 | core-y += arch/arm/net/ |
| 270 | core-y += arch/arm/crypto/ | 271 | core-y += arch/arm/crypto/ |
| 271 | core-y += arch/arm/firmware/ | 272 | core-y += arch/arm/firmware/ |
diff --git a/arch/arm/boot/dts/armada-370-db.dts b/arch/arm/boot/dts/armada-370-db.dts index 1466580be295..70b1943a86b1 100644 --- a/arch/arm/boot/dts/armada-370-db.dts +++ b/arch/arm/boot/dts/armada-370-db.dts | |||
| @@ -203,27 +203,3 @@ | |||
| 203 | compatible = "linux,spdif-dir"; | 203 | compatible = "linux,spdif-dir"; |
| 204 | }; | 204 | }; |
| 205 | }; | 205 | }; |
| 206 | |||
| 207 | &pinctrl { | ||
| 208 | /* | ||
| 209 | * These pins might be muxed as I2S by | ||
| 210 | * the bootloader, but it conflicts | ||
| 211 | * with the real I2S pins that are | ||
| 212 | * muxed using i2s_pins. We must mux | ||
| 213 | * those pins to a function other than | ||
| 214 | * I2S. | ||
| 215 | */ | ||
| 216 | pinctrl-0 = <&hog_pins1 &hog_pins2>; | ||
| 217 | pinctrl-names = "default"; | ||
| 218 | |||
| 219 | hog_pins1: hog-pins1 { | ||
| 220 | marvell,pins = "mpp6", "mpp8", "mpp10", | ||
| 221 | "mpp12", "mpp13"; | ||
| 222 | marvell,function = "gpio"; | ||
| 223 | }; | ||
| 224 | |||
| 225 | hog_pins2: hog-pins2 { | ||
| 226 | marvell,pins = "mpp5", "mpp7", "mpp9"; | ||
| 227 | marvell,function = "gpo"; | ||
| 228 | }; | ||
| 229 | }; | ||
diff --git a/arch/arm/configs/multi_v7_defconfig b/arch/arm/configs/multi_v7_defconfig index 2328fe752e9c..bc393b7e5ece 100644 --- a/arch/arm/configs/multi_v7_defconfig +++ b/arch/arm/configs/multi_v7_defconfig | |||
| @@ -338,6 +338,7 @@ CONFIG_USB=y | |||
| 338 | CONFIG_USB_XHCI_HCD=y | 338 | CONFIG_USB_XHCI_HCD=y |
| 339 | CONFIG_USB_XHCI_MVEBU=y | 339 | CONFIG_USB_XHCI_MVEBU=y |
| 340 | CONFIG_USB_EHCI_HCD=y | 340 | CONFIG_USB_EHCI_HCD=y |
| 341 | CONFIG_USB_EHCI_EXYNOS=y | ||
| 341 | CONFIG_USB_EHCI_TEGRA=y | 342 | CONFIG_USB_EHCI_TEGRA=y |
| 342 | CONFIG_USB_EHCI_HCD_STI=y | 343 | CONFIG_USB_EHCI_HCD_STI=y |
| 343 | CONFIG_USB_EHCI_HCD_PLATFORM=y | 344 | CONFIG_USB_EHCI_HCD_PLATFORM=y |
diff --git a/arch/arm/kernel/insn.h b/arch/arm/include/asm/insn.h index e96065da4dae..e96065da4dae 100644 --- a/arch/arm/kernel/insn.h +++ b/arch/arm/include/asm/insn.h | |||
diff --git a/arch/arm/include/asm/kprobes.h b/arch/arm/include/asm/kprobes.h index 49fa0dfaad33..3ea9be559726 100644 --- a/arch/arm/include/asm/kprobes.h +++ b/arch/arm/include/asm/kprobes.h | |||
| @@ -22,7 +22,6 @@ | |||
| 22 | 22 | ||
| 23 | #define __ARCH_WANT_KPROBES_INSN_SLOT | 23 | #define __ARCH_WANT_KPROBES_INSN_SLOT |
| 24 | #define MAX_INSN_SIZE 2 | 24 | #define MAX_INSN_SIZE 2 |
| 25 | #define MAX_STACK_SIZE 64 /* 32 would probably be OK */ | ||
| 26 | 25 | ||
| 27 | #define flush_insn_slot(p) do { } while (0) | 26 | #define flush_insn_slot(p) do { } while (0) |
| 28 | #define kretprobe_blacklist_size 0 | 27 | #define kretprobe_blacklist_size 0 |
| @@ -51,5 +50,37 @@ int kprobe_fault_handler(struct pt_regs *regs, unsigned int fsr); | |||
| 51 | int kprobe_exceptions_notify(struct notifier_block *self, | 50 | int kprobe_exceptions_notify(struct notifier_block *self, |
| 52 | unsigned long val, void *data); | 51 | unsigned long val, void *data); |
| 53 | 52 | ||
| 53 | /* optinsn template addresses */ | ||
| 54 | extern __visible kprobe_opcode_t optprobe_template_entry; | ||
| 55 | extern __visible kprobe_opcode_t optprobe_template_val; | ||
| 56 | extern __visible kprobe_opcode_t optprobe_template_call; | ||
| 57 | extern __visible kprobe_opcode_t optprobe_template_end; | ||
| 58 | extern __visible kprobe_opcode_t optprobe_template_sub_sp; | ||
| 59 | extern __visible kprobe_opcode_t optprobe_template_add_sp; | ||
| 60 | extern __visible kprobe_opcode_t optprobe_template_restore_begin; | ||
| 61 | extern __visible kprobe_opcode_t optprobe_template_restore_orig_insn; | ||
| 62 | extern __visible kprobe_opcode_t optprobe_template_restore_end; | ||
| 63 | |||
| 64 | #define MAX_OPTIMIZED_LENGTH 4 | ||
| 65 | #define MAX_OPTINSN_SIZE \ | ||
| 66 | ((unsigned long)&optprobe_template_end - \ | ||
| 67 | (unsigned long)&optprobe_template_entry) | ||
| 68 | #define RELATIVEJUMP_SIZE 4 | ||
| 69 | |||
| 70 | struct arch_optimized_insn { | ||
| 71 | /* | ||
| 72 | * copy of the original instructions. | ||
| 73 | * Different from x86, ARM kprobe_opcode_t is u32. | ||
| 74 | */ | ||
| 75 | #define MAX_COPIED_INSN DIV_ROUND_UP(RELATIVEJUMP_SIZE, sizeof(kprobe_opcode_t)) | ||
| 76 | kprobe_opcode_t copied_insn[MAX_COPIED_INSN]; | ||
| 77 | /* detour code buffer */ | ||
| 78 | kprobe_opcode_t *insn; | ||
| 79 | /* | ||
| 80 | * We always copy one instruction on ARM, | ||
| 81 | * so size will always be 4, and unlike x86, there is no | ||
| 82 | * need for a size field. | ||
| 83 | */ | ||
| 84 | }; | ||
| 54 | 85 | ||
| 55 | #endif /* _ARM_KPROBES_H */ | 86 | #endif /* _ARM_KPROBES_H */ |
diff --git a/arch/arm/kernel/patch.h b/arch/arm/include/asm/patch.h index 77e054c2f6cd..77e054c2f6cd 100644 --- a/arch/arm/kernel/patch.h +++ b/arch/arm/include/asm/patch.h | |||
diff --git a/arch/arm/include/asm/probes.h b/arch/arm/include/asm/probes.h index 806cfe622a9e..1e5b9bb92270 100644 --- a/arch/arm/include/asm/probes.h +++ b/arch/arm/include/asm/probes.h | |||
| @@ -19,6 +19,8 @@ | |||
| 19 | #ifndef _ASM_PROBES_H | 19 | #ifndef _ASM_PROBES_H |
| 20 | #define _ASM_PROBES_H | 20 | #define _ASM_PROBES_H |
| 21 | 21 | ||
| 22 | #ifndef __ASSEMBLY__ | ||
| 23 | |||
| 22 | typedef u32 probes_opcode_t; | 24 | typedef u32 probes_opcode_t; |
| 23 | 25 | ||
| 24 | struct arch_probes_insn; | 26 | struct arch_probes_insn; |
| @@ -38,6 +40,19 @@ struct arch_probes_insn { | |||
| 38 | probes_check_cc *insn_check_cc; | 40 | probes_check_cc *insn_check_cc; |
| 39 | probes_insn_singlestep_t *insn_singlestep; | 41 | probes_insn_singlestep_t *insn_singlestep; |
| 40 | probes_insn_fn_t *insn_fn; | 42 | probes_insn_fn_t *insn_fn; |
| 43 | int stack_space; | ||
| 44 | unsigned long register_usage_flags; | ||
| 45 | bool kprobe_direct_exec; | ||
| 41 | }; | 46 | }; |
| 42 | 47 | ||
| 48 | #endif /* __ASSEMBLY__ */ | ||
| 49 | |||
| 50 | /* | ||
| 51 | * We assume one instruction can consume at most 64 bytes stack, which is | ||
| 52 | * 'push {r0-r15}'. Instructions consume more or unknown stack space like | ||
| 53 | * 'str r0, [sp, #-80]' and 'str r0, [sp, r1]' should be prohibit to probe. | ||
| 54 | * Both kprobe and jprobe use this macro. | ||
| 55 | */ | ||
| 56 | #define MAX_STACK_SIZE 64 | ||
| 57 | |||
| 43 | #endif | 58 | #endif |
diff --git a/arch/arm/kernel/Makefile b/arch/arm/kernel/Makefile index fb2b71ebe3f2..902397dd1000 100644 --- a/arch/arm/kernel/Makefile +++ b/arch/arm/kernel/Makefile | |||
| @@ -51,20 +51,8 @@ obj-$(CONFIG_DYNAMIC_FTRACE) += ftrace.o insn.o | |||
| 51 | obj-$(CONFIG_FUNCTION_GRAPH_TRACER) += ftrace.o insn.o | 51 | obj-$(CONFIG_FUNCTION_GRAPH_TRACER) += ftrace.o insn.o |
| 52 | obj-$(CONFIG_JUMP_LABEL) += jump_label.o insn.o patch.o | 52 | obj-$(CONFIG_JUMP_LABEL) += jump_label.o insn.o patch.o |
| 53 | obj-$(CONFIG_KEXEC) += machine_kexec.o relocate_kernel.o | 53 | obj-$(CONFIG_KEXEC) += machine_kexec.o relocate_kernel.o |
| 54 | obj-$(CONFIG_UPROBES) += probes.o probes-arm.o uprobes.o uprobes-arm.o | 54 | # Main staffs in KPROBES are in arch/arm/probes/ . |
| 55 | obj-$(CONFIG_KPROBES) += probes.o kprobes.o kprobes-common.o patch.o | 55 | obj-$(CONFIG_KPROBES) += patch.o insn.o |
| 56 | ifdef CONFIG_THUMB2_KERNEL | ||
| 57 | obj-$(CONFIG_KPROBES) += kprobes-thumb.o probes-thumb.o | ||
| 58 | else | ||
| 59 | obj-$(CONFIG_KPROBES) += kprobes-arm.o probes-arm.o | ||
| 60 | endif | ||
| 61 | obj-$(CONFIG_ARM_KPROBES_TEST) += test-kprobes.o | ||
| 62 | test-kprobes-objs := kprobes-test.o | ||
| 63 | ifdef CONFIG_THUMB2_KERNEL | ||
| 64 | test-kprobes-objs += kprobes-test-thumb.o | ||
| 65 | else | ||
| 66 | test-kprobes-objs += kprobes-test-arm.o | ||
| 67 | endif | ||
| 68 | obj-$(CONFIG_OABI_COMPAT) += sys_oabi-compat.o | 56 | obj-$(CONFIG_OABI_COMPAT) += sys_oabi-compat.o |
| 69 | obj-$(CONFIG_ARM_THUMBEE) += thumbee.o | 57 | obj-$(CONFIG_ARM_THUMBEE) += thumbee.o |
| 70 | obj-$(CONFIG_KGDB) += kgdb.o patch.o | 58 | obj-$(CONFIG_KGDB) += kgdb.o patch.o |
diff --git a/arch/arm/kernel/entry-armv.S b/arch/arm/kernel/entry-armv.S index 2f5555d307b3..672b21942fff 100644 --- a/arch/arm/kernel/entry-armv.S +++ b/arch/arm/kernel/entry-armv.S | |||
| @@ -31,6 +31,7 @@ | |||
| 31 | 31 | ||
| 32 | #include "entry-header.S" | 32 | #include "entry-header.S" |
| 33 | #include <asm/entry-macro-multi.S> | 33 | #include <asm/entry-macro-multi.S> |
| 34 | #include <asm/probes.h> | ||
| 34 | 35 | ||
| 35 | /* | 36 | /* |
| 36 | * Interrupt handling. | 37 | * Interrupt handling. |
| @@ -249,7 +250,7 @@ __und_svc: | |||
| 249 | @ If a kprobe is about to simulate a "stmdb sp..." instruction, | 250 | @ If a kprobe is about to simulate a "stmdb sp..." instruction, |
| 250 | @ it obviously needs free stack space which then will belong to | 251 | @ it obviously needs free stack space which then will belong to |
| 251 | @ the saved context. | 252 | @ the saved context. |
| 252 | svc_entry 64 | 253 | svc_entry MAX_STACK_SIZE |
| 253 | #else | 254 | #else |
| 254 | svc_entry | 255 | svc_entry |
| 255 | #endif | 256 | #endif |
diff --git a/arch/arm/kernel/ftrace.c b/arch/arm/kernel/ftrace.c index b8c75e45a950..709ee1d6d4df 100644 --- a/arch/arm/kernel/ftrace.c +++ b/arch/arm/kernel/ftrace.c | |||
| @@ -20,8 +20,7 @@ | |||
| 20 | #include <asm/cacheflush.h> | 20 | #include <asm/cacheflush.h> |
| 21 | #include <asm/opcodes.h> | 21 | #include <asm/opcodes.h> |
| 22 | #include <asm/ftrace.h> | 22 | #include <asm/ftrace.h> |
| 23 | 23 | #include <asm/insn.h> | |
| 24 | #include "insn.h" | ||
| 25 | 24 | ||
| 26 | #ifdef CONFIG_THUMB2_KERNEL | 25 | #ifdef CONFIG_THUMB2_KERNEL |
| 27 | #define NOP 0xf85deb04 /* pop.w {lr} */ | 26 | #define NOP 0xf85deb04 /* pop.w {lr} */ |
diff --git a/arch/arm/kernel/jump_label.c b/arch/arm/kernel/jump_label.c index afeeb9ea6f43..e39cbf488cfe 100644 --- a/arch/arm/kernel/jump_label.c +++ b/arch/arm/kernel/jump_label.c | |||
| @@ -1,8 +1,7 @@ | |||
| 1 | #include <linux/kernel.h> | 1 | #include <linux/kernel.h> |
| 2 | #include <linux/jump_label.h> | 2 | #include <linux/jump_label.h> |
| 3 | 3 | #include <asm/patch.h> | |
| 4 | #include "insn.h" | 4 | #include <asm/insn.h> |
| 5 | #include "patch.h" | ||
| 6 | 5 | ||
| 7 | #ifdef HAVE_JUMP_LABEL | 6 | #ifdef HAVE_JUMP_LABEL |
| 8 | 7 | ||
diff --git a/arch/arm/kernel/kgdb.c b/arch/arm/kernel/kgdb.c index 07db2f8a1b45..a6ad93c9bce3 100644 --- a/arch/arm/kernel/kgdb.c +++ b/arch/arm/kernel/kgdb.c | |||
| @@ -14,10 +14,9 @@ | |||
| 14 | #include <linux/kgdb.h> | 14 | #include <linux/kgdb.h> |
| 15 | #include <linux/uaccess.h> | 15 | #include <linux/uaccess.h> |
| 16 | 16 | ||
| 17 | #include <asm/patch.h> | ||
| 17 | #include <asm/traps.h> | 18 | #include <asm/traps.h> |
| 18 | 19 | ||
| 19 | #include "patch.h" | ||
| 20 | |||
| 21 | struct dbg_reg_def_t dbg_reg_def[DBG_MAX_REG_NUM] = | 20 | struct dbg_reg_def_t dbg_reg_def[DBG_MAX_REG_NUM] = |
| 22 | { | 21 | { |
| 23 | { "r0", 4, offsetof(struct pt_regs, ARM_r0)}, | 22 | { "r0", 4, offsetof(struct pt_regs, ARM_r0)}, |
diff --git a/arch/arm/kernel/patch.c b/arch/arm/kernel/patch.c index 5038960e3c55..69bda1a5707e 100644 --- a/arch/arm/kernel/patch.c +++ b/arch/arm/kernel/patch.c | |||
| @@ -8,8 +8,7 @@ | |||
| 8 | #include <asm/fixmap.h> | 8 | #include <asm/fixmap.h> |
| 9 | #include <asm/smp_plat.h> | 9 | #include <asm/smp_plat.h> |
| 10 | #include <asm/opcodes.h> | 10 | #include <asm/opcodes.h> |
| 11 | 11 | #include <asm/patch.h> | |
| 12 | #include "patch.h" | ||
| 13 | 12 | ||
| 14 | struct patch { | 13 | struct patch { |
| 15 | void *addr; | 14 | void *addr; |
diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c index d13f185e7bd5..e55408e96559 100644 --- a/arch/arm/kernel/setup.c +++ b/arch/arm/kernel/setup.c | |||
| @@ -1049,6 +1049,15 @@ static int c_show(struct seq_file *m, void *v) | |||
| 1049 | seq_printf(m, "model name\t: %s rev %d (%s)\n", | 1049 | seq_printf(m, "model name\t: %s rev %d (%s)\n", |
| 1050 | cpu_name, cpuid & 15, elf_platform); | 1050 | cpu_name, cpuid & 15, elf_platform); |
| 1051 | 1051 | ||
| 1052 | #if defined(CONFIG_SMP) | ||
| 1053 | seq_printf(m, "BogoMIPS\t: %lu.%02lu\n", | ||
| 1054 | per_cpu(cpu_data, i).loops_per_jiffy / (500000UL/HZ), | ||
| 1055 | (per_cpu(cpu_data, i).loops_per_jiffy / (5000UL/HZ)) % 100); | ||
| 1056 | #else | ||
| 1057 | seq_printf(m, "BogoMIPS\t: %lu.%02lu\n", | ||
| 1058 | loops_per_jiffy / (500000/HZ), | ||
| 1059 | (loops_per_jiffy / (5000/HZ)) % 100); | ||
| 1060 | #endif | ||
| 1052 | /* dump out the processor features */ | 1061 | /* dump out the processor features */ |
| 1053 | seq_puts(m, "Features\t: "); | 1062 | seq_puts(m, "Features\t: "); |
| 1054 | 1063 | ||
diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c index 5e6052e18850..86ef244c5a24 100644 --- a/arch/arm/kernel/smp.c +++ b/arch/arm/kernel/smp.c | |||
| @@ -387,6 +387,18 @@ asmlinkage void secondary_start_kernel(void) | |||
| 387 | 387 | ||
| 388 | void __init smp_cpus_done(unsigned int max_cpus) | 388 | void __init smp_cpus_done(unsigned int max_cpus) |
| 389 | { | 389 | { |
| 390 | int cpu; | ||
| 391 | unsigned long bogosum = 0; | ||
| 392 | |||
| 393 | for_each_online_cpu(cpu) | ||
| 394 | bogosum += per_cpu(cpu_data, cpu).loops_per_jiffy; | ||
| 395 | |||
| 396 | printk(KERN_INFO "SMP: Total of %d processors activated " | ||
| 397 | "(%lu.%02lu BogoMIPS).\n", | ||
| 398 | num_online_cpus(), | ||
| 399 | bogosum / (500000/HZ), | ||
| 400 | (bogosum / (5000/HZ)) % 100); | ||
| 401 | |||
| 390 | hyp_mode_check(); | 402 | hyp_mode_check(); |
| 391 | } | 403 | } |
| 392 | 404 | ||
diff --git a/arch/arm/probes/Makefile b/arch/arm/probes/Makefile new file mode 100644 index 000000000000..aa1f8590dcdd --- /dev/null +++ b/arch/arm/probes/Makefile | |||
| @@ -0,0 +1,7 @@ | |||
| 1 | obj-$(CONFIG_UPROBES) += decode.o decode-arm.o uprobes/ | ||
| 2 | obj-$(CONFIG_KPROBES) += decode.o kprobes/ | ||
| 3 | ifdef CONFIG_THUMB2_KERNEL | ||
| 4 | obj-$(CONFIG_KPROBES) += decode-thumb.o | ||
| 5 | else | ||
| 6 | obj-$(CONFIG_KPROBES) += decode-arm.o | ||
| 7 | endif | ||
diff --git a/arch/arm/kernel/probes-arm.c b/arch/arm/probes/decode-arm.c index 8eaef81d8344..f72c33a2dcfb 100644 --- a/arch/arm/kernel/probes-arm.c +++ b/arch/arm/probes/decode-arm.c | |||
| @@ -1,5 +1,6 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * arch/arm/kernel/probes-arm.c | 2 | * |
| 3 | * arch/arm/probes/decode-arm.c | ||
| 3 | * | 4 | * |
| 4 | * Some code moved here from arch/arm/kernel/kprobes-arm.c | 5 | * Some code moved here from arch/arm/kernel/kprobes-arm.c |
| 5 | * | 6 | * |
| @@ -20,8 +21,8 @@ | |||
| 20 | #include <linux/stddef.h> | 21 | #include <linux/stddef.h> |
| 21 | #include <linux/ptrace.h> | 22 | #include <linux/ptrace.h> |
| 22 | 23 | ||
| 23 | #include "probes.h" | 24 | #include "decode.h" |
| 24 | #include "probes-arm.h" | 25 | #include "decode-arm.h" |
| 25 | 26 | ||
| 26 | #define sign_extend(x, signbit) ((x) | (0 - ((x) & (1 << (signbit))))) | 27 | #define sign_extend(x, signbit) ((x) | (0 - ((x) & (1 << (signbit))))) |
| 27 | 28 | ||
| @@ -369,17 +370,17 @@ static const union decode_item arm_cccc_001x_table[] = { | |||
| 369 | 370 | ||
| 370 | /* MOVW cccc 0011 0000 xxxx xxxx xxxx xxxx xxxx */ | 371 | /* MOVW cccc 0011 0000 xxxx xxxx xxxx xxxx xxxx */ |
| 371 | /* MOVT cccc 0011 0100 xxxx xxxx xxxx xxxx xxxx */ | 372 | /* MOVT cccc 0011 0100 xxxx xxxx xxxx xxxx xxxx */ |
| 372 | DECODE_EMULATEX (0x0fb00000, 0x03000000, PROBES_DATA_PROCESSING_IMM, | 373 | DECODE_EMULATEX (0x0fb00000, 0x03000000, PROBES_MOV_HALFWORD, |
| 373 | REGS(0, NOPC, 0, 0, 0)), | 374 | REGS(0, NOPC, 0, 0, 0)), |
| 374 | 375 | ||
| 375 | /* YIELD cccc 0011 0010 0000 xxxx xxxx 0000 0001 */ | 376 | /* YIELD cccc 0011 0010 0000 xxxx xxxx 0000 0001 */ |
| 376 | DECODE_OR (0x0fff00ff, 0x03200001), | 377 | DECODE_OR (0x0fff00ff, 0x03200001), |
| 377 | /* SEV cccc 0011 0010 0000 xxxx xxxx 0000 0100 */ | 378 | /* SEV cccc 0011 0010 0000 xxxx xxxx 0000 0100 */ |
| 378 | DECODE_EMULATE (0x0fff00ff, 0x03200004, PROBES_EMULATE_NONE), | 379 | DECODE_EMULATE (0x0fff00ff, 0x03200004, PROBES_SEV), |
| 379 | /* NOP cccc 0011 0010 0000 xxxx xxxx 0000 0000 */ | 380 | /* NOP cccc 0011 0010 0000 xxxx xxxx 0000 0000 */ |
| 380 | /* WFE cccc 0011 0010 0000 xxxx xxxx 0000 0010 */ | 381 | /* WFE cccc 0011 0010 0000 xxxx xxxx 0000 0010 */ |
| 381 | /* WFI cccc 0011 0010 0000 xxxx xxxx 0000 0011 */ | 382 | /* WFI cccc 0011 0010 0000 xxxx xxxx 0000 0011 */ |
| 382 | DECODE_SIMULATE (0x0fff00fc, 0x03200000, PROBES_SIMULATE_NOP), | 383 | DECODE_SIMULATE (0x0fff00fc, 0x03200000, PROBES_WFE), |
| 383 | /* DBG cccc 0011 0010 0000 xxxx xxxx ffff xxxx */ | 384 | /* DBG cccc 0011 0010 0000 xxxx xxxx ffff xxxx */ |
| 384 | /* unallocated hints cccc 0011 0010 0000 xxxx xxxx xxxx xxxx */ | 385 | /* unallocated hints cccc 0011 0010 0000 xxxx xxxx xxxx xxxx */ |
| 385 | /* MSR (immediate) cccc 0011 0x10 xxxx xxxx xxxx xxxx xxxx */ | 386 | /* MSR (immediate) cccc 0011 0x10 xxxx xxxx xxxx xxxx xxxx */ |
| @@ -725,10 +726,11 @@ static void __kprobes arm_singlestep(probes_opcode_t insn, | |||
| 725 | */ | 726 | */ |
| 726 | enum probes_insn __kprobes | 727 | enum probes_insn __kprobes |
| 727 | arm_probes_decode_insn(probes_opcode_t insn, struct arch_probes_insn *asi, | 728 | arm_probes_decode_insn(probes_opcode_t insn, struct arch_probes_insn *asi, |
| 728 | bool emulate, const union decode_action *actions) | 729 | bool emulate, const union decode_action *actions, |
| 730 | const struct decode_checker *checkers[]) | ||
| 729 | { | 731 | { |
| 730 | asi->insn_singlestep = arm_singlestep; | 732 | asi->insn_singlestep = arm_singlestep; |
| 731 | asi->insn_check_cc = probes_condition_checks[insn>>28]; | 733 | asi->insn_check_cc = probes_condition_checks[insn>>28]; |
| 732 | return probes_decode_insn(insn, asi, probes_decode_arm_table, false, | 734 | return probes_decode_insn(insn, asi, probes_decode_arm_table, false, |
| 733 | emulate, actions); | 735 | emulate, actions, checkers); |
| 734 | } | 736 | } |
diff --git a/arch/arm/kernel/probes-arm.h b/arch/arm/probes/decode-arm.h index ace6572f6e26..b3b80f6d414b 100644 --- a/arch/arm/kernel/probes-arm.h +++ b/arch/arm/probes/decode-arm.h | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * arch/arm/kernel/probes-arm.h | 2 | * arch/arm/probes/decode-arm.h |
| 3 | * | 3 | * |
| 4 | * Copyright 2013 Linaro Ltd. | 4 | * Copyright 2013 Linaro Ltd. |
| 5 | * Written by: David A. Long | 5 | * Written by: David A. Long |
| @@ -15,9 +15,9 @@ | |||
| 15 | #ifndef _ARM_KERNEL_PROBES_ARM_H | 15 | #ifndef _ARM_KERNEL_PROBES_ARM_H |
| 16 | #define _ARM_KERNEL_PROBES_ARM_H | 16 | #define _ARM_KERNEL_PROBES_ARM_H |
| 17 | 17 | ||
| 18 | #include "decode.h" | ||
| 19 | |||
| 18 | enum probes_arm_action { | 20 | enum probes_arm_action { |
| 19 | PROBES_EMULATE_NONE, | ||
| 20 | PROBES_SIMULATE_NOP, | ||
| 21 | PROBES_PRELOAD_IMM, | 21 | PROBES_PRELOAD_IMM, |
| 22 | PROBES_PRELOAD_REG, | 22 | PROBES_PRELOAD_REG, |
| 23 | PROBES_BRANCH_IMM, | 23 | PROBES_BRANCH_IMM, |
| @@ -68,6 +68,7 @@ extern const union decode_item probes_decode_arm_table[]; | |||
| 68 | 68 | ||
| 69 | enum probes_insn arm_probes_decode_insn(probes_opcode_t, | 69 | enum probes_insn arm_probes_decode_insn(probes_opcode_t, |
| 70 | struct arch_probes_insn *, bool emulate, | 70 | struct arch_probes_insn *, bool emulate, |
| 71 | const union decode_action *actions); | 71 | const union decode_action *actions, |
| 72 | const struct decode_checker *checkers[]); | ||
| 72 | 73 | ||
| 73 | #endif | 74 | #endif |
diff --git a/arch/arm/kernel/probes-thumb.c b/arch/arm/probes/decode-thumb.c index 4131351e812f..985e7dd4cac6 100644 --- a/arch/arm/kernel/probes-thumb.c +++ b/arch/arm/probes/decode-thumb.c | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * arch/arm/kernel/probes-thumb.c | 2 | * arch/arm/probes/decode-thumb.c |
| 3 | * | 3 | * |
| 4 | * Copyright (C) 2011 Jon Medhurst <tixy@yxit.co.uk>. | 4 | * Copyright (C) 2011 Jon Medhurst <tixy@yxit.co.uk>. |
| 5 | * | 5 | * |
| @@ -12,8 +12,8 @@ | |||
| 12 | #include <linux/kernel.h> | 12 | #include <linux/kernel.h> |
| 13 | #include <linux/module.h> | 13 | #include <linux/module.h> |
| 14 | 14 | ||
| 15 | #include "probes.h" | 15 | #include "decode.h" |
| 16 | #include "probes-thumb.h" | 16 | #include "decode-thumb.h" |
| 17 | 17 | ||
| 18 | 18 | ||
| 19 | static const union decode_item t32_table_1110_100x_x0xx[] = { | 19 | static const union decode_item t32_table_1110_100x_x0xx[] = { |
| @@ -863,20 +863,22 @@ static void __kprobes thumb32_singlestep(probes_opcode_t opcode, | |||
| 863 | 863 | ||
| 864 | enum probes_insn __kprobes | 864 | enum probes_insn __kprobes |
| 865 | thumb16_probes_decode_insn(probes_opcode_t insn, struct arch_probes_insn *asi, | 865 | thumb16_probes_decode_insn(probes_opcode_t insn, struct arch_probes_insn *asi, |
| 866 | bool emulate, const union decode_action *actions) | 866 | bool emulate, const union decode_action *actions, |
| 867 | const struct decode_checker *checkers[]) | ||
| 867 | { | 868 | { |
| 868 | asi->insn_singlestep = thumb16_singlestep; | 869 | asi->insn_singlestep = thumb16_singlestep; |
| 869 | asi->insn_check_cc = thumb_check_cc; | 870 | asi->insn_check_cc = thumb_check_cc; |
| 870 | return probes_decode_insn(insn, asi, probes_decode_thumb16_table, true, | 871 | return probes_decode_insn(insn, asi, probes_decode_thumb16_table, true, |
| 871 | emulate, actions); | 872 | emulate, actions, checkers); |
| 872 | } | 873 | } |
| 873 | 874 | ||
| 874 | enum probes_insn __kprobes | 875 | enum probes_insn __kprobes |
| 875 | thumb32_probes_decode_insn(probes_opcode_t insn, struct arch_probes_insn *asi, | 876 | thumb32_probes_decode_insn(probes_opcode_t insn, struct arch_probes_insn *asi, |
| 876 | bool emulate, const union decode_action *actions) | 877 | bool emulate, const union decode_action *actions, |
| 878 | const struct decode_checker *checkers[]) | ||
| 877 | { | 879 | { |
| 878 | asi->insn_singlestep = thumb32_singlestep; | 880 | asi->insn_singlestep = thumb32_singlestep; |
| 879 | asi->insn_check_cc = thumb_check_cc; | 881 | asi->insn_check_cc = thumb_check_cc; |
| 880 | return probes_decode_insn(insn, asi, probes_decode_thumb32_table, true, | 882 | return probes_decode_insn(insn, asi, probes_decode_thumb32_table, true, |
| 881 | emulate, actions); | 883 | emulate, actions, checkers); |
| 882 | } | 884 | } |
diff --git a/arch/arm/kernel/probes-thumb.h b/arch/arm/probes/decode-thumb.h index 7c6f6ebe514f..8457add0a2d8 100644 --- a/arch/arm/kernel/probes-thumb.h +++ b/arch/arm/probes/decode-thumb.h | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * arch/arm/kernel/probes-thumb.h | 2 | * arch/arm/probes/decode-thumb.h |
| 3 | * | 3 | * |
| 4 | * Copyright 2013 Linaro Ltd. | 4 | * Copyright 2013 Linaro Ltd. |
| 5 | * Written by: David A. Long | 5 | * Written by: David A. Long |
| @@ -15,6 +15,8 @@ | |||
| 15 | #ifndef _ARM_KERNEL_PROBES_THUMB_H | 15 | #ifndef _ARM_KERNEL_PROBES_THUMB_H |
| 16 | #define _ARM_KERNEL_PROBES_THUMB_H | 16 | #define _ARM_KERNEL_PROBES_THUMB_H |
| 17 | 17 | ||
| 18 | #include "decode.h" | ||
| 19 | |||
| 18 | /* | 20 | /* |
| 19 | * True if current instruction is in an IT block. | 21 | * True if current instruction is in an IT block. |
| 20 | */ | 22 | */ |
| @@ -89,9 +91,11 @@ extern const union decode_item probes_decode_thumb16_table[]; | |||
| 89 | 91 | ||
| 90 | enum probes_insn __kprobes | 92 | enum probes_insn __kprobes |
| 91 | thumb16_probes_decode_insn(probes_opcode_t insn, struct arch_probes_insn *asi, | 93 | thumb16_probes_decode_insn(probes_opcode_t insn, struct arch_probes_insn *asi, |
| 92 | bool emulate, const union decode_action *actions); | 94 | bool emulate, const union decode_action *actions, |
| 95 | const struct decode_checker *checkers[]); | ||
| 93 | enum probes_insn __kprobes | 96 | enum probes_insn __kprobes |
| 94 | thumb32_probes_decode_insn(probes_opcode_t insn, struct arch_probes_insn *asi, | 97 | thumb32_probes_decode_insn(probes_opcode_t insn, struct arch_probes_insn *asi, |
| 95 | bool emulate, const union decode_action *actions); | 98 | bool emulate, const union decode_action *actions, |
| 99 | const struct decode_checker *checkers[]); | ||
| 96 | 100 | ||
| 97 | #endif | 101 | #endif |
diff --git a/arch/arm/kernel/probes.c b/arch/arm/probes/decode.c index a8ab540d7e73..880ebe0cdf19 100644 --- a/arch/arm/kernel/probes.c +++ b/arch/arm/probes/decode.c | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * arch/arm/kernel/probes.c | 2 | * arch/arm/probes/decode.c |
| 3 | * | 3 | * |
| 4 | * Copyright (C) 2011 Jon Medhurst <tixy@yxit.co.uk>. | 4 | * Copyright (C) 2011 Jon Medhurst <tixy@yxit.co.uk>. |
| 5 | * | 5 | * |
| @@ -17,7 +17,7 @@ | |||
| 17 | #include <asm/ptrace.h> | 17 | #include <asm/ptrace.h> |
| 18 | #include <linux/bug.h> | 18 | #include <linux/bug.h> |
| 19 | 19 | ||
| 20 | #include "probes.h" | 20 | #include "decode.h" |
| 21 | 21 | ||
| 22 | 22 | ||
| 23 | #ifndef find_str_pc_offset | 23 | #ifndef find_str_pc_offset |
| @@ -342,6 +342,31 @@ static const int decode_struct_sizes[NUM_DECODE_TYPES] = { | |||
| 342 | [DECODE_TYPE_REJECT] = sizeof(struct decode_reject) | 342 | [DECODE_TYPE_REJECT] = sizeof(struct decode_reject) |
| 343 | }; | 343 | }; |
| 344 | 344 | ||
| 345 | static int run_checkers(const struct decode_checker *checkers[], | ||
| 346 | int action, probes_opcode_t insn, | ||
| 347 | struct arch_probes_insn *asi, | ||
| 348 | const struct decode_header *h) | ||
| 349 | { | ||
| 350 | const struct decode_checker **p; | ||
| 351 | |||
| 352 | if (!checkers) | ||
| 353 | return INSN_GOOD; | ||
| 354 | |||
| 355 | p = checkers; | ||
| 356 | while (*p != NULL) { | ||
| 357 | int retval; | ||
| 358 | probes_check_t *checker_func = (*p)[action].checker; | ||
| 359 | |||
| 360 | retval = INSN_GOOD; | ||
| 361 | if (checker_func) | ||
| 362 | retval = checker_func(insn, asi, h); | ||
| 363 | if (retval == INSN_REJECTED) | ||
| 364 | return retval; | ||
| 365 | p++; | ||
| 366 | } | ||
| 367 | return INSN_GOOD; | ||
| 368 | } | ||
| 369 | |||
| 345 | /* | 370 | /* |
| 346 | * probes_decode_insn operates on data tables in order to decode an ARM | 371 | * probes_decode_insn operates on data tables in order to decode an ARM |
| 347 | * architecture instruction onto which a kprobe has been placed. | 372 | * architecture instruction onto which a kprobe has been placed. |
| @@ -388,11 +413,34 @@ static const int decode_struct_sizes[NUM_DECODE_TYPES] = { | |||
| 388 | int __kprobes | 413 | int __kprobes |
| 389 | probes_decode_insn(probes_opcode_t insn, struct arch_probes_insn *asi, | 414 | probes_decode_insn(probes_opcode_t insn, struct arch_probes_insn *asi, |
| 390 | const union decode_item *table, bool thumb, | 415 | const union decode_item *table, bool thumb, |
| 391 | bool emulate, const union decode_action *actions) | 416 | bool emulate, const union decode_action *actions, |
| 417 | const struct decode_checker *checkers[]) | ||
| 392 | { | 418 | { |
| 393 | const struct decode_header *h = (struct decode_header *)table; | 419 | const struct decode_header *h = (struct decode_header *)table; |
| 394 | const struct decode_header *next; | 420 | const struct decode_header *next; |
| 395 | bool matched = false; | 421 | bool matched = false; |
| 422 | /* | ||
| 423 | * @insn can be modified by decode_regs. Save its original | ||
| 424 | * value for checkers. | ||
| 425 | */ | ||
| 426 | probes_opcode_t origin_insn = insn; | ||
| 427 | |||
| 428 | /* | ||
| 429 | * stack_space is initialized to 0 here. Checker functions | ||
| 430 | * should update is value if they find this is a stack store | ||
| 431 | * instruction: positive value means bytes of stack usage, | ||
| 432 | * negitive value means unable to determine stack usage | ||
| 433 | * statically. For instruction doesn't store to stack, checker | ||
| 434 | * do nothing with it. | ||
| 435 | */ | ||
| 436 | asi->stack_space = 0; | ||
| 437 | |||
| 438 | /* | ||
| 439 | * Similarly to stack_space, register_usage_flags is filled by | ||
| 440 | * checkers. Its default value is set to ~0, which is 'all | ||
| 441 | * registers are used', to prevent any potential optimization. | ||
| 442 | */ | ||
| 443 | asi->register_usage_flags = ~0UL; | ||
| 396 | 444 | ||
| 397 | if (emulate) | 445 | if (emulate) |
| 398 | insn = prepare_emulated_insn(insn, asi, thumb); | 446 | insn = prepare_emulated_insn(insn, asi, thumb); |
| @@ -422,24 +470,41 @@ probes_decode_insn(probes_opcode_t insn, struct arch_probes_insn *asi, | |||
| 422 | } | 470 | } |
| 423 | 471 | ||
| 424 | case DECODE_TYPE_CUSTOM: { | 472 | case DECODE_TYPE_CUSTOM: { |
| 473 | int err; | ||
| 425 | struct decode_custom *d = (struct decode_custom *)h; | 474 | struct decode_custom *d = (struct decode_custom *)h; |
| 426 | return actions[d->decoder.action].decoder(insn, asi, h); | 475 | int action = d->decoder.action; |
| 476 | |||
| 477 | err = run_checkers(checkers, action, origin_insn, asi, h); | ||
| 478 | if (err == INSN_REJECTED) | ||
| 479 | return INSN_REJECTED; | ||
| 480 | return actions[action].decoder(insn, asi, h); | ||
| 427 | } | 481 | } |
| 428 | 482 | ||
| 429 | case DECODE_TYPE_SIMULATE: { | 483 | case DECODE_TYPE_SIMULATE: { |
| 484 | int err; | ||
| 430 | struct decode_simulate *d = (struct decode_simulate *)h; | 485 | struct decode_simulate *d = (struct decode_simulate *)h; |
| 431 | asi->insn_handler = actions[d->handler.action].handler; | 486 | int action = d->handler.action; |
| 487 | |||
| 488 | err = run_checkers(checkers, action, origin_insn, asi, h); | ||
| 489 | if (err == INSN_REJECTED) | ||
| 490 | return INSN_REJECTED; | ||
| 491 | asi->insn_handler = actions[action].handler; | ||
| 432 | return INSN_GOOD_NO_SLOT; | 492 | return INSN_GOOD_NO_SLOT; |
| 433 | } | 493 | } |
| 434 | 494 | ||
| 435 | case DECODE_TYPE_EMULATE: { | 495 | case DECODE_TYPE_EMULATE: { |
| 496 | int err; | ||
| 436 | struct decode_emulate *d = (struct decode_emulate *)h; | 497 | struct decode_emulate *d = (struct decode_emulate *)h; |
| 498 | int action = d->handler.action; | ||
| 499 | |||
| 500 | err = run_checkers(checkers, action, origin_insn, asi, h); | ||
| 501 | if (err == INSN_REJECTED) | ||
| 502 | return INSN_REJECTED; | ||
| 437 | 503 | ||
| 438 | if (!emulate) | 504 | if (!emulate) |
| 439 | return actions[d->handler.action].decoder(insn, | 505 | return actions[action].decoder(insn, asi, h); |
| 440 | asi, h); | ||
| 441 | 506 | ||
| 442 | asi->insn_handler = actions[d->handler.action].handler; | 507 | asi->insn_handler = actions[action].handler; |
| 443 | set_emulated_insn(insn, asi, thumb); | 508 | set_emulated_insn(insn, asi, thumb); |
| 444 | return INSN_GOOD; | 509 | return INSN_GOOD; |
| 445 | } | 510 | } |
diff --git a/arch/arm/kernel/probes.h b/arch/arm/probes/decode.h index dba9f2466a93..f9b08ba7fe73 100644 --- a/arch/arm/kernel/probes.h +++ b/arch/arm/probes/decode.h | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * arch/arm/kernel/probes.h | 2 | * arch/arm/probes/decode.h |
| 3 | * | 3 | * |
| 4 | * Copyright (C) 2011 Jon Medhurst <tixy@yxit.co.uk>. | 4 | * Copyright (C) 2011 Jon Medhurst <tixy@yxit.co.uk>. |
| 5 | * | 5 | * |
| @@ -314,6 +314,14 @@ union decode_action { | |||
| 314 | probes_custom_decode_t *decoder; | 314 | probes_custom_decode_t *decoder; |
| 315 | }; | 315 | }; |
| 316 | 316 | ||
| 317 | typedef enum probes_insn (probes_check_t)(probes_opcode_t, | ||
| 318 | struct arch_probes_insn *, | ||
| 319 | const struct decode_header *); | ||
| 320 | |||
| 321 | struct decode_checker { | ||
| 322 | probes_check_t *checker; | ||
| 323 | }; | ||
| 324 | |||
| 317 | #define DECODE_END \ | 325 | #define DECODE_END \ |
| 318 | {.bits = DECODE_TYPE_END} | 326 | {.bits = DECODE_TYPE_END} |
| 319 | 327 | ||
| @@ -402,6 +410,7 @@ probes_insn_handler_t probes_emulate_none; | |||
| 402 | int __kprobes | 410 | int __kprobes |
| 403 | probes_decode_insn(probes_opcode_t insn, struct arch_probes_insn *asi, | 411 | probes_decode_insn(probes_opcode_t insn, struct arch_probes_insn *asi, |
| 404 | const union decode_item *table, bool thumb, bool emulate, | 412 | const union decode_item *table, bool thumb, bool emulate, |
| 405 | const union decode_action *actions); | 413 | const union decode_action *actions, |
| 414 | const struct decode_checker **checkers); | ||
| 406 | 415 | ||
| 407 | #endif | 416 | #endif |
diff --git a/arch/arm/probes/kprobes/Makefile b/arch/arm/probes/kprobes/Makefile new file mode 100644 index 000000000000..76a36bf102b7 --- /dev/null +++ b/arch/arm/probes/kprobes/Makefile | |||
| @@ -0,0 +1,12 @@ | |||
| 1 | obj-$(CONFIG_KPROBES) += core.o actions-common.o checkers-common.o | ||
| 2 | obj-$(CONFIG_ARM_KPROBES_TEST) += test-kprobes.o | ||
| 3 | test-kprobes-objs := test-core.o | ||
| 4 | |||
| 5 | ifdef CONFIG_THUMB2_KERNEL | ||
| 6 | obj-$(CONFIG_KPROBES) += actions-thumb.o checkers-thumb.o | ||
| 7 | test-kprobes-objs += test-thumb.o | ||
| 8 | else | ||
| 9 | obj-$(CONFIG_KPROBES) += actions-arm.o checkers-arm.o | ||
| 10 | obj-$(CONFIG_OPTPROBES) += opt-arm.o | ||
| 11 | test-kprobes-objs += test-arm.o | ||
| 12 | endif | ||
diff --git a/arch/arm/kernel/kprobes-arm.c b/arch/arm/probes/kprobes/actions-arm.c index ac300c60d656..b9056d649607 100644 --- a/arch/arm/kernel/kprobes-arm.c +++ b/arch/arm/probes/kprobes/actions-arm.c | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * arch/arm/kernel/kprobes-decode.c | 2 | * arch/arm/probes/kprobes/actions-arm.c |
| 3 | * | 3 | * |
| 4 | * Copyright (C) 2006, 2007 Motorola Inc. | 4 | * Copyright (C) 2006, 2007 Motorola Inc. |
| 5 | * | 5 | * |
| @@ -62,8 +62,9 @@ | |||
| 62 | #include <linux/kprobes.h> | 62 | #include <linux/kprobes.h> |
| 63 | #include <linux/ptrace.h> | 63 | #include <linux/ptrace.h> |
| 64 | 64 | ||
| 65 | #include "kprobes.h" | 65 | #include "../decode-arm.h" |
| 66 | #include "probes-arm.h" | 66 | #include "core.h" |
| 67 | #include "checkers.h" | ||
| 67 | 68 | ||
| 68 | #if __LINUX_ARM_ARCH__ >= 6 | 69 | #if __LINUX_ARM_ARCH__ >= 6 |
| 69 | #define BLX(reg) "blx "reg" \n\t" | 70 | #define BLX(reg) "blx "reg" \n\t" |
| @@ -302,8 +303,6 @@ emulate_rdlo12rdhi16rn0rm8_rwflags_nopc(probes_opcode_t insn, | |||
| 302 | } | 303 | } |
| 303 | 304 | ||
| 304 | const union decode_action kprobes_arm_actions[NUM_PROBES_ARM_ACTIONS] = { | 305 | const union decode_action kprobes_arm_actions[NUM_PROBES_ARM_ACTIONS] = { |
| 305 | [PROBES_EMULATE_NONE] = {.handler = probes_emulate_none}, | ||
| 306 | [PROBES_SIMULATE_NOP] = {.handler = probes_simulate_nop}, | ||
| 307 | [PROBES_PRELOAD_IMM] = {.handler = probes_simulate_nop}, | 306 | [PROBES_PRELOAD_IMM] = {.handler = probes_simulate_nop}, |
| 308 | [PROBES_PRELOAD_REG] = {.handler = probes_simulate_nop}, | 307 | [PROBES_PRELOAD_REG] = {.handler = probes_simulate_nop}, |
| 309 | [PROBES_BRANCH_IMM] = {.handler = simulate_blx1}, | 308 | [PROBES_BRANCH_IMM] = {.handler = simulate_blx1}, |
| @@ -341,3 +340,5 @@ const union decode_action kprobes_arm_actions[NUM_PROBES_ARM_ACTIONS] = { | |||
| 341 | [PROBES_BRANCH] = {.handler = simulate_bbl}, | 340 | [PROBES_BRANCH] = {.handler = simulate_bbl}, |
| 342 | [PROBES_LDMSTM] = {.decoder = kprobe_decode_ldmstm} | 341 | [PROBES_LDMSTM] = {.decoder = kprobe_decode_ldmstm} |
| 343 | }; | 342 | }; |
| 343 | |||
| 344 | const struct decode_checker *kprobes_arm_checkers[] = {arm_stack_checker, arm_regs_checker, NULL}; | ||
diff --git a/arch/arm/kernel/kprobes-common.c b/arch/arm/probes/kprobes/actions-common.c index 0bf5d64eba1d..bd20a71cd34a 100644 --- a/arch/arm/kernel/kprobes-common.c +++ b/arch/arm/probes/kprobes/actions-common.c | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * arch/arm/kernel/kprobes-common.c | 2 | * arch/arm/probes/kprobes/actions-common.c |
| 3 | * | 3 | * |
| 4 | * Copyright (C) 2011 Jon Medhurst <tixy@yxit.co.uk>. | 4 | * Copyright (C) 2011 Jon Medhurst <tixy@yxit.co.uk>. |
| 5 | * | 5 | * |
| @@ -15,7 +15,7 @@ | |||
| 15 | #include <linux/kprobes.h> | 15 | #include <linux/kprobes.h> |
| 16 | #include <asm/opcodes.h> | 16 | #include <asm/opcodes.h> |
| 17 | 17 | ||
| 18 | #include "kprobes.h" | 18 | #include "core.h" |
| 19 | 19 | ||
| 20 | 20 | ||
| 21 | static void __kprobes simulate_ldm1stm1(probes_opcode_t insn, | 21 | static void __kprobes simulate_ldm1stm1(probes_opcode_t insn, |
diff --git a/arch/arm/kernel/kprobes-thumb.c b/arch/arm/probes/kprobes/actions-thumb.c index 9495d7f3516f..07cfd9bef340 100644 --- a/arch/arm/kernel/kprobes-thumb.c +++ b/arch/arm/probes/kprobes/actions-thumb.c | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * arch/arm/kernel/kprobes-thumb.c | 2 | * arch/arm/probes/kprobes/actions-thumb.c |
| 3 | * | 3 | * |
| 4 | * Copyright (C) 2011 Jon Medhurst <tixy@yxit.co.uk>. | 4 | * Copyright (C) 2011 Jon Medhurst <tixy@yxit.co.uk>. |
| 5 | * | 5 | * |
| @@ -13,8 +13,9 @@ | |||
| 13 | #include <linux/ptrace.h> | 13 | #include <linux/ptrace.h> |
| 14 | #include <linux/kprobes.h> | 14 | #include <linux/kprobes.h> |
| 15 | 15 | ||
| 16 | #include "kprobes.h" | 16 | #include "../decode-thumb.h" |
| 17 | #include "probes-thumb.h" | 17 | #include "core.h" |
| 18 | #include "checkers.h" | ||
| 18 | 19 | ||
| 19 | /* These emulation encodings are functionally equivalent... */ | 20 | /* These emulation encodings are functionally equivalent... */ |
| 20 | #define t32_emulate_rd8rn16rm0ra12_noflags \ | 21 | #define t32_emulate_rd8rn16rm0ra12_noflags \ |
| @@ -664,3 +665,6 @@ const union decode_action kprobes_t32_actions[NUM_PROBES_T32_ACTIONS] = { | |||
| 664 | [PROBES_T32_MUL_ADD_LONG] = { | 665 | [PROBES_T32_MUL_ADD_LONG] = { |
| 665 | .handler = t32_emulate_rdlo12rdhi8rn16rm0_noflags}, | 666 | .handler = t32_emulate_rdlo12rdhi8rn16rm0_noflags}, |
| 666 | }; | 667 | }; |
| 668 | |||
| 669 | const struct decode_checker *kprobes_t32_checkers[] = {t32_stack_checker, NULL}; | ||
| 670 | const struct decode_checker *kprobes_t16_checkers[] = {t16_stack_checker, NULL}; | ||
diff --git a/arch/arm/probes/kprobes/checkers-arm.c b/arch/arm/probes/kprobes/checkers-arm.c new file mode 100644 index 000000000000..7b9817333b68 --- /dev/null +++ b/arch/arm/probes/kprobes/checkers-arm.c | |||
| @@ -0,0 +1,192 @@ | |||
| 1 | /* | ||
| 2 | * arch/arm/probes/kprobes/checkers-arm.c | ||
| 3 | * | ||
| 4 | * Copyright (C) 2014 Huawei Inc. | ||
| 5 | * | ||
| 6 | * This program is free software; you can redistribute it and/or modify | ||
| 7 | * it under the terms of the GNU General Public License version 2 as | ||
| 8 | * published by the Free Software Foundation. | ||
| 9 | * | ||
| 10 | * This program is distributed in the hope that it will be useful, | ||
| 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
| 13 | * General Public License for more details. | ||
| 14 | */ | ||
| 15 | |||
| 16 | #include <linux/kernel.h> | ||
| 17 | #include "../decode.h" | ||
| 18 | #include "../decode-arm.h" | ||
| 19 | #include "checkers.h" | ||
| 20 | |||
| 21 | static enum probes_insn __kprobes arm_check_stack(probes_opcode_t insn, | ||
| 22 | struct arch_probes_insn *asi, | ||
| 23 | const struct decode_header *h) | ||
| 24 | { | ||
| 25 | /* | ||
| 26 | * PROBES_LDRSTRD, PROBES_LDMSTM, PROBES_STORE, | ||
| 27 | * PROBES_STORE_EXTRA may get here. Simply mark all normal | ||
| 28 | * insns as STACK_USE_NONE. | ||
| 29 | */ | ||
| 30 | static const union decode_item table[] = { | ||
| 31 | /* | ||
| 32 | * 'STR{,D,B,H}, Rt, [Rn, Rm]' should be marked as UNKNOWN | ||
| 33 | * if Rn or Rm is SP. | ||
| 34 | * x | ||
| 35 | * STR (register) cccc 011x x0x0 xxxx xxxx xxxx xxxx xxxx | ||
| 36 | * STRB (register) cccc 011x x1x0 xxxx xxxx xxxx xxxx xxxx | ||
| 37 | */ | ||
| 38 | DECODE_OR (0x0e10000f, 0x0600000d), | ||
| 39 | DECODE_OR (0x0e1f0000, 0x060d0000), | ||
| 40 | |||
| 41 | /* | ||
| 42 | * x | ||
| 43 | * STRD (register) cccc 000x x0x0 xxxx xxxx xxxx 1111 xxxx | ||
| 44 | * STRH (register) cccc 000x x0x0 xxxx xxxx xxxx 1011 xxxx | ||
| 45 | */ | ||
| 46 | DECODE_OR (0x0e5000bf, 0x000000bd), | ||
| 47 | DECODE_CUSTOM (0x0e5f00b0, 0x000d00b0, STACK_USE_UNKNOWN), | ||
| 48 | |||
| 49 | /* | ||
| 50 | * For PROBES_LDMSTM, only stmdx sp, [...] need to examine | ||
| 51 | * | ||
| 52 | * Bit B/A (bit 24) encodes arithmetic operation order. 1 means | ||
| 53 | * before, 0 means after. | ||
| 54 | * Bit I/D (bit 23) encodes arithmetic operation. 1 means | ||
| 55 | * increment, 0 means decrement. | ||
| 56 | * | ||
| 57 | * So: | ||
| 58 | * B I | ||
| 59 | * / / | ||
| 60 | * A D | Rn | | ||
| 61 | * STMDX SP, [...] cccc 100x 00x0 xxxx xxxx xxxx xxxx xxxx | ||
| 62 | */ | ||
| 63 | DECODE_CUSTOM (0x0edf0000, 0x080d0000, STACK_USE_STMDX), | ||
| 64 | |||
| 65 | /* P U W | Rn | Rt | imm12 |*/ | ||
| 66 | /* STR (immediate) cccc 010x x0x0 1101 xxxx xxxx xxxx xxxx */ | ||
| 67 | /* STRB (immediate) cccc 010x x1x0 1101 xxxx xxxx xxxx xxxx */ | ||
| 68 | /* P U W | Rn | Rt |imm4| |imm4|*/ | ||
| 69 | /* STRD (immediate) cccc 000x x1x0 1101 xxxx xxxx 1111 xxxx */ | ||
| 70 | /* STRH (immediate) cccc 000x x1x0 1101 xxxx xxxx 1011 xxxx */ | ||
| 71 | /* | ||
| 72 | * index = (P == '1'); add = (U == '1'). | ||
| 73 | * Above insns with: | ||
| 74 | * index == 0 (str{,d,h} rx, [sp], #+/-imm) or | ||
| 75 | * add == 1 (str{,d,h} rx, [sp, #+<imm>]) | ||
| 76 | * should be STACK_USE_NONE. | ||
| 77 | * Only str{,b,d,h} rx,[sp,#-n] (P == 1 and U == 0) are | ||
| 78 | * required to be examined. | ||
| 79 | */ | ||
| 80 | /* STR{,B} Rt,[SP,#-n] cccc 0101 0xx0 1101 xxxx xxxx xxxx xxxx */ | ||
| 81 | DECODE_CUSTOM (0x0f9f0000, 0x050d0000, STACK_USE_FIXED_XXX), | ||
| 82 | |||
| 83 | /* STR{D,H} Rt,[SP,#-n] cccc 0001 01x0 1101 xxxx xxxx 1x11 xxxx */ | ||
| 84 | DECODE_CUSTOM (0x0fdf00b0, 0x014d00b0, STACK_USE_FIXED_X0X), | ||
| 85 | |||
| 86 | /* fall through */ | ||
| 87 | DECODE_CUSTOM (0, 0, STACK_USE_NONE), | ||
| 88 | DECODE_END | ||
| 89 | }; | ||
| 90 | |||
| 91 | return probes_decode_insn(insn, asi, table, false, false, stack_check_actions, NULL); | ||
| 92 | } | ||
| 93 | |||
| 94 | const struct decode_checker arm_stack_checker[NUM_PROBES_ARM_ACTIONS] = { | ||
| 95 | [PROBES_LDRSTRD] = {.checker = arm_check_stack}, | ||
| 96 | [PROBES_STORE_EXTRA] = {.checker = arm_check_stack}, | ||
| 97 | [PROBES_STORE] = {.checker = arm_check_stack}, | ||
| 98 | [PROBES_LDMSTM] = {.checker = arm_check_stack}, | ||
| 99 | }; | ||
| 100 | |||
| 101 | static enum probes_insn __kprobes arm_check_regs_nouse(probes_opcode_t insn, | ||
| 102 | struct arch_probes_insn *asi, | ||
| 103 | const struct decode_header *h) | ||
| 104 | { | ||
| 105 | asi->register_usage_flags = 0; | ||
| 106 | return INSN_GOOD; | ||
| 107 | } | ||
| 108 | |||
| 109 | static enum probes_insn arm_check_regs_normal(probes_opcode_t insn, | ||
| 110 | struct arch_probes_insn *asi, | ||
| 111 | const struct decode_header *h) | ||
| 112 | { | ||
| 113 | u32 regs = h->type_regs.bits >> DECODE_TYPE_BITS; | ||
| 114 | int i; | ||
| 115 | |||
| 116 | asi->register_usage_flags = 0; | ||
| 117 | for (i = 0; i < 5; regs >>= 4, insn >>= 4, i++) | ||
| 118 | if (regs & 0xf) | ||
| 119 | asi->register_usage_flags |= 1 << (insn & 0xf); | ||
| 120 | |||
| 121 | return INSN_GOOD; | ||
| 122 | } | ||
| 123 | |||
| 124 | |||
| 125 | static enum probes_insn arm_check_regs_ldmstm(probes_opcode_t insn, | ||
| 126 | struct arch_probes_insn *asi, | ||
| 127 | const struct decode_header *h) | ||
| 128 | { | ||
| 129 | unsigned int reglist = insn & 0xffff; | ||
| 130 | unsigned int rn = (insn >> 16) & 0xf; | ||
| 131 | asi->register_usage_flags = reglist | (1 << rn); | ||
| 132 | return INSN_GOOD; | ||
| 133 | } | ||
| 134 | |||
| 135 | static enum probes_insn arm_check_regs_mov_ip_sp(probes_opcode_t insn, | ||
| 136 | struct arch_probes_insn *asi, | ||
| 137 | const struct decode_header *h) | ||
| 138 | { | ||
| 139 | /* Instruction is 'mov ip, sp' i.e. 'mov r12, r13' */ | ||
| 140 | asi->register_usage_flags = (1 << 12) | (1<< 13); | ||
| 141 | return INSN_GOOD; | ||
| 142 | } | ||
| 143 | |||
| 144 | /* | ||
| 145 | * | Rn |Rt/d| | Rm | | ||
| 146 | * LDRD (register) cccc 000x x0x0 xxxx xxxx xxxx 1101 xxxx | ||
| 147 | * STRD (register) cccc 000x x0x0 xxxx xxxx xxxx 1111 xxxx | ||
| 148 | * | Rn |Rt/d| |imm4L| | ||
| 149 | * LDRD (immediate) cccc 000x x1x0 xxxx xxxx xxxx 1101 xxxx | ||
| 150 | * STRD (immediate) cccc 000x x1x0 xxxx xxxx xxxx 1111 xxxx | ||
| 151 | * | ||
| 152 | * Such instructions access Rt/d and its next register, so different | ||
| 153 | * from others, a specific checker is required to handle this extra | ||
| 154 | * implicit register usage. | ||
| 155 | */ | ||
| 156 | static enum probes_insn arm_check_regs_ldrdstrd(probes_opcode_t insn, | ||
| 157 | struct arch_probes_insn *asi, | ||
| 158 | const struct decode_header *h) | ||
| 159 | { | ||
| 160 | int rdt = (insn >> 12) & 0xf; | ||
| 161 | arm_check_regs_normal(insn, asi, h); | ||
| 162 | asi->register_usage_flags |= 1 << (rdt + 1); | ||
| 163 | return INSN_GOOD; | ||
| 164 | } | ||
| 165 | |||
| 166 | |||
| 167 | const struct decode_checker arm_regs_checker[NUM_PROBES_ARM_ACTIONS] = { | ||
| 168 | [PROBES_MRS] = {.checker = arm_check_regs_normal}, | ||
| 169 | [PROBES_SATURATING_ARITHMETIC] = {.checker = arm_check_regs_normal}, | ||
| 170 | [PROBES_MUL1] = {.checker = arm_check_regs_normal}, | ||
| 171 | [PROBES_MUL2] = {.checker = arm_check_regs_normal}, | ||
| 172 | [PROBES_MUL_ADD_LONG] = {.checker = arm_check_regs_normal}, | ||
| 173 | [PROBES_MUL_ADD] = {.checker = arm_check_regs_normal}, | ||
| 174 | [PROBES_LOAD] = {.checker = arm_check_regs_normal}, | ||
| 175 | [PROBES_LOAD_EXTRA] = {.checker = arm_check_regs_normal}, | ||
| 176 | [PROBES_STORE] = {.checker = arm_check_regs_normal}, | ||
| 177 | [PROBES_STORE_EXTRA] = {.checker = arm_check_regs_normal}, | ||
| 178 | [PROBES_DATA_PROCESSING_REG] = {.checker = arm_check_regs_normal}, | ||
| 179 | [PROBES_DATA_PROCESSING_IMM] = {.checker = arm_check_regs_normal}, | ||
| 180 | [PROBES_SEV] = {.checker = arm_check_regs_nouse}, | ||
| 181 | [PROBES_WFE] = {.checker = arm_check_regs_nouse}, | ||
| 182 | [PROBES_SATURATE] = {.checker = arm_check_regs_normal}, | ||
| 183 | [PROBES_REV] = {.checker = arm_check_regs_normal}, | ||
| 184 | [PROBES_MMI] = {.checker = arm_check_regs_normal}, | ||
| 185 | [PROBES_PACK] = {.checker = arm_check_regs_normal}, | ||
| 186 | [PROBES_EXTEND] = {.checker = arm_check_regs_normal}, | ||
| 187 | [PROBES_EXTEND_ADD] = {.checker = arm_check_regs_normal}, | ||
| 188 | [PROBES_BITFIELD] = {.checker = arm_check_regs_normal}, | ||
| 189 | [PROBES_LDMSTM] = {.checker = arm_check_regs_ldmstm}, | ||
| 190 | [PROBES_MOV_IP_SP] = {.checker = arm_check_regs_mov_ip_sp}, | ||
| 191 | [PROBES_LDRSTRD] = {.checker = arm_check_regs_ldrdstrd}, | ||
| 192 | }; | ||
diff --git a/arch/arm/probes/kprobes/checkers-common.c b/arch/arm/probes/kprobes/checkers-common.c new file mode 100644 index 000000000000..971119c29474 --- /dev/null +++ b/arch/arm/probes/kprobes/checkers-common.c | |||
| @@ -0,0 +1,101 @@ | |||
| 1 | /* | ||
| 2 | * arch/arm/probes/kprobes/checkers-common.c | ||
| 3 | * | ||
| 4 | * Copyright (C) 2014 Huawei Inc. | ||
| 5 | * | ||
| 6 | * This program is free software; you can redistribute it and/or modify | ||
| 7 | * it under the terms of the GNU General Public License version 2 as | ||
| 8 | * published by the Free Software Foundation. | ||
| 9 | * | ||
| 10 | * This program is distributed in the hope that it will be useful, | ||
| 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
| 13 | * General Public License for more details. | ||
| 14 | */ | ||
| 15 | |||
| 16 | #include <linux/kernel.h> | ||
| 17 | #include "../decode.h" | ||
| 18 | #include "../decode-arm.h" | ||
| 19 | #include "checkers.h" | ||
| 20 | |||
| 21 | enum probes_insn checker_stack_use_none(probes_opcode_t insn, | ||
| 22 | struct arch_probes_insn *asi, | ||
| 23 | const struct decode_header *h) | ||
| 24 | { | ||
| 25 | asi->stack_space = 0; | ||
| 26 | return INSN_GOOD_NO_SLOT; | ||
| 27 | } | ||
| 28 | |||
| 29 | enum probes_insn checker_stack_use_unknown(probes_opcode_t insn, | ||
| 30 | struct arch_probes_insn *asi, | ||
| 31 | const struct decode_header *h) | ||
| 32 | { | ||
| 33 | asi->stack_space = -1; | ||
| 34 | return INSN_GOOD_NO_SLOT; | ||
| 35 | } | ||
| 36 | |||
| 37 | #ifdef CONFIG_THUMB2_KERNEL | ||
| 38 | enum probes_insn checker_stack_use_imm_0xx(probes_opcode_t insn, | ||
| 39 | struct arch_probes_insn *asi, | ||
| 40 | const struct decode_header *h) | ||
| 41 | { | ||
| 42 | int imm = insn & 0xff; | ||
| 43 | asi->stack_space = imm; | ||
| 44 | return INSN_GOOD_NO_SLOT; | ||
| 45 | } | ||
| 46 | |||
| 47 | /* | ||
| 48 | * Different from other insn uses imm8, the real addressing offset of | ||
| 49 | * STRD in T32 encoding should be imm8 * 4. See ARMARM description. | ||
| 50 | */ | ||
| 51 | enum probes_insn checker_stack_use_t32strd(probes_opcode_t insn, | ||
| 52 | struct arch_probes_insn *asi, | ||
| 53 | const struct decode_header *h) | ||
| 54 | { | ||
| 55 | int imm = insn & 0xff; | ||
| 56 | asi->stack_space = imm << 2; | ||
| 57 | return INSN_GOOD_NO_SLOT; | ||
| 58 | } | ||
| 59 | #else | ||
| 60 | enum probes_insn checker_stack_use_imm_x0x(probes_opcode_t insn, | ||
| 61 | struct arch_probes_insn *asi, | ||
| 62 | const struct decode_header *h) | ||
| 63 | { | ||
| 64 | int imm = ((insn & 0xf00) >> 4) + (insn & 0xf); | ||
| 65 | asi->stack_space = imm; | ||
| 66 | return INSN_GOOD_NO_SLOT; | ||
| 67 | } | ||
| 68 | #endif | ||
| 69 | |||
| 70 | enum probes_insn checker_stack_use_imm_xxx(probes_opcode_t insn, | ||
| 71 | struct arch_probes_insn *asi, | ||
| 72 | const struct decode_header *h) | ||
| 73 | { | ||
| 74 | int imm = insn & 0xfff; | ||
| 75 | asi->stack_space = imm; | ||
| 76 | return INSN_GOOD_NO_SLOT; | ||
| 77 | } | ||
| 78 | |||
| 79 | enum probes_insn checker_stack_use_stmdx(probes_opcode_t insn, | ||
| 80 | struct arch_probes_insn *asi, | ||
| 81 | const struct decode_header *h) | ||
| 82 | { | ||
| 83 | unsigned int reglist = insn & 0xffff; | ||
| 84 | int pbit = insn & (1 << 24); | ||
| 85 | asi->stack_space = (hweight32(reglist) - (!pbit ? 1 : 0)) * 4; | ||
| 86 | |||
| 87 | return INSN_GOOD_NO_SLOT; | ||
| 88 | } | ||
| 89 | |||
| 90 | const union decode_action stack_check_actions[] = { | ||
| 91 | [STACK_USE_NONE] = {.decoder = checker_stack_use_none}, | ||
| 92 | [STACK_USE_UNKNOWN] = {.decoder = checker_stack_use_unknown}, | ||
| 93 | #ifdef CONFIG_THUMB2_KERNEL | ||
| 94 | [STACK_USE_FIXED_0XX] = {.decoder = checker_stack_use_imm_0xx}, | ||
| 95 | [STACK_USE_T32STRD] = {.decoder = checker_stack_use_t32strd}, | ||
| 96 | #else | ||
| 97 | [STACK_USE_FIXED_X0X] = {.decoder = checker_stack_use_imm_x0x}, | ||
| 98 | #endif | ||
| 99 | [STACK_USE_FIXED_XXX] = {.decoder = checker_stack_use_imm_xxx}, | ||
| 100 | [STACK_USE_STMDX] = {.decoder = checker_stack_use_stmdx}, | ||
| 101 | }; | ||
diff --git a/arch/arm/probes/kprobes/checkers-thumb.c b/arch/arm/probes/kprobes/checkers-thumb.c new file mode 100644 index 000000000000..d608e3b9017a --- /dev/null +++ b/arch/arm/probes/kprobes/checkers-thumb.c | |||
| @@ -0,0 +1,110 @@ | |||
| 1 | /* | ||
| 2 | * arch/arm/probes/kprobes/checkers-thumb.c | ||
| 3 | * | ||
| 4 | * Copyright (C) 2014 Huawei Inc. | ||
| 5 | * | ||
| 6 | * This program is free software; you can redistribute it and/or modify | ||
| 7 | * it under the terms of the GNU General Public License version 2 as | ||
| 8 | * published by the Free Software Foundation. | ||
| 9 | * | ||
| 10 | * This program is distributed in the hope that it will be useful, | ||
| 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
| 13 | * General Public License for more details. | ||
| 14 | */ | ||
| 15 | |||
| 16 | #include <linux/kernel.h> | ||
| 17 | #include "../decode.h" | ||
| 18 | #include "../decode-thumb.h" | ||
| 19 | #include "checkers.h" | ||
| 20 | |||
| 21 | static enum probes_insn __kprobes t32_check_stack(probes_opcode_t insn, | ||
| 22 | struct arch_probes_insn *asi, | ||
| 23 | const struct decode_header *h) | ||
| 24 | { | ||
| 25 | /* | ||
| 26 | * PROBES_T32_LDMSTM, PROBES_T32_LDRDSTRD and PROBES_T32_LDRSTR | ||
| 27 | * may get here. Simply mark all normal insns as STACK_USE_NONE. | ||
| 28 | */ | ||
| 29 | static const union decode_item table[] = { | ||
| 30 | |||
| 31 | /* | ||
| 32 | * First, filter out all ldr insns to make our life easier. | ||
| 33 | * Following load insns may come here: | ||
| 34 | * LDM, LDRD, LDR. | ||
| 35 | * In T32 encoding, bit 20 is enough for distinguishing | ||
| 36 | * load and store. All load insns have this bit set, when | ||
| 37 | * all store insns have this bit clear. | ||
| 38 | */ | ||
| 39 | DECODE_CUSTOM (0x00100000, 0x00100000, STACK_USE_NONE), | ||
| 40 | |||
| 41 | /* | ||
| 42 | * Mark all 'STR{,B,H}, Rt, [Rn, Rm]' as STACK_USE_UNKNOWN | ||
| 43 | * if Rn or Rm is SP. T32 doesn't encode STRD. | ||
| 44 | */ | ||
| 45 | /* xx | Rn | Rt | | Rm |*/ | ||
| 46 | /* STR (register) 1111 1000 0100 xxxx xxxx 0000 00xx xxxx */ | ||
| 47 | /* STRB (register) 1111 1000 0000 xxxx xxxx 0000 00xx xxxx */ | ||
| 48 | /* STRH (register) 1111 1000 0010 xxxx xxxx 0000 00xx xxxx */ | ||
| 49 | /* INVALID INSN 1111 1000 0110 xxxx xxxx 0000 00xx xxxx */ | ||
| 50 | /* By Introducing INVALID INSN, bit 21 and 22 can be ignored. */ | ||
| 51 | DECODE_OR (0xff9f0fc0, 0xf80d0000), | ||
| 52 | DECODE_CUSTOM (0xff900fcf, 0xf800000d, STACK_USE_UNKNOWN), | ||
| 53 | |||
| 54 | |||
| 55 | /* xx | Rn | Rt | PUW| imm8 |*/ | ||
| 56 | /* STR (imm 8) 1111 1000 0100 1101 xxxx 110x xxxx xxxx */ | ||
| 57 | /* STRB (imm 8) 1111 1000 0000 1101 xxxx 110x xxxx xxxx */ | ||
| 58 | /* STRH (imm 8) 1111 1000 0010 1101 xxxx 110x xxxx xxxx */ | ||
| 59 | /* INVALID INSN 1111 1000 0110 1101 xxxx 110x xxxx xxxx */ | ||
| 60 | /* Only consider U == 0 and P == 1: strx rx, [sp, #-<imm>] */ | ||
| 61 | DECODE_CUSTOM (0xff9f0e00, 0xf80d0c00, STACK_USE_FIXED_0XX), | ||
| 62 | |||
| 63 | /* For STR{,B,H} (imm 12), offset is always positive, so ignore them. */ | ||
| 64 | |||
| 65 | /* P U W | Rn | Rt | Rt2| imm8 |*/ | ||
| 66 | /* STRD (immediate) 1110 1001 01x0 1101 xxxx xxxx xxxx xxxx */ | ||
| 67 | /* | ||
| 68 | * Only consider U == 0 and P == 1. | ||
| 69 | * Also note that STRD in T32 encoding is special: | ||
| 70 | * imm = ZeroExtend(imm8:'00', 32) | ||
| 71 | */ | ||
| 72 | DECODE_CUSTOM (0xffdf0000, 0xe94d0000, STACK_USE_T32STRD), | ||
| 73 | |||
| 74 | /* | Rn | */ | ||
| 75 | /* STMDB 1110 1001 00x0 1101 xxxx xxxx xxxx xxxx */ | ||
| 76 | DECODE_CUSTOM (0xffdf0000, 0xe90d0000, STACK_USE_STMDX), | ||
| 77 | |||
| 78 | /* fall through */ | ||
| 79 | DECODE_CUSTOM (0, 0, STACK_USE_NONE), | ||
| 80 | DECODE_END | ||
| 81 | }; | ||
| 82 | |||
| 83 | return probes_decode_insn(insn, asi, table, false, false, stack_check_actions, NULL); | ||
| 84 | } | ||
| 85 | |||
| 86 | const struct decode_checker t32_stack_checker[NUM_PROBES_T32_ACTIONS] = { | ||
| 87 | [PROBES_T32_LDMSTM] = {.checker = t32_check_stack}, | ||
| 88 | [PROBES_T32_LDRDSTRD] = {.checker = t32_check_stack}, | ||
| 89 | [PROBES_T32_LDRSTR] = {.checker = t32_check_stack}, | ||
| 90 | }; | ||
| 91 | |||
| 92 | /* | ||
| 93 | * See following comments. This insn must be 'push'. | ||
| 94 | */ | ||
| 95 | static enum probes_insn __kprobes t16_check_stack(probes_opcode_t insn, | ||
| 96 | struct arch_probes_insn *asi, | ||
| 97 | const struct decode_header *h) | ||
| 98 | { | ||
| 99 | unsigned int reglist = insn & 0x1ff; | ||
| 100 | asi->stack_space = hweight32(reglist) * 4; | ||
| 101 | return INSN_GOOD; | ||
| 102 | } | ||
| 103 | |||
| 104 | /* | ||
| 105 | * T16 encoding is simple: only the 'push' insn can need extra stack space. | ||
| 106 | * Other insns, like str, can only use r0-r7 as Rn. | ||
| 107 | */ | ||
| 108 | const struct decode_checker t16_stack_checker[NUM_PROBES_T16_ACTIONS] = { | ||
| 109 | [PROBES_T16_PUSH] = {.checker = t16_check_stack}, | ||
| 110 | }; | ||
diff --git a/arch/arm/probes/kprobes/checkers.h b/arch/arm/probes/kprobes/checkers.h new file mode 100644 index 000000000000..cf6c9e74d666 --- /dev/null +++ b/arch/arm/probes/kprobes/checkers.h | |||
| @@ -0,0 +1,55 @@ | |||
| 1 | /* | ||
| 2 | * arch/arm/probes/kprobes/checkers.h | ||
| 3 | * | ||
| 4 | * Copyright (C) 2014 Huawei Inc. | ||
| 5 | * | ||
| 6 | * This program is free software; you can redistribute it and/or modify | ||
| 7 | * it under the terms of the GNU General Public License version 2 as | ||
| 8 | * published by the Free Software Foundation. | ||
| 9 | * | ||
| 10 | * This program is distributed in the hope that it will be useful, | ||
| 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
| 13 | * General Public License for more details. | ||
| 14 | */ | ||
| 15 | #ifndef _ARM_KERNEL_PROBES_CHECKERS_H | ||
| 16 | #define _ARM_KERNEL_PROBES_CHECKERS_H | ||
| 17 | |||
| 18 | #include <linux/kernel.h> | ||
| 19 | #include <linux/types.h> | ||
| 20 | #include "../decode.h" | ||
| 21 | |||
| 22 | extern probes_check_t checker_stack_use_none; | ||
| 23 | extern probes_check_t checker_stack_use_unknown; | ||
| 24 | #ifdef CONFIG_THUMB2_KERNEL | ||
| 25 | extern probes_check_t checker_stack_use_imm_0xx; | ||
| 26 | #else | ||
| 27 | extern probes_check_t checker_stack_use_imm_x0x; | ||
| 28 | #endif | ||
| 29 | extern probes_check_t checker_stack_use_imm_xxx; | ||
| 30 | extern probes_check_t checker_stack_use_stmdx; | ||
| 31 | |||
| 32 | enum { | ||
| 33 | STACK_USE_NONE, | ||
| 34 | STACK_USE_UNKNOWN, | ||
| 35 | #ifdef CONFIG_THUMB2_KERNEL | ||
| 36 | STACK_USE_FIXED_0XX, | ||
| 37 | STACK_USE_T32STRD, | ||
| 38 | #else | ||
| 39 | STACK_USE_FIXED_X0X, | ||
| 40 | #endif | ||
| 41 | STACK_USE_FIXED_XXX, | ||
| 42 | STACK_USE_STMDX, | ||
| 43 | NUM_STACK_USE_TYPES | ||
| 44 | }; | ||
| 45 | |||
| 46 | extern const union decode_action stack_check_actions[]; | ||
| 47 | |||
| 48 | #ifndef CONFIG_THUMB2_KERNEL | ||
| 49 | extern const struct decode_checker arm_stack_checker[]; | ||
| 50 | extern const struct decode_checker arm_regs_checker[]; | ||
| 51 | #else | ||
| 52 | #endif | ||
| 53 | extern const struct decode_checker t32_stack_checker[]; | ||
| 54 | extern const struct decode_checker t16_stack_checker[]; | ||
| 55 | #endif | ||
diff --git a/arch/arm/kernel/kprobes.c b/arch/arm/probes/kprobes/core.c index 6d644202c8dc..a4ec240ee7ba 100644 --- a/arch/arm/kernel/kprobes.c +++ b/arch/arm/probes/kprobes/core.c | |||
| @@ -30,11 +30,11 @@ | |||
| 30 | #include <asm/cacheflush.h> | 30 | #include <asm/cacheflush.h> |
| 31 | #include <linux/percpu.h> | 31 | #include <linux/percpu.h> |
| 32 | #include <linux/bug.h> | 32 | #include <linux/bug.h> |
| 33 | #include <asm/patch.h> | ||
| 33 | 34 | ||
| 34 | #include "kprobes.h" | 35 | #include "../decode-arm.h" |
| 35 | #include "probes-arm.h" | 36 | #include "../decode-thumb.h" |
| 36 | #include "probes-thumb.h" | 37 | #include "core.h" |
| 37 | #include "patch.h" | ||
| 38 | 38 | ||
| 39 | #define MIN_STACK_SIZE(addr) \ | 39 | #define MIN_STACK_SIZE(addr) \ |
| 40 | min((unsigned long)MAX_STACK_SIZE, \ | 40 | min((unsigned long)MAX_STACK_SIZE, \ |
| @@ -61,6 +61,7 @@ int __kprobes arch_prepare_kprobe(struct kprobe *p) | |||
| 61 | kprobe_decode_insn_t *decode_insn; | 61 | kprobe_decode_insn_t *decode_insn; |
| 62 | const union decode_action *actions; | 62 | const union decode_action *actions; |
| 63 | int is; | 63 | int is; |
| 64 | const struct decode_checker **checkers; | ||
| 64 | 65 | ||
| 65 | if (in_exception_text(addr)) | 66 | if (in_exception_text(addr)) |
| 66 | return -EINVAL; | 67 | return -EINVAL; |
| @@ -74,9 +75,11 @@ int __kprobes arch_prepare_kprobe(struct kprobe *p) | |||
| 74 | insn = __opcode_thumb32_compose(insn, inst2); | 75 | insn = __opcode_thumb32_compose(insn, inst2); |
| 75 | decode_insn = thumb32_probes_decode_insn; | 76 | decode_insn = thumb32_probes_decode_insn; |
| 76 | actions = kprobes_t32_actions; | 77 | actions = kprobes_t32_actions; |
| 78 | checkers = kprobes_t32_checkers; | ||
| 77 | } else { | 79 | } else { |
| 78 | decode_insn = thumb16_probes_decode_insn; | 80 | decode_insn = thumb16_probes_decode_insn; |
| 79 | actions = kprobes_t16_actions; | 81 | actions = kprobes_t16_actions; |
| 82 | checkers = kprobes_t16_checkers; | ||
| 80 | } | 83 | } |
| 81 | #else /* !CONFIG_THUMB2_KERNEL */ | 84 | #else /* !CONFIG_THUMB2_KERNEL */ |
| 82 | thumb = false; | 85 | thumb = false; |
| @@ -85,12 +88,13 @@ int __kprobes arch_prepare_kprobe(struct kprobe *p) | |||
| 85 | insn = __mem_to_opcode_arm(*p->addr); | 88 | insn = __mem_to_opcode_arm(*p->addr); |
| 86 | decode_insn = arm_probes_decode_insn; | 89 | decode_insn = arm_probes_decode_insn; |
| 87 | actions = kprobes_arm_actions; | 90 | actions = kprobes_arm_actions; |
| 91 | checkers = kprobes_arm_checkers; | ||
| 88 | #endif | 92 | #endif |
| 89 | 93 | ||
| 90 | p->opcode = insn; | 94 | p->opcode = insn; |
| 91 | p->ainsn.insn = tmp_insn; | 95 | p->ainsn.insn = tmp_insn; |
| 92 | 96 | ||
| 93 | switch ((*decode_insn)(insn, &p->ainsn, true, actions)) { | 97 | switch ((*decode_insn)(insn, &p->ainsn, true, actions, checkers)) { |
| 94 | case INSN_REJECTED: /* not supported */ | 98 | case INSN_REJECTED: /* not supported */ |
| 95 | return -EINVAL; | 99 | return -EINVAL; |
| 96 | 100 | ||
| @@ -111,6 +115,15 @@ int __kprobes arch_prepare_kprobe(struct kprobe *p) | |||
| 111 | break; | 115 | break; |
| 112 | } | 116 | } |
| 113 | 117 | ||
| 118 | /* | ||
| 119 | * Never instrument insn like 'str r0, [sp, +/-r1]'. Also, insn likes | ||
| 120 | * 'str r0, [sp, #-68]' should also be prohibited. | ||
| 121 | * See __und_svc. | ||
| 122 | */ | ||
| 123 | if ((p->ainsn.stack_space < 0) || | ||
| 124 | (p->ainsn.stack_space > MAX_STACK_SIZE)) | ||
| 125 | return -EINVAL; | ||
| 126 | |||
| 114 | return 0; | 127 | return 0; |
| 115 | } | 128 | } |
| 116 | 129 | ||
| @@ -150,19 +163,31 @@ void __kprobes arch_arm_kprobe(struct kprobe *p) | |||
| 150 | * memory. It is also needed to atomically set the two half-words of a 32-bit | 163 | * memory. It is also needed to atomically set the two half-words of a 32-bit |
| 151 | * Thumb breakpoint. | 164 | * Thumb breakpoint. |
| 152 | */ | 165 | */ |
| 153 | int __kprobes __arch_disarm_kprobe(void *p) | 166 | struct patch { |
| 154 | { | 167 | void *addr; |
| 155 | struct kprobe *kp = p; | 168 | unsigned int insn; |
| 156 | void *addr = (void *)((uintptr_t)kp->addr & ~1); | 169 | }; |
| 157 | |||
| 158 | __patch_text(addr, kp->opcode); | ||
| 159 | 170 | ||
| 171 | static int __kprobes_remove_breakpoint(void *data) | ||
| 172 | { | ||
| 173 | struct patch *p = data; | ||
| 174 | __patch_text(p->addr, p->insn); | ||
| 160 | return 0; | 175 | return 0; |
| 161 | } | 176 | } |
| 162 | 177 | ||
| 178 | void __kprobes kprobes_remove_breakpoint(void *addr, unsigned int insn) | ||
| 179 | { | ||
| 180 | struct patch p = { | ||
| 181 | .addr = addr, | ||
| 182 | .insn = insn, | ||
| 183 | }; | ||
| 184 | stop_machine(__kprobes_remove_breakpoint, &p, cpu_online_mask); | ||
| 185 | } | ||
| 186 | |||
| 163 | void __kprobes arch_disarm_kprobe(struct kprobe *p) | 187 | void __kprobes arch_disarm_kprobe(struct kprobe *p) |
| 164 | { | 188 | { |
| 165 | stop_machine(__arch_disarm_kprobe, p, cpu_online_mask); | 189 | kprobes_remove_breakpoint((void *)((uintptr_t)p->addr & ~1), |
| 190 | p->opcode); | ||
| 166 | } | 191 | } |
| 167 | 192 | ||
| 168 | void __kprobes arch_remove_kprobe(struct kprobe *p) | 193 | void __kprobes arch_remove_kprobe(struct kprobe *p) |
diff --git a/arch/arm/kernel/kprobes.h b/arch/arm/probes/kprobes/core.h index 9a2712ecefc3..ec5d1f20a085 100644 --- a/arch/arm/kernel/kprobes.h +++ b/arch/arm/probes/kprobes/core.h | |||
| @@ -19,7 +19,8 @@ | |||
| 19 | #ifndef _ARM_KERNEL_KPROBES_H | 19 | #ifndef _ARM_KERNEL_KPROBES_H |
| 20 | #define _ARM_KERNEL_KPROBES_H | 20 | #define _ARM_KERNEL_KPROBES_H |
| 21 | 21 | ||
| 22 | #include "probes.h" | 22 | #include <asm/kprobes.h> |
| 23 | #include "../decode.h" | ||
| 23 | 24 | ||
| 24 | /* | 25 | /* |
| 25 | * These undefined instructions must be unique and | 26 | * These undefined instructions must be unique and |
| @@ -29,6 +30,8 @@ | |||
| 29 | #define KPROBE_THUMB16_BREAKPOINT_INSTRUCTION 0xde18 | 30 | #define KPROBE_THUMB16_BREAKPOINT_INSTRUCTION 0xde18 |
| 30 | #define KPROBE_THUMB32_BREAKPOINT_INSTRUCTION 0xf7f0a018 | 31 | #define KPROBE_THUMB32_BREAKPOINT_INSTRUCTION 0xf7f0a018 |
| 31 | 32 | ||
| 33 | extern void kprobes_remove_breakpoint(void *addr, unsigned int insn); | ||
| 34 | |||
| 32 | enum probes_insn __kprobes | 35 | enum probes_insn __kprobes |
| 33 | kprobe_decode_ldmstm(kprobe_opcode_t insn, struct arch_probes_insn *asi, | 36 | kprobe_decode_ldmstm(kprobe_opcode_t insn, struct arch_probes_insn *asi, |
| 34 | const struct decode_header *h); | 37 | const struct decode_header *h); |
| @@ -36,16 +39,19 @@ kprobe_decode_ldmstm(kprobe_opcode_t insn, struct arch_probes_insn *asi, | |||
| 36 | typedef enum probes_insn (kprobe_decode_insn_t)(probes_opcode_t, | 39 | typedef enum probes_insn (kprobe_decode_insn_t)(probes_opcode_t, |
| 37 | struct arch_probes_insn *, | 40 | struct arch_probes_insn *, |
| 38 | bool, | 41 | bool, |
| 39 | const union decode_action *); | 42 | const union decode_action *, |
| 43 | const struct decode_checker *[]); | ||
| 40 | 44 | ||
| 41 | #ifdef CONFIG_THUMB2_KERNEL | 45 | #ifdef CONFIG_THUMB2_KERNEL |
| 42 | 46 | ||
| 43 | extern const union decode_action kprobes_t32_actions[]; | 47 | extern const union decode_action kprobes_t32_actions[]; |
| 44 | extern const union decode_action kprobes_t16_actions[]; | 48 | extern const union decode_action kprobes_t16_actions[]; |
| 45 | 49 | extern const struct decode_checker *kprobes_t32_checkers[]; | |
| 50 | extern const struct decode_checker *kprobes_t16_checkers[]; | ||
| 46 | #else /* !CONFIG_THUMB2_KERNEL */ | 51 | #else /* !CONFIG_THUMB2_KERNEL */ |
| 47 | 52 | ||
| 48 | extern const union decode_action kprobes_arm_actions[]; | 53 | extern const union decode_action kprobes_arm_actions[]; |
| 54 | extern const struct decode_checker *kprobes_arm_checkers[]; | ||
| 49 | 55 | ||
| 50 | #endif | 56 | #endif |
| 51 | 57 | ||
diff --git a/arch/arm/probes/kprobes/opt-arm.c b/arch/arm/probes/kprobes/opt-arm.c new file mode 100644 index 000000000000..bcdecc25461b --- /dev/null +++ b/arch/arm/probes/kprobes/opt-arm.c | |||
| @@ -0,0 +1,370 @@ | |||
| 1 | /* | ||
| 2 | * Kernel Probes Jump Optimization (Optprobes) | ||
| 3 | * | ||
| 4 | * This program is free software; you can redistribute it and/or modify | ||
| 5 | * it under the terms of the GNU General Public License as published by | ||
| 6 | * the Free Software Foundation; either version 2 of the License, or | ||
| 7 | * (at your option) any later version. | ||
| 8 | * | ||
| 9 | * This program is distributed in the hope that it will be useful, | ||
| 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 12 | * GNU General Public License for more details. | ||
| 13 | * | ||
| 14 | * You should have received a copy of the GNU General Public License | ||
| 15 | * along with this program; if not, write to the Free Software | ||
| 16 | * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | ||
| 17 | * | ||
| 18 | * Copyright (C) IBM Corporation, 2002, 2004 | ||
| 19 | * Copyright (C) Hitachi Ltd., 2012 | ||
| 20 | * Copyright (C) Huawei Inc., 2014 | ||
| 21 | */ | ||
| 22 | |||
| 23 | #include <linux/kprobes.h> | ||
| 24 | #include <linux/jump_label.h> | ||
| 25 | #include <asm/kprobes.h> | ||
| 26 | #include <asm/cacheflush.h> | ||
| 27 | /* for arm_gen_branch */ | ||
| 28 | #include <asm/insn.h> | ||
| 29 | /* for patch_text */ | ||
| 30 | #include <asm/patch.h> | ||
| 31 | |||
| 32 | #include "core.h" | ||
| 33 | |||
| 34 | /* | ||
| 35 | * See register_usage_flags. If the probed instruction doesn't use PC, | ||
| 36 | * we can copy it into template and have it executed directly without | ||
| 37 | * simulation or emulation. | ||
| 38 | */ | ||
| 39 | #define ARM_REG_PC 15 | ||
| 40 | #define can_kprobe_direct_exec(m) (!test_bit(ARM_REG_PC, &(m))) | ||
| 41 | |||
| 42 | /* | ||
| 43 | * NOTE: the first sub and add instruction will be modified according | ||
| 44 | * to the stack cost of the instruction. | ||
| 45 | */ | ||
| 46 | asm ( | ||
| 47 | ".global optprobe_template_entry\n" | ||
| 48 | "optprobe_template_entry:\n" | ||
| 49 | ".global optprobe_template_sub_sp\n" | ||
| 50 | "optprobe_template_sub_sp:" | ||
| 51 | " sub sp, sp, #0xff\n" | ||
| 52 | " stmia sp, {r0 - r14} \n" | ||
| 53 | ".global optprobe_template_add_sp\n" | ||
| 54 | "optprobe_template_add_sp:" | ||
| 55 | " add r3, sp, #0xff\n" | ||
| 56 | " str r3, [sp, #52]\n" | ||
| 57 | " mrs r4, cpsr\n" | ||
| 58 | " str r4, [sp, #64]\n" | ||
| 59 | " mov r1, sp\n" | ||
| 60 | " ldr r0, 1f\n" | ||
| 61 | " ldr r2, 2f\n" | ||
| 62 | /* | ||
| 63 | * AEABI requires an 8-bytes alignment stack. If | ||
| 64 | * SP % 8 != 0 (SP % 4 == 0 should be ensured), | ||
| 65 | * alloc more bytes here. | ||
| 66 | */ | ||
| 67 | " and r4, sp, #4\n" | ||
| 68 | " sub sp, sp, r4\n" | ||
| 69 | #if __LINUX_ARM_ARCH__ >= 5 | ||
| 70 | " blx r2\n" | ||
| 71 | #else | ||
| 72 | " mov lr, pc\n" | ||
| 73 | " mov pc, r2\n" | ||
| 74 | #endif | ||
| 75 | " add sp, sp, r4\n" | ||
| 76 | " ldr r1, [sp, #64]\n" | ||
| 77 | " tst r1, #"__stringify(PSR_T_BIT)"\n" | ||
| 78 | " ldrne r2, [sp, #60]\n" | ||
| 79 | " orrne r2, #1\n" | ||
| 80 | " strne r2, [sp, #60] @ set bit0 of PC for thumb\n" | ||
| 81 | " msr cpsr_cxsf, r1\n" | ||
| 82 | ".global optprobe_template_restore_begin\n" | ||
| 83 | "optprobe_template_restore_begin:\n" | ||
| 84 | " ldmia sp, {r0 - r15}\n" | ||
| 85 | ".global optprobe_template_restore_orig_insn\n" | ||
| 86 | "optprobe_template_restore_orig_insn:\n" | ||
| 87 | " nop\n" | ||
| 88 | ".global optprobe_template_restore_end\n" | ||
| 89 | "optprobe_template_restore_end:\n" | ||
| 90 | " nop\n" | ||
| 91 | ".global optprobe_template_val\n" | ||
| 92 | "optprobe_template_val:\n" | ||
| 93 | "1: .long 0\n" | ||
| 94 | ".global optprobe_template_call\n" | ||
| 95 | "optprobe_template_call:\n" | ||
| 96 | "2: .long 0\n" | ||
| 97 | ".global optprobe_template_end\n" | ||
| 98 | "optprobe_template_end:\n"); | ||
| 99 | |||
| 100 | #define TMPL_VAL_IDX \ | ||
| 101 | ((unsigned long *)&optprobe_template_val - (unsigned long *)&optprobe_template_entry) | ||
| 102 | #define TMPL_CALL_IDX \ | ||
| 103 | ((unsigned long *)&optprobe_template_call - (unsigned long *)&optprobe_template_entry) | ||
| 104 | #define TMPL_END_IDX \ | ||
| 105 | ((unsigned long *)&optprobe_template_end - (unsigned long *)&optprobe_template_entry) | ||
| 106 | #define TMPL_ADD_SP \ | ||
| 107 | ((unsigned long *)&optprobe_template_add_sp - (unsigned long *)&optprobe_template_entry) | ||
| 108 | #define TMPL_SUB_SP \ | ||
| 109 | ((unsigned long *)&optprobe_template_sub_sp - (unsigned long *)&optprobe_template_entry) | ||
| 110 | #define TMPL_RESTORE_BEGIN \ | ||
| 111 | ((unsigned long *)&optprobe_template_restore_begin - (unsigned long *)&optprobe_template_entry) | ||
| 112 | #define TMPL_RESTORE_ORIGN_INSN \ | ||
| 113 | ((unsigned long *)&optprobe_template_restore_orig_insn - (unsigned long *)&optprobe_template_entry) | ||
| 114 | #define TMPL_RESTORE_END \ | ||
| 115 | ((unsigned long *)&optprobe_template_restore_end - (unsigned long *)&optprobe_template_entry) | ||
| 116 | |||
| 117 | /* | ||
| 118 | * ARM can always optimize an instruction when using ARM ISA, except | ||
| 119 | * instructions like 'str r0, [sp, r1]' which store to stack and unable | ||
| 120 | * to determine stack space consumption statically. | ||
| 121 | */ | ||
| 122 | int arch_prepared_optinsn(struct arch_optimized_insn *optinsn) | ||
| 123 | { | ||
| 124 | return optinsn->insn != NULL; | ||
| 125 | } | ||
| 126 | |||
| 127 | /* | ||
| 128 | * In ARM ISA, kprobe opt always replace one instruction (4 bytes | ||
| 129 | * aligned and 4 bytes long). It is impossible to encounter another | ||
| 130 | * kprobe in the address range. So always return 0. | ||
| 131 | */ | ||
| 132 | int arch_check_optimized_kprobe(struct optimized_kprobe *op) | ||
| 133 | { | ||
| 134 | return 0; | ||
| 135 | } | ||
| 136 | |||
| 137 | /* Caller must ensure addr & 3 == 0 */ | ||
| 138 | static int can_optimize(struct kprobe *kp) | ||
| 139 | { | ||
| 140 | if (kp->ainsn.stack_space < 0) | ||
| 141 | return 0; | ||
| 142 | /* | ||
| 143 | * 255 is the biggest imm can be used in 'sub r0, r0, #<imm>'. | ||
| 144 | * Number larger than 255 needs special encoding. | ||
| 145 | */ | ||
| 146 | if (kp->ainsn.stack_space > 255 - sizeof(struct pt_regs)) | ||
| 147 | return 0; | ||
| 148 | return 1; | ||
| 149 | } | ||
| 150 | |||
| 151 | /* Free optimized instruction slot */ | ||
| 152 | static void | ||
| 153 | __arch_remove_optimized_kprobe(struct optimized_kprobe *op, int dirty) | ||
| 154 | { | ||
| 155 | if (op->optinsn.insn) { | ||
| 156 | free_optinsn_slot(op->optinsn.insn, dirty); | ||
| 157 | op->optinsn.insn = NULL; | ||
| 158 | } | ||
| 159 | } | ||
| 160 | |||
| 161 | extern void kprobe_handler(struct pt_regs *regs); | ||
| 162 | |||
| 163 | static void | ||
| 164 | optimized_callback(struct optimized_kprobe *op, struct pt_regs *regs) | ||
| 165 | { | ||
| 166 | unsigned long flags; | ||
| 167 | struct kprobe *p = &op->kp; | ||
| 168 | struct kprobe_ctlblk *kcb = get_kprobe_ctlblk(); | ||
| 169 | |||
| 170 | /* Save skipped registers */ | ||
| 171 | regs->ARM_pc = (unsigned long)op->kp.addr; | ||
| 172 | regs->ARM_ORIG_r0 = ~0UL; | ||
| 173 | |||
| 174 | local_irq_save(flags); | ||
| 175 | |||
| 176 | if (kprobe_running()) { | ||
| 177 | kprobes_inc_nmissed_count(&op->kp); | ||
| 178 | } else { | ||
| 179 | __this_cpu_write(current_kprobe, &op->kp); | ||
| 180 | kcb->kprobe_status = KPROBE_HIT_ACTIVE; | ||
| 181 | opt_pre_handler(&op->kp, regs); | ||
| 182 | __this_cpu_write(current_kprobe, NULL); | ||
| 183 | } | ||
| 184 | |||
| 185 | /* | ||
| 186 | * We singlestep the replaced instruction only when it can't be | ||
| 187 | * executed directly during restore. | ||
| 188 | */ | ||
| 189 | if (!p->ainsn.kprobe_direct_exec) | ||
| 190 | op->kp.ainsn.insn_singlestep(p->opcode, &p->ainsn, regs); | ||
| 191 | |||
| 192 | local_irq_restore(flags); | ||
| 193 | } | ||
| 194 | |||
| 195 | int arch_prepare_optimized_kprobe(struct optimized_kprobe *op, struct kprobe *orig) | ||
| 196 | { | ||
| 197 | kprobe_opcode_t *code; | ||
| 198 | unsigned long rel_chk; | ||
| 199 | unsigned long val; | ||
| 200 | unsigned long stack_protect = sizeof(struct pt_regs); | ||
| 201 | |||
| 202 | if (!can_optimize(orig)) | ||
| 203 | return -EILSEQ; | ||
| 204 | |||
| 205 | code = get_optinsn_slot(); | ||
| 206 | if (!code) | ||
| 207 | return -ENOMEM; | ||
| 208 | |||
| 209 | /* | ||
| 210 | * Verify if the address gap is in 32MiB range, because this uses | ||
| 211 | * a relative jump. | ||
| 212 | * | ||
| 213 | * kprobe opt use a 'b' instruction to branch to optinsn.insn. | ||
| 214 | * According to ARM manual, branch instruction is: | ||
| 215 | * | ||
| 216 | * 31 28 27 24 23 0 | ||
| 217 | * +------+---+---+---+---+----------------+ | ||
| 218 | * | cond | 1 | 0 | 1 | 0 | imm24 | | ||
| 219 | * +------+---+---+---+---+----------------+ | ||
| 220 | * | ||
| 221 | * imm24 is a signed 24 bits integer. The real branch offset is computed | ||
| 222 | * by: imm32 = SignExtend(imm24:'00', 32); | ||
| 223 | * | ||
| 224 | * So the maximum forward branch should be: | ||
| 225 | * (0x007fffff << 2) = 0x01fffffc = 0x1fffffc | ||
| 226 | * The maximum backword branch should be: | ||
| 227 | * (0xff800000 << 2) = 0xfe000000 = -0x2000000 | ||
| 228 | * | ||
| 229 | * We can simply check (rel & 0xfe000003): | ||
| 230 | * if rel is positive, (rel & 0xfe000000) shoule be 0 | ||
| 231 | * if rel is negitive, (rel & 0xfe000000) should be 0xfe000000 | ||
| 232 | * the last '3' is used for alignment checking. | ||
| 233 | */ | ||
| 234 | rel_chk = (unsigned long)((long)code - | ||
| 235 | (long)orig->addr + 8) & 0xfe000003; | ||
| 236 | |||
| 237 | if ((rel_chk != 0) && (rel_chk != 0xfe000000)) { | ||
| 238 | /* | ||
| 239 | * Different from x86, we free code buf directly instead of | ||
| 240 | * calling __arch_remove_optimized_kprobe() because | ||
| 241 | * we have not fill any field in op. | ||
| 242 | */ | ||
| 243 | free_optinsn_slot(code, 0); | ||
| 244 | return -ERANGE; | ||
| 245 | } | ||
| 246 | |||
| 247 | /* Copy arch-dep-instance from template. */ | ||
| 248 | memcpy(code, &optprobe_template_entry, | ||
| 249 | TMPL_END_IDX * sizeof(kprobe_opcode_t)); | ||
| 250 | |||
| 251 | /* Adjust buffer according to instruction. */ | ||
| 252 | BUG_ON(orig->ainsn.stack_space < 0); | ||
| 253 | |||
| 254 | stack_protect += orig->ainsn.stack_space; | ||
| 255 | |||
| 256 | /* Should have been filtered by can_optimize(). */ | ||
| 257 | BUG_ON(stack_protect > 255); | ||
| 258 | |||
| 259 | /* Create a 'sub sp, sp, #<stack_protect>' */ | ||
| 260 | code[TMPL_SUB_SP] = __opcode_to_mem_arm(0xe24dd000 | stack_protect); | ||
| 261 | /* Create a 'add r3, sp, #<stack_protect>' */ | ||
| 262 | code[TMPL_ADD_SP] = __opcode_to_mem_arm(0xe28d3000 | stack_protect); | ||
| 263 | |||
| 264 | /* Set probe information */ | ||
| 265 | val = (unsigned long)op; | ||
| 266 | code[TMPL_VAL_IDX] = val; | ||
| 267 | |||
| 268 | /* Set probe function call */ | ||
| 269 | val = (unsigned long)optimized_callback; | ||
| 270 | code[TMPL_CALL_IDX] = val; | ||
| 271 | |||
| 272 | /* If possible, copy insn and have it executed during restore */ | ||
| 273 | orig->ainsn.kprobe_direct_exec = false; | ||
| 274 | if (can_kprobe_direct_exec(orig->ainsn.register_usage_flags)) { | ||
| 275 | kprobe_opcode_t final_branch = arm_gen_branch( | ||
| 276 | (unsigned long)(&code[TMPL_RESTORE_END]), | ||
| 277 | (unsigned long)(op->kp.addr) + 4); | ||
| 278 | if (final_branch != 0) { | ||
| 279 | /* | ||
| 280 | * Replace original 'ldmia sp, {r0 - r15}' with | ||
| 281 | * 'ldmia {r0 - r14}', restore all registers except pc. | ||
| 282 | */ | ||
| 283 | code[TMPL_RESTORE_BEGIN] = __opcode_to_mem_arm(0xe89d7fff); | ||
| 284 | |||
| 285 | /* The original probed instruction */ | ||
| 286 | code[TMPL_RESTORE_ORIGN_INSN] = __opcode_to_mem_arm(orig->opcode); | ||
| 287 | |||
| 288 | /* Jump back to next instruction */ | ||
| 289 | code[TMPL_RESTORE_END] = __opcode_to_mem_arm(final_branch); | ||
| 290 | orig->ainsn.kprobe_direct_exec = true; | ||
| 291 | } | ||
| 292 | } | ||
| 293 | |||
| 294 | flush_icache_range((unsigned long)code, | ||
| 295 | (unsigned long)(&code[TMPL_END_IDX])); | ||
| 296 | |||
| 297 | /* Set op->optinsn.insn means prepared. */ | ||
| 298 | op->optinsn.insn = code; | ||
| 299 | return 0; | ||
| 300 | } | ||
| 301 | |||
| 302 | void __kprobes arch_optimize_kprobes(struct list_head *oplist) | ||
| 303 | { | ||
| 304 | struct optimized_kprobe *op, *tmp; | ||
| 305 | |||
| 306 | list_for_each_entry_safe(op, tmp, oplist, list) { | ||
| 307 | unsigned long insn; | ||
| 308 | WARN_ON(kprobe_disabled(&op->kp)); | ||
| 309 | |||
| 310 | /* | ||
| 311 | * Backup instructions which will be replaced | ||
| 312 | * by jump address | ||
| 313 | */ | ||
| 314 | memcpy(op->optinsn.copied_insn, op->kp.addr, | ||
| 315 | RELATIVEJUMP_SIZE); | ||
| 316 | |||
| 317 | insn = arm_gen_branch((unsigned long)op->kp.addr, | ||
| 318 | (unsigned long)op->optinsn.insn); | ||
| 319 | BUG_ON(insn == 0); | ||
| 320 | |||
| 321 | /* | ||
| 322 | * Make it a conditional branch if replaced insn | ||
| 323 | * is consitional | ||
| 324 | */ | ||
| 325 | insn = (__mem_to_opcode_arm( | ||
| 326 | op->optinsn.copied_insn[0]) & 0xf0000000) | | ||
| 327 | (insn & 0x0fffffff); | ||
| 328 | |||
| 329 | /* | ||
| 330 | * Similar to __arch_disarm_kprobe, operations which | ||
| 331 | * removing breakpoints must be wrapped by stop_machine | ||
| 332 | * to avoid racing. | ||
| 333 | */ | ||
| 334 | kprobes_remove_breakpoint(op->kp.addr, insn); | ||
| 335 | |||
| 336 | list_del_init(&op->list); | ||
| 337 | } | ||
| 338 | } | ||
| 339 | |||
| 340 | void arch_unoptimize_kprobe(struct optimized_kprobe *op) | ||
| 341 | { | ||
| 342 | arch_arm_kprobe(&op->kp); | ||
| 343 | } | ||
| 344 | |||
| 345 | /* | ||
| 346 | * Recover original instructions and breakpoints from relative jumps. | ||
| 347 | * Caller must call with locking kprobe_mutex. | ||
| 348 | */ | ||
| 349 | void arch_unoptimize_kprobes(struct list_head *oplist, | ||
| 350 | struct list_head *done_list) | ||
| 351 | { | ||
| 352 | struct optimized_kprobe *op, *tmp; | ||
| 353 | |||
| 354 | list_for_each_entry_safe(op, tmp, oplist, list) { | ||
| 355 | arch_unoptimize_kprobe(op); | ||
| 356 | list_move(&op->list, done_list); | ||
| 357 | } | ||
| 358 | } | ||
| 359 | |||
| 360 | int arch_within_optimized_kprobe(struct optimized_kprobe *op, | ||
| 361 | unsigned long addr) | ||
| 362 | { | ||
| 363 | return ((unsigned long)op->kp.addr <= addr && | ||
| 364 | (unsigned long)op->kp.addr + RELATIVEJUMP_SIZE > addr); | ||
| 365 | } | ||
| 366 | |||
| 367 | void arch_remove_optimized_kprobe(struct optimized_kprobe *op) | ||
| 368 | { | ||
| 369 | __arch_remove_optimized_kprobe(op, 1); | ||
| 370 | } | ||
diff --git a/arch/arm/kernel/kprobes-test-arm.c b/arch/arm/probes/kprobes/test-arm.c index cb1424240ff6..8866aedfdea2 100644 --- a/arch/arm/kernel/kprobes-test-arm.c +++ b/arch/arm/probes/kprobes/test-arm.c | |||
| @@ -12,8 +12,9 @@ | |||
| 12 | #include <linux/module.h> | 12 | #include <linux/module.h> |
| 13 | #include <asm/system_info.h> | 13 | #include <asm/system_info.h> |
| 14 | #include <asm/opcodes.h> | 14 | #include <asm/opcodes.h> |
| 15 | #include <asm/probes.h> | ||
| 15 | 16 | ||
| 16 | #include "kprobes-test.h" | 17 | #include "test-core.h" |
| 17 | 18 | ||
| 18 | 19 | ||
| 19 | #define TEST_ISA "32" | 20 | #define TEST_ISA "32" |
| @@ -203,9 +204,9 @@ void kprobe_arm_test_cases(void) | |||
| 203 | #endif | 204 | #endif |
| 204 | TEST_GROUP("Miscellaneous instructions") | 205 | TEST_GROUP("Miscellaneous instructions") |
| 205 | 206 | ||
| 206 | TEST("mrs r0, cpsr") | 207 | TEST_RMASKED("mrs r",0,~PSR_IGNORE_BITS,", cpsr") |
| 207 | TEST("mrspl r7, cpsr") | 208 | TEST_RMASKED("mrspl r",7,~PSR_IGNORE_BITS,", cpsr") |
| 208 | TEST("mrs r14, cpsr") | 209 | TEST_RMASKED("mrs r",14,~PSR_IGNORE_BITS,", cpsr") |
| 209 | TEST_UNSUPPORTED(__inst_arm(0xe10ff000) " @ mrs r15, cpsr") | 210 | TEST_UNSUPPORTED(__inst_arm(0xe10ff000) " @ mrs r15, cpsr") |
| 210 | TEST_UNSUPPORTED("mrs r0, spsr") | 211 | TEST_UNSUPPORTED("mrs r0, spsr") |
| 211 | TEST_UNSUPPORTED("mrs lr, spsr") | 212 | TEST_UNSUPPORTED("mrs lr, spsr") |
| @@ -214,9 +215,12 @@ void kprobe_arm_test_cases(void) | |||
| 214 | TEST_UNSUPPORTED("msr cpsr_f, lr") | 215 | TEST_UNSUPPORTED("msr cpsr_f, lr") |
| 215 | TEST_UNSUPPORTED("msr spsr, r0") | 216 | TEST_UNSUPPORTED("msr spsr, r0") |
| 216 | 217 | ||
| 218 | #if __LINUX_ARM_ARCH__ >= 5 || \ | ||
| 219 | (__LINUX_ARM_ARCH__ == 4 && !defined(CONFIG_CPU_32v4)) | ||
| 217 | TEST_BF_R("bx r",0,2f,"") | 220 | TEST_BF_R("bx r",0,2f,"") |
| 218 | TEST_BB_R("bx r",7,2f,"") | 221 | TEST_BB_R("bx r",7,2f,"") |
| 219 | TEST_BF_R("bxeq r",14,2f,"") | 222 | TEST_BF_R("bxeq r",14,2f,"") |
| 223 | #endif | ||
| 220 | 224 | ||
| 221 | #if __LINUX_ARM_ARCH__ >= 5 | 225 | #if __LINUX_ARM_ARCH__ >= 5 |
| 222 | TEST_R("clz r0, r",0, 0x0,"") | 226 | TEST_R("clz r0, r",0, 0x0,"") |
| @@ -476,7 +480,9 @@ void kprobe_arm_test_cases(void) | |||
| 476 | TEST_GROUP("Extra load/store instructions") | 480 | TEST_GROUP("Extra load/store instructions") |
| 477 | 481 | ||
| 478 | TEST_RPR( "strh r",0, VAL1,", [r",1, 48,", -r",2, 24,"]") | 482 | TEST_RPR( "strh r",0, VAL1,", [r",1, 48,", -r",2, 24,"]") |
| 479 | TEST_RPR( "streqh r",14,VAL2,", [r",13,0, ", r",12, 48,"]") | 483 | TEST_RPR( "streqh r",14,VAL2,", [r",11,0, ", r",12, 48,"]") |
| 484 | TEST_UNSUPPORTED( "streqh r14, [r13, r12]") | ||
| 485 | TEST_UNSUPPORTED( "streqh r14, [r12, r13]") | ||
| 480 | TEST_RPR( "strh r",1, VAL1,", [r",2, 24,", r",3, 48,"]!") | 486 | TEST_RPR( "strh r",1, VAL1,", [r",2, 24,", r",3, 48,"]!") |
| 481 | TEST_RPR( "strneh r",12,VAL2,", [r",11,48,", -r",10,24,"]!") | 487 | TEST_RPR( "strneh r",12,VAL2,", [r",11,48,", -r",10,24,"]!") |
| 482 | TEST_RPR( "strh r",2, VAL1,", [r",3, 24,"], r",4, 48,"") | 488 | TEST_RPR( "strh r",2, VAL1,", [r",3, 24,"], r",4, 48,"") |
| @@ -501,6 +507,9 @@ void kprobe_arm_test_cases(void) | |||
| 501 | TEST_RP( "strplh r",12,VAL2,", [r",11,24,", #-4]!") | 507 | TEST_RP( "strplh r",12,VAL2,", [r",11,24,", #-4]!") |
| 502 | TEST_RP( "strh r",2, VAL1,", [r",3, 24,"], #48") | 508 | TEST_RP( "strh r",2, VAL1,", [r",3, 24,"], #48") |
| 503 | TEST_RP( "strh r",10,VAL2,", [r",9, 64,"], #-48") | 509 | TEST_RP( "strh r",10,VAL2,", [r",9, 64,"], #-48") |
| 510 | TEST_RP( "strh r",3, VAL1,", [r",13,TEST_MEMORY_SIZE,", #-"__stringify(MAX_STACK_SIZE)"]!") | ||
| 511 | TEST_UNSUPPORTED("strh r3, [r13, #-"__stringify(MAX_STACK_SIZE)"-8]!") | ||
| 512 | TEST_RP( "strh r",4, VAL1,", [r",14,TEST_MEMORY_SIZE,", #-"__stringify(MAX_STACK_SIZE)"-8]!") | ||
| 504 | TEST_UNSUPPORTED(__inst_arm(0xe1efc3b0) " @ strh r12, [pc, #48]!") | 513 | TEST_UNSUPPORTED(__inst_arm(0xe1efc3b0) " @ strh r12, [pc, #48]!") |
| 505 | TEST_UNSUPPORTED(__inst_arm(0xe0c9f3b0) " @ strh pc, [r9], #48") | 514 | TEST_UNSUPPORTED(__inst_arm(0xe0c9f3b0) " @ strh pc, [r9], #48") |
| 506 | 515 | ||
| @@ -565,7 +574,9 @@ void kprobe_arm_test_cases(void) | |||
| 565 | 574 | ||
| 566 | #if __LINUX_ARM_ARCH__ >= 5 | 575 | #if __LINUX_ARM_ARCH__ >= 5 |
| 567 | TEST_RPR( "strd r",0, VAL1,", [r",1, 48,", -r",2,24,"]") | 576 | TEST_RPR( "strd r",0, VAL1,", [r",1, 48,", -r",2,24,"]") |
| 568 | TEST_RPR( "strccd r",8, VAL2,", [r",13,0, ", r",12,48,"]") | 577 | TEST_RPR( "strccd r",8, VAL2,", [r",11,0, ", r",12,48,"]") |
| 578 | TEST_UNSUPPORTED( "strccd r8, [r13, r12]") | ||
| 579 | TEST_UNSUPPORTED( "strccd r8, [r12, r13]") | ||
| 569 | TEST_RPR( "strd r",4, VAL1,", [r",2, 24,", r",3, 48,"]!") | 580 | TEST_RPR( "strd r",4, VAL1,", [r",2, 24,", r",3, 48,"]!") |
| 570 | TEST_RPR( "strcsd r",12,VAL2,", [r",11,48,", -r",10,24,"]!") | 581 | TEST_RPR( "strcsd r",12,VAL2,", [r",11,48,", -r",10,24,"]!") |
| 571 | TEST_RPR( "strd r",2, VAL1,", [r",5, 24,"], r",4,48,"") | 582 | TEST_RPR( "strd r",2, VAL1,", [r",5, 24,"], r",4,48,"") |
| @@ -589,6 +600,9 @@ void kprobe_arm_test_cases(void) | |||
| 589 | TEST_RP( "strvcd r",12,VAL2,", [r",11,24,", #-16]!") | 600 | TEST_RP( "strvcd r",12,VAL2,", [r",11,24,", #-16]!") |
| 590 | TEST_RP( "strd r",2, VAL1,", [r",4, 24,"], #48") | 601 | TEST_RP( "strd r",2, VAL1,", [r",4, 24,"], #48") |
| 591 | TEST_RP( "strd r",10,VAL2,", [r",9, 64,"], #-48") | 602 | TEST_RP( "strd r",10,VAL2,", [r",9, 64,"], #-48") |
| 603 | TEST_RP( "strd r",6, VAL1,", [r",13,TEST_MEMORY_SIZE,", #-"__stringify(MAX_STACK_SIZE)"]!") | ||
| 604 | TEST_UNSUPPORTED("strd r6, [r13, #-"__stringify(MAX_STACK_SIZE)"-8]!") | ||
| 605 | TEST_RP( "strd r",4, VAL1,", [r",12,TEST_MEMORY_SIZE,", #-"__stringify(MAX_STACK_SIZE)"-8]!") | ||
| 592 | TEST_UNSUPPORTED(__inst_arm(0xe1efc3f0) " @ strd r12, [pc, #48]!") | 606 | TEST_UNSUPPORTED(__inst_arm(0xe1efc3f0) " @ strd r12, [pc, #48]!") |
| 593 | 607 | ||
| 594 | TEST_P( "ldrd r0, [r",0, 24,", #-8]") | 608 | TEST_P( "ldrd r0, [r",0, 24,", #-8]") |
| @@ -637,14 +651,20 @@ void kprobe_arm_test_cases(void) | |||
| 637 | TEST_RP( "str"byte" r",12,VAL2,", [r",11,24,", #-4]!") \ | 651 | TEST_RP( "str"byte" r",12,VAL2,", [r",11,24,", #-4]!") \ |
| 638 | TEST_RP( "str"byte" r",2, VAL1,", [r",3, 24,"], #48") \ | 652 | TEST_RP( "str"byte" r",2, VAL1,", [r",3, 24,"], #48") \ |
| 639 | TEST_RP( "str"byte" r",10,VAL2,", [r",9, 64,"], #-48") \ | 653 | TEST_RP( "str"byte" r",10,VAL2,", [r",9, 64,"], #-48") \ |
| 654 | TEST_RP( "str"byte" r",3, VAL1,", [r",13,TEST_MEMORY_SIZE,", #-"__stringify(MAX_STACK_SIZE)"]!") \ | ||
| 655 | TEST_UNSUPPORTED("str"byte" r3, [r13, #-"__stringify(MAX_STACK_SIZE)"-8]!") \ | ||
| 656 | TEST_RP( "str"byte" r",4, VAL1,", [r",10,TEST_MEMORY_SIZE,", #-"__stringify(MAX_STACK_SIZE)"-8]!") \ | ||
| 640 | TEST_RPR("str"byte" r",0, VAL1,", [r",1, 48,", -r",2, 24,"]") \ | 657 | TEST_RPR("str"byte" r",0, VAL1,", [r",1, 48,", -r",2, 24,"]") \ |
| 641 | TEST_RPR("str"byte" r",14,VAL2,", [r",13,0, ", r",12, 48,"]") \ | 658 | TEST_RPR("str"byte" r",14,VAL2,", [r",11,0, ", r",12, 48,"]") \ |
| 659 | TEST_UNSUPPORTED("str"byte" r14, [r13, r12]") \ | ||
| 660 | TEST_UNSUPPORTED("str"byte" r14, [r12, r13]") \ | ||
| 642 | TEST_RPR("str"byte" r",1, VAL1,", [r",2, 24,", r",3, 48,"]!") \ | 661 | TEST_RPR("str"byte" r",1, VAL1,", [r",2, 24,", r",3, 48,"]!") \ |
| 643 | TEST_RPR("str"byte" r",12,VAL2,", [r",11,48,", -r",10,24,"]!") \ | 662 | TEST_RPR("str"byte" r",12,VAL2,", [r",11,48,", -r",10,24,"]!") \ |
| 644 | TEST_RPR("str"byte" r",2, VAL1,", [r",3, 24,"], r",4, 48,"") \ | 663 | TEST_RPR("str"byte" r",2, VAL1,", [r",3, 24,"], r",4, 48,"") \ |
| 645 | TEST_RPR("str"byte" r",10,VAL2,", [r",9, 48,"], -r",11,24,"") \ | 664 | TEST_RPR("str"byte" r",10,VAL2,", [r",9, 48,"], -r",11,24,"") \ |
| 646 | TEST_RPR("str"byte" r",0, VAL1,", [r",1, 24,", r",2, 32,", asl #1]")\ | 665 | TEST_RPR("str"byte" r",0, VAL1,", [r",1, 24,", r",2, 32,", asl #1]")\ |
| 647 | TEST_RPR("str"byte" r",14,VAL2,", [r",13,0, ", r",12, 32,", lsr #2]")\ | 666 | TEST_RPR("str"byte" r",14,VAL2,", [r",11,0, ", r",12, 32,", lsr #2]")\ |
| 667 | TEST_UNSUPPORTED("str"byte" r14, [r13, r12, lsr #2]") \ | ||
| 648 | TEST_RPR("str"byte" r",1, VAL1,", [r",2, 24,", r",3, 32,", asr #3]!")\ | 668 | TEST_RPR("str"byte" r",1, VAL1,", [r",2, 24,", r",3, 32,", asr #3]!")\ |
| 649 | TEST_RPR("str"byte" r",12,VAL2,", [r",11,24,", r",10, 4,", ror #31]!")\ | 669 | TEST_RPR("str"byte" r",12,VAL2,", [r",11,24,", r",10, 4,", ror #31]!")\ |
| 650 | TEST_P( "ldr"byte" r0, [r",0, 24,", #-2]") \ | 670 | TEST_P( "ldr"byte" r0, [r",0, 24,", #-2]") \ |
| @@ -668,12 +688,12 @@ void kprobe_arm_test_cases(void) | |||
| 668 | 688 | ||
| 669 | LOAD_STORE("") | 689 | LOAD_STORE("") |
| 670 | TEST_P( "str pc, [r",0,0,", #15*4]") | 690 | TEST_P( "str pc, [r",0,0,", #15*4]") |
| 671 | TEST_R( "str pc, [sp, r",2,15*4,"]") | 691 | TEST_UNSUPPORTED( "str pc, [sp, r2]") |
| 672 | TEST_BF( "ldr pc, [sp, #15*4]") | 692 | TEST_BF( "ldr pc, [sp, #15*4]") |
| 673 | TEST_BF_R("ldr pc, [sp, r",2,15*4,"]") | 693 | TEST_BF_R("ldr pc, [sp, r",2,15*4,"]") |
| 674 | 694 | ||
| 675 | TEST_P( "str sp, [r",0,0,", #13*4]") | 695 | TEST_P( "str sp, [r",0,0,", #13*4]") |
| 676 | TEST_R( "str sp, [sp, r",2,13*4,"]") | 696 | TEST_UNSUPPORTED( "str sp, [sp, r2]") |
| 677 | TEST_BF( "ldr sp, [sp, #13*4]") | 697 | TEST_BF( "ldr sp, [sp, #13*4]") |
| 678 | TEST_BF_R("ldr sp, [sp, r",2,13*4,"]") | 698 | TEST_BF_R("ldr sp, [sp, r",2,13*4,"]") |
| 679 | 699 | ||
diff --git a/arch/arm/kernel/kprobes-test.c b/arch/arm/probes/kprobes/test-core.c index b206d7790c77..9775de22e2ff 100644 --- a/arch/arm/kernel/kprobes-test.c +++ b/arch/arm/probes/kprobes/test-core.c | |||
| @@ -209,10 +209,10 @@ | |||
| 209 | #include <linux/bug.h> | 209 | #include <linux/bug.h> |
| 210 | #include <asm/opcodes.h> | 210 | #include <asm/opcodes.h> |
| 211 | 211 | ||
| 212 | #include "kprobes.h" | 212 | #include "core.h" |
| 213 | #include "probes-arm.h" | 213 | #include "test-core.h" |
| 214 | #include "probes-thumb.h" | 214 | #include "../decode-arm.h" |
| 215 | #include "kprobes-test.h" | 215 | #include "../decode-thumb.h" |
| 216 | 216 | ||
| 217 | 217 | ||
| 218 | #define BENCHMARKING 1 | 218 | #define BENCHMARKING 1 |
| @@ -236,6 +236,8 @@ static int tests_failed; | |||
| 236 | 236 | ||
| 237 | #ifndef CONFIG_THUMB2_KERNEL | 237 | #ifndef CONFIG_THUMB2_KERNEL |
| 238 | 238 | ||
| 239 | #define RET(reg) "mov pc, "#reg | ||
| 240 | |||
| 239 | long arm_func(long r0, long r1); | 241 | long arm_func(long r0, long r1); |
| 240 | 242 | ||
| 241 | static void __used __naked __arm_kprobes_test_func(void) | 243 | static void __used __naked __arm_kprobes_test_func(void) |
| @@ -245,7 +247,7 @@ static void __used __naked __arm_kprobes_test_func(void) | |||
| 245 | ".type arm_func, %%function \n\t" | 247 | ".type arm_func, %%function \n\t" |
| 246 | "arm_func: \n\t" | 248 | "arm_func: \n\t" |
| 247 | "adds r0, r0, r1 \n\t" | 249 | "adds r0, r0, r1 \n\t" |
| 248 | "bx lr \n\t" | 250 | "mov pc, lr \n\t" |
| 249 | ".code "NORMAL_ISA /* Back to Thumb if necessary */ | 251 | ".code "NORMAL_ISA /* Back to Thumb if necessary */ |
| 250 | : : : "r0", "r1", "cc" | 252 | : : : "r0", "r1", "cc" |
| 251 | ); | 253 | ); |
| @@ -253,6 +255,8 @@ static void __used __naked __arm_kprobes_test_func(void) | |||
| 253 | 255 | ||
| 254 | #else /* CONFIG_THUMB2_KERNEL */ | 256 | #else /* CONFIG_THUMB2_KERNEL */ |
| 255 | 257 | ||
| 258 | #define RET(reg) "bx "#reg | ||
| 259 | |||
| 256 | long thumb16_func(long r0, long r1); | 260 | long thumb16_func(long r0, long r1); |
| 257 | long thumb32even_func(long r0, long r1); | 261 | long thumb32even_func(long r0, long r1); |
| 258 | long thumb32odd_func(long r0, long r1); | 262 | long thumb32odd_func(long r0, long r1); |
| @@ -494,7 +498,7 @@ static void __naked benchmark_nop(void) | |||
| 494 | { | 498 | { |
| 495 | __asm__ __volatile__ ( | 499 | __asm__ __volatile__ ( |
| 496 | "nop \n\t" | 500 | "nop \n\t" |
| 497 | "bx lr" | 501 | RET(lr)" \n\t" |
| 498 | ); | 502 | ); |
| 499 | } | 503 | } |
| 500 | 504 | ||
| @@ -977,7 +981,7 @@ void __naked __kprobes_test_case_start(void) | |||
| 977 | "bic r0, lr, #1 @ r0 = inline data \n\t" | 981 | "bic r0, lr, #1 @ r0 = inline data \n\t" |
| 978 | "mov r1, sp \n\t" | 982 | "mov r1, sp \n\t" |
| 979 | "bl kprobes_test_case_start \n\t" | 983 | "bl kprobes_test_case_start \n\t" |
| 980 | "bx r0 \n\t" | 984 | RET(r0)" \n\t" |
| 981 | ); | 985 | ); |
| 982 | } | 986 | } |
| 983 | 987 | ||
| @@ -1056,15 +1060,6 @@ static int test_case_run_count; | |||
| 1056 | static bool test_case_is_thumb; | 1060 | static bool test_case_is_thumb; |
| 1057 | static int test_instance; | 1061 | static int test_instance; |
| 1058 | 1062 | ||
| 1059 | /* | ||
| 1060 | * We ignore the state of the imprecise abort disable flag (CPSR.A) because this | ||
| 1061 | * can change randomly as the kernel doesn't take care to preserve or initialise | ||
| 1062 | * this across context switches. Also, with Security Extentions, the flag may | ||
| 1063 | * not be under control of the kernel; for this reason we ignore the state of | ||
| 1064 | * the FIQ disable flag CPSR.F as well. | ||
| 1065 | */ | ||
| 1066 | #define PSR_IGNORE_BITS (PSR_A_BIT | PSR_F_BIT) | ||
| 1067 | |||
| 1068 | static unsigned long test_check_cc(int cc, unsigned long cpsr) | 1063 | static unsigned long test_check_cc(int cc, unsigned long cpsr) |
| 1069 | { | 1064 | { |
| 1070 | int ret = arm_check_condition(cc << 28, cpsr); | 1065 | int ret = arm_check_condition(cc << 28, cpsr); |
| @@ -1196,6 +1191,13 @@ static void setup_test_context(struct pt_regs *regs) | |||
| 1196 | regs->uregs[arg->reg] = | 1191 | regs->uregs[arg->reg] = |
| 1197 | (unsigned long)current_stack + arg->val; | 1192 | (unsigned long)current_stack + arg->val; |
| 1198 | memory_needs_checking = true; | 1193 | memory_needs_checking = true; |
| 1194 | /* | ||
| 1195 | * Test memory at an address below SP is in danger of | ||
| 1196 | * being altered by an interrupt occurring and pushing | ||
| 1197 | * data onto the stack. Disable interrupts to stop this. | ||
| 1198 | */ | ||
| 1199 | if (arg->reg == 13) | ||
| 1200 | regs->ARM_cpsr |= PSR_I_BIT; | ||
| 1199 | break; | 1201 | break; |
| 1200 | } | 1202 | } |
| 1201 | case ARG_TYPE_MEM: { | 1203 | case ARG_TYPE_MEM: { |
| @@ -1264,14 +1266,26 @@ test_case_pre_handler(struct kprobe *p, struct pt_regs *regs) | |||
| 1264 | static int __kprobes | 1266 | static int __kprobes |
| 1265 | test_after_pre_handler(struct kprobe *p, struct pt_regs *regs) | 1267 | test_after_pre_handler(struct kprobe *p, struct pt_regs *regs) |
| 1266 | { | 1268 | { |
| 1269 | struct test_arg *args; | ||
| 1270 | |||
| 1267 | if (container_of(p, struct test_probe, kprobe)->hit == test_instance) | 1271 | if (container_of(p, struct test_probe, kprobe)->hit == test_instance) |
| 1268 | return 0; /* Already run for this test instance */ | 1272 | return 0; /* Already run for this test instance */ |
| 1269 | 1273 | ||
| 1270 | result_regs = *regs; | 1274 | result_regs = *regs; |
| 1275 | |||
| 1276 | /* Mask out results which are indeterminate */ | ||
| 1271 | result_regs.ARM_cpsr &= ~PSR_IGNORE_BITS; | 1277 | result_regs.ARM_cpsr &= ~PSR_IGNORE_BITS; |
| 1278 | for (args = current_args; args[0].type != ARG_TYPE_END; ++args) | ||
| 1279 | if (args[0].type == ARG_TYPE_REG_MASKED) { | ||
| 1280 | struct test_arg_regptr *arg = | ||
| 1281 | (struct test_arg_regptr *)args; | ||
| 1282 | result_regs.uregs[arg->reg] &= arg->val; | ||
| 1283 | } | ||
| 1272 | 1284 | ||
| 1273 | /* Undo any changes done to SP by the test case */ | 1285 | /* Undo any changes done to SP by the test case */ |
| 1274 | regs->ARM_sp = (unsigned long)current_stack; | 1286 | regs->ARM_sp = (unsigned long)current_stack; |
| 1287 | /* Enable interrupts in case setup_test_context disabled them */ | ||
| 1288 | regs->ARM_cpsr &= ~PSR_I_BIT; | ||
| 1275 | 1289 | ||
| 1276 | container_of(p, struct test_probe, kprobe)->hit = test_instance; | 1290 | container_of(p, struct test_probe, kprobe)->hit = test_instance; |
| 1277 | return 0; | 1291 | return 0; |
diff --git a/arch/arm/kernel/kprobes-test.h b/arch/arm/probes/kprobes/test-core.h index 4430990e90e7..94285203e9f7 100644 --- a/arch/arm/kernel/kprobes-test.h +++ b/arch/arm/probes/kprobes/test-core.h | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * arch/arm/kernel/kprobes-test.h | 2 | * arch/arm/probes/kprobes/test-core.h |
| 3 | * | 3 | * |
| 4 | * Copyright (C) 2011 Jon Medhurst <tixy@yxit.co.uk>. | 4 | * Copyright (C) 2011 Jon Medhurst <tixy@yxit.co.uk>. |
| 5 | * | 5 | * |
| @@ -45,10 +45,11 @@ extern int kprobe_test_cc_position; | |||
| 45 | * | 45 | * |
| 46 | */ | 46 | */ |
| 47 | 47 | ||
| 48 | #define ARG_TYPE_END 0 | 48 | #define ARG_TYPE_END 0 |
| 49 | #define ARG_TYPE_REG 1 | 49 | #define ARG_TYPE_REG 1 |
| 50 | #define ARG_TYPE_PTR 2 | 50 | #define ARG_TYPE_PTR 2 |
| 51 | #define ARG_TYPE_MEM 3 | 51 | #define ARG_TYPE_MEM 3 |
| 52 | #define ARG_TYPE_REG_MASKED 4 | ||
| 52 | 53 | ||
| 53 | #define ARG_FLAG_UNSUPPORTED 0x01 | 54 | #define ARG_FLAG_UNSUPPORTED 0x01 |
| 54 | #define ARG_FLAG_SUPPORTED 0x02 | 55 | #define ARG_FLAG_SUPPORTED 0x02 |
| @@ -61,7 +62,7 @@ struct test_arg { | |||
| 61 | }; | 62 | }; |
| 62 | 63 | ||
| 63 | struct test_arg_regptr { | 64 | struct test_arg_regptr { |
| 64 | u8 type; /* ARG_TYPE_REG or ARG_TYPE_PTR */ | 65 | u8 type; /* ARG_TYPE_REG or ARG_TYPE_PTR or ARG_TYPE_REG_MASKED */ |
| 65 | u8 reg; | 66 | u8 reg; |
| 66 | u8 _padding[2]; | 67 | u8 _padding[2]; |
| 67 | u32 val; | 68 | u32 val; |
| @@ -138,6 +139,12 @@ struct test_arg_end { | |||
| 138 | ".short 0 \n\t" \ | 139 | ".short 0 \n\t" \ |
| 139 | ".word "#val" \n\t" | 140 | ".word "#val" \n\t" |
| 140 | 141 | ||
| 142 | #define TEST_ARG_REG_MASKED(reg, val) \ | ||
| 143 | ".byte "__stringify(ARG_TYPE_REG_MASKED)" \n\t" \ | ||
| 144 | ".byte "#reg" \n\t" \ | ||
| 145 | ".short 0 \n\t" \ | ||
| 146 | ".word "#val" \n\t" | ||
| 147 | |||
| 141 | #define TEST_ARG_END(flags) \ | 148 | #define TEST_ARG_END(flags) \ |
| 142 | ".byte "__stringify(ARG_TYPE_END)" \n\t" \ | 149 | ".byte "__stringify(ARG_TYPE_END)" \n\t" \ |
| 143 | ".byte "TEST_ISA flags" \n\t" \ | 150 | ".byte "TEST_ISA flags" \n\t" \ |
| @@ -395,6 +402,22 @@ struct test_arg_end { | |||
| 395 | " "codex" \n\t" \ | 402 | " "codex" \n\t" \ |
| 396 | TESTCASE_END | 403 | TESTCASE_END |
| 397 | 404 | ||
| 405 | #define TEST_RMASKED(code1, reg, mask, code2) \ | ||
| 406 | TESTCASE_START(code1 #reg code2) \ | ||
| 407 | TEST_ARG_REG_MASKED(reg, mask) \ | ||
| 408 | TEST_ARG_END("") \ | ||
| 409 | TEST_INSTRUCTION(code1 #reg code2) \ | ||
| 410 | TESTCASE_END | ||
| 411 | |||
| 412 | /* | ||
| 413 | * We ignore the state of the imprecise abort disable flag (CPSR.A) because this | ||
| 414 | * can change randomly as the kernel doesn't take care to preserve or initialise | ||
| 415 | * this across context switches. Also, with Security Extensions, the flag may | ||
| 416 | * not be under control of the kernel; for this reason we ignore the state of | ||
| 417 | * the FIQ disable flag CPSR.F as well. | ||
| 418 | */ | ||
| 419 | #define PSR_IGNORE_BITS (PSR_A_BIT | PSR_F_BIT) | ||
| 420 | |||
| 398 | 421 | ||
| 399 | /* | 422 | /* |
| 400 | * Macros for defining space directives spread over multiple lines. | 423 | * Macros for defining space directives spread over multiple lines. |
diff --git a/arch/arm/kernel/kprobes-test-thumb.c b/arch/arm/probes/kprobes/test-thumb.c index 844dd10d8593..b683b4517458 100644 --- a/arch/arm/kernel/kprobes-test-thumb.c +++ b/arch/arm/probes/kprobes/test-thumb.c | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * arch/arm/kernel/kprobes-test-thumb.c | 2 | * arch/arm/probes/kprobes/test-thumb.c |
| 3 | * | 3 | * |
| 4 | * Copyright (C) 2011 Jon Medhurst <tixy@yxit.co.uk>. | 4 | * Copyright (C) 2011 Jon Medhurst <tixy@yxit.co.uk>. |
| 5 | * | 5 | * |
| @@ -11,8 +11,9 @@ | |||
| 11 | #include <linux/kernel.h> | 11 | #include <linux/kernel.h> |
| 12 | #include <linux/module.h> | 12 | #include <linux/module.h> |
| 13 | #include <asm/opcodes.h> | 13 | #include <asm/opcodes.h> |
| 14 | #include <asm/probes.h> | ||
| 14 | 15 | ||
| 15 | #include "kprobes-test.h" | 16 | #include "test-core.h" |
| 16 | 17 | ||
| 17 | 18 | ||
| 18 | #define TEST_ISA "16" | 19 | #define TEST_ISA "16" |
| @@ -416,6 +417,9 @@ void kprobe_thumb32_test_cases(void) | |||
| 416 | TEST_RR( "strd r",14,VAL2,", r",12,VAL1,", [sp, #16]!") | 417 | TEST_RR( "strd r",14,VAL2,", r",12,VAL1,", [sp, #16]!") |
| 417 | TEST_RRP("strd r",1, VAL1,", r",0, VAL2,", [r",7, 24,"], #16") | 418 | TEST_RRP("strd r",1, VAL1,", r",0, VAL2,", [r",7, 24,"], #16") |
| 418 | TEST_RR( "strd r",7, VAL2,", r",8, VAL1,", [sp], #-16") | 419 | TEST_RR( "strd r",7, VAL2,", r",8, VAL1,", [sp], #-16") |
| 420 | TEST_RRP("strd r",6, VAL1,", r",7, VAL2,", [r",13, TEST_MEMORY_SIZE,", #-"__stringify(MAX_STACK_SIZE)"]!") | ||
| 421 | TEST_UNSUPPORTED("strd r6, r7, [r13, #-"__stringify(MAX_STACK_SIZE)"-8]!") | ||
| 422 | TEST_RRP("strd r",4, VAL1,", r",5, VAL2,", [r",14, TEST_MEMORY_SIZE,", #-"__stringify(MAX_STACK_SIZE)"-8]!") | ||
| 419 | TEST_UNSUPPORTED(__inst_thumb32(0xe9efec04) " @ strd r14, r12, [pc, #16]!") | 423 | TEST_UNSUPPORTED(__inst_thumb32(0xe9efec04) " @ strd r14, r12, [pc, #16]!") |
| 420 | TEST_UNSUPPORTED(__inst_thumb32(0xe8efec04) " @ strd r14, r12, [pc], #16") | 424 | TEST_UNSUPPORTED(__inst_thumb32(0xe8efec04) " @ strd r14, r12, [pc], #16") |
| 421 | 425 | ||
| @@ -774,8 +778,8 @@ CONDITION_INSTRUCTIONS(22, | |||
| 774 | 778 | ||
| 775 | TEST_UNSUPPORTED("subs pc, lr, #4") | 779 | TEST_UNSUPPORTED("subs pc, lr, #4") |
| 776 | 780 | ||
| 777 | TEST("mrs r0, cpsr") | 781 | TEST_RMASKED("mrs r",0,~PSR_IGNORE_BITS,", cpsr") |
| 778 | TEST("mrs r14, cpsr") | 782 | TEST_RMASKED("mrs r",14,~PSR_IGNORE_BITS,", cpsr") |
| 779 | TEST_UNSUPPORTED(__inst_thumb32(0xf3ef8d00) " @ mrs sp, spsr") | 783 | TEST_UNSUPPORTED(__inst_thumb32(0xf3ef8d00) " @ mrs sp, spsr") |
| 780 | TEST_UNSUPPORTED(__inst_thumb32(0xf3ef8f00) " @ mrs pc, spsr") | 784 | TEST_UNSUPPORTED(__inst_thumb32(0xf3ef8f00) " @ mrs pc, spsr") |
| 781 | TEST_UNSUPPORTED("mrs r0, spsr") | 785 | TEST_UNSUPPORTED("mrs r0, spsr") |
| @@ -821,14 +825,22 @@ CONDITION_INSTRUCTIONS(22, | |||
| 821 | TEST_RP( "str"size" r",14,VAL2,", [r",1, 256, ", #-128]!") \ | 825 | TEST_RP( "str"size" r",14,VAL2,", [r",1, 256, ", #-128]!") \ |
| 822 | TEST_RPR("str"size".w r",0, VAL1,", [r",1, 0,", r",2, 4,"]") \ | 826 | TEST_RPR("str"size".w r",0, VAL1,", [r",1, 0,", r",2, 4,"]") \ |
| 823 | TEST_RPR("str"size" r",14,VAL2,", [r",10,0,", r",11,4,", lsl #1]") \ | 827 | TEST_RPR("str"size" r",14,VAL2,", [r",10,0,", r",11,4,", lsl #1]") \ |
| 828 | TEST_UNSUPPORTED("str"size" r0, [r13, r1]") \ | ||
| 824 | TEST_R( "str"size".w r",7, VAL1,", [sp, #24]") \ | 829 | TEST_R( "str"size".w r",7, VAL1,", [sp, #24]") \ |
| 825 | TEST_RP( "str"size".w r",0, VAL2,", [r",0,0, "]") \ | 830 | TEST_RP( "str"size".w r",0, VAL2,", [r",0,0, "]") \ |
| 831 | TEST_RP( "str"size" r",6, VAL1,", [r",13, TEST_MEMORY_SIZE,", #-"__stringify(MAX_STACK_SIZE)"]!") \ | ||
| 832 | TEST_UNSUPPORTED("str"size" r6, [r13, #-"__stringify(MAX_STACK_SIZE)"-8]!") \ | ||
| 833 | TEST_RP( "str"size" r",4, VAL2,", [r",12, TEST_MEMORY_SIZE,", #-"__stringify(MAX_STACK_SIZE)"-8]!") \ | ||
| 826 | TEST_UNSUPPORTED("str"size"t r0, [r1, #4]") | 834 | TEST_UNSUPPORTED("str"size"t r0, [r1, #4]") |
| 827 | 835 | ||
| 828 | SINGLE_STORE("b") | 836 | SINGLE_STORE("b") |
| 829 | SINGLE_STORE("h") | 837 | SINGLE_STORE("h") |
| 830 | SINGLE_STORE("") | 838 | SINGLE_STORE("") |
| 831 | 839 | ||
| 840 | TEST_UNSUPPORTED(__inst_thumb32(0xf801000d) " @ strb r0, [r1, r13]") | ||
| 841 | TEST_UNSUPPORTED(__inst_thumb32(0xf821000d) " @ strh r0, [r1, r13]") | ||
| 842 | TEST_UNSUPPORTED(__inst_thumb32(0xf841000d) " @ str r0, [r1, r13]") | ||
| 843 | |||
| 832 | TEST("str sp, [sp]") | 844 | TEST("str sp, [sp]") |
| 833 | TEST_UNSUPPORTED(__inst_thumb32(0xf8cfe000) " @ str r14, [pc]") | 845 | TEST_UNSUPPORTED(__inst_thumb32(0xf8cfe000) " @ str r14, [pc]") |
| 834 | TEST_UNSUPPORTED(__inst_thumb32(0xf8cef000) " @ str pc, [r14]") | 846 | TEST_UNSUPPORTED(__inst_thumb32(0xf8cef000) " @ str pc, [r14]") |
diff --git a/arch/arm/probes/uprobes/Makefile b/arch/arm/probes/uprobes/Makefile new file mode 100644 index 000000000000..e1dc3d0f6d5a --- /dev/null +++ b/arch/arm/probes/uprobes/Makefile | |||
| @@ -0,0 +1 @@ | |||
| obj-$(CONFIG_UPROBES) += core.o actions-arm.o | |||
diff --git a/arch/arm/kernel/uprobes-arm.c b/arch/arm/probes/uprobes/actions-arm.c index d3b655ff17da..76eb44972ebe 100644 --- a/arch/arm/kernel/uprobes-arm.c +++ b/arch/arm/probes/uprobes/actions-arm.c | |||
| @@ -13,9 +13,9 @@ | |||
| 13 | #include <linux/uprobes.h> | 13 | #include <linux/uprobes.h> |
| 14 | #include <linux/module.h> | 14 | #include <linux/module.h> |
| 15 | 15 | ||
| 16 | #include "probes.h" | 16 | #include "../decode.h" |
| 17 | #include "probes-arm.h" | 17 | #include "../decode-arm.h" |
| 18 | #include "uprobes.h" | 18 | #include "core.h" |
| 19 | 19 | ||
| 20 | static int uprobes_substitute_pc(unsigned long *pinsn, u32 oregs) | 20 | static int uprobes_substitute_pc(unsigned long *pinsn, u32 oregs) |
| 21 | { | 21 | { |
| @@ -195,8 +195,6 @@ uprobe_decode_ldmstm(probes_opcode_t insn, | |||
| 195 | } | 195 | } |
| 196 | 196 | ||
| 197 | const union decode_action uprobes_probes_actions[] = { | 197 | const union decode_action uprobes_probes_actions[] = { |
| 198 | [PROBES_EMULATE_NONE] = {.handler = probes_simulate_nop}, | ||
| 199 | [PROBES_SIMULATE_NOP] = {.handler = probes_simulate_nop}, | ||
| 200 | [PROBES_PRELOAD_IMM] = {.handler = probes_simulate_nop}, | 198 | [PROBES_PRELOAD_IMM] = {.handler = probes_simulate_nop}, |
| 201 | [PROBES_PRELOAD_REG] = {.handler = probes_simulate_nop}, | 199 | [PROBES_PRELOAD_REG] = {.handler = probes_simulate_nop}, |
| 202 | [PROBES_BRANCH_IMM] = {.handler = simulate_blx1}, | 200 | [PROBES_BRANCH_IMM] = {.handler = simulate_blx1}, |
diff --git a/arch/arm/kernel/uprobes.c b/arch/arm/probes/uprobes/core.c index 56adf9c1fde0..d1329f1ba4e4 100644 --- a/arch/arm/kernel/uprobes.c +++ b/arch/arm/probes/uprobes/core.c | |||
| @@ -17,9 +17,9 @@ | |||
| 17 | #include <asm/opcodes.h> | 17 | #include <asm/opcodes.h> |
| 18 | #include <asm/traps.h> | 18 | #include <asm/traps.h> |
| 19 | 19 | ||
| 20 | #include "probes.h" | 20 | #include "../decode.h" |
| 21 | #include "probes-arm.h" | 21 | #include "../decode-arm.h" |
| 22 | #include "uprobes.h" | 22 | #include "core.h" |
| 23 | 23 | ||
| 24 | #define UPROBE_TRAP_NR UINT_MAX | 24 | #define UPROBE_TRAP_NR UINT_MAX |
| 25 | 25 | ||
| @@ -88,7 +88,7 @@ int arch_uprobe_analyze_insn(struct arch_uprobe *auprobe, struct mm_struct *mm, | |||
| 88 | auprobe->ixol[1] = __opcode_to_mem_arm(UPROBE_SS_ARM_INSN); | 88 | auprobe->ixol[1] = __opcode_to_mem_arm(UPROBE_SS_ARM_INSN); |
| 89 | 89 | ||
| 90 | ret = arm_probes_decode_insn(insn, &auprobe->asi, false, | 90 | ret = arm_probes_decode_insn(insn, &auprobe->asi, false, |
| 91 | uprobes_probes_actions); | 91 | uprobes_probes_actions, NULL); |
| 92 | switch (ret) { | 92 | switch (ret) { |
| 93 | case INSN_REJECTED: | 93 | case INSN_REJECTED: |
| 94 | return -EINVAL; | 94 | return -EINVAL; |
diff --git a/arch/arm/kernel/uprobes.h b/arch/arm/probes/uprobes/core.h index 1d0c12dfbd03..1d0c12dfbd03 100644 --- a/arch/arm/kernel/uprobes.h +++ b/arch/arm/probes/uprobes/core.h | |||
diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig index dd301be89ecc..5376d908eabe 100644 --- a/arch/arm64/configs/defconfig +++ b/arch/arm64/configs/defconfig | |||
| @@ -1,6 +1,7 @@ | |||
| 1 | # CONFIG_LOCALVERSION_AUTO is not set | 1 | # CONFIG_LOCALVERSION_AUTO is not set |
| 2 | CONFIG_SYSVIPC=y | 2 | CONFIG_SYSVIPC=y |
| 3 | CONFIG_POSIX_MQUEUE=y | 3 | CONFIG_POSIX_MQUEUE=y |
| 4 | CONFIG_FHANDLE=y | ||
| 4 | CONFIG_AUDIT=y | 5 | CONFIG_AUDIT=y |
| 5 | CONFIG_NO_HZ_IDLE=y | 6 | CONFIG_NO_HZ_IDLE=y |
| 6 | CONFIG_HIGH_RES_TIMERS=y | 7 | CONFIG_HIGH_RES_TIMERS=y |
| @@ -13,14 +14,12 @@ CONFIG_TASK_IO_ACCOUNTING=y | |||
| 13 | CONFIG_IKCONFIG=y | 14 | CONFIG_IKCONFIG=y |
| 14 | CONFIG_IKCONFIG_PROC=y | 15 | CONFIG_IKCONFIG_PROC=y |
| 15 | CONFIG_LOG_BUF_SHIFT=14 | 16 | CONFIG_LOG_BUF_SHIFT=14 |
| 16 | CONFIG_RESOURCE_COUNTERS=y | ||
| 17 | CONFIG_MEMCG=y | 17 | CONFIG_MEMCG=y |
| 18 | CONFIG_MEMCG_SWAP=y | 18 | CONFIG_MEMCG_SWAP=y |
| 19 | CONFIG_MEMCG_KMEM=y | 19 | CONFIG_MEMCG_KMEM=y |
| 20 | CONFIG_CGROUP_HUGETLB=y | 20 | CONFIG_CGROUP_HUGETLB=y |
| 21 | # CONFIG_UTS_NS is not set | 21 | # CONFIG_UTS_NS is not set |
| 22 | # CONFIG_IPC_NS is not set | 22 | # CONFIG_IPC_NS is not set |
| 23 | # CONFIG_PID_NS is not set | ||
| 24 | # CONFIG_NET_NS is not set | 23 | # CONFIG_NET_NS is not set |
| 25 | CONFIG_SCHED_AUTOGROUP=y | 24 | CONFIG_SCHED_AUTOGROUP=y |
| 26 | CONFIG_BLK_DEV_INITRD=y | 25 | CONFIG_BLK_DEV_INITRD=y |
| @@ -92,7 +91,6 @@ CONFIG_SERIAL_AMBA_PL011_CONSOLE=y | |||
| 92 | CONFIG_SERIAL_OF_PLATFORM=y | 91 | CONFIG_SERIAL_OF_PLATFORM=y |
| 93 | CONFIG_VIRTIO_CONSOLE=y | 92 | CONFIG_VIRTIO_CONSOLE=y |
| 94 | # CONFIG_HW_RANDOM is not set | 93 | # CONFIG_HW_RANDOM is not set |
| 95 | # CONFIG_HMC_DRV is not set | ||
| 96 | CONFIG_SPI=y | 94 | CONFIG_SPI=y |
| 97 | CONFIG_SPI_PL022=y | 95 | CONFIG_SPI_PL022=y |
| 98 | CONFIG_GPIO_PL061=y | 96 | CONFIG_GPIO_PL061=y |
| @@ -133,6 +131,8 @@ CONFIG_EXT3_FS=y | |||
| 133 | CONFIG_EXT4_FS=y | 131 | CONFIG_EXT4_FS=y |
| 134 | CONFIG_FANOTIFY=y | 132 | CONFIG_FANOTIFY=y |
| 135 | CONFIG_FANOTIFY_ACCESS_PERMISSIONS=y | 133 | CONFIG_FANOTIFY_ACCESS_PERMISSIONS=y |
| 134 | CONFIG_QUOTA=y | ||
| 135 | CONFIG_AUTOFS4_FS=y | ||
| 136 | CONFIG_FUSE_FS=y | 136 | CONFIG_FUSE_FS=y |
| 137 | CONFIG_CUSE=y | 137 | CONFIG_CUSE=y |
| 138 | CONFIG_VFAT_FS=y | 138 | CONFIG_VFAT_FS=y |
| @@ -152,14 +152,15 @@ CONFIG_MAGIC_SYSRQ=y | |||
| 152 | CONFIG_DEBUG_KERNEL=y | 152 | CONFIG_DEBUG_KERNEL=y |
| 153 | CONFIG_LOCKUP_DETECTOR=y | 153 | CONFIG_LOCKUP_DETECTOR=y |
| 154 | # CONFIG_SCHED_DEBUG is not set | 154 | # CONFIG_SCHED_DEBUG is not set |
| 155 | # CONFIG_DEBUG_PREEMPT is not set | ||
| 155 | # CONFIG_FTRACE is not set | 156 | # CONFIG_FTRACE is not set |
| 157 | CONFIG_KEYS=y | ||
| 156 | CONFIG_SECURITY=y | 158 | CONFIG_SECURITY=y |
| 157 | CONFIG_CRYPTO_ANSI_CPRNG=y | 159 | CONFIG_CRYPTO_ANSI_CPRNG=y |
| 158 | CONFIG_ARM64_CRYPTO=y | 160 | CONFIG_ARM64_CRYPTO=y |
| 159 | CONFIG_CRYPTO_SHA1_ARM64_CE=y | 161 | CONFIG_CRYPTO_SHA1_ARM64_CE=y |
| 160 | CONFIG_CRYPTO_SHA2_ARM64_CE=y | 162 | CONFIG_CRYPTO_SHA2_ARM64_CE=y |
| 161 | CONFIG_CRYPTO_GHASH_ARM64_CE=y | 163 | CONFIG_CRYPTO_GHASH_ARM64_CE=y |
| 162 | CONFIG_CRYPTO_AES_ARM64_CE=y | ||
| 163 | CONFIG_CRYPTO_AES_ARM64_CE_CCM=y | 164 | CONFIG_CRYPTO_AES_ARM64_CE_CCM=y |
| 164 | CONFIG_CRYPTO_AES_ARM64_CE_BLK=y | 165 | CONFIG_CRYPTO_AES_ARM64_CE_BLK=y |
| 165 | CONFIG_CRYPTO_AES_ARM64_NEON_BLK=y | 166 | CONFIG_CRYPTO_AES_ARM64_NEON_BLK=y |
diff --git a/arch/arm64/include/asm/dma-mapping.h b/arch/arm64/include/asm/dma-mapping.h index d34189bceff7..9ce3e680ae1c 100644 --- a/arch/arm64/include/asm/dma-mapping.h +++ b/arch/arm64/include/asm/dma-mapping.h | |||
| @@ -52,13 +52,14 @@ static inline void set_dma_ops(struct device *dev, struct dma_map_ops *ops) | |||
| 52 | dev->archdata.dma_ops = ops; | 52 | dev->archdata.dma_ops = ops; |
| 53 | } | 53 | } |
| 54 | 54 | ||
| 55 | static inline int set_arch_dma_coherent_ops(struct device *dev) | 55 | static inline void arch_setup_dma_ops(struct device *dev, u64 dma_base, u64 size, |
| 56 | struct iommu_ops *iommu, bool coherent) | ||
| 56 | { | 57 | { |
| 57 | dev->archdata.dma_coherent = true; | 58 | dev->archdata.dma_coherent = coherent; |
| 58 | set_dma_ops(dev, &coherent_swiotlb_dma_ops); | 59 | if (coherent) |
| 59 | return 0; | 60 | set_dma_ops(dev, &coherent_swiotlb_dma_ops); |
| 60 | } | 61 | } |
| 61 | #define set_arch_dma_coherent_ops set_arch_dma_coherent_ops | 62 | #define arch_setup_dma_ops arch_setup_dma_ops |
| 62 | 63 | ||
| 63 | /* do not use this function in a driver */ | 64 | /* do not use this function in a driver */ |
| 64 | static inline bool is_device_dma_coherent(struct device *dev) | 65 | static inline bool is_device_dma_coherent(struct device *dev) |
diff --git a/arch/arm64/include/asm/pgtable.h b/arch/arm64/include/asm/pgtable.h index df22314f57cf..210d632aa5ad 100644 --- a/arch/arm64/include/asm/pgtable.h +++ b/arch/arm64/include/asm/pgtable.h | |||
| @@ -298,7 +298,6 @@ void pmdp_splitting_flush(struct vm_area_struct *vma, unsigned long address, | |||
| 298 | #define pfn_pmd(pfn,prot) (__pmd(((phys_addr_t)(pfn) << PAGE_SHIFT) | pgprot_val(prot))) | 298 | #define pfn_pmd(pfn,prot) (__pmd(((phys_addr_t)(pfn) << PAGE_SHIFT) | pgprot_val(prot))) |
| 299 | #define mk_pmd(page,prot) pfn_pmd(page_to_pfn(page),prot) | 299 | #define mk_pmd(page,prot) pfn_pmd(page_to_pfn(page),prot) |
| 300 | 300 | ||
| 301 | #define pmd_page(pmd) pfn_to_page(__phys_to_pfn(pmd_val(pmd) & PHYS_MASK)) | ||
| 302 | #define pud_write(pud) pte_write(pud_pte(pud)) | 301 | #define pud_write(pud) pte_write(pud_pte(pud)) |
| 303 | #define pud_pfn(pud) (((pud_val(pud) & PUD_MASK) & PHYS_MASK) >> PAGE_SHIFT) | 302 | #define pud_pfn(pud) (((pud_val(pud) & PUD_MASK) & PHYS_MASK) >> PAGE_SHIFT) |
| 304 | 303 | ||
| @@ -401,7 +400,7 @@ static inline pmd_t *pmd_offset(pud_t *pud, unsigned long addr) | |||
| 401 | return (pmd_t *)pud_page_vaddr(*pud) + pmd_index(addr); | 400 | return (pmd_t *)pud_page_vaddr(*pud) + pmd_index(addr); |
| 402 | } | 401 | } |
| 403 | 402 | ||
| 404 | #define pud_page(pud) pmd_page(pud_pmd(pud)) | 403 | #define pud_page(pud) pfn_to_page(__phys_to_pfn(pud_val(pud) & PHYS_MASK)) |
| 405 | 404 | ||
| 406 | #endif /* CONFIG_ARM64_PGTABLE_LEVELS > 2 */ | 405 | #endif /* CONFIG_ARM64_PGTABLE_LEVELS > 2 */ |
| 407 | 406 | ||
| @@ -437,6 +436,8 @@ static inline pud_t *pud_offset(pgd_t *pgd, unsigned long addr) | |||
| 437 | return (pud_t *)pgd_page_vaddr(*pgd) + pud_index(addr); | 436 | return (pud_t *)pgd_page_vaddr(*pgd) + pud_index(addr); |
| 438 | } | 437 | } |
| 439 | 438 | ||
| 439 | #define pgd_page(pgd) pfn_to_page(__phys_to_pfn(pgd_val(pgd) & PHYS_MASK)) | ||
| 440 | |||
| 440 | #endif /* CONFIG_ARM64_PGTABLE_LEVELS > 3 */ | 441 | #endif /* CONFIG_ARM64_PGTABLE_LEVELS > 3 */ |
| 441 | 442 | ||
| 442 | #define pgd_ERROR(pgd) __pgd_error(__FILE__, __LINE__, pgd_val(pgd)) | 443 | #define pgd_ERROR(pgd) __pgd_error(__FILE__, __LINE__, pgd_val(pgd)) |
diff --git a/arch/arm64/kernel/suspend.c b/arch/arm64/kernel/suspend.c index 3771b72b6569..2d6b6065fe7f 100644 --- a/arch/arm64/kernel/suspend.c +++ b/arch/arm64/kernel/suspend.c | |||
| @@ -5,6 +5,7 @@ | |||
| 5 | #include <asm/debug-monitors.h> | 5 | #include <asm/debug-monitors.h> |
| 6 | #include <asm/pgtable.h> | 6 | #include <asm/pgtable.h> |
| 7 | #include <asm/memory.h> | 7 | #include <asm/memory.h> |
| 8 | #include <asm/mmu_context.h> | ||
| 8 | #include <asm/smp_plat.h> | 9 | #include <asm/smp_plat.h> |
| 9 | #include <asm/suspend.h> | 10 | #include <asm/suspend.h> |
| 10 | #include <asm/tlbflush.h> | 11 | #include <asm/tlbflush.h> |
| @@ -98,7 +99,18 @@ int __cpu_suspend(unsigned long arg, int (*fn)(unsigned long)) | |||
| 98 | */ | 99 | */ |
| 99 | ret = __cpu_suspend_enter(arg, fn); | 100 | ret = __cpu_suspend_enter(arg, fn); |
| 100 | if (ret == 0) { | 101 | if (ret == 0) { |
| 101 | cpu_switch_mm(mm->pgd, mm); | 102 | /* |
| 103 | * We are resuming from reset with TTBR0_EL1 set to the | ||
| 104 | * idmap to enable the MMU; restore the active_mm mappings in | ||
| 105 | * TTBR0_EL1 unless the active_mm == &init_mm, in which case | ||
| 106 | * the thread entered __cpu_suspend with TTBR0_EL1 set to | ||
| 107 | * reserved TTBR0 page tables and should be restored as such. | ||
| 108 | */ | ||
| 109 | if (mm == &init_mm) | ||
| 110 | cpu_set_reserved_ttbr0(); | ||
| 111 | else | ||
| 112 | cpu_switch_mm(mm->pgd, mm); | ||
| 113 | |||
| 102 | flush_tlb_all(); | 114 | flush_tlb_all(); |
| 103 | 115 | ||
| 104 | /* | 116 | /* |
diff --git a/arch/ia64/include/asm/unistd.h b/arch/ia64/include/asm/unistd.h index f3b51b57740a..95c39b95e97e 100644 --- a/arch/ia64/include/asm/unistd.h +++ b/arch/ia64/include/asm/unistd.h | |||
| @@ -11,7 +11,7 @@ | |||
| 11 | 11 | ||
| 12 | 12 | ||
| 13 | 13 | ||
| 14 | #define NR_syscalls 318 /* length of syscall table */ | 14 | #define NR_syscalls 319 /* length of syscall table */ |
| 15 | 15 | ||
| 16 | /* | 16 | /* |
| 17 | * The following defines stop scripts/checksyscalls.sh from complaining about | 17 | * The following defines stop scripts/checksyscalls.sh from complaining about |
diff --git a/arch/ia64/include/uapi/asm/unistd.h b/arch/ia64/include/uapi/asm/unistd.h index 4c2240c1b0cb..461079560c78 100644 --- a/arch/ia64/include/uapi/asm/unistd.h +++ b/arch/ia64/include/uapi/asm/unistd.h | |||
| @@ -331,5 +331,6 @@ | |||
| 331 | #define __NR_getrandom 1339 | 331 | #define __NR_getrandom 1339 |
| 332 | #define __NR_memfd_create 1340 | 332 | #define __NR_memfd_create 1340 |
| 333 | #define __NR_bpf 1341 | 333 | #define __NR_bpf 1341 |
| 334 | #define __NR_execveat 1342 | ||
| 334 | 335 | ||
| 335 | #endif /* _UAPI_ASM_IA64_UNISTD_H */ | 336 | #endif /* _UAPI_ASM_IA64_UNISTD_H */ |
diff --git a/arch/ia64/kernel/entry.S b/arch/ia64/kernel/entry.S index f5e96dffc63c..fcf8b8cbca0b 100644 --- a/arch/ia64/kernel/entry.S +++ b/arch/ia64/kernel/entry.S | |||
| @@ -1779,6 +1779,7 @@ sys_call_table: | |||
| 1779 | data8 sys_getrandom | 1779 | data8 sys_getrandom |
| 1780 | data8 sys_memfd_create // 1340 | 1780 | data8 sys_memfd_create // 1340 |
| 1781 | data8 sys_bpf | 1781 | data8 sys_bpf |
| 1782 | data8 sys_execveat | ||
| 1782 | 1783 | ||
| 1783 | .org sys_call_table + 8*NR_syscalls // guard against failures to increase NR_syscalls | 1784 | .org sys_call_table + 8*NR_syscalls // guard against failures to increase NR_syscalls |
| 1784 | #endif /* __IA64_ASM_PARAVIRTUALIZED_NATIVE */ | 1785 | #endif /* __IA64_ASM_PARAVIRTUALIZED_NATIVE */ |
diff --git a/arch/nios2/kernel/cpuinfo.c b/arch/nios2/kernel/cpuinfo.c index 51d5bb90d3e5..a223691dff4f 100644 --- a/arch/nios2/kernel/cpuinfo.c +++ b/arch/nios2/kernel/cpuinfo.c | |||
| @@ -72,6 +72,7 @@ void __init setup_cpuinfo(void) | |||
| 72 | cpuinfo.has_div = fcpu_has(cpu, "altr,has-div"); | 72 | cpuinfo.has_div = fcpu_has(cpu, "altr,has-div"); |
| 73 | cpuinfo.has_mul = fcpu_has(cpu, "altr,has-mul"); | 73 | cpuinfo.has_mul = fcpu_has(cpu, "altr,has-mul"); |
| 74 | cpuinfo.has_mulx = fcpu_has(cpu, "altr,has-mulx"); | 74 | cpuinfo.has_mulx = fcpu_has(cpu, "altr,has-mulx"); |
| 75 | cpuinfo.mmu = fcpu_has(cpu, "altr,has-mmu"); | ||
| 75 | 76 | ||
| 76 | if (IS_ENABLED(CONFIG_NIOS2_HW_DIV_SUPPORT) && !cpuinfo.has_div) | 77 | if (IS_ENABLED(CONFIG_NIOS2_HW_DIV_SUPPORT) && !cpuinfo.has_div) |
| 77 | err_cpu("DIV"); | 78 | err_cpu("DIV"); |
diff --git a/arch/nios2/kernel/entry.S b/arch/nios2/kernel/entry.S index 83bca17d1008..0bdfd13ff98b 100644 --- a/arch/nios2/kernel/entry.S +++ b/arch/nios2/kernel/entry.S | |||
| @@ -365,30 +365,14 @@ ENTRY(ret_from_interrupt) | |||
| 365 | GET_THREAD_INFO r1 | 365 | GET_THREAD_INFO r1 |
| 366 | ldw r4, TI_PREEMPT_COUNT(r1) | 366 | ldw r4, TI_PREEMPT_COUNT(r1) |
| 367 | bne r4, r0, restore_all | 367 | bne r4, r0, restore_all |
| 368 | |||
| 369 | need_resched: | ||
| 370 | ldw r4, TI_FLAGS(r1) /* ? Need resched set */ | 368 | ldw r4, TI_FLAGS(r1) /* ? Need resched set */ |
| 371 | BTBZ r10, r4, TIF_NEED_RESCHED, restore_all | 369 | BTBZ r10, r4, TIF_NEED_RESCHED, restore_all |
| 372 | ldw r4, PT_ESTATUS(sp) /* ? Interrupts off */ | 370 | ldw r4, PT_ESTATUS(sp) /* ? Interrupts off */ |
| 373 | andi r10, r4, ESTATUS_EPIE | 371 | andi r10, r4, ESTATUS_EPIE |
| 374 | beq r10, r0, restore_all | 372 | beq r10, r0, restore_all |
| 375 | movia r4, PREEMPT_ACTIVE | 373 | call preempt_schedule_irq |
| 376 | stw r4, TI_PREEMPT_COUNT(r1) | ||
| 377 | rdctl r10, status /* enable intrs again */ | ||
| 378 | ori r10, r10 ,STATUS_PIE | ||
| 379 | wrctl status, r10 | ||
| 380 | PUSH r1 | ||
| 381 | call schedule | ||
| 382 | POP r1 | ||
| 383 | mov r4, r0 | ||
| 384 | stw r4, TI_PREEMPT_COUNT(r1) | ||
| 385 | rdctl r10, status /* disable intrs */ | ||
| 386 | andi r10, r10, %lo(~STATUS_PIE) | ||
| 387 | wrctl status, r10 | ||
| 388 | br need_resched | ||
| 389 | #else | ||
| 390 | br restore_all | ||
| 391 | #endif | 374 | #endif |
| 375 | br restore_all | ||
| 392 | 376 | ||
| 393 | /*********************************************************************** | 377 | /*********************************************************************** |
| 394 | * A few syscall wrappers | 378 | * A few syscall wrappers |
diff --git a/arch/parisc/include/asm/ldcw.h b/arch/parisc/include/asm/ldcw.h index d2d11b7055ba..8121aa6db2ff 100644 --- a/arch/parisc/include/asm/ldcw.h +++ b/arch/parisc/include/asm/ldcw.h | |||
| @@ -33,11 +33,18 @@ | |||
| 33 | 33 | ||
| 34 | #endif /*!CONFIG_PA20*/ | 34 | #endif /*!CONFIG_PA20*/ |
| 35 | 35 | ||
| 36 | /* LDCW, the only atomic read-write operation PA-RISC has. *sigh*. */ | 36 | /* LDCW, the only atomic read-write operation PA-RISC has. *sigh*. |
| 37 | We don't explicitly expose that "*a" may be written as reload | ||
| 38 | fails to find a register in class R1_REGS when "a" needs to be | ||
| 39 | reloaded when generating 64-bit PIC code. Instead, we clobber | ||
| 40 | memory to indicate to the compiler that the assembly code reads | ||
| 41 | or writes to items other than those listed in the input and output | ||
| 42 | operands. This may pessimize the code somewhat but __ldcw is | ||
| 43 | usually used within code blocks surrounded by memory barriors. */ | ||
| 37 | #define __ldcw(a) ({ \ | 44 | #define __ldcw(a) ({ \ |
| 38 | unsigned __ret; \ | 45 | unsigned __ret; \ |
| 39 | __asm__ __volatile__(__LDCW " 0(%2),%0" \ | 46 | __asm__ __volatile__(__LDCW " 0(%1),%0" \ |
| 40 | : "=r" (__ret), "+m" (*(a)) : "r" (a)); \ | 47 | : "=r" (__ret) : "r" (a) : "memory"); \ |
| 41 | __ret; \ | 48 | __ret; \ |
| 42 | }) | 49 | }) |
| 43 | 50 | ||
diff --git a/arch/powerpc/include/asm/kexec.h b/arch/powerpc/include/asm/kexec.h index 19c36cba37c4..a46f5f45570c 100644 --- a/arch/powerpc/include/asm/kexec.h +++ b/arch/powerpc/include/asm/kexec.h | |||
| @@ -86,6 +86,11 @@ extern int overlaps_crashkernel(unsigned long start, unsigned long size); | |||
| 86 | extern void reserve_crashkernel(void); | 86 | extern void reserve_crashkernel(void); |
| 87 | extern void machine_kexec_mask_interrupts(void); | 87 | extern void machine_kexec_mask_interrupts(void); |
| 88 | 88 | ||
| 89 | static inline bool kdump_in_progress(void) | ||
| 90 | { | ||
| 91 | return crashing_cpu >= 0; | ||
| 92 | } | ||
| 93 | |||
| 89 | #else /* !CONFIG_KEXEC */ | 94 | #else /* !CONFIG_KEXEC */ |
| 90 | static inline void crash_kexec_secondary(struct pt_regs *regs) { } | 95 | static inline void crash_kexec_secondary(struct pt_regs *regs) { } |
| 91 | 96 | ||
| @@ -106,6 +111,11 @@ static inline int crash_shutdown_unregister(crash_shutdown_t handler) | |||
| 106 | return 0; | 111 | return 0; |
| 107 | } | 112 | } |
| 108 | 113 | ||
| 114 | static inline bool kdump_in_progress(void) | ||
| 115 | { | ||
| 116 | return false; | ||
| 117 | } | ||
| 118 | |||
| 109 | #endif /* CONFIG_KEXEC */ | 119 | #endif /* CONFIG_KEXEC */ |
| 110 | #endif /* ! __ASSEMBLY__ */ | 120 | #endif /* ! __ASSEMBLY__ */ |
| 111 | #endif /* __KERNEL__ */ | 121 | #endif /* __KERNEL__ */ |
diff --git a/arch/powerpc/include/asm/systbl.h b/arch/powerpc/include/asm/systbl.h index ce9577d693be..91062eef582f 100644 --- a/arch/powerpc/include/asm/systbl.h +++ b/arch/powerpc/include/asm/systbl.h | |||
| @@ -366,3 +366,4 @@ SYSCALL_SPU(seccomp) | |||
| 366 | SYSCALL_SPU(getrandom) | 366 | SYSCALL_SPU(getrandom) |
| 367 | SYSCALL_SPU(memfd_create) | 367 | SYSCALL_SPU(memfd_create) |
| 368 | SYSCALL_SPU(bpf) | 368 | SYSCALL_SPU(bpf) |
| 369 | COMPAT_SYS(execveat) | ||
diff --git a/arch/powerpc/include/asm/unistd.h b/arch/powerpc/include/asm/unistd.h index e0da021caa00..36b79c31eedd 100644 --- a/arch/powerpc/include/asm/unistd.h +++ b/arch/powerpc/include/asm/unistd.h | |||
| @@ -12,7 +12,7 @@ | |||
| 12 | #include <uapi/asm/unistd.h> | 12 | #include <uapi/asm/unistd.h> |
| 13 | 13 | ||
| 14 | 14 | ||
| 15 | #define __NR_syscalls 362 | 15 | #define __NR_syscalls 363 |
| 16 | 16 | ||
| 17 | #define __NR__exit __NR_exit | 17 | #define __NR__exit __NR_exit |
| 18 | #define NR_syscalls __NR_syscalls | 18 | #define NR_syscalls __NR_syscalls |
diff --git a/arch/powerpc/include/uapi/asm/unistd.h b/arch/powerpc/include/uapi/asm/unistd.h index f55351f2e66e..ef5b5b1f3123 100644 --- a/arch/powerpc/include/uapi/asm/unistd.h +++ b/arch/powerpc/include/uapi/asm/unistd.h | |||
| @@ -384,5 +384,6 @@ | |||
| 384 | #define __NR_getrandom 359 | 384 | #define __NR_getrandom 359 |
| 385 | #define __NR_memfd_create 360 | 385 | #define __NR_memfd_create 360 |
| 386 | #define __NR_bpf 361 | 386 | #define __NR_bpf 361 |
| 387 | #define __NR_execveat 362 | ||
| 387 | 388 | ||
| 388 | #endif /* _UAPI_ASM_POWERPC_UNISTD_H_ */ | 389 | #endif /* _UAPI_ASM_POWERPC_UNISTD_H_ */ |
diff --git a/arch/powerpc/kernel/machine_kexec_64.c b/arch/powerpc/kernel/machine_kexec_64.c index 879b3aacac32..f96d1ec24189 100644 --- a/arch/powerpc/kernel/machine_kexec_64.c +++ b/arch/powerpc/kernel/machine_kexec_64.c | |||
| @@ -330,7 +330,7 @@ void default_machine_kexec(struct kimage *image) | |||
| 330 | * using debugger IPI. | 330 | * using debugger IPI. |
| 331 | */ | 331 | */ |
| 332 | 332 | ||
| 333 | if (crashing_cpu == -1) | 333 | if (!kdump_in_progress()) |
| 334 | kexec_prepare_cpus(); | 334 | kexec_prepare_cpus(); |
| 335 | 335 | ||
| 336 | pr_debug("kexec: Starting switchover sequence.\n"); | 336 | pr_debug("kexec: Starting switchover sequence.\n"); |
diff --git a/arch/powerpc/kernel/smp.c b/arch/powerpc/kernel/smp.c index 8ec017cb4446..8b2d2dc8ef10 100644 --- a/arch/powerpc/kernel/smp.c +++ b/arch/powerpc/kernel/smp.c | |||
| @@ -700,6 +700,7 @@ void start_secondary(void *unused) | |||
| 700 | smp_store_cpu_info(cpu); | 700 | smp_store_cpu_info(cpu); |
| 701 | set_dec(tb_ticks_per_jiffy); | 701 | set_dec(tb_ticks_per_jiffy); |
| 702 | preempt_disable(); | 702 | preempt_disable(); |
| 703 | cpu_callin_map[cpu] = 1; | ||
| 703 | 704 | ||
| 704 | if (smp_ops->setup_cpu) | 705 | if (smp_ops->setup_cpu) |
| 705 | smp_ops->setup_cpu(cpu); | 706 | smp_ops->setup_cpu(cpu); |
| @@ -738,14 +739,6 @@ void start_secondary(void *unused) | |||
| 738 | notify_cpu_starting(cpu); | 739 | notify_cpu_starting(cpu); |
| 739 | set_cpu_online(cpu, true); | 740 | set_cpu_online(cpu, true); |
| 740 | 741 | ||
| 741 | /* | ||
| 742 | * CPU must be marked active and online before we signal back to the | ||
| 743 | * master, because the scheduler needs to see the cpu_online and | ||
| 744 | * cpu_active bits set. | ||
| 745 | */ | ||
| 746 | smp_wmb(); | ||
| 747 | cpu_callin_map[cpu] = 1; | ||
| 748 | |||
| 749 | local_irq_enable(); | 742 | local_irq_enable(); |
| 750 | 743 | ||
| 751 | cpu_startup_entry(CPUHP_ONLINE); | 744 | cpu_startup_entry(CPUHP_ONLINE); |
diff --git a/arch/powerpc/platforms/pseries/lpar.c b/arch/powerpc/platforms/pseries/lpar.c index 469751d92004..b5682fd6c984 100644 --- a/arch/powerpc/platforms/pseries/lpar.c +++ b/arch/powerpc/platforms/pseries/lpar.c | |||
| @@ -43,6 +43,7 @@ | |||
| 43 | #include <asm/trace.h> | 43 | #include <asm/trace.h> |
| 44 | #include <asm/firmware.h> | 44 | #include <asm/firmware.h> |
| 45 | #include <asm/plpar_wrappers.h> | 45 | #include <asm/plpar_wrappers.h> |
| 46 | #include <asm/kexec.h> | ||
| 46 | #include <asm/fadump.h> | 47 | #include <asm/fadump.h> |
| 47 | 48 | ||
| 48 | #include "pseries.h" | 49 | #include "pseries.h" |
| @@ -267,8 +268,13 @@ static void pSeries_lpar_hptab_clear(void) | |||
| 267 | * out to the user, but at least this will stop us from | 268 | * out to the user, but at least this will stop us from |
| 268 | * continuing on further and creating an even more | 269 | * continuing on further and creating an even more |
| 269 | * difficult to debug situation. | 270 | * difficult to debug situation. |
| 271 | * | ||
| 272 | * There is a known problem when kdump'ing, if cpus are offline | ||
| 273 | * the above call will fail. Rather than panicking again, keep | ||
| 274 | * going and hope the kdump kernel is also little endian, which | ||
| 275 | * it usually is. | ||
| 270 | */ | 276 | */ |
| 271 | if (rc) | 277 | if (rc && !kdump_in_progress()) |
| 272 | panic("Could not enable big endian exceptions"); | 278 | panic("Could not enable big endian exceptions"); |
| 273 | } | 279 | } |
| 274 | #endif | 280 | #endif |
diff --git a/arch/um/Kconfig.common b/arch/um/Kconfig.common index 87bc86821bc9..d195a87ca542 100644 --- a/arch/um/Kconfig.common +++ b/arch/um/Kconfig.common | |||
| @@ -3,6 +3,7 @@ config UML | |||
| 3 | default y | 3 | default y |
| 4 | select HAVE_ARCH_AUDITSYSCALL | 4 | select HAVE_ARCH_AUDITSYSCALL |
| 5 | select HAVE_UID16 | 5 | select HAVE_UID16 |
| 6 | select HAVE_FUTEX_CMPXCHG if FUTEX | ||
| 6 | select GENERIC_IRQ_SHOW | 7 | select GENERIC_IRQ_SHOW |
| 7 | select GENERIC_CPU_DEVICES | 8 | select GENERIC_CPU_DEVICES |
| 8 | select GENERIC_IO | 9 | select GENERIC_IO |
diff --git a/arch/x86/kernel/kprobes/opt.c b/arch/x86/kernel/kprobes/opt.c index 7c523bbf3dc8..0dd8d089c315 100644 --- a/arch/x86/kernel/kprobes/opt.c +++ b/arch/x86/kernel/kprobes/opt.c | |||
| @@ -322,7 +322,8 @@ void arch_remove_optimized_kprobe(struct optimized_kprobe *op) | |||
| 322 | * Target instructions MUST be relocatable (checked inside) | 322 | * Target instructions MUST be relocatable (checked inside) |
| 323 | * This is called when new aggr(opt)probe is allocated or reused. | 323 | * This is called when new aggr(opt)probe is allocated or reused. |
| 324 | */ | 324 | */ |
| 325 | int arch_prepare_optimized_kprobe(struct optimized_kprobe *op) | 325 | int arch_prepare_optimized_kprobe(struct optimized_kprobe *op, |
| 326 | struct kprobe *__unused) | ||
| 326 | { | 327 | { |
| 327 | u8 *buf; | 328 | u8 *buf; |
| 328 | int ret; | 329 | int ret; |
diff --git a/arch/x86/kvm/mmu.c b/arch/x86/kvm/mmu.c index 10fbed126b11..f83fc6c5e0ba 100644 --- a/arch/x86/kvm/mmu.c +++ b/arch/x86/kvm/mmu.c | |||
| @@ -4448,7 +4448,7 @@ void kvm_mmu_invalidate_mmio_sptes(struct kvm *kvm) | |||
| 4448 | * zap all shadow pages. | 4448 | * zap all shadow pages. |
| 4449 | */ | 4449 | */ |
| 4450 | if (unlikely(kvm_current_mmio_generation(kvm) == 0)) { | 4450 | if (unlikely(kvm_current_mmio_generation(kvm) == 0)) { |
| 4451 | printk_ratelimited(KERN_INFO "kvm: zapping shadow pages for mmio generation wraparound\n"); | 4451 | printk_ratelimited(KERN_DEBUG "kvm: zapping shadow pages for mmio generation wraparound\n"); |
| 4452 | kvm_mmu_invalidate_zap_all_pages(kvm); | 4452 | kvm_mmu_invalidate_zap_all_pages(kvm); |
| 4453 | } | 4453 | } |
| 4454 | } | 4454 | } |
diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c index feb852b04598..d4c58d884838 100644 --- a/arch/x86/kvm/vmx.c +++ b/arch/x86/kvm/vmx.c | |||
| @@ -5840,53 +5840,10 @@ static __init int hardware_setup(void) | |||
| 5840 | memset(vmx_msr_bitmap_legacy, 0xff, PAGE_SIZE); | 5840 | memset(vmx_msr_bitmap_legacy, 0xff, PAGE_SIZE); |
| 5841 | memset(vmx_msr_bitmap_longmode, 0xff, PAGE_SIZE); | 5841 | memset(vmx_msr_bitmap_longmode, 0xff, PAGE_SIZE); |
| 5842 | 5842 | ||
| 5843 | vmx_disable_intercept_for_msr(MSR_FS_BASE, false); | ||
| 5844 | vmx_disable_intercept_for_msr(MSR_GS_BASE, false); | ||
| 5845 | vmx_disable_intercept_for_msr(MSR_KERNEL_GS_BASE, true); | ||
| 5846 | vmx_disable_intercept_for_msr(MSR_IA32_SYSENTER_CS, false); | ||
| 5847 | vmx_disable_intercept_for_msr(MSR_IA32_SYSENTER_ESP, false); | ||
| 5848 | vmx_disable_intercept_for_msr(MSR_IA32_SYSENTER_EIP, false); | ||
| 5849 | vmx_disable_intercept_for_msr(MSR_IA32_BNDCFGS, true); | ||
| 5850 | |||
| 5851 | memcpy(vmx_msr_bitmap_legacy_x2apic, | ||
| 5852 | vmx_msr_bitmap_legacy, PAGE_SIZE); | ||
| 5853 | memcpy(vmx_msr_bitmap_longmode_x2apic, | ||
| 5854 | vmx_msr_bitmap_longmode, PAGE_SIZE); | ||
| 5855 | |||
| 5856 | if (enable_apicv) { | ||
| 5857 | for (msr = 0x800; msr <= 0x8ff; msr++) | ||
| 5858 | vmx_disable_intercept_msr_read_x2apic(msr); | ||
| 5859 | |||
| 5860 | /* According SDM, in x2apic mode, the whole id reg is used. | ||
| 5861 | * But in KVM, it only use the highest eight bits. Need to | ||
| 5862 | * intercept it */ | ||
| 5863 | vmx_enable_intercept_msr_read_x2apic(0x802); | ||
| 5864 | /* TMCCT */ | ||
| 5865 | vmx_enable_intercept_msr_read_x2apic(0x839); | ||
| 5866 | /* TPR */ | ||
| 5867 | vmx_disable_intercept_msr_write_x2apic(0x808); | ||
| 5868 | /* EOI */ | ||
| 5869 | vmx_disable_intercept_msr_write_x2apic(0x80b); | ||
| 5870 | /* SELF-IPI */ | ||
| 5871 | vmx_disable_intercept_msr_write_x2apic(0x83f); | ||
| 5872 | } | ||
| 5873 | |||
| 5874 | if (enable_ept) { | ||
| 5875 | kvm_mmu_set_mask_ptes(0ull, | ||
| 5876 | (enable_ept_ad_bits) ? VMX_EPT_ACCESS_BIT : 0ull, | ||
| 5877 | (enable_ept_ad_bits) ? VMX_EPT_DIRTY_BIT : 0ull, | ||
| 5878 | 0ull, VMX_EPT_EXECUTABLE_MASK); | ||
| 5879 | ept_set_mmio_spte_mask(); | ||
| 5880 | kvm_enable_tdp(); | ||
| 5881 | } else | ||
| 5882 | kvm_disable_tdp(); | ||
| 5883 | |||
| 5884 | update_ple_window_actual_max(); | ||
| 5885 | |||
| 5886 | if (setup_vmcs_config(&vmcs_config) < 0) { | 5843 | if (setup_vmcs_config(&vmcs_config) < 0) { |
| 5887 | r = -EIO; | 5844 | r = -EIO; |
| 5888 | goto out7; | 5845 | goto out7; |
| 5889 | } | 5846 | } |
| 5890 | 5847 | ||
| 5891 | if (boot_cpu_has(X86_FEATURE_NX)) | 5848 | if (boot_cpu_has(X86_FEATURE_NX)) |
| 5892 | kvm_enable_efer_bits(EFER_NX); | 5849 | kvm_enable_efer_bits(EFER_NX); |
| @@ -5945,6 +5902,49 @@ static __init int hardware_setup(void) | |||
| 5945 | if (nested) | 5902 | if (nested) |
| 5946 | nested_vmx_setup_ctls_msrs(); | 5903 | nested_vmx_setup_ctls_msrs(); |
| 5947 | 5904 | ||
| 5905 | vmx_disable_intercept_for_msr(MSR_FS_BASE, false); | ||
| 5906 | vmx_disable_intercept_for_msr(MSR_GS_BASE, false); | ||
| 5907 | vmx_disable_intercept_for_msr(MSR_KERNEL_GS_BASE, true); | ||
| 5908 | vmx_disable_intercept_for_msr(MSR_IA32_SYSENTER_CS, false); | ||
| 5909 | vmx_disable_intercept_for_msr(MSR_IA32_SYSENTER_ESP, false); | ||
| 5910 | vmx_disable_intercept_for_msr(MSR_IA32_SYSENTER_EIP, false); | ||
| 5911 | vmx_disable_intercept_for_msr(MSR_IA32_BNDCFGS, true); | ||
| 5912 | |||
| 5913 | memcpy(vmx_msr_bitmap_legacy_x2apic, | ||
| 5914 | vmx_msr_bitmap_legacy, PAGE_SIZE); | ||
| 5915 | memcpy(vmx_msr_bitmap_longmode_x2apic, | ||
| 5916 | vmx_msr_bitmap_longmode, PAGE_SIZE); | ||
| 5917 | |||
| 5918 | if (enable_apicv) { | ||
| 5919 | for (msr = 0x800; msr <= 0x8ff; msr++) | ||
| 5920 | vmx_disable_intercept_msr_read_x2apic(msr); | ||
| 5921 | |||
| 5922 | /* According SDM, in x2apic mode, the whole id reg is used. | ||
| 5923 | * But in KVM, it only use the highest eight bits. Need to | ||
| 5924 | * intercept it */ | ||
| 5925 | vmx_enable_intercept_msr_read_x2apic(0x802); | ||
| 5926 | /* TMCCT */ | ||
| 5927 | vmx_enable_intercept_msr_read_x2apic(0x839); | ||
| 5928 | /* TPR */ | ||
| 5929 | vmx_disable_intercept_msr_write_x2apic(0x808); | ||
| 5930 | /* EOI */ | ||
| 5931 | vmx_disable_intercept_msr_write_x2apic(0x80b); | ||
| 5932 | /* SELF-IPI */ | ||
| 5933 | vmx_disable_intercept_msr_write_x2apic(0x83f); | ||
| 5934 | } | ||
| 5935 | |||
| 5936 | if (enable_ept) { | ||
| 5937 | kvm_mmu_set_mask_ptes(0ull, | ||
| 5938 | (enable_ept_ad_bits) ? VMX_EPT_ACCESS_BIT : 0ull, | ||
| 5939 | (enable_ept_ad_bits) ? VMX_EPT_DIRTY_BIT : 0ull, | ||
| 5940 | 0ull, VMX_EPT_EXECUTABLE_MASK); | ||
| 5941 | ept_set_mmio_spte_mask(); | ||
| 5942 | kvm_enable_tdp(); | ||
| 5943 | } else | ||
| 5944 | kvm_disable_tdp(); | ||
| 5945 | |||
| 5946 | update_ple_window_actual_max(); | ||
| 5947 | |||
| 5948 | return alloc_kvm_area(); | 5948 | return alloc_kvm_area(); |
| 5949 | 5949 | ||
| 5950 | out7: | 5950 | out7: |
diff --git a/arch/x86/um/sys_call_table_32.c b/arch/x86/um/sys_call_table_32.c index 531d4269e2e3..bd16d6c370ec 100644 --- a/arch/x86/um/sys_call_table_32.c +++ b/arch/x86/um/sys_call_table_32.c | |||
| @@ -34,7 +34,7 @@ typedef asmlinkage void (*sys_call_ptr_t)(void); | |||
| 34 | 34 | ||
| 35 | extern asmlinkage void sys_ni_syscall(void); | 35 | extern asmlinkage void sys_ni_syscall(void); |
| 36 | 36 | ||
| 37 | const sys_call_ptr_t sys_call_table[] __cacheline_aligned = { | 37 | const sys_call_ptr_t sys_call_table[] ____cacheline_aligned = { |
| 38 | /* | 38 | /* |
| 39 | * Smells like a compiler bug -- it doesn't work | 39 | * Smells like a compiler bug -- it doesn't work |
| 40 | * when the & below is removed. | 40 | * when the & below is removed. |
diff --git a/arch/x86/um/sys_call_table_64.c b/arch/x86/um/sys_call_table_64.c index 20c3649d0691..5cdfa9db2217 100644 --- a/arch/x86/um/sys_call_table_64.c +++ b/arch/x86/um/sys_call_table_64.c | |||
| @@ -47,7 +47,7 @@ typedef void (*sys_call_ptr_t)(void); | |||
| 47 | 47 | ||
| 48 | extern void sys_ni_syscall(void); | 48 | extern void sys_ni_syscall(void); |
| 49 | 49 | ||
| 50 | const sys_call_ptr_t sys_call_table[] __cacheline_aligned = { | 50 | const sys_call_ptr_t sys_call_table[] ____cacheline_aligned = { |
| 51 | /* | 51 | /* |
| 52 | * Smells like a compiler bug -- it doesn't work | 52 | * Smells like a compiler bug -- it doesn't work |
| 53 | * when the & below is removed. | 53 | * when the & below is removed. |
diff --git a/crypto/af_alg.c b/crypto/af_alg.c index 1fa7bc31be63..4665b79c729a 100644 --- a/crypto/af_alg.c +++ b/crypto/af_alg.c | |||
| @@ -455,6 +455,9 @@ void af_alg_complete(struct crypto_async_request *req, int err) | |||
| 455 | { | 455 | { |
| 456 | struct af_alg_completion *completion = req->data; | 456 | struct af_alg_completion *completion = req->data; |
| 457 | 457 | ||
| 458 | if (err == -EINPROGRESS) | ||
| 459 | return; | ||
| 460 | |||
| 458 | completion->err = err; | 461 | completion->err = err; |
| 459 | complete(&completion->completion); | 462 | complete(&completion->completion); |
| 460 | } | 463 | } |
diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c index 499536504698..87b704e41877 100644 --- a/drivers/acpi/processor_idle.c +++ b/drivers/acpi/processor_idle.c | |||
| @@ -985,8 +985,6 @@ static int acpi_processor_setup_cpuidle_states(struct acpi_processor *pr) | |||
| 985 | state->flags = 0; | 985 | state->flags = 0; |
| 986 | switch (cx->type) { | 986 | switch (cx->type) { |
| 987 | case ACPI_STATE_C1: | 987 | case ACPI_STATE_C1: |
| 988 | if (cx->entry_method != ACPI_CSTATE_FFH) | ||
| 989 | state->flags |= CPUIDLE_FLAG_TIME_INVALID; | ||
| 990 | 988 | ||
| 991 | state->enter = acpi_idle_enter_c1; | 989 | state->enter = acpi_idle_enter_c1; |
| 992 | state->enter_dead = acpi_idle_play_dead; | 990 | state->enter_dead = acpi_idle_play_dead; |
diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c index 1eaadff2e198..c72e79d2c5ad 100644 --- a/drivers/acpi/video.c +++ b/drivers/acpi/video.c | |||
| @@ -505,6 +505,23 @@ static struct dmi_system_id video_dmi_table[] __initdata = { | |||
| 505 | DMI_MATCH(DMI_PRODUCT_NAME, "HP ENVY 15 Notebook PC"), | 505 | DMI_MATCH(DMI_PRODUCT_NAME, "HP ENVY 15 Notebook PC"), |
| 506 | }, | 506 | }, |
| 507 | }, | 507 | }, |
| 508 | |||
| 509 | { | ||
| 510 | .callback = video_disable_native_backlight, | ||
| 511 | .ident = "SAMSUNG 870Z5E/880Z5E/680Z5E", | ||
| 512 | .matches = { | ||
| 513 | DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD."), | ||
| 514 | DMI_MATCH(DMI_PRODUCT_NAME, "870Z5E/880Z5E/680Z5E"), | ||
| 515 | }, | ||
| 516 | }, | ||
| 517 | { | ||
| 518 | .callback = video_disable_native_backlight, | ||
| 519 | .ident = "SAMSUNG 370R4E/370R4V/370R5E/3570RE/370R5V", | ||
| 520 | .matches = { | ||
| 521 | DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD."), | ||
| 522 | DMI_MATCH(DMI_PRODUCT_NAME, "370R4E/370R4V/370R5E/3570RE/370R5V"), | ||
| 523 | }, | ||
| 524 | }, | ||
| 508 | {} | 525 | {} |
| 509 | }; | 526 | }; |
| 510 | 527 | ||
diff --git a/drivers/base/power/domain.c b/drivers/base/power/domain.c index 6a103a35ea9b..0d8780c04a5e 100644 --- a/drivers/base/power/domain.c +++ b/drivers/base/power/domain.c | |||
| @@ -2088,7 +2088,7 @@ EXPORT_SYMBOL_GPL(of_genpd_del_provider); | |||
| 2088 | * Returns a valid pointer to struct generic_pm_domain on success or ERR_PTR() | 2088 | * Returns a valid pointer to struct generic_pm_domain on success or ERR_PTR() |
| 2089 | * on failure. | 2089 | * on failure. |
| 2090 | */ | 2090 | */ |
| 2091 | static struct generic_pm_domain *of_genpd_get_from_provider( | 2091 | struct generic_pm_domain *of_genpd_get_from_provider( |
| 2092 | struct of_phandle_args *genpdspec) | 2092 | struct of_phandle_args *genpdspec) |
| 2093 | { | 2093 | { |
| 2094 | struct generic_pm_domain *genpd = ERR_PTR(-ENOENT); | 2094 | struct generic_pm_domain *genpd = ERR_PTR(-ENOENT); |
| @@ -2108,6 +2108,7 @@ static struct generic_pm_domain *of_genpd_get_from_provider( | |||
| 2108 | 2108 | ||
| 2109 | return genpd; | 2109 | return genpd; |
| 2110 | } | 2110 | } |
| 2111 | EXPORT_SYMBOL_GPL(of_genpd_get_from_provider); | ||
| 2111 | 2112 | ||
| 2112 | /** | 2113 | /** |
| 2113 | * genpd_dev_pm_detach - Detach a device from its PM domain. | 2114 | * genpd_dev_pm_detach - Detach a device from its PM domain. |
diff --git a/drivers/base/power/opp.c b/drivers/base/power/opp.c index d24dd614a0bd..106c69359306 100644 --- a/drivers/base/power/opp.c +++ b/drivers/base/power/opp.c | |||
| @@ -108,6 +108,14 @@ static LIST_HEAD(dev_opp_list); | |||
| 108 | /* Lock to allow exclusive modification to the device and opp lists */ | 108 | /* Lock to allow exclusive modification to the device and opp lists */ |
| 109 | static DEFINE_MUTEX(dev_opp_list_lock); | 109 | static DEFINE_MUTEX(dev_opp_list_lock); |
| 110 | 110 | ||
| 111 | #define opp_rcu_lockdep_assert() \ | ||
| 112 | do { \ | ||
| 113 | rcu_lockdep_assert(rcu_read_lock_held() || \ | ||
| 114 | lockdep_is_held(&dev_opp_list_lock), \ | ||
| 115 | "Missing rcu_read_lock() or " \ | ||
| 116 | "dev_opp_list_lock protection"); \ | ||
| 117 | } while (0) | ||
| 118 | |||
| 111 | /** | 119 | /** |
| 112 | * find_device_opp() - find device_opp struct using device pointer | 120 | * find_device_opp() - find device_opp struct using device pointer |
| 113 | * @dev: device pointer used to lookup device OPPs | 121 | * @dev: device pointer used to lookup device OPPs |
| @@ -208,9 +216,7 @@ EXPORT_SYMBOL_GPL(dev_pm_opp_get_freq); | |||
| 208 | * This function returns the number of available opps if there are any, | 216 | * This function returns the number of available opps if there are any, |
| 209 | * else returns 0 if none or the corresponding error value. | 217 | * else returns 0 if none or the corresponding error value. |
| 210 | * | 218 | * |
| 211 | * Locking: This function must be called under rcu_read_lock(). This function | 219 | * Locking: This function takes rcu_read_lock(). |
| 212 | * internally references two RCU protected structures: device_opp and opp which | ||
| 213 | * are safe as long as we are under a common RCU locked section. | ||
| 214 | */ | 220 | */ |
| 215 | int dev_pm_opp_get_opp_count(struct device *dev) | 221 | int dev_pm_opp_get_opp_count(struct device *dev) |
| 216 | { | 222 | { |
| @@ -218,11 +224,14 @@ int dev_pm_opp_get_opp_count(struct device *dev) | |||
| 218 | struct dev_pm_opp *temp_opp; | 224 | struct dev_pm_opp *temp_opp; |
| 219 | int count = 0; | 225 | int count = 0; |
| 220 | 226 | ||
| 227 | rcu_read_lock(); | ||
| 228 | |||
| 221 | dev_opp = find_device_opp(dev); | 229 | dev_opp = find_device_opp(dev); |
| 222 | if (IS_ERR(dev_opp)) { | 230 | if (IS_ERR(dev_opp)) { |
| 223 | int r = PTR_ERR(dev_opp); | 231 | count = PTR_ERR(dev_opp); |
| 224 | dev_err(dev, "%s: device OPP not found (%d)\n", __func__, r); | 232 | dev_err(dev, "%s: device OPP not found (%d)\n", |
| 225 | return r; | 233 | __func__, count); |
| 234 | goto out_unlock; | ||
| 226 | } | 235 | } |
| 227 | 236 | ||
| 228 | list_for_each_entry_rcu(temp_opp, &dev_opp->opp_list, node) { | 237 | list_for_each_entry_rcu(temp_opp, &dev_opp->opp_list, node) { |
| @@ -230,6 +239,8 @@ int dev_pm_opp_get_opp_count(struct device *dev) | |||
| 230 | count++; | 239 | count++; |
| 231 | } | 240 | } |
| 232 | 241 | ||
| 242 | out_unlock: | ||
| 243 | rcu_read_unlock(); | ||
| 233 | return count; | 244 | return count; |
| 234 | } | 245 | } |
| 235 | EXPORT_SYMBOL_GPL(dev_pm_opp_get_opp_count); | 246 | EXPORT_SYMBOL_GPL(dev_pm_opp_get_opp_count); |
| @@ -267,6 +278,8 @@ struct dev_pm_opp *dev_pm_opp_find_freq_exact(struct device *dev, | |||
| 267 | struct device_opp *dev_opp; | 278 | struct device_opp *dev_opp; |
| 268 | struct dev_pm_opp *temp_opp, *opp = ERR_PTR(-ERANGE); | 279 | struct dev_pm_opp *temp_opp, *opp = ERR_PTR(-ERANGE); |
| 269 | 280 | ||
| 281 | opp_rcu_lockdep_assert(); | ||
| 282 | |||
| 270 | dev_opp = find_device_opp(dev); | 283 | dev_opp = find_device_opp(dev); |
| 271 | if (IS_ERR(dev_opp)) { | 284 | if (IS_ERR(dev_opp)) { |
| 272 | int r = PTR_ERR(dev_opp); | 285 | int r = PTR_ERR(dev_opp); |
| @@ -313,6 +326,8 @@ struct dev_pm_opp *dev_pm_opp_find_freq_ceil(struct device *dev, | |||
| 313 | struct device_opp *dev_opp; | 326 | struct device_opp *dev_opp; |
| 314 | struct dev_pm_opp *temp_opp, *opp = ERR_PTR(-ERANGE); | 327 | struct dev_pm_opp *temp_opp, *opp = ERR_PTR(-ERANGE); |
| 315 | 328 | ||
| 329 | opp_rcu_lockdep_assert(); | ||
| 330 | |||
| 316 | if (!dev || !freq) { | 331 | if (!dev || !freq) { |
| 317 | dev_err(dev, "%s: Invalid argument freq=%p\n", __func__, freq); | 332 | dev_err(dev, "%s: Invalid argument freq=%p\n", __func__, freq); |
| 318 | return ERR_PTR(-EINVAL); | 333 | return ERR_PTR(-EINVAL); |
| @@ -361,6 +376,8 @@ struct dev_pm_opp *dev_pm_opp_find_freq_floor(struct device *dev, | |||
| 361 | struct device_opp *dev_opp; | 376 | struct device_opp *dev_opp; |
| 362 | struct dev_pm_opp *temp_opp, *opp = ERR_PTR(-ERANGE); | 377 | struct dev_pm_opp *temp_opp, *opp = ERR_PTR(-ERANGE); |
| 363 | 378 | ||
| 379 | opp_rcu_lockdep_assert(); | ||
| 380 | |||
| 364 | if (!dev || !freq) { | 381 | if (!dev || !freq) { |
| 365 | dev_err(dev, "%s: Invalid argument freq=%p\n", __func__, freq); | 382 | dev_err(dev, "%s: Invalid argument freq=%p\n", __func__, freq); |
| 366 | return ERR_PTR(-EINVAL); | 383 | return ERR_PTR(-EINVAL); |
| @@ -783,9 +800,15 @@ void of_free_opp_table(struct device *dev) | |||
| 783 | 800 | ||
| 784 | /* Check for existing list for 'dev' */ | 801 | /* Check for existing list for 'dev' */ |
| 785 | dev_opp = find_device_opp(dev); | 802 | dev_opp = find_device_opp(dev); |
| 786 | if (WARN(IS_ERR(dev_opp), "%s: dev_opp: %ld\n", dev_name(dev), | 803 | if (IS_ERR(dev_opp)) { |
| 787 | PTR_ERR(dev_opp))) | 804 | int error = PTR_ERR(dev_opp); |
| 805 | if (error != -ENODEV) | ||
| 806 | WARN(1, "%s: dev_opp: %d\n", | ||
| 807 | IS_ERR_OR_NULL(dev) ? | ||
| 808 | "Invalid device" : dev_name(dev), | ||
| 809 | error); | ||
| 788 | return; | 810 | return; |
| 811 | } | ||
| 789 | 812 | ||
| 790 | /* Hold our list modification lock here */ | 813 | /* Hold our list modification lock here */ |
| 791 | mutex_lock(&dev_opp_list_lock); | 814 | mutex_lock(&dev_opp_list_lock); |
diff --git a/drivers/char/agp/ali-agp.c b/drivers/char/agp/ali-agp.c index 19db03667650..dcbbb4ea3cc1 100644 --- a/drivers/char/agp/ali-agp.c +++ b/drivers/char/agp/ali-agp.c | |||
| @@ -417,6 +417,6 @@ static void __exit agp_ali_cleanup(void) | |||
| 417 | module_init(agp_ali_init); | 417 | module_init(agp_ali_init); |
| 418 | module_exit(agp_ali_cleanup); | 418 | module_exit(agp_ali_cleanup); |
| 419 | 419 | ||
| 420 | MODULE_AUTHOR("Dave Jones <davej@redhat.com>"); | 420 | MODULE_AUTHOR("Dave Jones"); |
| 421 | MODULE_LICENSE("GPL and additional rights"); | 421 | MODULE_LICENSE("GPL and additional rights"); |
| 422 | 422 | ||
diff --git a/drivers/char/agp/amd64-agp.c b/drivers/char/agp/amd64-agp.c index 3b47ed0310e1..0ef350010766 100644 --- a/drivers/char/agp/amd64-agp.c +++ b/drivers/char/agp/amd64-agp.c | |||
| @@ -813,6 +813,6 @@ static void __exit agp_amd64_cleanup(void) | |||
| 813 | module_init(agp_amd64_mod_init); | 813 | module_init(agp_amd64_mod_init); |
| 814 | module_exit(agp_amd64_cleanup); | 814 | module_exit(agp_amd64_cleanup); |
| 815 | 815 | ||
| 816 | MODULE_AUTHOR("Dave Jones <davej@redhat.com>, Andi Kleen"); | 816 | MODULE_AUTHOR("Dave Jones, Andi Kleen"); |
| 817 | module_param(agp_try_unsupported, bool, 0); | 817 | module_param(agp_try_unsupported, bool, 0); |
| 818 | MODULE_LICENSE("GPL"); | 818 | MODULE_LICENSE("GPL"); |
diff --git a/drivers/char/agp/ati-agp.c b/drivers/char/agp/ati-agp.c index 18a7a6baa304..75a9786a77e6 100644 --- a/drivers/char/agp/ati-agp.c +++ b/drivers/char/agp/ati-agp.c | |||
| @@ -579,6 +579,6 @@ static void __exit agp_ati_cleanup(void) | |||
| 579 | module_init(agp_ati_init); | 579 | module_init(agp_ati_init); |
| 580 | module_exit(agp_ati_cleanup); | 580 | module_exit(agp_ati_cleanup); |
| 581 | 581 | ||
| 582 | MODULE_AUTHOR("Dave Jones <davej@redhat.com>"); | 582 | MODULE_AUTHOR("Dave Jones"); |
| 583 | MODULE_LICENSE("GPL and additional rights"); | 583 | MODULE_LICENSE("GPL and additional rights"); |
| 584 | 584 | ||
diff --git a/drivers/char/agp/backend.c b/drivers/char/agp/backend.c index 317c28ce8328..38ffb281df97 100644 --- a/drivers/char/agp/backend.c +++ b/drivers/char/agp/backend.c | |||
| @@ -356,7 +356,7 @@ static __init int agp_setup(char *s) | |||
| 356 | __setup("agp=", agp_setup); | 356 | __setup("agp=", agp_setup); |
| 357 | #endif | 357 | #endif |
| 358 | 358 | ||
| 359 | MODULE_AUTHOR("Dave Jones <davej@redhat.com>"); | 359 | MODULE_AUTHOR("Dave Jones, Jeff Hartmann"); |
| 360 | MODULE_DESCRIPTION("AGP GART driver"); | 360 | MODULE_DESCRIPTION("AGP GART driver"); |
| 361 | MODULE_LICENSE("GPL and additional rights"); | 361 | MODULE_LICENSE("GPL and additional rights"); |
| 362 | MODULE_ALIAS_MISCDEV(AGPGART_MINOR); | 362 | MODULE_ALIAS_MISCDEV(AGPGART_MINOR); |
diff --git a/drivers/char/agp/intel-agp.c b/drivers/char/agp/intel-agp.c index f9b9ca5d31b7..0a21daed5b62 100644 --- a/drivers/char/agp/intel-agp.c +++ b/drivers/char/agp/intel-agp.c | |||
| @@ -920,5 +920,5 @@ static void __exit agp_intel_cleanup(void) | |||
| 920 | module_init(agp_intel_init); | 920 | module_init(agp_intel_init); |
| 921 | module_exit(agp_intel_cleanup); | 921 | module_exit(agp_intel_cleanup); |
| 922 | 922 | ||
| 923 | MODULE_AUTHOR("Dave Jones <davej@redhat.com>"); | 923 | MODULE_AUTHOR("Dave Jones, Various @Intel"); |
| 924 | MODULE_LICENSE("GPL and additional rights"); | 924 | MODULE_LICENSE("GPL and additional rights"); |
diff --git a/drivers/char/agp/intel-gtt.c b/drivers/char/agp/intel-gtt.c index f3334829e55a..92aa43fa8d70 100644 --- a/drivers/char/agp/intel-gtt.c +++ b/drivers/char/agp/intel-gtt.c | |||
| @@ -1438,5 +1438,5 @@ void intel_gmch_remove(void) | |||
| 1438 | } | 1438 | } |
| 1439 | EXPORT_SYMBOL(intel_gmch_remove); | 1439 | EXPORT_SYMBOL(intel_gmch_remove); |
| 1440 | 1440 | ||
| 1441 | MODULE_AUTHOR("Dave Jones <davej@redhat.com>"); | 1441 | MODULE_AUTHOR("Dave Jones, Various @Intel"); |
| 1442 | MODULE_LICENSE("GPL and additional rights"); | 1442 | MODULE_LICENSE("GPL and additional rights"); |
diff --git a/drivers/char/agp/nvidia-agp.c b/drivers/char/agp/nvidia-agp.c index a1861b75eb31..6c8d39cb566e 100644 --- a/drivers/char/agp/nvidia-agp.c +++ b/drivers/char/agp/nvidia-agp.c | |||
| @@ -1,7 +1,7 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * Nvidia AGPGART routines. | 2 | * Nvidia AGPGART routines. |
| 3 | * Based upon a 2.4 agpgart diff by the folks from NVIDIA, and hacked up | 3 | * Based upon a 2.4 agpgart diff by the folks from NVIDIA, and hacked up |
| 4 | * to work in 2.5 by Dave Jones <davej@redhat.com> | 4 | * to work in 2.5 by Dave Jones. |
| 5 | */ | 5 | */ |
| 6 | 6 | ||
| 7 | #include <linux/module.h> | 7 | #include <linux/module.h> |
diff --git a/drivers/char/agp/via-agp.c b/drivers/char/agp/via-agp.c index 228f20cddc05..a4961d35e940 100644 --- a/drivers/char/agp/via-agp.c +++ b/drivers/char/agp/via-agp.c | |||
| @@ -595,4 +595,4 @@ module_init(agp_via_init); | |||
| 595 | module_exit(agp_via_cleanup); | 595 | module_exit(agp_via_cleanup); |
| 596 | 596 | ||
| 597 | MODULE_LICENSE("GPL"); | 597 | MODULE_LICENSE("GPL"); |
| 598 | MODULE_AUTHOR("Dave Jones <davej@redhat.com>"); | 598 | MODULE_AUTHOR("Dave Jones"); |
diff --git a/drivers/char/ipmi/ipmi_msghandler.c b/drivers/char/ipmi/ipmi_msghandler.c index 5fa83f751378..6b65fa4e0c55 100644 --- a/drivers/char/ipmi/ipmi_msghandler.c +++ b/drivers/char/ipmi/ipmi_msghandler.c | |||
| @@ -199,18 +199,6 @@ struct bmc_device { | |||
| 199 | int guid_set; | 199 | int guid_set; |
| 200 | char name[16]; | 200 | char name[16]; |
| 201 | struct kref usecount; | 201 | struct kref usecount; |
| 202 | |||
| 203 | /* bmc device attributes */ | ||
| 204 | struct device_attribute device_id_attr; | ||
| 205 | struct device_attribute provides_dev_sdrs_attr; | ||
| 206 | struct device_attribute revision_attr; | ||
| 207 | struct device_attribute firmware_rev_attr; | ||
| 208 | struct device_attribute version_attr; | ||
| 209 | struct device_attribute add_dev_support_attr; | ||
| 210 | struct device_attribute manufacturer_id_attr; | ||
| 211 | struct device_attribute product_id_attr; | ||
| 212 | struct device_attribute guid_attr; | ||
| 213 | struct device_attribute aux_firmware_rev_attr; | ||
| 214 | }; | 202 | }; |
| 215 | #define to_bmc_device(x) container_of((x), struct bmc_device, pdev.dev) | 203 | #define to_bmc_device(x) container_of((x), struct bmc_device, pdev.dev) |
| 216 | 204 | ||
| @@ -2252,7 +2240,7 @@ static ssize_t device_id_show(struct device *dev, | |||
| 2252 | 2240 | ||
| 2253 | return snprintf(buf, 10, "%u\n", bmc->id.device_id); | 2241 | return snprintf(buf, 10, "%u\n", bmc->id.device_id); |
| 2254 | } | 2242 | } |
| 2255 | DEVICE_ATTR(device_id, S_IRUGO, device_id_show, NULL); | 2243 | static DEVICE_ATTR(device_id, S_IRUGO, device_id_show, NULL); |
| 2256 | 2244 | ||
| 2257 | static ssize_t provides_device_sdrs_show(struct device *dev, | 2245 | static ssize_t provides_device_sdrs_show(struct device *dev, |
| 2258 | struct device_attribute *attr, | 2246 | struct device_attribute *attr, |
| @@ -2263,7 +2251,8 @@ static ssize_t provides_device_sdrs_show(struct device *dev, | |||
| 2263 | return snprintf(buf, 10, "%u\n", | 2251 | return snprintf(buf, 10, "%u\n", |
| 2264 | (bmc->id.device_revision & 0x80) >> 7); | 2252 | (bmc->id.device_revision & 0x80) >> 7); |
| 2265 | } | 2253 | } |
| 2266 | DEVICE_ATTR(provides_device_sdrs, S_IRUGO, provides_device_sdrs_show, NULL); | 2254 | static DEVICE_ATTR(provides_device_sdrs, S_IRUGO, provides_device_sdrs_show, |
| 2255 | NULL); | ||
| 2267 | 2256 | ||
| 2268 | static ssize_t revision_show(struct device *dev, struct device_attribute *attr, | 2257 | static ssize_t revision_show(struct device *dev, struct device_attribute *attr, |
| 2269 | char *buf) | 2258 | char *buf) |
| @@ -2273,7 +2262,7 @@ static ssize_t revision_show(struct device *dev, struct device_attribute *attr, | |||
| 2273 | return snprintf(buf, 20, "%u\n", | 2262 | return snprintf(buf, 20, "%u\n", |
| 2274 | bmc->id.device_revision & 0x0F); | 2263 | bmc->id.device_revision & 0x0F); |
| 2275 | } | 2264 | } |
| 2276 | DEVICE_ATTR(revision, S_IRUGO, revision_show, NULL); | 2265 | static DEVICE_ATTR(revision, S_IRUGO, revision_show, NULL); |
| 2277 | 2266 | ||
| 2278 | static ssize_t firmware_revision_show(struct device *dev, | 2267 | static ssize_t firmware_revision_show(struct device *dev, |
| 2279 | struct device_attribute *attr, | 2268 | struct device_attribute *attr, |
| @@ -2284,7 +2273,7 @@ static ssize_t firmware_revision_show(struct device *dev, | |||
| 2284 | return snprintf(buf, 20, "%u.%x\n", bmc->id.firmware_revision_1, | 2273 | return snprintf(buf, 20, "%u.%x\n", bmc->id.firmware_revision_1, |
| 2285 | bmc->id.firmware_revision_2); | 2274 | bmc->id.firmware_revision_2); |
| 2286 | } | 2275 | } |
| 2287 | DEVICE_ATTR(firmware_revision, S_IRUGO, firmware_revision_show, NULL); | 2276 | static DEVICE_ATTR(firmware_revision, S_IRUGO, firmware_revision_show, NULL); |
| 2288 | 2277 | ||
| 2289 | static ssize_t ipmi_version_show(struct device *dev, | 2278 | static ssize_t ipmi_version_show(struct device *dev, |
| 2290 | struct device_attribute *attr, | 2279 | struct device_attribute *attr, |
| @@ -2296,7 +2285,7 @@ static ssize_t ipmi_version_show(struct device *dev, | |||
| 2296 | ipmi_version_major(&bmc->id), | 2285 | ipmi_version_major(&bmc->id), |
| 2297 | ipmi_version_minor(&bmc->id)); | 2286 | ipmi_version_minor(&bmc->id)); |
| 2298 | } | 2287 | } |
| 2299 | DEVICE_ATTR(ipmi_version, S_IRUGO, ipmi_version_show, NULL); | 2288 | static DEVICE_ATTR(ipmi_version, S_IRUGO, ipmi_version_show, NULL); |
| 2300 | 2289 | ||
| 2301 | static ssize_t add_dev_support_show(struct device *dev, | 2290 | static ssize_t add_dev_support_show(struct device *dev, |
| 2302 | struct device_attribute *attr, | 2291 | struct device_attribute *attr, |
| @@ -2307,7 +2296,8 @@ static ssize_t add_dev_support_show(struct device *dev, | |||
| 2307 | return snprintf(buf, 10, "0x%02x\n", | 2296 | return snprintf(buf, 10, "0x%02x\n", |
| 2308 | bmc->id.additional_device_support); | 2297 | bmc->id.additional_device_support); |
| 2309 | } | 2298 | } |
| 2310 | DEVICE_ATTR(additional_device_support, S_IRUGO, add_dev_support_show, NULL); | 2299 | static DEVICE_ATTR(additional_device_support, S_IRUGO, add_dev_support_show, |
| 2300 | NULL); | ||
| 2311 | 2301 | ||
| 2312 | static ssize_t manufacturer_id_show(struct device *dev, | 2302 | static ssize_t manufacturer_id_show(struct device *dev, |
| 2313 | struct device_attribute *attr, | 2303 | struct device_attribute *attr, |
| @@ -2317,7 +2307,7 @@ static ssize_t manufacturer_id_show(struct device *dev, | |||
| 2317 | 2307 | ||
| 2318 | return snprintf(buf, 20, "0x%6.6x\n", bmc->id.manufacturer_id); | 2308 | return snprintf(buf, 20, "0x%6.6x\n", bmc->id.manufacturer_id); |
| 2319 | } | 2309 | } |
| 2320 | DEVICE_ATTR(manufacturer_id, S_IRUGO, manufacturer_id_show, NULL); | 2310 | static DEVICE_ATTR(manufacturer_id, S_IRUGO, manufacturer_id_show, NULL); |
| 2321 | 2311 | ||
| 2322 | static ssize_t product_id_show(struct device *dev, | 2312 | static ssize_t product_id_show(struct device *dev, |
| 2323 | struct device_attribute *attr, | 2313 | struct device_attribute *attr, |
| @@ -2327,7 +2317,7 @@ static ssize_t product_id_show(struct device *dev, | |||
| 2327 | 2317 | ||
| 2328 | return snprintf(buf, 10, "0x%4.4x\n", bmc->id.product_id); | 2318 | return snprintf(buf, 10, "0x%4.4x\n", bmc->id.product_id); |
| 2329 | } | 2319 | } |
| 2330 | DEVICE_ATTR(product_id, S_IRUGO, product_id_show, NULL); | 2320 | static DEVICE_ATTR(product_id, S_IRUGO, product_id_show, NULL); |
| 2331 | 2321 | ||
| 2332 | static ssize_t aux_firmware_rev_show(struct device *dev, | 2322 | static ssize_t aux_firmware_rev_show(struct device *dev, |
| 2333 | struct device_attribute *attr, | 2323 | struct device_attribute *attr, |
| @@ -2341,7 +2331,7 @@ static ssize_t aux_firmware_rev_show(struct device *dev, | |||
| 2341 | bmc->id.aux_firmware_revision[1], | 2331 | bmc->id.aux_firmware_revision[1], |
| 2342 | bmc->id.aux_firmware_revision[0]); | 2332 | bmc->id.aux_firmware_revision[0]); |
| 2343 | } | 2333 | } |
| 2344 | DEVICE_ATTR(aux_firmware_revision, S_IRUGO, aux_firmware_rev_show, NULL); | 2334 | static DEVICE_ATTR(aux_firmware_revision, S_IRUGO, aux_firmware_rev_show, NULL); |
| 2345 | 2335 | ||
| 2346 | static ssize_t guid_show(struct device *dev, struct device_attribute *attr, | 2336 | static ssize_t guid_show(struct device *dev, struct device_attribute *attr, |
| 2347 | char *buf) | 2337 | char *buf) |
| @@ -2352,7 +2342,7 @@ static ssize_t guid_show(struct device *dev, struct device_attribute *attr, | |||
| 2352 | (long long) bmc->guid[0], | 2342 | (long long) bmc->guid[0], |
| 2353 | (long long) bmc->guid[8]); | 2343 | (long long) bmc->guid[8]); |
| 2354 | } | 2344 | } |
| 2355 | DEVICE_ATTR(guid, S_IRUGO, guid_show, NULL); | 2345 | static DEVICE_ATTR(guid, S_IRUGO, guid_show, NULL); |
| 2356 | 2346 | ||
| 2357 | static struct attribute *bmc_dev_attrs[] = { | 2347 | static struct attribute *bmc_dev_attrs[] = { |
| 2358 | &dev_attr_device_id.attr, | 2348 | &dev_attr_device_id.attr, |
| @@ -2392,10 +2382,10 @@ cleanup_bmc_device(struct kref *ref) | |||
| 2392 | 2382 | ||
| 2393 | if (bmc->id.aux_firmware_revision_set) | 2383 | if (bmc->id.aux_firmware_revision_set) |
| 2394 | device_remove_file(&bmc->pdev.dev, | 2384 | device_remove_file(&bmc->pdev.dev, |
| 2395 | &bmc->aux_firmware_rev_attr); | 2385 | &dev_attr_aux_firmware_revision); |
| 2396 | if (bmc->guid_set) | 2386 | if (bmc->guid_set) |
| 2397 | device_remove_file(&bmc->pdev.dev, | 2387 | device_remove_file(&bmc->pdev.dev, |
| 2398 | &bmc->guid_attr); | 2388 | &dev_attr_guid); |
| 2399 | 2389 | ||
| 2400 | platform_device_unregister(&bmc->pdev); | 2390 | platform_device_unregister(&bmc->pdev); |
| 2401 | } | 2391 | } |
| @@ -2422,16 +2412,14 @@ static int create_bmc_files(struct bmc_device *bmc) | |||
| 2422 | int err; | 2412 | int err; |
| 2423 | 2413 | ||
| 2424 | if (bmc->id.aux_firmware_revision_set) { | 2414 | if (bmc->id.aux_firmware_revision_set) { |
| 2425 | bmc->aux_firmware_rev_attr.attr.name = "aux_firmware_revision"; | ||
| 2426 | err = device_create_file(&bmc->pdev.dev, | 2415 | err = device_create_file(&bmc->pdev.dev, |
| 2427 | &bmc->aux_firmware_rev_attr); | 2416 | &dev_attr_aux_firmware_revision); |
| 2428 | if (err) | 2417 | if (err) |
| 2429 | goto out; | 2418 | goto out; |
| 2430 | } | 2419 | } |
| 2431 | if (bmc->guid_set) { | 2420 | if (bmc->guid_set) { |
| 2432 | bmc->guid_attr.attr.name = "guid"; | ||
| 2433 | err = device_create_file(&bmc->pdev.dev, | 2421 | err = device_create_file(&bmc->pdev.dev, |
| 2434 | &bmc->guid_attr); | 2422 | &dev_attr_guid); |
| 2435 | if (err) | 2423 | if (err) |
| 2436 | goto out_aux_firm; | 2424 | goto out_aux_firm; |
| 2437 | } | 2425 | } |
| @@ -2441,7 +2429,7 @@ static int create_bmc_files(struct bmc_device *bmc) | |||
| 2441 | out_aux_firm: | 2429 | out_aux_firm: |
| 2442 | if (bmc->id.aux_firmware_revision_set) | 2430 | if (bmc->id.aux_firmware_revision_set) |
| 2443 | device_remove_file(&bmc->pdev.dev, | 2431 | device_remove_file(&bmc->pdev.dev, |
| 2444 | &bmc->aux_firmware_rev_attr); | 2432 | &dev_attr_aux_firmware_revision); |
| 2445 | out: | 2433 | out: |
| 2446 | return err; | 2434 | return err; |
| 2447 | } | 2435 | } |
diff --git a/drivers/char/ipmi/ipmi_ssif.c b/drivers/char/ipmi/ipmi_ssif.c index e178ac27e73c..fd5a5e85d7dc 100644 --- a/drivers/char/ipmi/ipmi_ssif.c +++ b/drivers/char/ipmi/ipmi_ssif.c | |||
| @@ -52,6 +52,7 @@ | |||
| 52 | #include <linux/dmi.h> | 52 | #include <linux/dmi.h> |
| 53 | #include <linux/kthread.h> | 53 | #include <linux/kthread.h> |
| 54 | #include <linux/acpi.h> | 54 | #include <linux/acpi.h> |
| 55 | #include <linux/ctype.h> | ||
| 55 | 56 | ||
| 56 | #define PFX "ipmi_ssif: " | 57 | #define PFX "ipmi_ssif: " |
| 57 | #define DEVICE_NAME "ipmi_ssif" | 58 | #define DEVICE_NAME "ipmi_ssif" |
diff --git a/drivers/clocksource/arm_arch_timer.c b/drivers/clocksource/arm_arch_timer.c index 6a79fc4f900c..095c1774592c 100644 --- a/drivers/clocksource/arm_arch_timer.c +++ b/drivers/clocksource/arm_arch_timer.c | |||
| @@ -462,7 +462,7 @@ static void __init arch_counter_register(unsigned type) | |||
| 462 | 462 | ||
| 463 | /* Register the CP15 based counter if we have one */ | 463 | /* Register the CP15 based counter if we have one */ |
| 464 | if (type & ARCH_CP15_TIMER) { | 464 | if (type & ARCH_CP15_TIMER) { |
| 465 | if (arch_timer_use_virtual) | 465 | if (IS_ENABLED(CONFIG_ARM64) || arch_timer_use_virtual) |
| 466 | arch_timer_read_counter = arch_counter_get_cntvct; | 466 | arch_timer_read_counter = arch_counter_get_cntvct; |
| 467 | else | 467 | else |
| 468 | arch_timer_read_counter = arch_counter_get_cntpct; | 468 | arch_timer_read_counter = arch_counter_get_cntpct; |
diff --git a/drivers/cpufreq/cpufreq-dt.c b/drivers/cpufreq/cpufreq-dt.c index f56147a1daed..fde97d6e31d6 100644 --- a/drivers/cpufreq/cpufreq-dt.c +++ b/drivers/cpufreq/cpufreq-dt.c | |||
| @@ -211,6 +211,17 @@ static int cpufreq_init(struct cpufreq_policy *policy) | |||
| 211 | /* OPPs might be populated at runtime, don't check for error here */ | 211 | /* OPPs might be populated at runtime, don't check for error here */ |
| 212 | of_init_opp_table(cpu_dev); | 212 | of_init_opp_table(cpu_dev); |
| 213 | 213 | ||
| 214 | /* | ||
| 215 | * But we need OPP table to function so if it is not there let's | ||
| 216 | * give platform code chance to provide it for us. | ||
| 217 | */ | ||
| 218 | ret = dev_pm_opp_get_opp_count(cpu_dev); | ||
| 219 | if (ret <= 0) { | ||
| 220 | pr_debug("OPP table is not ready, deferring probe\n"); | ||
| 221 | ret = -EPROBE_DEFER; | ||
| 222 | goto out_free_opp; | ||
| 223 | } | ||
| 224 | |||
| 214 | priv = kzalloc(sizeof(*priv), GFP_KERNEL); | 225 | priv = kzalloc(sizeof(*priv), GFP_KERNEL); |
| 215 | if (!priv) { | 226 | if (!priv) { |
| 216 | ret = -ENOMEM; | 227 | ret = -ENOMEM; |
diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c index a09a29c312a9..46bed4f81cde 100644 --- a/drivers/cpufreq/cpufreq.c +++ b/drivers/cpufreq/cpufreq.c | |||
| @@ -2028,6 +2028,12 @@ static int __cpufreq_governor(struct cpufreq_policy *policy, | |||
| 2028 | /* Don't start any governor operations if we are entering suspend */ | 2028 | /* Don't start any governor operations if we are entering suspend */ |
| 2029 | if (cpufreq_suspended) | 2029 | if (cpufreq_suspended) |
| 2030 | return 0; | 2030 | return 0; |
| 2031 | /* | ||
| 2032 | * Governor might not be initiated here if ACPI _PPC changed | ||
| 2033 | * notification happened, so check it. | ||
| 2034 | */ | ||
| 2035 | if (!policy->governor) | ||
| 2036 | return -EINVAL; | ||
| 2031 | 2037 | ||
| 2032 | if (policy->governor->max_transition_latency && | 2038 | if (policy->governor->max_transition_latency && |
| 2033 | policy->cpuinfo.transition_latency > | 2039 | policy->cpuinfo.transition_latency > |
diff --git a/drivers/cpuidle/governors/ladder.c b/drivers/cpuidle/governors/ladder.c index 37263d9a1051..401c0106ed34 100644 --- a/drivers/cpuidle/governors/ladder.c +++ b/drivers/cpuidle/governors/ladder.c | |||
| @@ -79,12 +79,7 @@ static int ladder_select_state(struct cpuidle_driver *drv, | |||
| 79 | 79 | ||
| 80 | last_state = &ldev->states[last_idx]; | 80 | last_state = &ldev->states[last_idx]; |
| 81 | 81 | ||
| 82 | if (!(drv->states[last_idx].flags & CPUIDLE_FLAG_TIME_INVALID)) { | 82 | last_residency = cpuidle_get_last_residency(dev) - drv->states[last_idx].exit_latency; |
| 83 | last_residency = cpuidle_get_last_residency(dev) - \ | ||
| 84 | drv->states[last_idx].exit_latency; | ||
| 85 | } | ||
| 86 | else | ||
| 87 | last_residency = last_state->threshold.promotion_time + 1; | ||
| 88 | 83 | ||
| 89 | /* consider promotion */ | 84 | /* consider promotion */ |
| 90 | if (last_idx < drv->state_count - 1 && | 85 | if (last_idx < drv->state_count - 1 && |
diff --git a/drivers/cpuidle/governors/menu.c b/drivers/cpuidle/governors/menu.c index 659d7b0c9ebf..40580794e23d 100644 --- a/drivers/cpuidle/governors/menu.c +++ b/drivers/cpuidle/governors/menu.c | |||
| @@ -396,8 +396,8 @@ static void menu_update(struct cpuidle_driver *drv, struct cpuidle_device *dev) | |||
| 396 | * power state and occurrence of the wakeup event. | 396 | * power state and occurrence of the wakeup event. |
| 397 | * | 397 | * |
| 398 | * If the entered idle state didn't support residency measurements, | 398 | * If the entered idle state didn't support residency measurements, |
| 399 | * we are basically lost in the dark how much time passed. | 399 | * we use them anyway if they are short, and if long, |
| 400 | * As a compromise, assume we slept for the whole expected time. | 400 | * truncate to the whole expected time. |
| 401 | * | 401 | * |
| 402 | * Any measured amount of time will include the exit latency. | 402 | * Any measured amount of time will include the exit latency. |
| 403 | * Since we are interested in when the wakeup begun, not when it | 403 | * Since we are interested in when the wakeup begun, not when it |
| @@ -405,22 +405,17 @@ static void menu_update(struct cpuidle_driver *drv, struct cpuidle_device *dev) | |||
| 405 | * the measured amount of time is less than the exit latency, | 405 | * the measured amount of time is less than the exit latency, |
| 406 | * assume the state was never reached and the exit latency is 0. | 406 | * assume the state was never reached and the exit latency is 0. |
| 407 | */ | 407 | */ |
| 408 | if (unlikely(target->flags & CPUIDLE_FLAG_TIME_INVALID)) { | ||
| 409 | /* Use timer value as is */ | ||
| 410 | measured_us = data->next_timer_us; | ||
| 411 | 408 | ||
| 412 | } else { | 409 | /* measured value */ |
| 413 | /* Use measured value */ | 410 | measured_us = cpuidle_get_last_residency(dev); |
| 414 | measured_us = cpuidle_get_last_residency(dev); | ||
| 415 | 411 | ||
| 416 | /* Deduct exit latency */ | 412 | /* Deduct exit latency */ |
| 417 | if (measured_us > target->exit_latency) | 413 | if (measured_us > target->exit_latency) |
| 418 | measured_us -= target->exit_latency; | 414 | measured_us -= target->exit_latency; |
| 419 | 415 | ||
| 420 | /* Make sure our coefficients do not exceed unity */ | 416 | /* Make sure our coefficients do not exceed unity */ |
| 421 | if (measured_us > data->next_timer_us) | 417 | if (measured_us > data->next_timer_us) |
| 422 | measured_us = data->next_timer_us; | 418 | measured_us = data->next_timer_us; |
| 423 | } | ||
| 424 | 419 | ||
| 425 | /* Update our correction ratio */ | 420 | /* Update our correction ratio */ |
| 426 | new_factor = data->correction_factor[data->bucket]; | 421 | new_factor = data->correction_factor[data->bucket]; |
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c b/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c index 4f7b275f2f7b..7d4974b83af7 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c | |||
| @@ -121,13 +121,9 @@ static int kfd_open(struct inode *inode, struct file *filep) | |||
| 121 | if (IS_ERR(process)) | 121 | if (IS_ERR(process)) |
| 122 | return PTR_ERR(process); | 122 | return PTR_ERR(process); |
| 123 | 123 | ||
| 124 | process->is_32bit_user_mode = is_32bit_user_mode; | ||
| 125 | |||
| 126 | dev_dbg(kfd_device, "process %d opened, compat mode (32 bit) - %d\n", | 124 | dev_dbg(kfd_device, "process %d opened, compat mode (32 bit) - %d\n", |
| 127 | process->pasid, process->is_32bit_user_mode); | 125 | process->pasid, process->is_32bit_user_mode); |
| 128 | 126 | ||
| 129 | kfd_init_apertures(process); | ||
| 130 | |||
| 131 | return 0; | 127 | return 0; |
| 132 | } | 128 | } |
| 133 | 129 | ||
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_flat_memory.c b/drivers/gpu/drm/amd/amdkfd/kfd_flat_memory.c index 66df4da01c29..e64aa99e5e41 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_flat_memory.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_flat_memory.c | |||
| @@ -299,13 +299,13 @@ int kfd_init_apertures(struct kfd_process *process) | |||
| 299 | struct kfd_dev *dev; | 299 | struct kfd_dev *dev; |
| 300 | struct kfd_process_device *pdd; | 300 | struct kfd_process_device *pdd; |
| 301 | 301 | ||
| 302 | mutex_lock(&process->mutex); | ||
| 303 | |||
| 304 | /*Iterating over all devices*/ | 302 | /*Iterating over all devices*/ |
| 305 | while ((dev = kfd_topology_enum_kfd_devices(id)) != NULL && | 303 | while ((dev = kfd_topology_enum_kfd_devices(id)) != NULL && |
| 306 | id < NUM_OF_SUPPORTED_GPUS) { | 304 | id < NUM_OF_SUPPORTED_GPUS) { |
| 307 | 305 | ||
| 308 | pdd = kfd_get_process_device_data(dev, process, 1); | 306 | pdd = kfd_get_process_device_data(dev, process, 1); |
| 307 | if (!pdd) | ||
| 308 | return -1; | ||
| 309 | 309 | ||
| 310 | /* | 310 | /* |
| 311 | * For 64 bit process aperture will be statically reserved in | 311 | * For 64 bit process aperture will be statically reserved in |
| @@ -348,8 +348,6 @@ int kfd_init_apertures(struct kfd_process *process) | |||
| 348 | id++; | 348 | id++; |
| 349 | } | 349 | } |
| 350 | 350 | ||
| 351 | mutex_unlock(&process->mutex); | ||
| 352 | |||
| 353 | return 0; | 351 | return 0; |
| 354 | } | 352 | } |
| 355 | 353 | ||
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_process.c b/drivers/gpu/drm/amd/amdkfd/kfd_process.c index b85eb0b830b4..3c76ef05cbcf 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_process.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_process.c | |||
| @@ -26,6 +26,8 @@ | |||
| 26 | #include <linux/slab.h> | 26 | #include <linux/slab.h> |
| 27 | #include <linux/amd-iommu.h> | 27 | #include <linux/amd-iommu.h> |
| 28 | #include <linux/notifier.h> | 28 | #include <linux/notifier.h> |
| 29 | #include <linux/compat.h> | ||
| 30 | |||
| 29 | struct mm_struct; | 31 | struct mm_struct; |
| 30 | 32 | ||
| 31 | #include "kfd_priv.h" | 33 | #include "kfd_priv.h" |
| @@ -285,8 +287,15 @@ static struct kfd_process *create_process(const struct task_struct *thread) | |||
| 285 | if (err != 0) | 287 | if (err != 0) |
| 286 | goto err_process_pqm_init; | 288 | goto err_process_pqm_init; |
| 287 | 289 | ||
| 290 | /* init process apertures*/ | ||
| 291 | process->is_32bit_user_mode = is_compat_task(); | ||
| 292 | if (kfd_init_apertures(process) != 0) | ||
| 293 | goto err_init_apretures; | ||
| 294 | |||
| 288 | return process; | 295 | return process; |
| 289 | 296 | ||
| 297 | err_init_apretures: | ||
| 298 | pqm_uninit(&process->pqm); | ||
| 290 | err_process_pqm_init: | 299 | err_process_pqm_init: |
| 291 | hash_del_rcu(&process->kfd_processes); | 300 | hash_del_rcu(&process->kfd_processes); |
| 292 | synchronize_rcu(); | 301 | synchronize_rcu(); |
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_topology.c b/drivers/gpu/drm/amd/amdkfd/kfd_topology.c index 5733e2859e8a..b11792d7e70e 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_topology.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_topology.c | |||
| @@ -700,8 +700,6 @@ static ssize_t node_show(struct kobject *kobj, struct attribute *attr, | |||
| 700 | dev->node_props.simd_per_cu); | 700 | dev->node_props.simd_per_cu); |
| 701 | sysfs_show_32bit_prop(buffer, "max_slots_scratch_cu", | 701 | sysfs_show_32bit_prop(buffer, "max_slots_scratch_cu", |
| 702 | dev->node_props.max_slots_scratch_cu); | 702 | dev->node_props.max_slots_scratch_cu); |
| 703 | sysfs_show_32bit_prop(buffer, "engine_id", | ||
| 704 | dev->node_props.engine_id); | ||
| 705 | sysfs_show_32bit_prop(buffer, "vendor_id", | 703 | sysfs_show_32bit_prop(buffer, "vendor_id", |
| 706 | dev->node_props.vendor_id); | 704 | dev->node_props.vendor_id); |
| 707 | sysfs_show_32bit_prop(buffer, "device_id", | 705 | sysfs_show_32bit_prop(buffer, "device_id", |
| @@ -715,6 +713,12 @@ static ssize_t node_show(struct kobject *kobj, struct attribute *attr, | |||
| 715 | dev->gpu->kgd)); | 713 | dev->gpu->kgd)); |
| 716 | sysfs_show_64bit_prop(buffer, "local_mem_size", | 714 | sysfs_show_64bit_prop(buffer, "local_mem_size", |
| 717 | kfd2kgd->get_vmem_size(dev->gpu->kgd)); | 715 | kfd2kgd->get_vmem_size(dev->gpu->kgd)); |
| 716 | |||
| 717 | sysfs_show_32bit_prop(buffer, "fw_version", | ||
| 718 | kfd2kgd->get_fw_version( | ||
| 719 | dev->gpu->kgd, | ||
| 720 | KGD_ENGINE_MEC1)); | ||
| 721 | |||
| 718 | } | 722 | } |
| 719 | 723 | ||
| 720 | ret = sysfs_show_32bit_prop(buffer, "max_engine_clk_ccompute", | 724 | ret = sysfs_show_32bit_prop(buffer, "max_engine_clk_ccompute", |
diff --git a/drivers/gpu/drm/amd/include/kgd_kfd_interface.h b/drivers/gpu/drm/amd/include/kgd_kfd_interface.h index 9c729dd8dd50..47b551970a14 100644 --- a/drivers/gpu/drm/amd/include/kgd_kfd_interface.h +++ b/drivers/gpu/drm/amd/include/kgd_kfd_interface.h | |||
| @@ -45,6 +45,17 @@ enum kgd_memory_pool { | |||
| 45 | KGD_POOL_FRAMEBUFFER = 3, | 45 | KGD_POOL_FRAMEBUFFER = 3, |
| 46 | }; | 46 | }; |
| 47 | 47 | ||
| 48 | enum kgd_engine_type { | ||
| 49 | KGD_ENGINE_PFP = 1, | ||
| 50 | KGD_ENGINE_ME, | ||
| 51 | KGD_ENGINE_CE, | ||
| 52 | KGD_ENGINE_MEC1, | ||
| 53 | KGD_ENGINE_MEC2, | ||
| 54 | KGD_ENGINE_RLC, | ||
| 55 | KGD_ENGINE_SDMA, | ||
| 56 | KGD_ENGINE_MAX | ||
| 57 | }; | ||
| 58 | |||
| 48 | struct kgd2kfd_shared_resources { | 59 | struct kgd2kfd_shared_resources { |
| 49 | /* Bit n == 1 means VMID n is available for KFD. */ | 60 | /* Bit n == 1 means VMID n is available for KFD. */ |
| 50 | unsigned int compute_vmid_bitmap; | 61 | unsigned int compute_vmid_bitmap; |
| @@ -137,6 +148,8 @@ struct kgd2kfd_calls { | |||
| 137 | * | 148 | * |
| 138 | * @hqd_destroy: Destructs and preempts the queue assigned to that hqd slot. | 149 | * @hqd_destroy: Destructs and preempts the queue assigned to that hqd slot. |
| 139 | * | 150 | * |
| 151 | * @get_fw_version: Returns FW versions from the header | ||
| 152 | * | ||
| 140 | * This structure contains function pointers to services that the kgd driver | 153 | * This structure contains function pointers to services that the kgd driver |
| 141 | * provides to amdkfd driver. | 154 | * provides to amdkfd driver. |
| 142 | * | 155 | * |
| @@ -176,6 +189,8 @@ struct kfd2kgd_calls { | |||
| 176 | int (*hqd_destroy)(struct kgd_dev *kgd, uint32_t reset_type, | 189 | int (*hqd_destroy)(struct kgd_dev *kgd, uint32_t reset_type, |
| 177 | unsigned int timeout, uint32_t pipe_id, | 190 | unsigned int timeout, uint32_t pipe_id, |
| 178 | uint32_t queue_id); | 191 | uint32_t queue_id); |
| 192 | uint16_t (*get_fw_version)(struct kgd_dev *kgd, | ||
| 193 | enum kgd_engine_type type); | ||
| 179 | }; | 194 | }; |
| 180 | 195 | ||
| 181 | bool kgd2kfd_init(unsigned interface_version, | 196 | bool kgd2kfd_init(unsigned interface_version, |
diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c index 4a78a773151c..bbdbe4721573 100644 --- a/drivers/gpu/drm/drm_atomic_helper.c +++ b/drivers/gpu/drm/drm_atomic_helper.c | |||
| @@ -61,7 +61,7 @@ drm_atomic_helper_plane_changed(struct drm_atomic_state *state, | |||
| 61 | struct drm_crtc_state *crtc_state; | 61 | struct drm_crtc_state *crtc_state; |
| 62 | 62 | ||
| 63 | if (plane->state->crtc) { | 63 | if (plane->state->crtc) { |
| 64 | crtc_state = state->crtc_states[drm_crtc_index(plane->crtc)]; | 64 | crtc_state = state->crtc_states[drm_crtc_index(plane->state->crtc)]; |
| 65 | 65 | ||
| 66 | if (WARN_ON(!crtc_state)) | 66 | if (WARN_ON(!crtc_state)) |
| 67 | return; | 67 | return; |
diff --git a/drivers/gpu/drm/drm_irq.c b/drivers/gpu/drm/drm_irq.c index f5a5f18efa5b..4d79dad9d44f 100644 --- a/drivers/gpu/drm/drm_irq.c +++ b/drivers/gpu/drm/drm_irq.c | |||
| @@ -830,6 +830,8 @@ drm_get_last_vbltimestamp(struct drm_device *dev, int crtc, | |||
| 830 | * vblank events since the system was booted, including lost events due to | 830 | * vblank events since the system was booted, including lost events due to |
| 831 | * modesetting activity. | 831 | * modesetting activity. |
| 832 | * | 832 | * |
| 833 | * This is the legacy version of drm_crtc_vblank_count(). | ||
| 834 | * | ||
| 833 | * Returns: | 835 | * Returns: |
| 834 | * The software vblank counter. | 836 | * The software vblank counter. |
| 835 | */ | 837 | */ |
| @@ -844,6 +846,25 @@ u32 drm_vblank_count(struct drm_device *dev, int crtc) | |||
| 844 | EXPORT_SYMBOL(drm_vblank_count); | 846 | EXPORT_SYMBOL(drm_vblank_count); |
| 845 | 847 | ||
| 846 | /** | 848 | /** |
| 849 | * drm_crtc_vblank_count - retrieve "cooked" vblank counter value | ||
| 850 | * @crtc: which counter to retrieve | ||
| 851 | * | ||
| 852 | * Fetches the "cooked" vblank count value that represents the number of | ||
| 853 | * vblank events since the system was booted, including lost events due to | ||
| 854 | * modesetting activity. | ||
| 855 | * | ||
| 856 | * This is the native KMS version of drm_vblank_count(). | ||
| 857 | * | ||
| 858 | * Returns: | ||
| 859 | * The software vblank counter. | ||
| 860 | */ | ||
| 861 | u32 drm_crtc_vblank_count(struct drm_crtc *crtc) | ||
| 862 | { | ||
| 863 | return drm_vblank_count(crtc->dev, drm_crtc_index(crtc)); | ||
| 864 | } | ||
| 865 | EXPORT_SYMBOL(drm_crtc_vblank_count); | ||
| 866 | |||
| 867 | /** | ||
| 847 | * drm_vblank_count_and_time - retrieve "cooked" vblank counter value | 868 | * drm_vblank_count_and_time - retrieve "cooked" vblank counter value |
| 848 | * and the system timestamp corresponding to that vblank counter value. | 869 | * and the system timestamp corresponding to that vblank counter value. |
| 849 | * | 870 | * |
| @@ -904,6 +925,8 @@ static void send_vblank_event(struct drm_device *dev, | |||
| 904 | * | 925 | * |
| 905 | * Updates sequence # and timestamp on event, and sends it to userspace. | 926 | * Updates sequence # and timestamp on event, and sends it to userspace. |
| 906 | * Caller must hold event lock. | 927 | * Caller must hold event lock. |
| 928 | * | ||
| 929 | * This is the legacy version of drm_crtc_send_vblank_event(). | ||
| 907 | */ | 930 | */ |
| 908 | void drm_send_vblank_event(struct drm_device *dev, int crtc, | 931 | void drm_send_vblank_event(struct drm_device *dev, int crtc, |
| 909 | struct drm_pending_vblank_event *e) | 932 | struct drm_pending_vblank_event *e) |
| @@ -923,6 +946,23 @@ void drm_send_vblank_event(struct drm_device *dev, int crtc, | |||
| 923 | EXPORT_SYMBOL(drm_send_vblank_event); | 946 | EXPORT_SYMBOL(drm_send_vblank_event); |
| 924 | 947 | ||
| 925 | /** | 948 | /** |
| 949 | * drm_crtc_send_vblank_event - helper to send vblank event after pageflip | ||
| 950 | * @crtc: the source CRTC of the vblank event | ||
| 951 | * @e: the event to send | ||
| 952 | * | ||
| 953 | * Updates sequence # and timestamp on event, and sends it to userspace. | ||
| 954 | * Caller must hold event lock. | ||
| 955 | * | ||
| 956 | * This is the native KMS version of drm_send_vblank_event(). | ||
| 957 | */ | ||
| 958 | void drm_crtc_send_vblank_event(struct drm_crtc *crtc, | ||
| 959 | struct drm_pending_vblank_event *e) | ||
| 960 | { | ||
| 961 | drm_send_vblank_event(crtc->dev, drm_crtc_index(crtc), e); | ||
| 962 | } | ||
| 963 | EXPORT_SYMBOL(drm_crtc_send_vblank_event); | ||
| 964 | |||
| 965 | /** | ||
| 926 | * drm_vblank_enable - enable the vblank interrupt on a CRTC | 966 | * drm_vblank_enable - enable the vblank interrupt on a CRTC |
| 927 | * @dev: DRM device | 967 | * @dev: DRM device |
| 928 | * @crtc: CRTC in question | 968 | * @crtc: CRTC in question |
| @@ -1594,6 +1634,8 @@ static void drm_handle_vblank_events(struct drm_device *dev, int crtc) | |||
| 1594 | * | 1634 | * |
| 1595 | * Drivers should call this routine in their vblank interrupt handlers to | 1635 | * Drivers should call this routine in their vblank interrupt handlers to |
| 1596 | * update the vblank counter and send any signals that may be pending. | 1636 | * update the vblank counter and send any signals that may be pending. |
| 1637 | * | ||
| 1638 | * This is the legacy version of drm_crtc_handle_vblank(). | ||
| 1597 | */ | 1639 | */ |
| 1598 | bool drm_handle_vblank(struct drm_device *dev, int crtc) | 1640 | bool drm_handle_vblank(struct drm_device *dev, int crtc) |
| 1599 | { | 1641 | { |
| @@ -1670,3 +1712,21 @@ bool drm_handle_vblank(struct drm_device *dev, int crtc) | |||
| 1670 | return true; | 1712 | return true; |
| 1671 | } | 1713 | } |
| 1672 | EXPORT_SYMBOL(drm_handle_vblank); | 1714 | EXPORT_SYMBOL(drm_handle_vblank); |
| 1715 | |||
| 1716 | /** | ||
| 1717 | * drm_crtc_handle_vblank - handle a vblank event | ||
| 1718 | * @crtc: where this event occurred | ||
| 1719 | * | ||
| 1720 | * Drivers should call this routine in their vblank interrupt handlers to | ||
| 1721 | * update the vblank counter and send any signals that may be pending. | ||
| 1722 | * | ||
| 1723 | * This is the native KMS version of drm_handle_vblank(). | ||
| 1724 | * | ||
| 1725 | * Returns: | ||
| 1726 | * True if the event was successfully handled, false on failure. | ||
| 1727 | */ | ||
| 1728 | bool drm_crtc_handle_vblank(struct drm_crtc *crtc) | ||
| 1729 | { | ||
| 1730 | return drm_handle_vblank(crtc->dev, drm_crtc_index(crtc)); | ||
| 1731 | } | ||
| 1732 | EXPORT_SYMBOL(drm_crtc_handle_vblank); | ||
diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index f990ab4c3efb..574057cd1d09 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c | |||
| @@ -811,6 +811,8 @@ int i915_reset(struct drm_device *dev) | |||
| 811 | if (!i915.reset) | 811 | if (!i915.reset) |
| 812 | return 0; | 812 | return 0; |
| 813 | 813 | ||
| 814 | intel_reset_gt_powersave(dev); | ||
| 815 | |||
| 814 | mutex_lock(&dev->struct_mutex); | 816 | mutex_lock(&dev->struct_mutex); |
| 815 | 817 | ||
| 816 | i915_gem_reset(dev); | 818 | i915_gem_reset(dev); |
| @@ -880,7 +882,7 @@ int i915_reset(struct drm_device *dev) | |||
| 880 | * of re-init after reset. | 882 | * of re-init after reset. |
| 881 | */ | 883 | */ |
| 882 | if (INTEL_INFO(dev)->gen > 5) | 884 | if (INTEL_INFO(dev)->gen > 5) |
| 883 | intel_reset_gt_powersave(dev); | 885 | intel_enable_gt_powersave(dev); |
| 884 | } else { | 886 | } else { |
| 885 | mutex_unlock(&dev->struct_mutex); | 887 | mutex_unlock(&dev->struct_mutex); |
| 886 | } | 888 | } |
| @@ -1584,7 +1586,7 @@ static struct drm_driver driver = { | |||
| 1584 | .gem_prime_import = i915_gem_prime_import, | 1586 | .gem_prime_import = i915_gem_prime_import, |
| 1585 | 1587 | ||
| 1586 | .dumb_create = i915_gem_dumb_create, | 1588 | .dumb_create = i915_gem_dumb_create, |
| 1587 | .dumb_map_offset = i915_gem_dumb_map_offset, | 1589 | .dumb_map_offset = i915_gem_mmap_gtt, |
| 1588 | .dumb_destroy = drm_gem_dumb_destroy, | 1590 | .dumb_destroy = drm_gem_dumb_destroy, |
| 1589 | .ioctls = i915_ioctls, | 1591 | .ioctls = i915_ioctls, |
| 1590 | .fops = &i915_driver_fops, | 1592 | .fops = &i915_driver_fops, |
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 63bcda5541ec..70d0f0f06f1a 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h | |||
| @@ -2501,9 +2501,8 @@ void i915_vma_move_to_active(struct i915_vma *vma, | |||
| 2501 | int i915_gem_dumb_create(struct drm_file *file_priv, | 2501 | int i915_gem_dumb_create(struct drm_file *file_priv, |
| 2502 | struct drm_device *dev, | 2502 | struct drm_device *dev, |
| 2503 | struct drm_mode_create_dumb *args); | 2503 | struct drm_mode_create_dumb *args); |
| 2504 | int i915_gem_dumb_map_offset(struct drm_file *file_priv, | 2504 | int i915_gem_mmap_gtt(struct drm_file *file_priv, struct drm_device *dev, |
| 2505 | struct drm_device *dev, uint32_t handle, | 2505 | uint32_t handle, uint64_t *offset); |
| 2506 | uint64_t *offset); | ||
| 2507 | /** | 2506 | /** |
| 2508 | * Returns true if seq1 is later than seq2. | 2507 | * Returns true if seq1 is later than seq2. |
| 2509 | */ | 2508 | */ |
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 4a9faea626db..52adcb680be3 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c | |||
| @@ -401,7 +401,6 @@ static int | |||
| 401 | i915_gem_create(struct drm_file *file, | 401 | i915_gem_create(struct drm_file *file, |
| 402 | struct drm_device *dev, | 402 | struct drm_device *dev, |
| 403 | uint64_t size, | 403 | uint64_t size, |
| 404 | bool dumb, | ||
| 405 | uint32_t *handle_p) | 404 | uint32_t *handle_p) |
| 406 | { | 405 | { |
| 407 | struct drm_i915_gem_object *obj; | 406 | struct drm_i915_gem_object *obj; |
| @@ -417,7 +416,6 @@ i915_gem_create(struct drm_file *file, | |||
| 417 | if (obj == NULL) | 416 | if (obj == NULL) |
| 418 | return -ENOMEM; | 417 | return -ENOMEM; |
| 419 | 418 | ||
| 420 | obj->base.dumb = dumb; | ||
| 421 | ret = drm_gem_handle_create(file, &obj->base, &handle); | 419 | ret = drm_gem_handle_create(file, &obj->base, &handle); |
| 422 | /* drop reference from allocate - handle holds it now */ | 420 | /* drop reference from allocate - handle holds it now */ |
| 423 | drm_gem_object_unreference_unlocked(&obj->base); | 421 | drm_gem_object_unreference_unlocked(&obj->base); |
| @@ -437,7 +435,7 @@ i915_gem_dumb_create(struct drm_file *file, | |||
| 437 | args->pitch = ALIGN(args->width * DIV_ROUND_UP(args->bpp, 8), 64); | 435 | args->pitch = ALIGN(args->width * DIV_ROUND_UP(args->bpp, 8), 64); |
| 438 | args->size = args->pitch * args->height; | 436 | args->size = args->pitch * args->height; |
| 439 | return i915_gem_create(file, dev, | 437 | return i915_gem_create(file, dev, |
| 440 | args->size, true, &args->handle); | 438 | args->size, &args->handle); |
| 441 | } | 439 | } |
| 442 | 440 | ||
| 443 | /** | 441 | /** |
| @@ -450,7 +448,7 @@ i915_gem_create_ioctl(struct drm_device *dev, void *data, | |||
| 450 | struct drm_i915_gem_create *args = data; | 448 | struct drm_i915_gem_create *args = data; |
| 451 | 449 | ||
| 452 | return i915_gem_create(file, dev, | 450 | return i915_gem_create(file, dev, |
| 453 | args->size, false, &args->handle); | 451 | args->size, &args->handle); |
| 454 | } | 452 | } |
| 455 | 453 | ||
| 456 | static inline int | 454 | static inline int |
| @@ -1840,10 +1838,10 @@ static void i915_gem_object_free_mmap_offset(struct drm_i915_gem_object *obj) | |||
| 1840 | drm_gem_free_mmap_offset(&obj->base); | 1838 | drm_gem_free_mmap_offset(&obj->base); |
| 1841 | } | 1839 | } |
| 1842 | 1840 | ||
| 1843 | static int | 1841 | int |
| 1844 | i915_gem_mmap_gtt(struct drm_file *file, | 1842 | i915_gem_mmap_gtt(struct drm_file *file, |
| 1845 | struct drm_device *dev, | 1843 | struct drm_device *dev, |
| 1846 | uint32_t handle, bool dumb, | 1844 | uint32_t handle, |
| 1847 | uint64_t *offset) | 1845 | uint64_t *offset) |
| 1848 | { | 1846 | { |
| 1849 | struct drm_i915_private *dev_priv = dev->dev_private; | 1847 | struct drm_i915_private *dev_priv = dev->dev_private; |
| @@ -1860,13 +1858,6 @@ i915_gem_mmap_gtt(struct drm_file *file, | |||
| 1860 | goto unlock; | 1858 | goto unlock; |
| 1861 | } | 1859 | } |
| 1862 | 1860 | ||
| 1863 | /* | ||
| 1864 | * We don't allow dumb mmaps on objects created using another | ||
| 1865 | * interface. | ||
| 1866 | */ | ||
| 1867 | WARN_ONCE(dumb && !(obj->base.dumb || obj->base.import_attach), | ||
| 1868 | "Illegal dumb map of accelerated buffer.\n"); | ||
| 1869 | |||
| 1870 | if (obj->base.size > dev_priv->gtt.mappable_end) { | 1861 | if (obj->base.size > dev_priv->gtt.mappable_end) { |
| 1871 | ret = -E2BIG; | 1862 | ret = -E2BIG; |
| 1872 | goto out; | 1863 | goto out; |
| @@ -1891,15 +1882,6 @@ unlock: | |||
| 1891 | return ret; | 1882 | return ret; |
| 1892 | } | 1883 | } |
| 1893 | 1884 | ||
| 1894 | int | ||
| 1895 | i915_gem_dumb_map_offset(struct drm_file *file, | ||
| 1896 | struct drm_device *dev, | ||
| 1897 | uint32_t handle, | ||
| 1898 | uint64_t *offset) | ||
| 1899 | { | ||
| 1900 | return i915_gem_mmap_gtt(file, dev, handle, true, offset); | ||
| 1901 | } | ||
| 1902 | |||
| 1903 | /** | 1885 | /** |
| 1904 | * i915_gem_mmap_gtt_ioctl - prepare an object for GTT mmap'ing | 1886 | * i915_gem_mmap_gtt_ioctl - prepare an object for GTT mmap'ing |
| 1905 | * @dev: DRM device | 1887 | * @dev: DRM device |
| @@ -1921,7 +1903,7 @@ i915_gem_mmap_gtt_ioctl(struct drm_device *dev, void *data, | |||
| 1921 | { | 1903 | { |
| 1922 | struct drm_i915_gem_mmap_gtt *args = data; | 1904 | struct drm_i915_gem_mmap_gtt *args = data; |
| 1923 | 1905 | ||
| 1924 | return i915_gem_mmap_gtt(file, dev, args->handle, false, &args->offset); | 1906 | return i915_gem_mmap_gtt(file, dev, args->handle, &args->offset); |
| 1925 | } | 1907 | } |
| 1926 | 1908 | ||
| 1927 | static inline int | 1909 | static inline int |
diff --git a/drivers/gpu/drm/i915/i915_gem_context.c b/drivers/gpu/drm/i915/i915_gem_context.c index d17ff435f276..d011ec82ef1e 100644 --- a/drivers/gpu/drm/i915/i915_gem_context.c +++ b/drivers/gpu/drm/i915/i915_gem_context.c | |||
| @@ -473,7 +473,12 @@ mi_set_context(struct intel_engine_cs *ring, | |||
| 473 | u32 hw_flags) | 473 | u32 hw_flags) |
| 474 | { | 474 | { |
| 475 | u32 flags = hw_flags | MI_MM_SPACE_GTT; | 475 | u32 flags = hw_flags | MI_MM_SPACE_GTT; |
| 476 | int ret; | 476 | const int num_rings = |
| 477 | /* Use an extended w/a on ivb+ if signalling from other rings */ | ||
| 478 | i915_semaphore_is_enabled(ring->dev) ? | ||
| 479 | hweight32(INTEL_INFO(ring->dev)->ring_mask) - 1 : | ||
| 480 | 0; | ||
| 481 | int len, i, ret; | ||
| 477 | 482 | ||
| 478 | /* w/a: If Flush TLB Invalidation Mode is enabled, driver must do a TLB | 483 | /* w/a: If Flush TLB Invalidation Mode is enabled, driver must do a TLB |
| 479 | * invalidation prior to MI_SET_CONTEXT. On GEN6 we don't set the value | 484 | * invalidation prior to MI_SET_CONTEXT. On GEN6 we don't set the value |
| @@ -490,15 +495,31 @@ mi_set_context(struct intel_engine_cs *ring, | |||
| 490 | if (!IS_HASWELL(ring->dev) && INTEL_INFO(ring->dev)->gen < 8) | 495 | if (!IS_HASWELL(ring->dev) && INTEL_INFO(ring->dev)->gen < 8) |
| 491 | flags |= (MI_SAVE_EXT_STATE_EN | MI_RESTORE_EXT_STATE_EN); | 496 | flags |= (MI_SAVE_EXT_STATE_EN | MI_RESTORE_EXT_STATE_EN); |
| 492 | 497 | ||
| 493 | ret = intel_ring_begin(ring, 6); | 498 | |
| 499 | len = 4; | ||
| 500 | if (INTEL_INFO(ring->dev)->gen >= 7) | ||
| 501 | len += 2 + (num_rings ? 4*num_rings + 2 : 0); | ||
| 502 | |||
| 503 | ret = intel_ring_begin(ring, len); | ||
| 494 | if (ret) | 504 | if (ret) |
| 495 | return ret; | 505 | return ret; |
| 496 | 506 | ||
| 497 | /* WaProgramMiArbOnOffAroundMiSetContext:ivb,vlv,hsw,bdw,chv */ | 507 | /* WaProgramMiArbOnOffAroundMiSetContext:ivb,vlv,hsw,bdw,chv */ |
| 498 | if (INTEL_INFO(ring->dev)->gen >= 7) | 508 | if (INTEL_INFO(ring->dev)->gen >= 7) { |
| 499 | intel_ring_emit(ring, MI_ARB_ON_OFF | MI_ARB_DISABLE); | 509 | intel_ring_emit(ring, MI_ARB_ON_OFF | MI_ARB_DISABLE); |
| 500 | else | 510 | if (num_rings) { |
| 501 | intel_ring_emit(ring, MI_NOOP); | 511 | struct intel_engine_cs *signaller; |
| 512 | |||
| 513 | intel_ring_emit(ring, MI_LOAD_REGISTER_IMM(num_rings)); | ||
| 514 | for_each_ring(signaller, to_i915(ring->dev), i) { | ||
| 515 | if (signaller == ring) | ||
| 516 | continue; | ||
| 517 | |||
| 518 | intel_ring_emit(ring, RING_PSMI_CTL(signaller->mmio_base)); | ||
| 519 | intel_ring_emit(ring, _MASKED_BIT_ENABLE(GEN6_PSMI_SLEEP_MSG_DISABLE)); | ||
| 520 | } | ||
| 521 | } | ||
| 522 | } | ||
| 502 | 523 | ||
| 503 | intel_ring_emit(ring, MI_NOOP); | 524 | intel_ring_emit(ring, MI_NOOP); |
| 504 | intel_ring_emit(ring, MI_SET_CONTEXT); | 525 | intel_ring_emit(ring, MI_SET_CONTEXT); |
| @@ -510,10 +531,21 @@ mi_set_context(struct intel_engine_cs *ring, | |||
| 510 | */ | 531 | */ |
| 511 | intel_ring_emit(ring, MI_NOOP); | 532 | intel_ring_emit(ring, MI_NOOP); |
| 512 | 533 | ||
| 513 | if (INTEL_INFO(ring->dev)->gen >= 7) | 534 | if (INTEL_INFO(ring->dev)->gen >= 7) { |
| 535 | if (num_rings) { | ||
| 536 | struct intel_engine_cs *signaller; | ||
| 537 | |||
| 538 | intel_ring_emit(ring, MI_LOAD_REGISTER_IMM(num_rings)); | ||
| 539 | for_each_ring(signaller, to_i915(ring->dev), i) { | ||
| 540 | if (signaller == ring) | ||
| 541 | continue; | ||
| 542 | |||
| 543 | intel_ring_emit(ring, RING_PSMI_CTL(signaller->mmio_base)); | ||
| 544 | intel_ring_emit(ring, _MASKED_BIT_DISABLE(GEN6_PSMI_SLEEP_MSG_DISABLE)); | ||
| 545 | } | ||
| 546 | } | ||
| 514 | intel_ring_emit(ring, MI_ARB_ON_OFF | MI_ARB_ENABLE); | 547 | intel_ring_emit(ring, MI_ARB_ON_OFF | MI_ARB_ENABLE); |
| 515 | else | 548 | } |
| 516 | intel_ring_emit(ring, MI_NOOP); | ||
| 517 | 549 | ||
| 518 | intel_ring_advance(ring); | 550 | intel_ring_advance(ring); |
| 519 | 551 | ||
diff --git a/drivers/gpu/drm/i915/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/i915_gem_execbuffer.c index f06027ba3ee5..11738316394a 100644 --- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c +++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c | |||
| @@ -121,9 +121,6 @@ eb_lookup_vmas(struct eb_vmas *eb, | |||
| 121 | goto err; | 121 | goto err; |
| 122 | } | 122 | } |
| 123 | 123 | ||
| 124 | WARN_ONCE(obj->base.dumb, | ||
| 125 | "GPU use of dumb buffer is illegal.\n"); | ||
| 126 | |||
| 127 | drm_gem_object_reference(&obj->base); | 124 | drm_gem_object_reference(&obj->base); |
| 128 | list_add_tail(&obj->obj_exec_link, &objects); | 125 | list_add_tail(&obj->obj_exec_link, &objects); |
| 129 | } | 126 | } |
diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index 981834b0f9b6..996c2931c499 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c | |||
| @@ -281,10 +281,14 @@ void gen6_enable_rps_interrupts(struct drm_device *dev) | |||
| 281 | struct drm_i915_private *dev_priv = dev->dev_private; | 281 | struct drm_i915_private *dev_priv = dev->dev_private; |
| 282 | 282 | ||
| 283 | spin_lock_irq(&dev_priv->irq_lock); | 283 | spin_lock_irq(&dev_priv->irq_lock); |
| 284 | |||
| 284 | WARN_ON(dev_priv->rps.pm_iir); | 285 | WARN_ON(dev_priv->rps.pm_iir); |
| 285 | WARN_ON(I915_READ(gen6_pm_iir(dev_priv)) & dev_priv->pm_rps_events); | 286 | WARN_ON(I915_READ(gen6_pm_iir(dev_priv)) & dev_priv->pm_rps_events); |
| 286 | dev_priv->rps.interrupts_enabled = true; | 287 | dev_priv->rps.interrupts_enabled = true; |
| 288 | I915_WRITE(gen6_pm_ier(dev_priv), I915_READ(gen6_pm_ier(dev_priv)) | | ||
| 289 | dev_priv->pm_rps_events); | ||
| 287 | gen6_enable_pm_irq(dev_priv, dev_priv->pm_rps_events); | 290 | gen6_enable_pm_irq(dev_priv, dev_priv->pm_rps_events); |
| 291 | |||
| 288 | spin_unlock_irq(&dev_priv->irq_lock); | 292 | spin_unlock_irq(&dev_priv->irq_lock); |
| 289 | } | 293 | } |
| 290 | 294 | ||
| @@ -3307,8 +3311,10 @@ static void gen5_gt_irq_postinstall(struct drm_device *dev) | |||
| 3307 | GEN5_IRQ_INIT(GT, dev_priv->gt_irq_mask, gt_irqs); | 3311 | GEN5_IRQ_INIT(GT, dev_priv->gt_irq_mask, gt_irqs); |
| 3308 | 3312 | ||
| 3309 | if (INTEL_INFO(dev)->gen >= 6) { | 3313 | if (INTEL_INFO(dev)->gen >= 6) { |
| 3310 | pm_irqs |= dev_priv->pm_rps_events; | 3314 | /* |
| 3311 | 3315 | * RPS interrupts will get enabled/disabled on demand when RPS | |
| 3316 | * itself is enabled/disabled. | ||
| 3317 | */ | ||
| 3312 | if (HAS_VEBOX(dev)) | 3318 | if (HAS_VEBOX(dev)) |
| 3313 | pm_irqs |= PM_VEBOX_USER_INTERRUPT; | 3319 | pm_irqs |= PM_VEBOX_USER_INTERRUPT; |
| 3314 | 3320 | ||
| @@ -3520,7 +3526,11 @@ static void gen8_gt_irq_postinstall(struct drm_i915_private *dev_priv) | |||
| 3520 | dev_priv->pm_irq_mask = 0xffffffff; | 3526 | dev_priv->pm_irq_mask = 0xffffffff; |
| 3521 | GEN8_IRQ_INIT_NDX(GT, 0, ~gt_interrupts[0], gt_interrupts[0]); | 3527 | GEN8_IRQ_INIT_NDX(GT, 0, ~gt_interrupts[0], gt_interrupts[0]); |
| 3522 | GEN8_IRQ_INIT_NDX(GT, 1, ~gt_interrupts[1], gt_interrupts[1]); | 3528 | GEN8_IRQ_INIT_NDX(GT, 1, ~gt_interrupts[1], gt_interrupts[1]); |
| 3523 | GEN8_IRQ_INIT_NDX(GT, 2, dev_priv->pm_irq_mask, dev_priv->pm_rps_events); | 3529 | /* |
| 3530 | * RPS interrupts will get enabled/disabled on demand when RPS itself | ||
| 3531 | * is enabled/disabled. | ||
| 3532 | */ | ||
| 3533 | GEN8_IRQ_INIT_NDX(GT, 2, dev_priv->pm_irq_mask, 0); | ||
| 3524 | GEN8_IRQ_INIT_NDX(GT, 3, ~gt_interrupts[3], gt_interrupts[3]); | 3534 | GEN8_IRQ_INIT_NDX(GT, 3, ~gt_interrupts[3], gt_interrupts[3]); |
| 3525 | } | 3535 | } |
| 3526 | 3536 | ||
| @@ -3609,7 +3619,7 @@ static void vlv_display_irq_uninstall(struct drm_i915_private *dev_priv) | |||
| 3609 | 3619 | ||
| 3610 | vlv_display_irq_reset(dev_priv); | 3620 | vlv_display_irq_reset(dev_priv); |
| 3611 | 3621 | ||
| 3612 | dev_priv->irq_mask = 0; | 3622 | dev_priv->irq_mask = ~0; |
| 3613 | } | 3623 | } |
| 3614 | 3624 | ||
| 3615 | static void valleyview_irq_uninstall(struct drm_device *dev) | 3625 | static void valleyview_irq_uninstall(struct drm_device *dev) |
diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index eefdc238f70b..172de3b3433b 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h | |||
| @@ -395,6 +395,7 @@ | |||
| 395 | #define PIPE_CONTROL_STORE_DATA_INDEX (1<<21) | 395 | #define PIPE_CONTROL_STORE_DATA_INDEX (1<<21) |
| 396 | #define PIPE_CONTROL_CS_STALL (1<<20) | 396 | #define PIPE_CONTROL_CS_STALL (1<<20) |
| 397 | #define PIPE_CONTROL_TLB_INVALIDATE (1<<18) | 397 | #define PIPE_CONTROL_TLB_INVALIDATE (1<<18) |
| 398 | #define PIPE_CONTROL_MEDIA_STATE_CLEAR (1<<16) | ||
| 398 | #define PIPE_CONTROL_QW_WRITE (1<<14) | 399 | #define PIPE_CONTROL_QW_WRITE (1<<14) |
| 399 | #define PIPE_CONTROL_POST_SYNC_OP_MASK (3<<14) | 400 | #define PIPE_CONTROL_POST_SYNC_OP_MASK (3<<14) |
| 400 | #define PIPE_CONTROL_DEPTH_STALL (1<<13) | 401 | #define PIPE_CONTROL_DEPTH_STALL (1<<13) |
| @@ -1128,6 +1129,7 @@ enum punit_power_well { | |||
| 1128 | #define GEN6_VERSYNC (RING_SYNC_1(VEBOX_RING_BASE)) | 1129 | #define GEN6_VERSYNC (RING_SYNC_1(VEBOX_RING_BASE)) |
| 1129 | #define GEN6_VEVSYNC (RING_SYNC_2(VEBOX_RING_BASE)) | 1130 | #define GEN6_VEVSYNC (RING_SYNC_2(VEBOX_RING_BASE)) |
| 1130 | #define GEN6_NOSYNC 0 | 1131 | #define GEN6_NOSYNC 0 |
| 1132 | #define RING_PSMI_CTL(base) ((base)+0x50) | ||
| 1131 | #define RING_MAX_IDLE(base) ((base)+0x54) | 1133 | #define RING_MAX_IDLE(base) ((base)+0x54) |
| 1132 | #define RING_HWS_PGA(base) ((base)+0x80) | 1134 | #define RING_HWS_PGA(base) ((base)+0x80) |
| 1133 | #define RING_HWS_PGA_GEN6(base) ((base)+0x2080) | 1135 | #define RING_HWS_PGA_GEN6(base) ((base)+0x2080) |
| @@ -1458,6 +1460,7 @@ enum punit_power_well { | |||
| 1458 | #define GEN6_BLITTER_FBC_NOTIFY (1<<3) | 1460 | #define GEN6_BLITTER_FBC_NOTIFY (1<<3) |
| 1459 | 1461 | ||
| 1460 | #define GEN6_RC_SLEEP_PSMI_CONTROL 0x2050 | 1462 | #define GEN6_RC_SLEEP_PSMI_CONTROL 0x2050 |
| 1463 | #define GEN6_PSMI_SLEEP_MSG_DISABLE (1 << 0) | ||
| 1461 | #define GEN8_RC_SEMA_IDLE_MSG_DISABLE (1 << 12) | 1464 | #define GEN8_RC_SEMA_IDLE_MSG_DISABLE (1 << 12) |
| 1462 | #define GEN8_FF_DOP_CLOCK_GATE_DISABLE (1<<10) | 1465 | #define GEN8_FF_DOP_CLOCK_GATE_DISABLE (1<<10) |
| 1463 | 1466 | ||
diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 1f4b56e273c8..964b28e3c630 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c | |||
| @@ -6191,6 +6191,20 @@ void intel_cleanup_gt_powersave(struct drm_device *dev) | |||
| 6191 | valleyview_cleanup_gt_powersave(dev); | 6191 | valleyview_cleanup_gt_powersave(dev); |
| 6192 | } | 6192 | } |
| 6193 | 6193 | ||
| 6194 | static void gen6_suspend_rps(struct drm_device *dev) | ||
| 6195 | { | ||
| 6196 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
| 6197 | |||
| 6198 | flush_delayed_work(&dev_priv->rps.delayed_resume_work); | ||
| 6199 | |||
| 6200 | /* | ||
| 6201 | * TODO: disable RPS interrupts on GEN9+ too once RPS support | ||
| 6202 | * is added for it. | ||
| 6203 | */ | ||
| 6204 | if (INTEL_INFO(dev)->gen < 9) | ||
| 6205 | gen6_disable_rps_interrupts(dev); | ||
| 6206 | } | ||
| 6207 | |||
| 6194 | /** | 6208 | /** |
| 6195 | * intel_suspend_gt_powersave - suspend PM work and helper threads | 6209 | * intel_suspend_gt_powersave - suspend PM work and helper threads |
| 6196 | * @dev: drm device | 6210 | * @dev: drm device |
| @@ -6206,14 +6220,7 @@ void intel_suspend_gt_powersave(struct drm_device *dev) | |||
| 6206 | if (INTEL_INFO(dev)->gen < 6) | 6220 | if (INTEL_INFO(dev)->gen < 6) |
| 6207 | return; | 6221 | return; |
| 6208 | 6222 | ||
| 6209 | flush_delayed_work(&dev_priv->rps.delayed_resume_work); | 6223 | gen6_suspend_rps(dev); |
| 6210 | |||
| 6211 | /* | ||
| 6212 | * TODO: disable RPS interrupts on GEN9+ too once RPS support | ||
| 6213 | * is added for it. | ||
| 6214 | */ | ||
| 6215 | if (INTEL_INFO(dev)->gen < 9) | ||
| 6216 | gen6_disable_rps_interrupts(dev); | ||
| 6217 | 6224 | ||
| 6218 | /* Force GPU to min freq during suspend */ | 6225 | /* Force GPU to min freq during suspend */ |
| 6219 | gen6_rps_idle(dev_priv); | 6226 | gen6_rps_idle(dev_priv); |
| @@ -6316,8 +6323,11 @@ void intel_reset_gt_powersave(struct drm_device *dev) | |||
| 6316 | { | 6323 | { |
| 6317 | struct drm_i915_private *dev_priv = dev->dev_private; | 6324 | struct drm_i915_private *dev_priv = dev->dev_private; |
| 6318 | 6325 | ||
| 6326 | if (INTEL_INFO(dev)->gen < 6) | ||
| 6327 | return; | ||
| 6328 | |||
| 6329 | gen6_suspend_rps(dev); | ||
| 6319 | dev_priv->rps.enabled = false; | 6330 | dev_priv->rps.enabled = false; |
| 6320 | intel_enable_gt_powersave(dev); | ||
| 6321 | } | 6331 | } |
| 6322 | 6332 | ||
| 6323 | static void ibx_init_clock_gating(struct drm_device *dev) | 6333 | static void ibx_init_clock_gating(struct drm_device *dev) |
diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c index 9f445e9a75d1..c7bc93d28d84 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.c +++ b/drivers/gpu/drm/i915/intel_ringbuffer.c | |||
| @@ -362,12 +362,15 @@ gen7_render_ring_flush(struct intel_engine_cs *ring, | |||
| 362 | flags |= PIPE_CONTROL_VF_CACHE_INVALIDATE; | 362 | flags |= PIPE_CONTROL_VF_CACHE_INVALIDATE; |
| 363 | flags |= PIPE_CONTROL_CONST_CACHE_INVALIDATE; | 363 | flags |= PIPE_CONTROL_CONST_CACHE_INVALIDATE; |
| 364 | flags |= PIPE_CONTROL_STATE_CACHE_INVALIDATE; | 364 | flags |= PIPE_CONTROL_STATE_CACHE_INVALIDATE; |
| 365 | flags |= PIPE_CONTROL_MEDIA_STATE_CLEAR; | ||
| 365 | /* | 366 | /* |
| 366 | * TLB invalidate requires a post-sync write. | 367 | * TLB invalidate requires a post-sync write. |
| 367 | */ | 368 | */ |
| 368 | flags |= PIPE_CONTROL_QW_WRITE; | 369 | flags |= PIPE_CONTROL_QW_WRITE; |
| 369 | flags |= PIPE_CONTROL_GLOBAL_GTT_IVB; | 370 | flags |= PIPE_CONTROL_GLOBAL_GTT_IVB; |
| 370 | 371 | ||
| 372 | flags |= PIPE_CONTROL_STALL_AT_SCOREBOARD; | ||
| 373 | |||
| 371 | /* Workaround: we must issue a pipe_control with CS-stall bit | 374 | /* Workaround: we must issue a pipe_control with CS-stall bit |
| 372 | * set before a pipe_control command that has the state cache | 375 | * set before a pipe_control command that has the state cache |
| 373 | * invalidate bit set. */ | 376 | * invalidate bit set. */ |
diff --git a/drivers/gpu/drm/msm/adreno/adreno_gpu.c b/drivers/gpu/drm/msm/adreno/adreno_gpu.c index aa873048308b..94a5bee69fe7 100644 --- a/drivers/gpu/drm/msm/adreno/adreno_gpu.c +++ b/drivers/gpu/drm/msm/adreno/adreno_gpu.c | |||
| @@ -386,9 +386,7 @@ void adreno_gpu_cleanup(struct adreno_gpu *gpu) | |||
| 386 | msm_gem_put_iova(gpu->memptrs_bo, gpu->base.id); | 386 | msm_gem_put_iova(gpu->memptrs_bo, gpu->base.id); |
| 387 | drm_gem_object_unreference(gpu->memptrs_bo); | 387 | drm_gem_object_unreference(gpu->memptrs_bo); |
| 388 | } | 388 | } |
| 389 | if (gpu->pm4) | 389 | release_firmware(gpu->pm4); |
| 390 | release_firmware(gpu->pm4); | 390 | release_firmware(gpu->pfp); |
| 391 | if (gpu->pfp) | ||
| 392 | release_firmware(gpu->pfp); | ||
| 393 | msm_gpu_cleanup(&gpu->base); | 391 | msm_gpu_cleanup(&gpu->base); |
| 394 | } | 392 | } |
diff --git a/drivers/gpu/drm/msm/hdmi/hdmi_connector.c b/drivers/gpu/drm/msm/hdmi/hdmi_connector.c index fbebb0405d76..b4e70e0e3cfa 100644 --- a/drivers/gpu/drm/msm/hdmi/hdmi_connector.c +++ b/drivers/gpu/drm/msm/hdmi/hdmi_connector.c | |||
| @@ -141,6 +141,15 @@ static int hpd_enable(struct hdmi_connector *hdmi_connector) | |||
| 141 | uint32_t hpd_ctrl; | 141 | uint32_t hpd_ctrl; |
| 142 | int i, ret; | 142 | int i, ret; |
| 143 | 143 | ||
| 144 | for (i = 0; i < config->hpd_reg_cnt; i++) { | ||
| 145 | ret = regulator_enable(hdmi->hpd_regs[i]); | ||
| 146 | if (ret) { | ||
| 147 | dev_err(dev->dev, "failed to enable hpd regulator: %s (%d)\n", | ||
| 148 | config->hpd_reg_names[i], ret); | ||
| 149 | goto fail; | ||
| 150 | } | ||
| 151 | } | ||
| 152 | |||
| 144 | ret = gpio_config(hdmi, true); | 153 | ret = gpio_config(hdmi, true); |
| 145 | if (ret) { | 154 | if (ret) { |
| 146 | dev_err(dev->dev, "failed to configure GPIOs: %d\n", ret); | 155 | dev_err(dev->dev, "failed to configure GPIOs: %d\n", ret); |
| @@ -164,15 +173,6 @@ static int hpd_enable(struct hdmi_connector *hdmi_connector) | |||
| 164 | } | 173 | } |
| 165 | } | 174 | } |
| 166 | 175 | ||
| 167 | for (i = 0; i < config->hpd_reg_cnt; i++) { | ||
| 168 | ret = regulator_enable(hdmi->hpd_regs[i]); | ||
| 169 | if (ret) { | ||
| 170 | dev_err(dev->dev, "failed to enable hpd regulator: %s (%d)\n", | ||
| 171 | config->hpd_reg_names[i], ret); | ||
| 172 | goto fail; | ||
| 173 | } | ||
| 174 | } | ||
| 175 | |||
| 176 | hdmi_set_mode(hdmi, false); | 176 | hdmi_set_mode(hdmi, false); |
| 177 | phy->funcs->reset(phy); | 177 | phy->funcs->reset(phy); |
| 178 | hdmi_set_mode(hdmi, true); | 178 | hdmi_set_mode(hdmi, true); |
| @@ -200,7 +200,7 @@ fail: | |||
| 200 | return ret; | 200 | return ret; |
| 201 | } | 201 | } |
| 202 | 202 | ||
| 203 | static int hdp_disable(struct hdmi_connector *hdmi_connector) | 203 | static void hdp_disable(struct hdmi_connector *hdmi_connector) |
| 204 | { | 204 | { |
| 205 | struct hdmi *hdmi = hdmi_connector->hdmi; | 205 | struct hdmi *hdmi = hdmi_connector->hdmi; |
| 206 | const struct hdmi_platform_config *config = hdmi->config; | 206 | const struct hdmi_platform_config *config = hdmi->config; |
| @@ -212,28 +212,19 @@ static int hdp_disable(struct hdmi_connector *hdmi_connector) | |||
| 212 | 212 | ||
| 213 | hdmi_set_mode(hdmi, false); | 213 | hdmi_set_mode(hdmi, false); |
| 214 | 214 | ||
| 215 | for (i = 0; i < config->hpd_reg_cnt; i++) { | ||
| 216 | ret = regulator_disable(hdmi->hpd_regs[i]); | ||
| 217 | if (ret) { | ||
| 218 | dev_err(dev->dev, "failed to disable hpd regulator: %s (%d)\n", | ||
| 219 | config->hpd_reg_names[i], ret); | ||
| 220 | goto fail; | ||
| 221 | } | ||
| 222 | } | ||
| 223 | |||
| 224 | for (i = 0; i < config->hpd_clk_cnt; i++) | 215 | for (i = 0; i < config->hpd_clk_cnt; i++) |
| 225 | clk_disable_unprepare(hdmi->hpd_clks[i]); | 216 | clk_disable_unprepare(hdmi->hpd_clks[i]); |
| 226 | 217 | ||
| 227 | ret = gpio_config(hdmi, false); | 218 | ret = gpio_config(hdmi, false); |
| 228 | if (ret) { | 219 | if (ret) |
| 229 | dev_err(dev->dev, "failed to unconfigure GPIOs: %d\n", ret); | 220 | dev_warn(dev->dev, "failed to unconfigure GPIOs: %d\n", ret); |
| 230 | goto fail; | ||
| 231 | } | ||
| 232 | |||
| 233 | return 0; | ||
| 234 | 221 | ||
| 235 | fail: | 222 | for (i = 0; i < config->hpd_reg_cnt; i++) { |
| 236 | return ret; | 223 | ret = regulator_disable(hdmi->hpd_regs[i]); |
| 224 | if (ret) | ||
| 225 | dev_warn(dev->dev, "failed to disable hpd regulator: %s (%d)\n", | ||
| 226 | config->hpd_reg_names[i], ret); | ||
| 227 | } | ||
| 237 | } | 228 | } |
| 238 | 229 | ||
| 239 | static void | 230 | static void |
| @@ -260,11 +251,11 @@ void hdmi_connector_irq(struct drm_connector *connector) | |||
| 260 | (hpd_int_status & HDMI_HPD_INT_STATUS_INT)) { | 251 | (hpd_int_status & HDMI_HPD_INT_STATUS_INT)) { |
| 261 | bool detected = !!(hpd_int_status & HDMI_HPD_INT_STATUS_CABLE_DETECTED); | 252 | bool detected = !!(hpd_int_status & HDMI_HPD_INT_STATUS_CABLE_DETECTED); |
| 262 | 253 | ||
| 263 | DBG("status=%04x, ctrl=%04x", hpd_int_status, hpd_int_ctrl); | 254 | /* ack & disable (temporarily) HPD events: */ |
| 264 | |||
| 265 | /* ack the irq: */ | ||
| 266 | hdmi_write(hdmi, REG_HDMI_HPD_INT_CTRL, | 255 | hdmi_write(hdmi, REG_HDMI_HPD_INT_CTRL, |
| 267 | hpd_int_ctrl | HDMI_HPD_INT_CTRL_INT_ACK); | 256 | HDMI_HPD_INT_CTRL_INT_ACK); |
| 257 | |||
| 258 | DBG("status=%04x, ctrl=%04x", hpd_int_status, hpd_int_ctrl); | ||
| 268 | 259 | ||
| 269 | /* detect disconnect if we are connected or visa versa: */ | 260 | /* detect disconnect if we are connected or visa versa: */ |
| 270 | hpd_int_ctrl = HDMI_HPD_INT_CTRL_INT_EN; | 261 | hpd_int_ctrl = HDMI_HPD_INT_CTRL_INT_EN; |
diff --git a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_crtc.c b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_crtc.c index a7672e100d8b..3449213f1e76 100644 --- a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_crtc.c +++ b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_crtc.c | |||
| @@ -331,17 +331,8 @@ static int mdp4_crtc_atomic_check(struct drm_crtc *crtc, | |||
| 331 | struct drm_crtc_state *state) | 331 | struct drm_crtc_state *state) |
| 332 | { | 332 | { |
| 333 | struct mdp4_crtc *mdp4_crtc = to_mdp4_crtc(crtc); | 333 | struct mdp4_crtc *mdp4_crtc = to_mdp4_crtc(crtc); |
| 334 | struct drm_device *dev = crtc->dev; | ||
| 335 | |||
| 336 | DBG("%s: check", mdp4_crtc->name); | 334 | DBG("%s: check", mdp4_crtc->name); |
| 337 | |||
| 338 | if (mdp4_crtc->event) { | ||
| 339 | dev_err(dev->dev, "already pending flip!\n"); | ||
| 340 | return -EBUSY; | ||
| 341 | } | ||
| 342 | |||
| 343 | // TODO anything else to check? | 335 | // TODO anything else to check? |
| 344 | |||
| 345 | return 0; | 336 | return 0; |
| 346 | } | 337 | } |
| 347 | 338 | ||
| @@ -357,7 +348,7 @@ static void mdp4_crtc_atomic_flush(struct drm_crtc *crtc) | |||
| 357 | struct drm_device *dev = crtc->dev; | 348 | struct drm_device *dev = crtc->dev; |
| 358 | unsigned long flags; | 349 | unsigned long flags; |
| 359 | 350 | ||
| 360 | DBG("%s: flush", mdp4_crtc->name); | 351 | DBG("%s: event: %p", mdp4_crtc->name, crtc->state->event); |
| 361 | 352 | ||
| 362 | WARN_ON(mdp4_crtc->event); | 353 | WARN_ON(mdp4_crtc->event); |
| 363 | 354 | ||
diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c index 0e9a2e3a82d7..f021f960a8a2 100644 --- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c +++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c | |||
| @@ -303,11 +303,6 @@ static int mdp5_crtc_atomic_check(struct drm_crtc *crtc, | |||
| 303 | 303 | ||
| 304 | DBG("%s: check", mdp5_crtc->name); | 304 | DBG("%s: check", mdp5_crtc->name); |
| 305 | 305 | ||
| 306 | if (mdp5_crtc->event) { | ||
| 307 | dev_err(dev->dev, "already pending flip!\n"); | ||
| 308 | return -EBUSY; | ||
| 309 | } | ||
| 310 | |||
| 311 | /* request a free CTL, if none is already allocated for this CRTC */ | 306 | /* request a free CTL, if none is already allocated for this CRTC */ |
| 312 | if (state->enable && !mdp5_crtc->ctl) { | 307 | if (state->enable && !mdp5_crtc->ctl) { |
| 313 | mdp5_crtc->ctl = mdp5_ctlm_request(mdp5_kms->ctlm, crtc); | 308 | mdp5_crtc->ctl = mdp5_ctlm_request(mdp5_kms->ctlm, crtc); |
| @@ -364,7 +359,7 @@ static void mdp5_crtc_atomic_flush(struct drm_crtc *crtc) | |||
| 364 | struct drm_device *dev = crtc->dev; | 359 | struct drm_device *dev = crtc->dev; |
| 365 | unsigned long flags; | 360 | unsigned long flags; |
| 366 | 361 | ||
| 367 | DBG("%s: flush", mdp5_crtc->name); | 362 | DBG("%s: event: %p", mdp5_crtc->name, crtc->state->event); |
| 368 | 363 | ||
| 369 | WARN_ON(mdp5_crtc->event); | 364 | WARN_ON(mdp5_crtc->event); |
| 370 | 365 | ||
| @@ -460,10 +455,7 @@ void mdp5_crtc_set_intf(struct drm_crtc *crtc, int intf, | |||
| 460 | /* now that we know what irq's we want: */ | 455 | /* now that we know what irq's we want: */ |
| 461 | mdp5_crtc->err.irqmask = intf2err(intf); | 456 | mdp5_crtc->err.irqmask = intf2err(intf); |
| 462 | mdp5_crtc->vblank.irqmask = intf2vblank(intf); | 457 | mdp5_crtc->vblank.irqmask = intf2vblank(intf); |
| 463 | 458 | mdp_irq_update(&mdp5_kms->base); | |
| 464 | /* when called from modeset_init(), skip the rest until later: */ | ||
| 465 | if (!mdp5_kms) | ||
| 466 | return; | ||
| 467 | 459 | ||
| 468 | spin_lock_irqsave(&mdp5_kms->resource_lock, flags); | 460 | spin_lock_irqsave(&mdp5_kms->resource_lock, flags); |
| 469 | intf_sel = mdp5_read(mdp5_kms, REG_MDP5_DISP_INTF_SEL); | 461 | intf_sel = mdp5_read(mdp5_kms, REG_MDP5_DISP_INTF_SEL); |
diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c index a11f1b80c488..9f01a4f21af2 100644 --- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c +++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c | |||
| @@ -216,17 +216,7 @@ static int modeset_init(struct mdp5_kms *mdp5_kms) | |||
| 216 | goto fail; | 216 | goto fail; |
| 217 | } | 217 | } |
| 218 | 218 | ||
| 219 | /* NOTE: the vsync and error irq's are actually associated with | 219 | encoder->possible_crtcs = (1 << priv->num_crtcs) - 1;; |
| 220 | * the INTF/encoder.. the easiest way to deal with this (ie. what | ||
| 221 | * we do now) is assume a fixed relationship between crtc's and | ||
| 222 | * encoders. I'm not sure if there is ever a need to more freely | ||
| 223 | * assign crtcs to encoders, but if there is then we need to take | ||
| 224 | * care of error and vblank irq's that the crtc has registered, | ||
| 225 | * and also update user-requested vblank_mask. | ||
| 226 | */ | ||
| 227 | encoder->possible_crtcs = BIT(0); | ||
| 228 | mdp5_crtc_set_intf(priv->crtcs[0], 3, INTF_HDMI); | ||
| 229 | |||
| 230 | priv->encoders[priv->num_encoders++] = encoder; | 220 | priv->encoders[priv->num_encoders++] = encoder; |
| 231 | 221 | ||
| 232 | /* Construct bridge/connector for HDMI: */ | 222 | /* Construct bridge/connector for HDMI: */ |
diff --git a/drivers/gpu/drm/msm/mdp/mdp_kms.c b/drivers/gpu/drm/msm/mdp/mdp_kms.c index 03455b64a245..2a731722d840 100644 --- a/drivers/gpu/drm/msm/mdp/mdp_kms.c +++ b/drivers/gpu/drm/msm/mdp/mdp_kms.c | |||
| @@ -42,7 +42,10 @@ static void update_irq(struct mdp_kms *mdp_kms) | |||
| 42 | mdp_kms->funcs->set_irqmask(mdp_kms, irqmask); | 42 | mdp_kms->funcs->set_irqmask(mdp_kms, irqmask); |
| 43 | } | 43 | } |
| 44 | 44 | ||
| 45 | static void update_irq_unlocked(struct mdp_kms *mdp_kms) | 45 | /* if an mdp_irq's irqmask has changed, such as when mdp5 crtc<->encoder |
| 46 | * link changes, this must be called to figure out the new global irqmask | ||
| 47 | */ | ||
| 48 | void mdp_irq_update(struct mdp_kms *mdp_kms) | ||
| 46 | { | 49 | { |
| 47 | unsigned long flags; | 50 | unsigned long flags; |
| 48 | spin_lock_irqsave(&list_lock, flags); | 51 | spin_lock_irqsave(&list_lock, flags); |
| @@ -122,7 +125,7 @@ void mdp_irq_register(struct mdp_kms *mdp_kms, struct mdp_irq *irq) | |||
| 122 | spin_unlock_irqrestore(&list_lock, flags); | 125 | spin_unlock_irqrestore(&list_lock, flags); |
| 123 | 126 | ||
| 124 | if (needs_update) | 127 | if (needs_update) |
| 125 | update_irq_unlocked(mdp_kms); | 128 | mdp_irq_update(mdp_kms); |
| 126 | } | 129 | } |
| 127 | 130 | ||
| 128 | void mdp_irq_unregister(struct mdp_kms *mdp_kms, struct mdp_irq *irq) | 131 | void mdp_irq_unregister(struct mdp_kms *mdp_kms, struct mdp_irq *irq) |
| @@ -141,5 +144,5 @@ void mdp_irq_unregister(struct mdp_kms *mdp_kms, struct mdp_irq *irq) | |||
| 141 | spin_unlock_irqrestore(&list_lock, flags); | 144 | spin_unlock_irqrestore(&list_lock, flags); |
| 142 | 145 | ||
| 143 | if (needs_update) | 146 | if (needs_update) |
| 144 | update_irq_unlocked(mdp_kms); | 147 | mdp_irq_update(mdp_kms); |
| 145 | } | 148 | } |
diff --git a/drivers/gpu/drm/msm/mdp/mdp_kms.h b/drivers/gpu/drm/msm/mdp/mdp_kms.h index 99557b5ad4fd..b268ce95d394 100644 --- a/drivers/gpu/drm/msm/mdp/mdp_kms.h +++ b/drivers/gpu/drm/msm/mdp/mdp_kms.h | |||
| @@ -75,7 +75,7 @@ void mdp_update_vblank_mask(struct mdp_kms *mdp_kms, uint32_t mask, bool enable) | |||
| 75 | void mdp_irq_wait(struct mdp_kms *mdp_kms, uint32_t irqmask); | 75 | void mdp_irq_wait(struct mdp_kms *mdp_kms, uint32_t irqmask); |
| 76 | void mdp_irq_register(struct mdp_kms *mdp_kms, struct mdp_irq *irq); | 76 | void mdp_irq_register(struct mdp_kms *mdp_kms, struct mdp_irq *irq); |
| 77 | void mdp_irq_unregister(struct mdp_kms *mdp_kms, struct mdp_irq *irq); | 77 | void mdp_irq_unregister(struct mdp_kms *mdp_kms, struct mdp_irq *irq); |
| 78 | 78 | void mdp_irq_update(struct mdp_kms *mdp_kms); | |
| 79 | 79 | ||
| 80 | /* | 80 | /* |
| 81 | * pixel format helpers: | 81 | * pixel format helpers: |
diff --git a/drivers/gpu/drm/msm/msm_atomic.c b/drivers/gpu/drm/msm/msm_atomic.c index f0de412e13dc..191968256c58 100644 --- a/drivers/gpu/drm/msm/msm_atomic.c +++ b/drivers/gpu/drm/msm/msm_atomic.c | |||
| @@ -23,10 +23,41 @@ struct msm_commit { | |||
| 23 | struct drm_atomic_state *state; | 23 | struct drm_atomic_state *state; |
| 24 | uint32_t fence; | 24 | uint32_t fence; |
| 25 | struct msm_fence_cb fence_cb; | 25 | struct msm_fence_cb fence_cb; |
| 26 | uint32_t crtc_mask; | ||
| 26 | }; | 27 | }; |
| 27 | 28 | ||
| 28 | static void fence_cb(struct msm_fence_cb *cb); | 29 | static void fence_cb(struct msm_fence_cb *cb); |
| 29 | 30 | ||
| 31 | /* block until specified crtcs are no longer pending update, and | ||
| 32 | * atomically mark them as pending update | ||
| 33 | */ | ||
| 34 | static int start_atomic(struct msm_drm_private *priv, uint32_t crtc_mask) | ||
| 35 | { | ||
| 36 | int ret; | ||
| 37 | |||
| 38 | spin_lock(&priv->pending_crtcs_event.lock); | ||
| 39 | ret = wait_event_interruptible_locked(priv->pending_crtcs_event, | ||
| 40 | !(priv->pending_crtcs & crtc_mask)); | ||
| 41 | if (ret == 0) { | ||
| 42 | DBG("start: %08x", crtc_mask); | ||
| 43 | priv->pending_crtcs |= crtc_mask; | ||
| 44 | } | ||
| 45 | spin_unlock(&priv->pending_crtcs_event.lock); | ||
| 46 | |||
| 47 | return ret; | ||
| 48 | } | ||
| 49 | |||
| 50 | /* clear specified crtcs (no longer pending update) | ||
| 51 | */ | ||
| 52 | static void end_atomic(struct msm_drm_private *priv, uint32_t crtc_mask) | ||
| 53 | { | ||
| 54 | spin_lock(&priv->pending_crtcs_event.lock); | ||
| 55 | DBG("end: %08x", crtc_mask); | ||
| 56 | priv->pending_crtcs &= ~crtc_mask; | ||
| 57 | wake_up_all_locked(&priv->pending_crtcs_event); | ||
| 58 | spin_unlock(&priv->pending_crtcs_event.lock); | ||
| 59 | } | ||
| 60 | |||
| 30 | static struct msm_commit *new_commit(struct drm_atomic_state *state) | 61 | static struct msm_commit *new_commit(struct drm_atomic_state *state) |
| 31 | { | 62 | { |
| 32 | struct msm_commit *c = kzalloc(sizeof(*c), GFP_KERNEL); | 63 | struct msm_commit *c = kzalloc(sizeof(*c), GFP_KERNEL); |
| @@ -58,12 +89,27 @@ static void complete_commit(struct msm_commit *c) | |||
| 58 | 89 | ||
| 59 | drm_atomic_helper_commit_post_planes(dev, state); | 90 | drm_atomic_helper_commit_post_planes(dev, state); |
| 60 | 91 | ||
| 92 | /* NOTE: _wait_for_vblanks() only waits for vblank on | ||
| 93 | * enabled CRTCs. So we end up faulting when disabling | ||
| 94 | * due to (potentially) unref'ing the outgoing fb's | ||
| 95 | * before the vblank when the disable has latched. | ||
| 96 | * | ||
| 97 | * But if it did wait on disabled (or newly disabled) | ||
| 98 | * CRTCs, that would be racy (ie. we could have missed | ||
| 99 | * the irq. We need some way to poll for pipe shut | ||
| 100 | * down. Or just live with occasionally hitting the | ||
| 101 | * timeout in the CRTC disable path (which really should | ||
| 102 | * not be critical path) | ||
| 103 | */ | ||
| 104 | |||
| 61 | drm_atomic_helper_wait_for_vblanks(dev, state); | 105 | drm_atomic_helper_wait_for_vblanks(dev, state); |
| 62 | 106 | ||
| 63 | drm_atomic_helper_cleanup_planes(dev, state); | 107 | drm_atomic_helper_cleanup_planes(dev, state); |
| 64 | 108 | ||
| 65 | drm_atomic_state_free(state); | 109 | drm_atomic_state_free(state); |
| 66 | 110 | ||
| 111 | end_atomic(dev->dev_private, c->crtc_mask); | ||
| 112 | |||
| 67 | kfree(c); | 113 | kfree(c); |
| 68 | } | 114 | } |
| 69 | 115 | ||
| @@ -97,8 +143,9 @@ static void add_fb(struct msm_commit *c, struct drm_framebuffer *fb) | |||
| 97 | int msm_atomic_commit(struct drm_device *dev, | 143 | int msm_atomic_commit(struct drm_device *dev, |
| 98 | struct drm_atomic_state *state, bool async) | 144 | struct drm_atomic_state *state, bool async) |
| 99 | { | 145 | { |
| 100 | struct msm_commit *c; | ||
| 101 | int nplanes = dev->mode_config.num_total_plane; | 146 | int nplanes = dev->mode_config.num_total_plane; |
| 147 | int ncrtcs = dev->mode_config.num_crtc; | ||
| 148 | struct msm_commit *c; | ||
| 102 | int i, ret; | 149 | int i, ret; |
| 103 | 150 | ||
| 104 | ret = drm_atomic_helper_prepare_planes(dev, state); | 151 | ret = drm_atomic_helper_prepare_planes(dev, state); |
| @@ -106,6 +153,18 @@ int msm_atomic_commit(struct drm_device *dev, | |||
| 106 | return ret; | 153 | return ret; |
| 107 | 154 | ||
| 108 | c = new_commit(state); | 155 | c = new_commit(state); |
| 156 | if (!c) | ||
| 157 | return -ENOMEM; | ||
| 158 | |||
| 159 | /* | ||
| 160 | * Figure out what crtcs we have: | ||
| 161 | */ | ||
| 162 | for (i = 0; i < ncrtcs; i++) { | ||
| 163 | struct drm_crtc *crtc = state->crtcs[i]; | ||
| 164 | if (!crtc) | ||
| 165 | continue; | ||
| 166 | c->crtc_mask |= (1 << drm_crtc_index(crtc)); | ||
| 167 | } | ||
| 109 | 168 | ||
| 110 | /* | 169 | /* |
| 111 | * Figure out what fence to wait for: | 170 | * Figure out what fence to wait for: |
| @@ -122,6 +181,14 @@ int msm_atomic_commit(struct drm_device *dev, | |||
| 122 | } | 181 | } |
| 123 | 182 | ||
| 124 | /* | 183 | /* |
| 184 | * Wait for pending updates on any of the same crtc's and then | ||
| 185 | * mark our set of crtc's as busy: | ||
| 186 | */ | ||
| 187 | ret = start_atomic(dev->dev_private, c->crtc_mask); | ||
| 188 | if (ret) | ||
| 189 | return ret; | ||
| 190 | |||
| 191 | /* | ||
| 125 | * This is the point of no return - everything below never fails except | 192 | * This is the point of no return - everything below never fails except |
| 126 | * when the hw goes bonghits. Which means we can commit the new state on | 193 | * when the hw goes bonghits. Which means we can commit the new state on |
| 127 | * the software side now. | 194 | * the software side now. |
diff --git a/drivers/gpu/drm/msm/msm_drv.c b/drivers/gpu/drm/msm/msm_drv.c index c795217e1bfc..9a61546a0b05 100644 --- a/drivers/gpu/drm/msm/msm_drv.c +++ b/drivers/gpu/drm/msm/msm_drv.c | |||
| @@ -193,6 +193,7 @@ static int msm_load(struct drm_device *dev, unsigned long flags) | |||
| 193 | 193 | ||
| 194 | priv->wq = alloc_ordered_workqueue("msm", 0); | 194 | priv->wq = alloc_ordered_workqueue("msm", 0); |
| 195 | init_waitqueue_head(&priv->fence_event); | 195 | init_waitqueue_head(&priv->fence_event); |
| 196 | init_waitqueue_head(&priv->pending_crtcs_event); | ||
| 196 | 197 | ||
| 197 | INIT_LIST_HEAD(&priv->inactive_list); | 198 | INIT_LIST_HEAD(&priv->inactive_list); |
| 198 | INIT_LIST_HEAD(&priv->fence_cbs); | 199 | INIT_LIST_HEAD(&priv->fence_cbs); |
diff --git a/drivers/gpu/drm/msm/msm_drv.h b/drivers/gpu/drm/msm/msm_drv.h index 136303818436..b69ef2d5a26c 100644 --- a/drivers/gpu/drm/msm/msm_drv.h +++ b/drivers/gpu/drm/msm/msm_drv.h | |||
| @@ -96,6 +96,10 @@ struct msm_drm_private { | |||
| 96 | /* callbacks deferred until bo is inactive: */ | 96 | /* callbacks deferred until bo is inactive: */ |
| 97 | struct list_head fence_cbs; | 97 | struct list_head fence_cbs; |
| 98 | 98 | ||
| 99 | /* crtcs pending async atomic updates: */ | ||
| 100 | uint32_t pending_crtcs; | ||
| 101 | wait_queue_head_t pending_crtcs_event; | ||
| 102 | |||
| 99 | /* registered MMUs: */ | 103 | /* registered MMUs: */ |
| 100 | unsigned int num_mmus; | 104 | unsigned int num_mmus; |
| 101 | struct msm_mmu *mmus[NUM_DOMAINS]; | 105 | struct msm_mmu *mmus[NUM_DOMAINS]; |
diff --git a/drivers/gpu/drm/msm/msm_fbdev.c b/drivers/gpu/drm/msm/msm_fbdev.c index 94d55e526b4e..1f3af13ccede 100644 --- a/drivers/gpu/drm/msm/msm_fbdev.c +++ b/drivers/gpu/drm/msm/msm_fbdev.c | |||
| @@ -190,8 +190,7 @@ fail_unlock: | |||
| 190 | fail: | 190 | fail: |
| 191 | 191 | ||
| 192 | if (ret) { | 192 | if (ret) { |
| 193 | if (fbi) | 193 | framebuffer_release(fbi); |
| 194 | framebuffer_release(fbi); | ||
| 195 | if (fb) { | 194 | if (fb) { |
| 196 | drm_framebuffer_unregister_private(fb); | 195 | drm_framebuffer_unregister_private(fb); |
| 197 | drm_framebuffer_remove(fb); | 196 | drm_framebuffer_remove(fb); |
diff --git a/drivers/gpu/drm/msm/msm_gem.c b/drivers/gpu/drm/msm/msm_gem.c index 4a6f0e49d5b5..49dea4fb55ac 100644 --- a/drivers/gpu/drm/msm/msm_gem.c +++ b/drivers/gpu/drm/msm/msm_gem.c | |||
| @@ -535,8 +535,7 @@ void msm_gem_free_object(struct drm_gem_object *obj) | |||
| 535 | drm_free_large(msm_obj->pages); | 535 | drm_free_large(msm_obj->pages); |
| 536 | 536 | ||
| 537 | } else { | 537 | } else { |
| 538 | if (msm_obj->vaddr) | 538 | vunmap(msm_obj->vaddr); |
| 539 | vunmap(msm_obj->vaddr); | ||
| 540 | put_pages(obj); | 539 | put_pages(obj); |
| 541 | } | 540 | } |
| 542 | 541 | ||
diff --git a/drivers/gpu/drm/nouveau/nouveau_display.c b/drivers/gpu/drm/nouveau/nouveau_display.c index 5d93902a91ab..f8042433752b 100644 --- a/drivers/gpu/drm/nouveau/nouveau_display.c +++ b/drivers/gpu/drm/nouveau/nouveau_display.c | |||
| @@ -876,7 +876,6 @@ nouveau_display_dumb_create(struct drm_file *file_priv, struct drm_device *dev, | |||
| 876 | if (ret) | 876 | if (ret) |
| 877 | return ret; | 877 | return ret; |
| 878 | 878 | ||
| 879 | bo->gem.dumb = true; | ||
| 880 | ret = drm_gem_handle_create(file_priv, &bo->gem, &args->handle); | 879 | ret = drm_gem_handle_create(file_priv, &bo->gem, &args->handle); |
| 881 | drm_gem_object_unreference_unlocked(&bo->gem); | 880 | drm_gem_object_unreference_unlocked(&bo->gem); |
| 882 | return ret; | 881 | return ret; |
| @@ -892,14 +891,6 @@ nouveau_display_dumb_map_offset(struct drm_file *file_priv, | |||
| 892 | gem = drm_gem_object_lookup(dev, file_priv, handle); | 891 | gem = drm_gem_object_lookup(dev, file_priv, handle); |
| 893 | if (gem) { | 892 | if (gem) { |
| 894 | struct nouveau_bo *bo = nouveau_gem_object(gem); | 893 | struct nouveau_bo *bo = nouveau_gem_object(gem); |
| 895 | |||
| 896 | /* | ||
| 897 | * We don't allow dumb mmaps on objects created using another | ||
| 898 | * interface. | ||
| 899 | */ | ||
| 900 | WARN_ONCE(!(gem->dumb || gem->import_attach), | ||
| 901 | "Illegal dumb map of accelerated buffer.\n"); | ||
| 902 | |||
| 903 | *poffset = drm_vma_node_offset_addr(&bo->bo.vma_node); | 894 | *poffset = drm_vma_node_offset_addr(&bo->bo.vma_node); |
| 904 | drm_gem_object_unreference_unlocked(gem); | 895 | drm_gem_object_unreference_unlocked(gem); |
| 905 | return 0; | 896 | return 0; |
diff --git a/drivers/gpu/drm/nouveau/nouveau_gem.c b/drivers/gpu/drm/nouveau/nouveau_gem.c index 28d51a22a4bf..42c34babc2e5 100644 --- a/drivers/gpu/drm/nouveau/nouveau_gem.c +++ b/drivers/gpu/drm/nouveau/nouveau_gem.c | |||
| @@ -444,9 +444,6 @@ validate_list(struct nouveau_channel *chan, struct nouveau_cli *cli, | |||
| 444 | list_for_each_entry(nvbo, list, entry) { | 444 | list_for_each_entry(nvbo, list, entry) { |
| 445 | struct drm_nouveau_gem_pushbuf_bo *b = &pbbo[nvbo->pbbo_index]; | 445 | struct drm_nouveau_gem_pushbuf_bo *b = &pbbo[nvbo->pbbo_index]; |
| 446 | 446 | ||
| 447 | WARN_ONCE(nvbo->gem.dumb, | ||
| 448 | "GPU use of dumb buffer is illegal.\n"); | ||
| 449 | |||
| 450 | ret = nouveau_gem_set_domain(&nvbo->gem, b->read_domains, | 447 | ret = nouveau_gem_set_domain(&nvbo->gem, b->read_domains, |
| 451 | b->write_domains, | 448 | b->write_domains, |
| 452 | b->valid_domains); | 449 | b->valid_domains); |
diff --git a/drivers/gpu/drm/nouveau/nouveau_ttm.c b/drivers/gpu/drm/nouveau/nouveau_ttm.c index 753a6def61e7..3d1cfcb96b6b 100644 --- a/drivers/gpu/drm/nouveau/nouveau_ttm.c +++ b/drivers/gpu/drm/nouveau/nouveau_ttm.c | |||
| @@ -28,6 +28,7 @@ | |||
| 28 | #include "nouveau_ttm.h" | 28 | #include "nouveau_ttm.h" |
| 29 | #include "nouveau_gem.h" | 29 | #include "nouveau_gem.h" |
| 30 | 30 | ||
| 31 | #include "drm_legacy.h" | ||
| 31 | static int | 32 | static int |
| 32 | nouveau_vram_manager_init(struct ttm_mem_type_manager *man, unsigned long psize) | 33 | nouveau_vram_manager_init(struct ttm_mem_type_manager *man, unsigned long psize) |
| 33 | { | 34 | { |
| @@ -281,7 +282,7 @@ nouveau_ttm_mmap(struct file *filp, struct vm_area_struct *vma) | |||
| 281 | struct nouveau_drm *drm = nouveau_drm(file_priv->minor->dev); | 282 | struct nouveau_drm *drm = nouveau_drm(file_priv->minor->dev); |
| 282 | 283 | ||
| 283 | if (unlikely(vma->vm_pgoff < DRM_FILE_PAGE_OFFSET)) | 284 | if (unlikely(vma->vm_pgoff < DRM_FILE_PAGE_OFFSET)) |
| 284 | return -EINVAL; | 285 | return drm_legacy_mmap(filp, vma); |
| 285 | 286 | ||
| 286 | return ttm_bo_mmap(filp, vma, &drm->ttm.bdev); | 287 | return ttm_bo_mmap(filp, vma, &drm->ttm.bdev); |
| 287 | } | 288 | } |
diff --git a/drivers/gpu/drm/radeon/radeon_gem.c b/drivers/gpu/drm/radeon/radeon_gem.c index fe48f229043e..a46f73737994 100644 --- a/drivers/gpu/drm/radeon/radeon_gem.c +++ b/drivers/gpu/drm/radeon/radeon_gem.c | |||
| @@ -394,10 +394,9 @@ int radeon_gem_set_domain_ioctl(struct drm_device *dev, void *data, | |||
| 394 | return r; | 394 | return r; |
| 395 | } | 395 | } |
| 396 | 396 | ||
| 397 | static int radeon_mode_mmap(struct drm_file *filp, | 397 | int radeon_mode_dumb_mmap(struct drm_file *filp, |
| 398 | struct drm_device *dev, | 398 | struct drm_device *dev, |
| 399 | uint32_t handle, bool dumb, | 399 | uint32_t handle, uint64_t *offset_p) |
| 400 | uint64_t *offset_p) | ||
| 401 | { | 400 | { |
| 402 | struct drm_gem_object *gobj; | 401 | struct drm_gem_object *gobj; |
| 403 | struct radeon_bo *robj; | 402 | struct radeon_bo *robj; |
| @@ -406,14 +405,6 @@ static int radeon_mode_mmap(struct drm_file *filp, | |||
| 406 | if (gobj == NULL) { | 405 | if (gobj == NULL) { |
| 407 | return -ENOENT; | 406 | return -ENOENT; |
| 408 | } | 407 | } |
| 409 | |||
| 410 | /* | ||
| 411 | * We don't allow dumb mmaps on objects created using another | ||
| 412 | * interface. | ||
| 413 | */ | ||
| 414 | WARN_ONCE(dumb && !(gobj->dumb || gobj->import_attach), | ||
| 415 | "Illegal dumb map of GPU buffer.\n"); | ||
| 416 | |||
| 417 | robj = gem_to_radeon_bo(gobj); | 408 | robj = gem_to_radeon_bo(gobj); |
| 418 | if (radeon_ttm_tt_has_userptr(robj->tbo.ttm)) { | 409 | if (radeon_ttm_tt_has_userptr(robj->tbo.ttm)) { |
| 419 | drm_gem_object_unreference_unlocked(gobj); | 410 | drm_gem_object_unreference_unlocked(gobj); |
| @@ -424,20 +415,12 @@ static int radeon_mode_mmap(struct drm_file *filp, | |||
| 424 | return 0; | 415 | return 0; |
| 425 | } | 416 | } |
| 426 | 417 | ||
| 427 | int radeon_mode_dumb_mmap(struct drm_file *filp, | ||
| 428 | struct drm_device *dev, | ||
| 429 | uint32_t handle, uint64_t *offset_p) | ||
| 430 | { | ||
| 431 | return radeon_mode_mmap(filp, dev, handle, true, offset_p); | ||
| 432 | } | ||
| 433 | |||
| 434 | int radeon_gem_mmap_ioctl(struct drm_device *dev, void *data, | 418 | int radeon_gem_mmap_ioctl(struct drm_device *dev, void *data, |
| 435 | struct drm_file *filp) | 419 | struct drm_file *filp) |
| 436 | { | 420 | { |
| 437 | struct drm_radeon_gem_mmap *args = data; | 421 | struct drm_radeon_gem_mmap *args = data; |
| 438 | 422 | ||
| 439 | return radeon_mode_mmap(filp, dev, args->handle, false, | 423 | return radeon_mode_dumb_mmap(filp, dev, args->handle, &args->addr_ptr); |
| 440 | &args->addr_ptr); | ||
| 441 | } | 424 | } |
| 442 | 425 | ||
| 443 | int radeon_gem_busy_ioctl(struct drm_device *dev, void *data, | 426 | int radeon_gem_busy_ioctl(struct drm_device *dev, void *data, |
| @@ -763,7 +746,6 @@ int radeon_mode_dumb_create(struct drm_file *file_priv, | |||
| 763 | return -ENOMEM; | 746 | return -ENOMEM; |
| 764 | 747 | ||
| 765 | r = drm_gem_handle_create(file_priv, gobj, &handle); | 748 | r = drm_gem_handle_create(file_priv, gobj, &handle); |
| 766 | gobj->dumb = true; | ||
| 767 | /* drop reference from allocate - handle holds it now */ | 749 | /* drop reference from allocate - handle holds it now */ |
| 768 | drm_gem_object_unreference_unlocked(gobj); | 750 | drm_gem_object_unreference_unlocked(gobj); |
| 769 | if (r) { | 751 | if (r) { |
diff --git a/drivers/gpu/drm/radeon/radeon_kfd.c b/drivers/gpu/drm/radeon/radeon_kfd.c index 065d02068ec3..242fd8b1b221 100644 --- a/drivers/gpu/drm/radeon/radeon_kfd.c +++ b/drivers/gpu/drm/radeon/radeon_kfd.c | |||
| @@ -28,6 +28,8 @@ | |||
| 28 | #include "cikd.h" | 28 | #include "cikd.h" |
| 29 | #include "cik_reg.h" | 29 | #include "cik_reg.h" |
| 30 | #include "radeon_kfd.h" | 30 | #include "radeon_kfd.h" |
| 31 | #include "radeon_ucode.h" | ||
| 32 | #include <linux/firmware.h> | ||
| 31 | 33 | ||
| 32 | #define CIK_PIPE_PER_MEC (4) | 34 | #define CIK_PIPE_PER_MEC (4) |
| 33 | 35 | ||
| @@ -49,6 +51,7 @@ static uint64_t get_vmem_size(struct kgd_dev *kgd); | |||
| 49 | static uint64_t get_gpu_clock_counter(struct kgd_dev *kgd); | 51 | static uint64_t get_gpu_clock_counter(struct kgd_dev *kgd); |
| 50 | 52 | ||
| 51 | static uint32_t get_max_engine_clock_in_mhz(struct kgd_dev *kgd); | 53 | static uint32_t get_max_engine_clock_in_mhz(struct kgd_dev *kgd); |
| 54 | static uint16_t get_fw_version(struct kgd_dev *kgd, enum kgd_engine_type type); | ||
| 52 | 55 | ||
| 53 | /* | 56 | /* |
| 54 | * Register access functions | 57 | * Register access functions |
| @@ -91,6 +94,7 @@ static const struct kfd2kgd_calls kfd2kgd = { | |||
| 91 | .hqd_load = kgd_hqd_load, | 94 | .hqd_load = kgd_hqd_load, |
| 92 | .hqd_is_occupies = kgd_hqd_is_occupies, | 95 | .hqd_is_occupies = kgd_hqd_is_occupies, |
| 93 | .hqd_destroy = kgd_hqd_destroy, | 96 | .hqd_destroy = kgd_hqd_destroy, |
| 97 | .get_fw_version = get_fw_version | ||
| 94 | }; | 98 | }; |
| 95 | 99 | ||
| 96 | static const struct kgd2kfd_calls *kgd2kfd; | 100 | static const struct kgd2kfd_calls *kgd2kfd; |
| @@ -561,3 +565,52 @@ static int kgd_hqd_destroy(struct kgd_dev *kgd, uint32_t reset_type, | |||
| 561 | release_queue(kgd); | 565 | release_queue(kgd); |
| 562 | return 0; | 566 | return 0; |
| 563 | } | 567 | } |
| 568 | |||
| 569 | static uint16_t get_fw_version(struct kgd_dev *kgd, enum kgd_engine_type type) | ||
| 570 | { | ||
| 571 | struct radeon_device *rdev = (struct radeon_device *) kgd; | ||
| 572 | const union radeon_firmware_header *hdr; | ||
| 573 | |||
| 574 | BUG_ON(kgd == NULL || rdev->mec_fw == NULL); | ||
| 575 | |||
| 576 | switch (type) { | ||
| 577 | case KGD_ENGINE_PFP: | ||
| 578 | hdr = (const union radeon_firmware_header *) rdev->pfp_fw->data; | ||
| 579 | break; | ||
| 580 | |||
| 581 | case KGD_ENGINE_ME: | ||
| 582 | hdr = (const union radeon_firmware_header *) rdev->me_fw->data; | ||
| 583 | break; | ||
| 584 | |||
| 585 | case KGD_ENGINE_CE: | ||
| 586 | hdr = (const union radeon_firmware_header *) rdev->ce_fw->data; | ||
| 587 | break; | ||
| 588 | |||
| 589 | case KGD_ENGINE_MEC1: | ||
| 590 | hdr = (const union radeon_firmware_header *) rdev->mec_fw->data; | ||
| 591 | break; | ||
| 592 | |||
| 593 | case KGD_ENGINE_MEC2: | ||
| 594 | hdr = (const union radeon_firmware_header *) | ||
| 595 | rdev->mec2_fw->data; | ||
| 596 | break; | ||
| 597 | |||
| 598 | case KGD_ENGINE_RLC: | ||
| 599 | hdr = (const union radeon_firmware_header *) rdev->rlc_fw->data; | ||
| 600 | break; | ||
| 601 | |||
| 602 | case KGD_ENGINE_SDMA: | ||
| 603 | hdr = (const union radeon_firmware_header *) | ||
| 604 | rdev->sdma_fw->data; | ||
| 605 | break; | ||
| 606 | |||
| 607 | default: | ||
| 608 | return 0; | ||
| 609 | } | ||
| 610 | |||
| 611 | if (hdr == NULL) | ||
| 612 | return 0; | ||
| 613 | |||
| 614 | /* Only 12 bit in use*/ | ||
| 615 | return hdr->common.ucode_version; | ||
| 616 | } | ||
diff --git a/drivers/gpu/drm/radeon/radeon_object.c b/drivers/gpu/drm/radeon/radeon_object.c index 7d68223eb469..86fc56434b28 100644 --- a/drivers/gpu/drm/radeon/radeon_object.c +++ b/drivers/gpu/drm/radeon/radeon_object.c | |||
| @@ -529,9 +529,6 @@ int radeon_bo_list_validate(struct radeon_device *rdev, | |||
| 529 | u32 current_domain = | 529 | u32 current_domain = |
| 530 | radeon_mem_type_to_domain(bo->tbo.mem.mem_type); | 530 | radeon_mem_type_to_domain(bo->tbo.mem.mem_type); |
| 531 | 531 | ||
| 532 | WARN_ONCE(bo->gem_base.dumb, | ||
| 533 | "GPU use of dumb buffer is illegal.\n"); | ||
| 534 | |||
| 535 | /* Check if this buffer will be moved and don't move it | 532 | /* Check if this buffer will be moved and don't move it |
| 536 | * if we have moved too many buffers for this IB already. | 533 | * if we have moved too many buffers for this IB already. |
| 537 | * | 534 | * |
diff --git a/drivers/gpu/drm/tegra/dc.c b/drivers/gpu/drm/tegra/dc.c index 3367960286a6..978993fa3a36 100644 --- a/drivers/gpu/drm/tegra/dc.c +++ b/drivers/gpu/drm/tegra/dc.c | |||
| @@ -168,7 +168,7 @@ static int tegra_dc_setup_window(struct tegra_dc *dc, unsigned int index, | |||
| 168 | const struct tegra_dc_window *window) | 168 | const struct tegra_dc_window *window) |
| 169 | { | 169 | { |
| 170 | unsigned h_offset, v_offset, h_size, v_size, h_dda, v_dda, bpp; | 170 | unsigned h_offset, v_offset, h_size, v_size, h_dda, v_dda, bpp; |
| 171 | unsigned long value; | 171 | unsigned long value, flags; |
| 172 | bool yuv, planar; | 172 | bool yuv, planar; |
| 173 | 173 | ||
| 174 | /* | 174 | /* |
| @@ -181,6 +181,8 @@ static int tegra_dc_setup_window(struct tegra_dc *dc, unsigned int index, | |||
| 181 | else | 181 | else |
| 182 | bpp = planar ? 1 : 2; | 182 | bpp = planar ? 1 : 2; |
| 183 | 183 | ||
| 184 | spin_lock_irqsave(&dc->lock, flags); | ||
| 185 | |||
| 184 | value = WINDOW_A_SELECT << index; | 186 | value = WINDOW_A_SELECT << index; |
| 185 | tegra_dc_writel(dc, value, DC_CMD_DISPLAY_WINDOW_HEADER); | 187 | tegra_dc_writel(dc, value, DC_CMD_DISPLAY_WINDOW_HEADER); |
| 186 | 188 | ||
| @@ -273,6 +275,7 @@ static int tegra_dc_setup_window(struct tegra_dc *dc, unsigned int index, | |||
| 273 | 275 | ||
| 274 | case TEGRA_BO_TILING_MODE_BLOCK: | 276 | case TEGRA_BO_TILING_MODE_BLOCK: |
| 275 | DRM_ERROR("hardware doesn't support block linear mode\n"); | 277 | DRM_ERROR("hardware doesn't support block linear mode\n"); |
| 278 | spin_unlock_irqrestore(&dc->lock, flags); | ||
| 276 | return -EINVAL; | 279 | return -EINVAL; |
| 277 | } | 280 | } |
| 278 | 281 | ||
| @@ -331,6 +334,8 @@ static int tegra_dc_setup_window(struct tegra_dc *dc, unsigned int index, | |||
| 331 | 334 | ||
| 332 | tegra_dc_window_commit(dc, index); | 335 | tegra_dc_window_commit(dc, index); |
| 333 | 336 | ||
| 337 | spin_unlock_irqrestore(&dc->lock, flags); | ||
| 338 | |||
| 334 | return 0; | 339 | return 0; |
| 335 | } | 340 | } |
| 336 | 341 | ||
| @@ -338,11 +343,14 @@ static int tegra_window_plane_disable(struct drm_plane *plane) | |||
| 338 | { | 343 | { |
| 339 | struct tegra_dc *dc = to_tegra_dc(plane->crtc); | 344 | struct tegra_dc *dc = to_tegra_dc(plane->crtc); |
| 340 | struct tegra_plane *p = to_tegra_plane(plane); | 345 | struct tegra_plane *p = to_tegra_plane(plane); |
| 346 | unsigned long flags; | ||
| 341 | u32 value; | 347 | u32 value; |
| 342 | 348 | ||
| 343 | if (!plane->crtc) | 349 | if (!plane->crtc) |
| 344 | return 0; | 350 | return 0; |
| 345 | 351 | ||
| 352 | spin_lock_irqsave(&dc->lock, flags); | ||
| 353 | |||
| 346 | value = WINDOW_A_SELECT << p->index; | 354 | value = WINDOW_A_SELECT << p->index; |
| 347 | tegra_dc_writel(dc, value, DC_CMD_DISPLAY_WINDOW_HEADER); | 355 | tegra_dc_writel(dc, value, DC_CMD_DISPLAY_WINDOW_HEADER); |
| 348 | 356 | ||
| @@ -352,6 +360,8 @@ static int tegra_window_plane_disable(struct drm_plane *plane) | |||
| 352 | 360 | ||
| 353 | tegra_dc_window_commit(dc, p->index); | 361 | tegra_dc_window_commit(dc, p->index); |
| 354 | 362 | ||
| 363 | spin_unlock_irqrestore(&dc->lock, flags); | ||
| 364 | |||
| 355 | return 0; | 365 | return 0; |
| 356 | } | 366 | } |
| 357 | 367 | ||
| @@ -699,14 +709,16 @@ static int tegra_dc_set_base(struct tegra_dc *dc, int x, int y, | |||
| 699 | struct tegra_bo *bo = tegra_fb_get_plane(fb, 0); | 709 | struct tegra_bo *bo = tegra_fb_get_plane(fb, 0); |
| 700 | unsigned int h_offset = 0, v_offset = 0; | 710 | unsigned int h_offset = 0, v_offset = 0; |
| 701 | struct tegra_bo_tiling tiling; | 711 | struct tegra_bo_tiling tiling; |
| 712 | unsigned long value, flags; | ||
| 702 | unsigned int format, swap; | 713 | unsigned int format, swap; |
| 703 | unsigned long value; | ||
| 704 | int err; | 714 | int err; |
| 705 | 715 | ||
| 706 | err = tegra_fb_get_tiling(fb, &tiling); | 716 | err = tegra_fb_get_tiling(fb, &tiling); |
| 707 | if (err < 0) | 717 | if (err < 0) |
| 708 | return err; | 718 | return err; |
| 709 | 719 | ||
| 720 | spin_lock_irqsave(&dc->lock, flags); | ||
| 721 | |||
| 710 | tegra_dc_writel(dc, WINDOW_A_SELECT, DC_CMD_DISPLAY_WINDOW_HEADER); | 722 | tegra_dc_writel(dc, WINDOW_A_SELECT, DC_CMD_DISPLAY_WINDOW_HEADER); |
| 711 | 723 | ||
| 712 | value = fb->offsets[0] + y * fb->pitches[0] + | 724 | value = fb->offsets[0] + y * fb->pitches[0] + |
| @@ -752,6 +764,7 @@ static int tegra_dc_set_base(struct tegra_dc *dc, int x, int y, | |||
| 752 | 764 | ||
| 753 | case TEGRA_BO_TILING_MODE_BLOCK: | 765 | case TEGRA_BO_TILING_MODE_BLOCK: |
| 754 | DRM_ERROR("hardware doesn't support block linear mode\n"); | 766 | DRM_ERROR("hardware doesn't support block linear mode\n"); |
| 767 | spin_unlock_irqrestore(&dc->lock, flags); | ||
| 755 | return -EINVAL; | 768 | return -EINVAL; |
| 756 | } | 769 | } |
| 757 | 770 | ||
| @@ -778,6 +791,8 @@ static int tegra_dc_set_base(struct tegra_dc *dc, int x, int y, | |||
| 778 | tegra_dc_writel(dc, value << 8, DC_CMD_STATE_CONTROL); | 791 | tegra_dc_writel(dc, value << 8, DC_CMD_STATE_CONTROL); |
| 779 | tegra_dc_writel(dc, value, DC_CMD_STATE_CONTROL); | 792 | tegra_dc_writel(dc, value, DC_CMD_STATE_CONTROL); |
| 780 | 793 | ||
| 794 | spin_unlock_irqrestore(&dc->lock, flags); | ||
| 795 | |||
| 781 | return 0; | 796 | return 0; |
| 782 | } | 797 | } |
| 783 | 798 | ||
| @@ -814,23 +829,32 @@ static void tegra_dc_finish_page_flip(struct tegra_dc *dc) | |||
| 814 | unsigned long flags, base; | 829 | unsigned long flags, base; |
| 815 | struct tegra_bo *bo; | 830 | struct tegra_bo *bo; |
| 816 | 831 | ||
| 817 | if (!dc->event) | 832 | spin_lock_irqsave(&drm->event_lock, flags); |
| 833 | |||
| 834 | if (!dc->event) { | ||
| 835 | spin_unlock_irqrestore(&drm->event_lock, flags); | ||
| 818 | return; | 836 | return; |
| 837 | } | ||
| 819 | 838 | ||
| 820 | bo = tegra_fb_get_plane(crtc->primary->fb, 0); | 839 | bo = tegra_fb_get_plane(crtc->primary->fb, 0); |
| 821 | 840 | ||
| 841 | spin_lock_irqsave(&dc->lock, flags); | ||
| 842 | |||
| 822 | /* check if new start address has been latched */ | 843 | /* check if new start address has been latched */ |
| 844 | tegra_dc_writel(dc, WINDOW_A_SELECT, DC_CMD_DISPLAY_WINDOW_HEADER); | ||
| 823 | tegra_dc_writel(dc, READ_MUX, DC_CMD_STATE_ACCESS); | 845 | tegra_dc_writel(dc, READ_MUX, DC_CMD_STATE_ACCESS); |
| 824 | base = tegra_dc_readl(dc, DC_WINBUF_START_ADDR); | 846 | base = tegra_dc_readl(dc, DC_WINBUF_START_ADDR); |
| 825 | tegra_dc_writel(dc, 0, DC_CMD_STATE_ACCESS); | 847 | tegra_dc_writel(dc, 0, DC_CMD_STATE_ACCESS); |
| 826 | 848 | ||
| 849 | spin_unlock_irqrestore(&dc->lock, flags); | ||
| 850 | |||
| 827 | if (base == bo->paddr + crtc->primary->fb->offsets[0]) { | 851 | if (base == bo->paddr + crtc->primary->fb->offsets[0]) { |
| 828 | spin_lock_irqsave(&drm->event_lock, flags); | 852 | drm_crtc_send_vblank_event(crtc, dc->event); |
| 829 | drm_send_vblank_event(drm, dc->pipe, dc->event); | 853 | drm_crtc_vblank_put(crtc); |
| 830 | drm_vblank_put(drm, dc->pipe); | ||
| 831 | dc->event = NULL; | 854 | dc->event = NULL; |
| 832 | spin_unlock_irqrestore(&drm->event_lock, flags); | ||
| 833 | } | 855 | } |
| 856 | |||
| 857 | spin_unlock_irqrestore(&drm->event_lock, flags); | ||
| 834 | } | 858 | } |
| 835 | 859 | ||
| 836 | void tegra_dc_cancel_page_flip(struct drm_crtc *crtc, struct drm_file *file) | 860 | void tegra_dc_cancel_page_flip(struct drm_crtc *crtc, struct drm_file *file) |
| @@ -843,7 +867,7 @@ void tegra_dc_cancel_page_flip(struct drm_crtc *crtc, struct drm_file *file) | |||
| 843 | 867 | ||
| 844 | if (dc->event && dc->event->base.file_priv == file) { | 868 | if (dc->event && dc->event->base.file_priv == file) { |
| 845 | dc->event->base.destroy(&dc->event->base); | 869 | dc->event->base.destroy(&dc->event->base); |
| 846 | drm_vblank_put(drm, dc->pipe); | 870 | drm_crtc_vblank_put(crtc); |
| 847 | dc->event = NULL; | 871 | dc->event = NULL; |
| 848 | } | 872 | } |
| 849 | 873 | ||
| @@ -853,16 +877,16 @@ void tegra_dc_cancel_page_flip(struct drm_crtc *crtc, struct drm_file *file) | |||
| 853 | static int tegra_dc_page_flip(struct drm_crtc *crtc, struct drm_framebuffer *fb, | 877 | static int tegra_dc_page_flip(struct drm_crtc *crtc, struct drm_framebuffer *fb, |
| 854 | struct drm_pending_vblank_event *event, uint32_t page_flip_flags) | 878 | struct drm_pending_vblank_event *event, uint32_t page_flip_flags) |
| 855 | { | 879 | { |
| 880 | unsigned int pipe = drm_crtc_index(crtc); | ||
| 856 | struct tegra_dc *dc = to_tegra_dc(crtc); | 881 | struct tegra_dc *dc = to_tegra_dc(crtc); |
| 857 | struct drm_device *drm = crtc->dev; | ||
| 858 | 882 | ||
| 859 | if (dc->event) | 883 | if (dc->event) |
| 860 | return -EBUSY; | 884 | return -EBUSY; |
| 861 | 885 | ||
| 862 | if (event) { | 886 | if (event) { |
| 863 | event->pipe = dc->pipe; | 887 | event->pipe = pipe; |
| 864 | dc->event = event; | 888 | dc->event = event; |
| 865 | drm_vblank_get(drm, dc->pipe); | 889 | drm_crtc_vblank_get(crtc); |
| 866 | } | 890 | } |
| 867 | 891 | ||
| 868 | tegra_dc_set_base(dc, 0, 0, fb); | 892 | tegra_dc_set_base(dc, 0, 0, fb); |
| @@ -1127,7 +1151,7 @@ static irqreturn_t tegra_dc_irq(int irq, void *data) | |||
| 1127 | /* | 1151 | /* |
| 1128 | dev_dbg(dc->dev, "%s(): vertical blank\n", __func__); | 1152 | dev_dbg(dc->dev, "%s(): vertical blank\n", __func__); |
| 1129 | */ | 1153 | */ |
| 1130 | drm_handle_vblank(dc->base.dev, dc->pipe); | 1154 | drm_crtc_handle_vblank(&dc->base); |
| 1131 | tegra_dc_finish_page_flip(dc); | 1155 | tegra_dc_finish_page_flip(dc); |
| 1132 | } | 1156 | } |
| 1133 | 1157 | ||
diff --git a/drivers/gpu/drm/tegra/drm.c b/drivers/gpu/drm/tegra/drm.c index e549afeece1f..d4f827593dfa 100644 --- a/drivers/gpu/drm/tegra/drm.c +++ b/drivers/gpu/drm/tegra/drm.c | |||
| @@ -694,24 +694,28 @@ static const struct file_operations tegra_drm_fops = { | |||
| 694 | .llseek = noop_llseek, | 694 | .llseek = noop_llseek, |
| 695 | }; | 695 | }; |
| 696 | 696 | ||
| 697 | static struct drm_crtc *tegra_crtc_from_pipe(struct drm_device *drm, int pipe) | 697 | static struct drm_crtc *tegra_crtc_from_pipe(struct drm_device *drm, |
| 698 | unsigned int pipe) | ||
| 698 | { | 699 | { |
| 699 | struct drm_crtc *crtc; | 700 | struct drm_crtc *crtc; |
| 700 | 701 | ||
| 701 | list_for_each_entry(crtc, &drm->mode_config.crtc_list, head) { | 702 | list_for_each_entry(crtc, &drm->mode_config.crtc_list, head) { |
| 702 | struct tegra_dc *dc = to_tegra_dc(crtc); | 703 | if (pipe == drm_crtc_index(crtc)) |
| 703 | |||
| 704 | if (dc->pipe == pipe) | ||
| 705 | return crtc; | 704 | return crtc; |
| 706 | } | 705 | } |
| 707 | 706 | ||
| 708 | return NULL; | 707 | return NULL; |
| 709 | } | 708 | } |
| 710 | 709 | ||
| 711 | static u32 tegra_drm_get_vblank_counter(struct drm_device *dev, int crtc) | 710 | static u32 tegra_drm_get_vblank_counter(struct drm_device *drm, int pipe) |
| 712 | { | 711 | { |
| 712 | struct drm_crtc *crtc = tegra_crtc_from_pipe(drm, pipe); | ||
| 713 | |||
| 714 | if (!crtc) | ||
| 715 | return 0; | ||
| 716 | |||
| 713 | /* TODO: implement real hardware counter using syncpoints */ | 717 | /* TODO: implement real hardware counter using syncpoints */ |
| 714 | return drm_vblank_count(dev, crtc); | 718 | return drm_crtc_vblank_count(crtc); |
| 715 | } | 719 | } |
| 716 | 720 | ||
| 717 | static int tegra_drm_enable_vblank(struct drm_device *drm, int pipe) | 721 | static int tegra_drm_enable_vblank(struct drm_device *drm, int pipe) |
diff --git a/drivers/gpu/drm/tegra/gem.c b/drivers/gpu/drm/tegra/gem.c index da32086cbeaf..8777b7f75791 100644 --- a/drivers/gpu/drm/tegra/gem.c +++ b/drivers/gpu/drm/tegra/gem.c | |||
| @@ -216,32 +216,58 @@ static void tegra_bo_free(struct drm_device *drm, struct tegra_bo *bo) | |||
| 216 | } | 216 | } |
| 217 | } | 217 | } |
| 218 | 218 | ||
| 219 | static int tegra_bo_get_pages(struct drm_device *drm, struct tegra_bo *bo, | 219 | static int tegra_bo_get_pages(struct drm_device *drm, struct tegra_bo *bo) |
| 220 | size_t size) | ||
| 221 | { | 220 | { |
| 221 | struct scatterlist *s; | ||
| 222 | struct sg_table *sgt; | ||
| 223 | unsigned int i; | ||
| 224 | |||
| 222 | bo->pages = drm_gem_get_pages(&bo->gem); | 225 | bo->pages = drm_gem_get_pages(&bo->gem); |
| 223 | if (IS_ERR(bo->pages)) | 226 | if (IS_ERR(bo->pages)) |
| 224 | return PTR_ERR(bo->pages); | 227 | return PTR_ERR(bo->pages); |
| 225 | 228 | ||
| 226 | bo->num_pages = size >> PAGE_SHIFT; | 229 | bo->num_pages = bo->gem.size >> PAGE_SHIFT; |
| 227 | 230 | ||
| 228 | bo->sgt = drm_prime_pages_to_sg(bo->pages, bo->num_pages); | 231 | sgt = drm_prime_pages_to_sg(bo->pages, bo->num_pages); |
| 229 | if (IS_ERR(bo->sgt)) { | 232 | if (IS_ERR(sgt)) |
| 230 | drm_gem_put_pages(&bo->gem, bo->pages, false, false); | 233 | goto put_pages; |
| 231 | return PTR_ERR(bo->sgt); | 234 | |
| 235 | /* | ||
| 236 | * Fake up the SG table so that dma_map_sg() can be used to flush the | ||
| 237 | * pages associated with it. Note that this relies on the fact that | ||
| 238 | * the DMA API doesn't hook into IOMMU on Tegra, therefore mapping is | ||
| 239 | * only cache maintenance. | ||
| 240 | * | ||
| 241 | * TODO: Replace this by drm_clflash_sg() once it can be implemented | ||
| 242 | * without relying on symbols that are not exported. | ||
| 243 | */ | ||
| 244 | for_each_sg(sgt->sgl, s, sgt->nents, i) | ||
| 245 | sg_dma_address(s) = sg_phys(s); | ||
| 246 | |||
| 247 | if (dma_map_sg(drm->dev, sgt->sgl, sgt->nents, DMA_TO_DEVICE) == 0) { | ||
| 248 | sgt = ERR_PTR(-ENOMEM); | ||
| 249 | goto release_sgt; | ||
| 232 | } | 250 | } |
| 233 | 251 | ||
| 252 | bo->sgt = sgt; | ||
| 253 | |||
| 234 | return 0; | 254 | return 0; |
| 255 | |||
| 256 | release_sgt: | ||
| 257 | sg_free_table(sgt); | ||
| 258 | kfree(sgt); | ||
| 259 | put_pages: | ||
| 260 | drm_gem_put_pages(&bo->gem, bo->pages, false, false); | ||
| 261 | return PTR_ERR(sgt); | ||
| 235 | } | 262 | } |
| 236 | 263 | ||
| 237 | static int tegra_bo_alloc(struct drm_device *drm, struct tegra_bo *bo, | 264 | static int tegra_bo_alloc(struct drm_device *drm, struct tegra_bo *bo) |
| 238 | size_t size) | ||
| 239 | { | 265 | { |
| 240 | struct tegra_drm *tegra = drm->dev_private; | 266 | struct tegra_drm *tegra = drm->dev_private; |
| 241 | int err; | 267 | int err; |
| 242 | 268 | ||
| 243 | if (tegra->domain) { | 269 | if (tegra->domain) { |
| 244 | err = tegra_bo_get_pages(drm, bo, size); | 270 | err = tegra_bo_get_pages(drm, bo); |
| 245 | if (err < 0) | 271 | if (err < 0) |
| 246 | return err; | 272 | return err; |
| 247 | 273 | ||
| @@ -251,6 +277,8 @@ static int tegra_bo_alloc(struct drm_device *drm, struct tegra_bo *bo, | |||
| 251 | return err; | 277 | return err; |
| 252 | } | 278 | } |
| 253 | } else { | 279 | } else { |
| 280 | size_t size = bo->gem.size; | ||
| 281 | |||
| 254 | bo->vaddr = dma_alloc_writecombine(drm->dev, size, &bo->paddr, | 282 | bo->vaddr = dma_alloc_writecombine(drm->dev, size, &bo->paddr, |
| 255 | GFP_KERNEL | __GFP_NOWARN); | 283 | GFP_KERNEL | __GFP_NOWARN); |
| 256 | if (!bo->vaddr) { | 284 | if (!bo->vaddr) { |
| @@ -274,7 +302,7 @@ struct tegra_bo *tegra_bo_create(struct drm_device *drm, size_t size, | |||
| 274 | if (IS_ERR(bo)) | 302 | if (IS_ERR(bo)) |
| 275 | return bo; | 303 | return bo; |
| 276 | 304 | ||
| 277 | err = tegra_bo_alloc(drm, bo, size); | 305 | err = tegra_bo_alloc(drm, bo); |
| 278 | if (err < 0) | 306 | if (err < 0) |
| 279 | goto release; | 307 | goto release; |
| 280 | 308 | ||
diff --git a/drivers/input/evdev.c b/drivers/input/evdev.c index 8afa28e4570e..18d4b2c8fe55 100644 --- a/drivers/input/evdev.c +++ b/drivers/input/evdev.c | |||
| @@ -28,6 +28,13 @@ | |||
| 28 | #include <linux/cdev.h> | 28 | #include <linux/cdev.h> |
| 29 | #include "input-compat.h" | 29 | #include "input-compat.h" |
| 30 | 30 | ||
| 31 | enum evdev_clock_type { | ||
| 32 | EV_CLK_REAL = 0, | ||
| 33 | EV_CLK_MONO, | ||
| 34 | EV_CLK_BOOT, | ||
| 35 | EV_CLK_MAX | ||
| 36 | }; | ||
| 37 | |||
| 31 | struct evdev { | 38 | struct evdev { |
| 32 | int open; | 39 | int open; |
| 33 | struct input_handle handle; | 40 | struct input_handle handle; |
| @@ -49,12 +56,32 @@ struct evdev_client { | |||
| 49 | struct fasync_struct *fasync; | 56 | struct fasync_struct *fasync; |
| 50 | struct evdev *evdev; | 57 | struct evdev *evdev; |
| 51 | struct list_head node; | 58 | struct list_head node; |
| 52 | int clkid; | 59 | int clk_type; |
| 53 | bool revoked; | 60 | bool revoked; |
| 54 | unsigned int bufsize; | 61 | unsigned int bufsize; |
| 55 | struct input_event buffer[]; | 62 | struct input_event buffer[]; |
| 56 | }; | 63 | }; |
| 57 | 64 | ||
| 65 | static int evdev_set_clk_type(struct evdev_client *client, unsigned int clkid) | ||
| 66 | { | ||
| 67 | switch (clkid) { | ||
| 68 | |||
| 69 | case CLOCK_REALTIME: | ||
| 70 | client->clk_type = EV_CLK_REAL; | ||
| 71 | break; | ||
| 72 | case CLOCK_MONOTONIC: | ||
| 73 | client->clk_type = EV_CLK_MONO; | ||
| 74 | break; | ||
| 75 | case CLOCK_BOOTTIME: | ||
| 76 | client->clk_type = EV_CLK_BOOT; | ||
| 77 | break; | ||
| 78 | default: | ||
| 79 | return -EINVAL; | ||
| 80 | } | ||
| 81 | |||
| 82 | return 0; | ||
| 83 | } | ||
| 84 | |||
| 58 | /* flush queued events of type @type, caller must hold client->buffer_lock */ | 85 | /* flush queued events of type @type, caller must hold client->buffer_lock */ |
| 59 | static void __evdev_flush_queue(struct evdev_client *client, unsigned int type) | 86 | static void __evdev_flush_queue(struct evdev_client *client, unsigned int type) |
| 60 | { | 87 | { |
| @@ -108,8 +135,11 @@ static void evdev_queue_syn_dropped(struct evdev_client *client) | |||
| 108 | struct input_event ev; | 135 | struct input_event ev; |
| 109 | ktime_t time; | 136 | ktime_t time; |
| 110 | 137 | ||
| 111 | time = (client->clkid == CLOCK_MONOTONIC) ? | 138 | time = client->clk_type == EV_CLK_REAL ? |
| 112 | ktime_get() : ktime_get_real(); | 139 | ktime_get_real() : |
| 140 | client->clk_type == EV_CLK_MONO ? | ||
| 141 | ktime_get() : | ||
| 142 | ktime_get_boottime(); | ||
| 113 | 143 | ||
| 114 | ev.time = ktime_to_timeval(time); | 144 | ev.time = ktime_to_timeval(time); |
| 115 | ev.type = EV_SYN; | 145 | ev.type = EV_SYN; |
| @@ -159,7 +189,7 @@ static void __pass_event(struct evdev_client *client, | |||
| 159 | 189 | ||
| 160 | static void evdev_pass_values(struct evdev_client *client, | 190 | static void evdev_pass_values(struct evdev_client *client, |
| 161 | const struct input_value *vals, unsigned int count, | 191 | const struct input_value *vals, unsigned int count, |
| 162 | ktime_t mono, ktime_t real) | 192 | ktime_t *ev_time) |
| 163 | { | 193 | { |
| 164 | struct evdev *evdev = client->evdev; | 194 | struct evdev *evdev = client->evdev; |
| 165 | const struct input_value *v; | 195 | const struct input_value *v; |
| @@ -169,8 +199,7 @@ static void evdev_pass_values(struct evdev_client *client, | |||
| 169 | if (client->revoked) | 199 | if (client->revoked) |
| 170 | return; | 200 | return; |
| 171 | 201 | ||
| 172 | event.time = ktime_to_timeval(client->clkid == CLOCK_MONOTONIC ? | 202 | event.time = ktime_to_timeval(ev_time[client->clk_type]); |
| 173 | mono : real); | ||
| 174 | 203 | ||
| 175 | /* Interrupts are disabled, just acquire the lock. */ | 204 | /* Interrupts are disabled, just acquire the lock. */ |
| 176 | spin_lock(&client->buffer_lock); | 205 | spin_lock(&client->buffer_lock); |
| @@ -198,21 +227,22 @@ static void evdev_events(struct input_handle *handle, | |||
| 198 | { | 227 | { |
| 199 | struct evdev *evdev = handle->private; | 228 | struct evdev *evdev = handle->private; |
| 200 | struct evdev_client *client; | 229 | struct evdev_client *client; |
| 201 | ktime_t time_mono, time_real; | 230 | ktime_t ev_time[EV_CLK_MAX]; |
| 202 | 231 | ||
| 203 | time_mono = ktime_get(); | 232 | ev_time[EV_CLK_MONO] = ktime_get(); |
| 204 | time_real = ktime_mono_to_real(time_mono); | 233 | ev_time[EV_CLK_REAL] = ktime_mono_to_real(ev_time[EV_CLK_MONO]); |
| 234 | ev_time[EV_CLK_BOOT] = ktime_mono_to_any(ev_time[EV_CLK_MONO], | ||
| 235 | TK_OFFS_BOOT); | ||
| 205 | 236 | ||
| 206 | rcu_read_lock(); | 237 | rcu_read_lock(); |
| 207 | 238 | ||
| 208 | client = rcu_dereference(evdev->grab); | 239 | client = rcu_dereference(evdev->grab); |
| 209 | 240 | ||
| 210 | if (client) | 241 | if (client) |
| 211 | evdev_pass_values(client, vals, count, time_mono, time_real); | 242 | evdev_pass_values(client, vals, count, ev_time); |
| 212 | else | 243 | else |
| 213 | list_for_each_entry_rcu(client, &evdev->client_list, node) | 244 | list_for_each_entry_rcu(client, &evdev->client_list, node) |
| 214 | evdev_pass_values(client, vals, count, | 245 | evdev_pass_values(client, vals, count, ev_time); |
| 215 | time_mono, time_real); | ||
| 216 | 246 | ||
| 217 | rcu_read_unlock(); | 247 | rcu_read_unlock(); |
| 218 | } | 248 | } |
| @@ -877,10 +907,8 @@ static long evdev_do_ioctl(struct file *file, unsigned int cmd, | |||
| 877 | case EVIOCSCLOCKID: | 907 | case EVIOCSCLOCKID: |
| 878 | if (copy_from_user(&i, p, sizeof(unsigned int))) | 908 | if (copy_from_user(&i, p, sizeof(unsigned int))) |
| 879 | return -EFAULT; | 909 | return -EFAULT; |
| 880 | if (i != CLOCK_MONOTONIC && i != CLOCK_REALTIME) | 910 | |
| 881 | return -EINVAL; | 911 | return evdev_set_clk_type(client, i); |
| 882 | client->clkid = i; | ||
| 883 | return 0; | ||
| 884 | 912 | ||
| 885 | case EVIOCGKEYCODE: | 913 | case EVIOCGKEYCODE: |
| 886 | return evdev_handle_get_keycode(dev, p); | 914 | return evdev_handle_get_keycode(dev, p); |
diff --git a/drivers/input/input.c b/drivers/input/input.c index 04217c2e345c..213e3a1903ee 100644 --- a/drivers/input/input.c +++ b/drivers/input/input.c | |||
| @@ -1974,18 +1974,22 @@ static unsigned int input_estimate_events_per_packet(struct input_dev *dev) | |||
| 1974 | 1974 | ||
| 1975 | events = mt_slots + 1; /* count SYN_MT_REPORT and SYN_REPORT */ | 1975 | events = mt_slots + 1; /* count SYN_MT_REPORT and SYN_REPORT */ |
| 1976 | 1976 | ||
| 1977 | for (i = 0; i < ABS_CNT; i++) { | 1977 | if (test_bit(EV_ABS, dev->evbit)) { |
| 1978 | if (test_bit(i, dev->absbit)) { | 1978 | for (i = 0; i < ABS_CNT; i++) { |
| 1979 | if (input_is_mt_axis(i)) | 1979 | if (test_bit(i, dev->absbit)) { |
| 1980 | events += mt_slots; | 1980 | if (input_is_mt_axis(i)) |
| 1981 | else | 1981 | events += mt_slots; |
| 1982 | events++; | 1982 | else |
| 1983 | events++; | ||
| 1984 | } | ||
| 1983 | } | 1985 | } |
| 1984 | } | 1986 | } |
| 1985 | 1987 | ||
| 1986 | for (i = 0; i < REL_CNT; i++) | 1988 | if (test_bit(EV_REL, dev->evbit)) { |
| 1987 | if (test_bit(i, dev->relbit)) | 1989 | for (i = 0; i < REL_CNT; i++) |
| 1988 | events++; | 1990 | if (test_bit(i, dev->relbit)) |
| 1991 | events++; | ||
| 1992 | } | ||
| 1989 | 1993 | ||
| 1990 | /* Make room for KEY and MSC events */ | 1994 | /* Make room for KEY and MSC events */ |
| 1991 | events += 7; | 1995 | events += 7; |
diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig index 96ee26c555e0..a5d9b3f3c871 100644 --- a/drivers/input/keyboard/Kconfig +++ b/drivers/input/keyboard/Kconfig | |||
| @@ -559,6 +559,7 @@ config KEYBOARD_SH_KEYSC | |||
| 559 | config KEYBOARD_STMPE | 559 | config KEYBOARD_STMPE |
| 560 | tristate "STMPE keypad support" | 560 | tristate "STMPE keypad support" |
| 561 | depends on MFD_STMPE | 561 | depends on MFD_STMPE |
| 562 | depends on OF | ||
| 562 | select INPUT_MATRIXKMAP | 563 | select INPUT_MATRIXKMAP |
| 563 | help | 564 | help |
| 564 | Say Y here if you want to use the keypad controller on STMPE I/O | 565 | Say Y here if you want to use the keypad controller on STMPE I/O |
diff --git a/drivers/input/keyboard/gpio_keys.c b/drivers/input/keyboard/gpio_keys.c index d4dd78a7d56b..883d6aed5b9a 100644 --- a/drivers/input/keyboard/gpio_keys.c +++ b/drivers/input/keyboard/gpio_keys.c | |||
| @@ -35,9 +35,13 @@ | |||
| 35 | struct gpio_button_data { | 35 | struct gpio_button_data { |
| 36 | const struct gpio_keys_button *button; | 36 | const struct gpio_keys_button *button; |
| 37 | struct input_dev *input; | 37 | struct input_dev *input; |
| 38 | struct timer_list timer; | 38 | |
| 39 | struct work_struct work; | 39 | struct timer_list release_timer; |
| 40 | unsigned int timer_debounce; /* in msecs */ | 40 | unsigned int release_delay; /* in msecs, for IRQ-only buttons */ |
| 41 | |||
| 42 | struct delayed_work work; | ||
| 43 | unsigned int software_debounce; /* in msecs, for GPIO-driven buttons */ | ||
| 44 | |||
| 41 | unsigned int irq; | 45 | unsigned int irq; |
| 42 | spinlock_t lock; | 46 | spinlock_t lock; |
| 43 | bool disabled; | 47 | bool disabled; |
| @@ -116,11 +120,14 @@ static void gpio_keys_disable_button(struct gpio_button_data *bdata) | |||
| 116 | { | 120 | { |
| 117 | if (!bdata->disabled) { | 121 | if (!bdata->disabled) { |
| 118 | /* | 122 | /* |
| 119 | * Disable IRQ and possible debouncing timer. | 123 | * Disable IRQ and associated timer/work structure. |
| 120 | */ | 124 | */ |
| 121 | disable_irq(bdata->irq); | 125 | disable_irq(bdata->irq); |
| 122 | if (bdata->timer_debounce) | 126 | |
| 123 | del_timer_sync(&bdata->timer); | 127 | if (gpio_is_valid(bdata->button->gpio)) |
| 128 | cancel_delayed_work_sync(&bdata->work); | ||
| 129 | else | ||
| 130 | del_timer_sync(&bdata->release_timer); | ||
| 124 | 131 | ||
| 125 | bdata->disabled = true; | 132 | bdata->disabled = true; |
| 126 | } | 133 | } |
| @@ -343,7 +350,7 @@ static void gpio_keys_gpio_report_event(struct gpio_button_data *bdata) | |||
| 343 | static void gpio_keys_gpio_work_func(struct work_struct *work) | 350 | static void gpio_keys_gpio_work_func(struct work_struct *work) |
| 344 | { | 351 | { |
| 345 | struct gpio_button_data *bdata = | 352 | struct gpio_button_data *bdata = |
| 346 | container_of(work, struct gpio_button_data, work); | 353 | container_of(work, struct gpio_button_data, work.work); |
| 347 | 354 | ||
| 348 | gpio_keys_gpio_report_event(bdata); | 355 | gpio_keys_gpio_report_event(bdata); |
| 349 | 356 | ||
| @@ -351,13 +358,6 @@ static void gpio_keys_gpio_work_func(struct work_struct *work) | |||
| 351 | pm_relax(bdata->input->dev.parent); | 358 | pm_relax(bdata->input->dev.parent); |
| 352 | } | 359 | } |
| 353 | 360 | ||
| 354 | static void gpio_keys_gpio_timer(unsigned long _data) | ||
| 355 | { | ||
| 356 | struct gpio_button_data *bdata = (struct gpio_button_data *)_data; | ||
| 357 | |||
| 358 | schedule_work(&bdata->work); | ||
| 359 | } | ||
| 360 | |||
| 361 | static irqreturn_t gpio_keys_gpio_isr(int irq, void *dev_id) | 361 | static irqreturn_t gpio_keys_gpio_isr(int irq, void *dev_id) |
| 362 | { | 362 | { |
| 363 | struct gpio_button_data *bdata = dev_id; | 363 | struct gpio_button_data *bdata = dev_id; |
| @@ -366,11 +366,10 @@ static irqreturn_t gpio_keys_gpio_isr(int irq, void *dev_id) | |||
| 366 | 366 | ||
| 367 | if (bdata->button->wakeup) | 367 | if (bdata->button->wakeup) |
| 368 | pm_stay_awake(bdata->input->dev.parent); | 368 | pm_stay_awake(bdata->input->dev.parent); |
| 369 | if (bdata->timer_debounce) | 369 | |
| 370 | mod_timer(&bdata->timer, | 370 | mod_delayed_work(system_wq, |
| 371 | jiffies + msecs_to_jiffies(bdata->timer_debounce)); | 371 | &bdata->work, |
| 372 | else | 372 | msecs_to_jiffies(bdata->software_debounce)); |
| 373 | schedule_work(&bdata->work); | ||
| 374 | 373 | ||
| 375 | return IRQ_HANDLED; | 374 | return IRQ_HANDLED; |
| 376 | } | 375 | } |
| @@ -408,7 +407,7 @@ static irqreturn_t gpio_keys_irq_isr(int irq, void *dev_id) | |||
| 408 | input_event(input, EV_KEY, button->code, 1); | 407 | input_event(input, EV_KEY, button->code, 1); |
| 409 | input_sync(input); | 408 | input_sync(input); |
| 410 | 409 | ||
| 411 | if (!bdata->timer_debounce) { | 410 | if (!bdata->release_delay) { |
| 412 | input_event(input, EV_KEY, button->code, 0); | 411 | input_event(input, EV_KEY, button->code, 0); |
| 413 | input_sync(input); | 412 | input_sync(input); |
| 414 | goto out; | 413 | goto out; |
| @@ -417,9 +416,9 @@ static irqreturn_t gpio_keys_irq_isr(int irq, void *dev_id) | |||
| 417 | bdata->key_pressed = true; | 416 | bdata->key_pressed = true; |
| 418 | } | 417 | } |
| 419 | 418 | ||
| 420 | if (bdata->timer_debounce) | 419 | if (bdata->release_delay) |
| 421 | mod_timer(&bdata->timer, | 420 | mod_timer(&bdata->release_timer, |
| 422 | jiffies + msecs_to_jiffies(bdata->timer_debounce)); | 421 | jiffies + msecs_to_jiffies(bdata->release_delay)); |
| 423 | out: | 422 | out: |
| 424 | spin_unlock_irqrestore(&bdata->lock, flags); | 423 | spin_unlock_irqrestore(&bdata->lock, flags); |
| 425 | return IRQ_HANDLED; | 424 | return IRQ_HANDLED; |
| @@ -429,10 +428,10 @@ static void gpio_keys_quiesce_key(void *data) | |||
| 429 | { | 428 | { |
| 430 | struct gpio_button_data *bdata = data; | 429 | struct gpio_button_data *bdata = data; |
| 431 | 430 | ||
| 432 | if (bdata->timer_debounce) | 431 | if (gpio_is_valid(bdata->button->gpio)) |
| 433 | del_timer_sync(&bdata->timer); | 432 | cancel_delayed_work_sync(&bdata->work); |
| 434 | 433 | else | |
| 435 | cancel_work_sync(&bdata->work); | 434 | del_timer_sync(&bdata->release_timer); |
| 436 | } | 435 | } |
| 437 | 436 | ||
| 438 | static int gpio_keys_setup_key(struct platform_device *pdev, | 437 | static int gpio_keys_setup_key(struct platform_device *pdev, |
| @@ -466,23 +465,25 @@ static int gpio_keys_setup_key(struct platform_device *pdev, | |||
| 466 | button->debounce_interval * 1000); | 465 | button->debounce_interval * 1000); |
| 467 | /* use timer if gpiolib doesn't provide debounce */ | 466 | /* use timer if gpiolib doesn't provide debounce */ |
| 468 | if (error < 0) | 467 | if (error < 0) |
| 469 | bdata->timer_debounce = | 468 | bdata->software_debounce = |
| 470 | button->debounce_interval; | 469 | button->debounce_interval; |
| 471 | } | 470 | } |
| 472 | 471 | ||
| 473 | irq = gpio_to_irq(button->gpio); | 472 | if (button->irq) { |
| 474 | if (irq < 0) { | 473 | bdata->irq = button->irq; |
| 475 | error = irq; | 474 | } else { |
| 476 | dev_err(dev, | 475 | irq = gpio_to_irq(button->gpio); |
| 477 | "Unable to get irq number for GPIO %d, error %d\n", | 476 | if (irq < 0) { |
| 478 | button->gpio, error); | 477 | error = irq; |
| 479 | return error; | 478 | dev_err(dev, |
| 479 | "Unable to get irq number for GPIO %d, error %d\n", | ||
| 480 | button->gpio, error); | ||
| 481 | return error; | ||
| 482 | } | ||
| 483 | bdata->irq = irq; | ||
| 480 | } | 484 | } |
| 481 | bdata->irq = irq; | ||
| 482 | 485 | ||
| 483 | INIT_WORK(&bdata->work, gpio_keys_gpio_work_func); | 486 | INIT_DELAYED_WORK(&bdata->work, gpio_keys_gpio_work_func); |
| 484 | setup_timer(&bdata->timer, | ||
| 485 | gpio_keys_gpio_timer, (unsigned long)bdata); | ||
| 486 | 487 | ||
| 487 | isr = gpio_keys_gpio_isr; | 488 | isr = gpio_keys_gpio_isr; |
| 488 | irqflags = IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING; | 489 | irqflags = IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING; |
| @@ -499,8 +500,8 @@ static int gpio_keys_setup_key(struct platform_device *pdev, | |||
| 499 | return -EINVAL; | 500 | return -EINVAL; |
| 500 | } | 501 | } |
| 501 | 502 | ||
| 502 | bdata->timer_debounce = button->debounce_interval; | 503 | bdata->release_delay = button->debounce_interval; |
| 503 | setup_timer(&bdata->timer, | 504 | setup_timer(&bdata->release_timer, |
| 504 | gpio_keys_irq_timer, (unsigned long)bdata); | 505 | gpio_keys_irq_timer, (unsigned long)bdata); |
| 505 | 506 | ||
| 506 | isr = gpio_keys_irq_isr; | 507 | isr = gpio_keys_irq_isr; |
| @@ -510,7 +511,7 @@ static int gpio_keys_setup_key(struct platform_device *pdev, | |||
| 510 | input_set_capability(input, button->type ?: EV_KEY, button->code); | 511 | input_set_capability(input, button->type ?: EV_KEY, button->code); |
| 511 | 512 | ||
| 512 | /* | 513 | /* |
| 513 | * Install custom action to cancel debounce timer and | 514 | * Install custom action to cancel release timer and |
| 514 | * workqueue item. | 515 | * workqueue item. |
| 515 | */ | 516 | */ |
| 516 | error = devm_add_action(&pdev->dev, gpio_keys_quiesce_key, bdata); | 517 | error = devm_add_action(&pdev->dev, gpio_keys_quiesce_key, bdata); |
| @@ -618,33 +619,30 @@ gpio_keys_get_devtree_pdata(struct device *dev) | |||
| 618 | 619 | ||
| 619 | i = 0; | 620 | i = 0; |
| 620 | for_each_child_of_node(node, pp) { | 621 | for_each_child_of_node(node, pp) { |
| 621 | int gpio = -1; | ||
| 622 | enum of_gpio_flags flags; | 622 | enum of_gpio_flags flags; |
| 623 | 623 | ||
| 624 | button = &pdata->buttons[i++]; | 624 | button = &pdata->buttons[i++]; |
| 625 | 625 | ||
| 626 | if (!of_find_property(pp, "gpios", NULL)) { | 626 | button->gpio = of_get_gpio_flags(pp, 0, &flags); |
| 627 | button->irq = irq_of_parse_and_map(pp, 0); | 627 | if (button->gpio < 0) { |
| 628 | if (button->irq == 0) { | 628 | error = button->gpio; |
| 629 | i--; | 629 | if (error != -ENOENT) { |
| 630 | pdata->nbuttons--; | ||
| 631 | dev_warn(dev, "Found button without gpios or irqs\n"); | ||
| 632 | continue; | ||
| 633 | } | ||
| 634 | } else { | ||
| 635 | gpio = of_get_gpio_flags(pp, 0, &flags); | ||
| 636 | if (gpio < 0) { | ||
| 637 | error = gpio; | ||
| 638 | if (error != -EPROBE_DEFER) | 630 | if (error != -EPROBE_DEFER) |
| 639 | dev_err(dev, | 631 | dev_err(dev, |
| 640 | "Failed to get gpio flags, error: %d\n", | 632 | "Failed to get gpio flags, error: %d\n", |
| 641 | error); | 633 | error); |
| 642 | return ERR_PTR(error); | 634 | return ERR_PTR(error); |
| 643 | } | 635 | } |
| 636 | } else { | ||
| 637 | button->active_low = flags & OF_GPIO_ACTIVE_LOW; | ||
| 644 | } | 638 | } |
| 645 | 639 | ||
| 646 | button->gpio = gpio; | 640 | button->irq = irq_of_parse_and_map(pp, 0); |
| 647 | button->active_low = flags & OF_GPIO_ACTIVE_LOW; | 641 | |
| 642 | if (!gpio_is_valid(button->gpio) && !button->irq) { | ||
| 643 | dev_err(dev, "Found button without gpios or irqs\n"); | ||
| 644 | return ERR_PTR(-EINVAL); | ||
| 645 | } | ||
| 648 | 646 | ||
| 649 | if (of_property_read_u32(pp, "linux,code", &button->code)) { | 647 | if (of_property_read_u32(pp, "linux,code", &button->code)) { |
| 650 | dev_err(dev, "Button without keycode: 0x%x\n", | 648 | dev_err(dev, "Button without keycode: 0x%x\n", |
| @@ -659,6 +657,8 @@ gpio_keys_get_devtree_pdata(struct device *dev) | |||
| 659 | 657 | ||
| 660 | button->wakeup = !!of_get_property(pp, "gpio-key,wakeup", NULL); | 658 | button->wakeup = !!of_get_property(pp, "gpio-key,wakeup", NULL); |
| 661 | 659 | ||
| 660 | button->can_disable = !!of_get_property(pp, "linux,can-disable", NULL); | ||
| 661 | |||
| 662 | if (of_property_read_u32(pp, "debounce-interval", | 662 | if (of_property_read_u32(pp, "debounce-interval", |
| 663 | &button->debounce_interval)) | 663 | &button->debounce_interval)) |
| 664 | button->debounce_interval = 5; | 664 | button->debounce_interval = 5; |
diff --git a/drivers/input/keyboard/hil_kbd.c b/drivers/input/keyboard/hil_kbd.c index 610a8af795a1..5b152f25a8e1 100644 --- a/drivers/input/keyboard/hil_kbd.c +++ b/drivers/input/keyboard/hil_kbd.c | |||
| @@ -473,7 +473,7 @@ static int hil_dev_connect(struct serio *serio, struct serio_driver *drv) | |||
| 473 | if (error) | 473 | if (error) |
| 474 | goto bail1; | 474 | goto bail1; |
| 475 | 475 | ||
| 476 | init_completion(&dev->cmd_done); | 476 | reinit_completion(&dev->cmd_done); |
| 477 | serio_write(serio, 0); | 477 | serio_write(serio, 0); |
| 478 | serio_write(serio, 0); | 478 | serio_write(serio, 0); |
| 479 | serio_write(serio, HIL_PKT_CMD >> 8); | 479 | serio_write(serio, HIL_PKT_CMD >> 8); |
| @@ -482,7 +482,7 @@ static int hil_dev_connect(struct serio *serio, struct serio_driver *drv) | |||
| 482 | if (error) | 482 | if (error) |
| 483 | goto bail1; | 483 | goto bail1; |
| 484 | 484 | ||
| 485 | init_completion(&dev->cmd_done); | 485 | reinit_completion(&dev->cmd_done); |
| 486 | serio_write(serio, 0); | 486 | serio_write(serio, 0); |
| 487 | serio_write(serio, 0); | 487 | serio_write(serio, 0); |
| 488 | serio_write(serio, HIL_PKT_CMD >> 8); | 488 | serio_write(serio, HIL_PKT_CMD >> 8); |
| @@ -491,7 +491,7 @@ static int hil_dev_connect(struct serio *serio, struct serio_driver *drv) | |||
| 491 | if (error) | 491 | if (error) |
| 492 | goto bail1; | 492 | goto bail1; |
| 493 | 493 | ||
| 494 | init_completion(&dev->cmd_done); | 494 | reinit_completion(&dev->cmd_done); |
| 495 | serio_write(serio, 0); | 495 | serio_write(serio, 0); |
| 496 | serio_write(serio, 0); | 496 | serio_write(serio, 0); |
| 497 | serio_write(serio, HIL_PKT_CMD >> 8); | 497 | serio_write(serio, HIL_PKT_CMD >> 8); |
diff --git a/drivers/input/keyboard/stmpe-keypad.c b/drivers/input/keyboard/stmpe-keypad.c index ef5e67fb567e..fe6e3f22eed7 100644 --- a/drivers/input/keyboard/stmpe-keypad.c +++ b/drivers/input/keyboard/stmpe-keypad.c | |||
| @@ -45,13 +45,14 @@ | |||
| 45 | #define STMPE_KEYPAD_MAX_ROWS 8 | 45 | #define STMPE_KEYPAD_MAX_ROWS 8 |
| 46 | #define STMPE_KEYPAD_MAX_COLS 8 | 46 | #define STMPE_KEYPAD_MAX_COLS 8 |
| 47 | #define STMPE_KEYPAD_ROW_SHIFT 3 | 47 | #define STMPE_KEYPAD_ROW_SHIFT 3 |
| 48 | #define STMPE_KEYPAD_KEYMAP_SIZE \ | 48 | #define STMPE_KEYPAD_KEYMAP_MAX_SIZE \ |
| 49 | (STMPE_KEYPAD_MAX_ROWS * STMPE_KEYPAD_MAX_COLS) | 49 | (STMPE_KEYPAD_MAX_ROWS * STMPE_KEYPAD_MAX_COLS) |
| 50 | 50 | ||
| 51 | /** | 51 | /** |
| 52 | * struct stmpe_keypad_variant - model-specific attributes | 52 | * struct stmpe_keypad_variant - model-specific attributes |
| 53 | * @auto_increment: whether the KPC_DATA_BYTE register address | 53 | * @auto_increment: whether the KPC_DATA_BYTE register address |
| 54 | * auto-increments on multiple read | 54 | * auto-increments on multiple read |
| 55 | * @set_pullup: whether the pins need to have their pull-ups set | ||
| 55 | * @num_data: number of data bytes | 56 | * @num_data: number of data bytes |
| 56 | * @num_normal_data: number of normal keys' data bytes | 57 | * @num_normal_data: number of normal keys' data bytes |
| 57 | * @max_cols: maximum number of columns supported | 58 | * @max_cols: maximum number of columns supported |
| @@ -61,6 +62,7 @@ | |||
| 61 | */ | 62 | */ |
| 62 | struct stmpe_keypad_variant { | 63 | struct stmpe_keypad_variant { |
| 63 | bool auto_increment; | 64 | bool auto_increment; |
| 65 | bool set_pullup; | ||
| 64 | int num_data; | 66 | int num_data; |
| 65 | int num_normal_data; | 67 | int num_normal_data; |
| 66 | int max_cols; | 68 | int max_cols; |
| @@ -81,6 +83,7 @@ static const struct stmpe_keypad_variant stmpe_keypad_variants[] = { | |||
| 81 | }, | 83 | }, |
| 82 | [STMPE2401] = { | 84 | [STMPE2401] = { |
| 83 | .auto_increment = false, | 85 | .auto_increment = false, |
| 86 | .set_pullup = true, | ||
| 84 | .num_data = 3, | 87 | .num_data = 3, |
| 85 | .num_normal_data = 2, | 88 | .num_normal_data = 2, |
| 86 | .max_cols = 8, | 89 | .max_cols = 8, |
| @@ -90,6 +93,7 @@ static const struct stmpe_keypad_variant stmpe_keypad_variants[] = { | |||
| 90 | }, | 93 | }, |
| 91 | [STMPE2403] = { | 94 | [STMPE2403] = { |
| 92 | .auto_increment = true, | 95 | .auto_increment = true, |
| 96 | .set_pullup = true, | ||
| 93 | .num_data = 5, | 97 | .num_data = 5, |
| 94 | .num_normal_data = 3, | 98 | .num_normal_data = 3, |
| 95 | .max_cols = 8, | 99 | .max_cols = 8, |
| @@ -99,16 +103,30 @@ static const struct stmpe_keypad_variant stmpe_keypad_variants[] = { | |||
| 99 | }, | 103 | }, |
| 100 | }; | 104 | }; |
| 101 | 105 | ||
| 106 | /** | ||
| 107 | * struct stmpe_keypad - STMPE keypad state container | ||
| 108 | * @stmpe: pointer to parent STMPE device | ||
| 109 | * @input: spawned input device | ||
| 110 | * @variant: STMPE variant | ||
| 111 | * @debounce_ms: debounce interval, in ms. Maximum is | ||
| 112 | * %STMPE_KEYPAD_MAX_DEBOUNCE. | ||
| 113 | * @scan_count: number of key scanning cycles to confirm key data. | ||
| 114 | * Maximum is %STMPE_KEYPAD_MAX_SCAN_COUNT. | ||
| 115 | * @no_autorepeat: disable key autorepeat | ||
| 116 | * @rows: bitmask for the rows | ||
| 117 | * @cols: bitmask for the columns | ||
| 118 | * @keymap: the keymap | ||
| 119 | */ | ||
| 102 | struct stmpe_keypad { | 120 | struct stmpe_keypad { |
| 103 | struct stmpe *stmpe; | 121 | struct stmpe *stmpe; |
| 104 | struct input_dev *input; | 122 | struct input_dev *input; |
| 105 | const struct stmpe_keypad_variant *variant; | 123 | const struct stmpe_keypad_variant *variant; |
| 106 | const struct stmpe_keypad_platform_data *plat; | 124 | unsigned int debounce_ms; |
| 107 | 125 | unsigned int scan_count; | |
| 126 | bool no_autorepeat; | ||
| 108 | unsigned int rows; | 127 | unsigned int rows; |
| 109 | unsigned int cols; | 128 | unsigned int cols; |
| 110 | 129 | unsigned short keymap[STMPE_KEYPAD_KEYMAP_MAX_SIZE]; | |
| 111 | unsigned short keymap[STMPE_KEYPAD_KEYMAP_SIZE]; | ||
| 112 | }; | 130 | }; |
| 113 | 131 | ||
| 114 | static int stmpe_keypad_read_data(struct stmpe_keypad *keypad, u8 *data) | 132 | static int stmpe_keypad_read_data(struct stmpe_keypad *keypad, u8 *data) |
| @@ -171,7 +189,10 @@ static int stmpe_keypad_altfunc_init(struct stmpe_keypad *keypad) | |||
| 171 | unsigned int col_gpios = variant->col_gpios; | 189 | unsigned int col_gpios = variant->col_gpios; |
| 172 | unsigned int row_gpios = variant->row_gpios; | 190 | unsigned int row_gpios = variant->row_gpios; |
| 173 | struct stmpe *stmpe = keypad->stmpe; | 191 | struct stmpe *stmpe = keypad->stmpe; |
| 192 | u8 pureg = stmpe->regs[STMPE_IDX_GPPUR_LSB]; | ||
| 174 | unsigned int pins = 0; | 193 | unsigned int pins = 0; |
| 194 | unsigned int pu_pins = 0; | ||
| 195 | int ret; | ||
| 175 | int i; | 196 | int i; |
| 176 | 197 | ||
| 177 | /* | 198 | /* |
| @@ -188,8 +209,10 @@ static int stmpe_keypad_altfunc_init(struct stmpe_keypad *keypad) | |||
| 188 | for (i = 0; i < variant->max_cols; i++) { | 209 | for (i = 0; i < variant->max_cols; i++) { |
| 189 | int num = __ffs(col_gpios); | 210 | int num = __ffs(col_gpios); |
| 190 | 211 | ||
| 191 | if (keypad->cols & (1 << i)) | 212 | if (keypad->cols & (1 << i)) { |
| 192 | pins |= 1 << num; | 213 | pins |= 1 << num; |
| 214 | pu_pins |= 1 << num; | ||
| 215 | } | ||
| 193 | 216 | ||
| 194 | col_gpios &= ~(1 << num); | 217 | col_gpios &= ~(1 << num); |
| 195 | } | 218 | } |
| @@ -203,20 +226,43 @@ static int stmpe_keypad_altfunc_init(struct stmpe_keypad *keypad) | |||
| 203 | row_gpios &= ~(1 << num); | 226 | row_gpios &= ~(1 << num); |
| 204 | } | 227 | } |
| 205 | 228 | ||
| 206 | return stmpe_set_altfunc(stmpe, pins, STMPE_BLOCK_KEYPAD); | 229 | ret = stmpe_set_altfunc(stmpe, pins, STMPE_BLOCK_KEYPAD); |
| 230 | if (ret) | ||
| 231 | return ret; | ||
| 232 | |||
| 233 | /* | ||
| 234 | * On STMPE24xx, set pin bias to pull-up on all keypad input | ||
| 235 | * pins (columns), this incidentally happen to be maximum 8 pins | ||
| 236 | * and placed at GPIO0-7 so only the LSB of the pull up register | ||
| 237 | * ever needs to be written. | ||
| 238 | */ | ||
| 239 | if (variant->set_pullup) { | ||
| 240 | u8 val; | ||
| 241 | |||
| 242 | ret = stmpe_reg_read(stmpe, pureg); | ||
| 243 | if (ret) | ||
| 244 | return ret; | ||
| 245 | |||
| 246 | /* Do not touch unused pins, may be used for GPIO */ | ||
| 247 | val = ret & ~pu_pins; | ||
| 248 | val |= pu_pins; | ||
| 249 | |||
| 250 | ret = stmpe_reg_write(stmpe, pureg, val); | ||
| 251 | } | ||
| 252 | |||
| 253 | return 0; | ||
| 207 | } | 254 | } |
| 208 | 255 | ||
| 209 | static int stmpe_keypad_chip_init(struct stmpe_keypad *keypad) | 256 | static int stmpe_keypad_chip_init(struct stmpe_keypad *keypad) |
| 210 | { | 257 | { |
| 211 | const struct stmpe_keypad_platform_data *plat = keypad->plat; | ||
| 212 | const struct stmpe_keypad_variant *variant = keypad->variant; | 258 | const struct stmpe_keypad_variant *variant = keypad->variant; |
| 213 | struct stmpe *stmpe = keypad->stmpe; | 259 | struct stmpe *stmpe = keypad->stmpe; |
| 214 | int ret; | 260 | int ret; |
| 215 | 261 | ||
| 216 | if (plat->debounce_ms > STMPE_KEYPAD_MAX_DEBOUNCE) | 262 | if (keypad->debounce_ms > STMPE_KEYPAD_MAX_DEBOUNCE) |
| 217 | return -EINVAL; | 263 | return -EINVAL; |
| 218 | 264 | ||
| 219 | if (plat->scan_count > STMPE_KEYPAD_MAX_SCAN_COUNT) | 265 | if (keypad->scan_count > STMPE_KEYPAD_MAX_SCAN_COUNT) |
| 220 | return -EINVAL; | 266 | return -EINVAL; |
| 221 | 267 | ||
| 222 | ret = stmpe_enable(stmpe, STMPE_BLOCK_KEYPAD); | 268 | ret = stmpe_enable(stmpe, STMPE_BLOCK_KEYPAD); |
| @@ -245,7 +291,7 @@ static int stmpe_keypad_chip_init(struct stmpe_keypad *keypad) | |||
| 245 | 291 | ||
| 246 | ret = stmpe_set_bits(stmpe, STMPE_KPC_CTRL_MSB, | 292 | ret = stmpe_set_bits(stmpe, STMPE_KPC_CTRL_MSB, |
| 247 | STMPE_KPC_CTRL_MSB_SCAN_COUNT, | 293 | STMPE_KPC_CTRL_MSB_SCAN_COUNT, |
| 248 | plat->scan_count << 4); | 294 | keypad->scan_count << 4); |
| 249 | if (ret < 0) | 295 | if (ret < 0) |
| 250 | return ret; | 296 | return ret; |
| 251 | 297 | ||
| @@ -253,17 +299,18 @@ static int stmpe_keypad_chip_init(struct stmpe_keypad *keypad) | |||
| 253 | STMPE_KPC_CTRL_LSB_SCAN | | 299 | STMPE_KPC_CTRL_LSB_SCAN | |
| 254 | STMPE_KPC_CTRL_LSB_DEBOUNCE, | 300 | STMPE_KPC_CTRL_LSB_DEBOUNCE, |
| 255 | STMPE_KPC_CTRL_LSB_SCAN | | 301 | STMPE_KPC_CTRL_LSB_SCAN | |
| 256 | (plat->debounce_ms << 1)); | 302 | (keypad->debounce_ms << 1)); |
| 257 | } | 303 | } |
| 258 | 304 | ||
| 259 | static void stmpe_keypad_fill_used_pins(struct stmpe_keypad *keypad) | 305 | static void stmpe_keypad_fill_used_pins(struct stmpe_keypad *keypad, |
| 306 | u32 used_rows, u32 used_cols) | ||
| 260 | { | 307 | { |
| 261 | int row, col; | 308 | int row, col; |
| 262 | 309 | ||
| 263 | for (row = 0; row < STMPE_KEYPAD_MAX_ROWS; row++) { | 310 | for (row = 0; row < used_rows; row++) { |
| 264 | for (col = 0; col < STMPE_KEYPAD_MAX_COLS; col++) { | 311 | for (col = 0; col < used_cols; col++) { |
| 265 | int code = MATRIX_SCAN_CODE(row, col, | 312 | int code = MATRIX_SCAN_CODE(row, col, |
| 266 | STMPE_KEYPAD_ROW_SHIFT); | 313 | STMPE_KEYPAD_ROW_SHIFT); |
| 267 | if (keypad->keymap[code] != KEY_RESERVED) { | 314 | if (keypad->keymap[code] != KEY_RESERVED) { |
| 268 | keypad->rows |= 1 << row; | 315 | keypad->rows |= 1 << row; |
| 269 | keypad->cols |= 1 << col; | 316 | keypad->cols |= 1 << col; |
| @@ -272,51 +319,17 @@ static void stmpe_keypad_fill_used_pins(struct stmpe_keypad *keypad) | |||
| 272 | } | 319 | } |
| 273 | } | 320 | } |
| 274 | 321 | ||
| 275 | #ifdef CONFIG_OF | ||
| 276 | static const struct stmpe_keypad_platform_data * | ||
| 277 | stmpe_keypad_of_probe(struct device *dev) | ||
| 278 | { | ||
| 279 | struct device_node *np = dev->of_node; | ||
| 280 | struct stmpe_keypad_platform_data *plat; | ||
| 281 | |||
| 282 | if (!np) | ||
| 283 | return ERR_PTR(-ENODEV); | ||
| 284 | |||
| 285 | plat = devm_kzalloc(dev, sizeof(*plat), GFP_KERNEL); | ||
| 286 | if (!plat) | ||
| 287 | return ERR_PTR(-ENOMEM); | ||
| 288 | |||
| 289 | of_property_read_u32(np, "debounce-interval", &plat->debounce_ms); | ||
| 290 | of_property_read_u32(np, "st,scan-count", &plat->scan_count); | ||
| 291 | |||
| 292 | plat->no_autorepeat = of_property_read_bool(np, "st,no-autorepeat"); | ||
| 293 | |||
| 294 | return plat; | ||
| 295 | } | ||
| 296 | #else | ||
| 297 | static inline const struct stmpe_keypad_platform_data * | ||
| 298 | stmpe_keypad_of_probe(struct device *dev) | ||
| 299 | { | ||
| 300 | return ERR_PTR(-EINVAL); | ||
| 301 | } | ||
| 302 | #endif | ||
| 303 | |||
| 304 | static int stmpe_keypad_probe(struct platform_device *pdev) | 322 | static int stmpe_keypad_probe(struct platform_device *pdev) |
| 305 | { | 323 | { |
| 306 | struct stmpe *stmpe = dev_get_drvdata(pdev->dev.parent); | 324 | struct stmpe *stmpe = dev_get_drvdata(pdev->dev.parent); |
| 307 | const struct stmpe_keypad_platform_data *plat; | 325 | struct device_node *np = pdev->dev.of_node; |
| 308 | struct stmpe_keypad *keypad; | 326 | struct stmpe_keypad *keypad; |
| 309 | struct input_dev *input; | 327 | struct input_dev *input; |
| 328 | u32 rows; | ||
| 329 | u32 cols; | ||
| 310 | int error; | 330 | int error; |
| 311 | int irq; | 331 | int irq; |
| 312 | 332 | ||
| 313 | plat = stmpe->pdata->keypad; | ||
| 314 | if (!plat) { | ||
| 315 | plat = stmpe_keypad_of_probe(&pdev->dev); | ||
| 316 | if (IS_ERR(plat)) | ||
| 317 | return PTR_ERR(plat); | ||
| 318 | } | ||
| 319 | |||
| 320 | irq = platform_get_irq(pdev, 0); | 333 | irq = platform_get_irq(pdev, 0); |
| 321 | if (irq < 0) | 334 | if (irq < 0) |
| 322 | return irq; | 335 | return irq; |
| @@ -326,6 +339,13 @@ static int stmpe_keypad_probe(struct platform_device *pdev) | |||
| 326 | if (!keypad) | 339 | if (!keypad) |
| 327 | return -ENOMEM; | 340 | return -ENOMEM; |
| 328 | 341 | ||
| 342 | keypad->stmpe = stmpe; | ||
| 343 | keypad->variant = &stmpe_keypad_variants[stmpe->partnum]; | ||
| 344 | |||
| 345 | of_property_read_u32(np, "debounce-interval", &keypad->debounce_ms); | ||
| 346 | of_property_read_u32(np, "st,scan-count", &keypad->scan_count); | ||
| 347 | keypad->no_autorepeat = of_property_read_bool(np, "st,no-autorepeat"); | ||
| 348 | |||
| 329 | input = devm_input_allocate_device(&pdev->dev); | 349 | input = devm_input_allocate_device(&pdev->dev); |
| 330 | if (!input) | 350 | if (!input) |
| 331 | return -ENOMEM; | 351 | return -ENOMEM; |
| @@ -334,23 +354,22 @@ static int stmpe_keypad_probe(struct platform_device *pdev) | |||
| 334 | input->id.bustype = BUS_I2C; | 354 | input->id.bustype = BUS_I2C; |
| 335 | input->dev.parent = &pdev->dev; | 355 | input->dev.parent = &pdev->dev; |
| 336 | 356 | ||
| 337 | error = matrix_keypad_build_keymap(plat->keymap_data, NULL, | 357 | error = matrix_keypad_parse_of_params(&pdev->dev, &rows, &cols); |
| 338 | STMPE_KEYPAD_MAX_ROWS, | 358 | if (error) |
| 339 | STMPE_KEYPAD_MAX_COLS, | 359 | return error; |
| 360 | |||
| 361 | error = matrix_keypad_build_keymap(NULL, NULL, rows, cols, | ||
| 340 | keypad->keymap, input); | 362 | keypad->keymap, input); |
| 341 | if (error) | 363 | if (error) |
| 342 | return error; | 364 | return error; |
| 343 | 365 | ||
| 344 | input_set_capability(input, EV_MSC, MSC_SCAN); | 366 | input_set_capability(input, EV_MSC, MSC_SCAN); |
| 345 | if (!plat->no_autorepeat) | 367 | if (!keypad->no_autorepeat) |
| 346 | __set_bit(EV_REP, input->evbit); | 368 | __set_bit(EV_REP, input->evbit); |
| 347 | 369 | ||
| 348 | stmpe_keypad_fill_used_pins(keypad); | 370 | stmpe_keypad_fill_used_pins(keypad, rows, cols); |
| 349 | 371 | ||
| 350 | keypad->stmpe = stmpe; | ||
| 351 | keypad->plat = plat; | ||
| 352 | keypad->input = input; | 372 | keypad->input = input; |
| 353 | keypad->variant = &stmpe_keypad_variants[stmpe->partnum]; | ||
| 354 | 373 | ||
| 355 | error = stmpe_keypad_chip_init(keypad); | 374 | error = stmpe_keypad_chip_init(keypad); |
| 356 | if (error < 0) | 375 | if (error < 0) |
diff --git a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c index d125a019383f..d88d73d83552 100644 --- a/drivers/input/mouse/alps.c +++ b/drivers/input/mouse/alps.c | |||
| @@ -881,6 +881,34 @@ static void alps_get_finger_coordinate_v7(struct input_mt_pos *mt, | |||
| 881 | unsigned char *pkt, | 881 | unsigned char *pkt, |
| 882 | unsigned char pkt_id) | 882 | unsigned char pkt_id) |
| 883 | { | 883 | { |
| 884 | /* | ||
| 885 | * packet-fmt b7 b6 b5 b4 b3 b2 b1 b0 | ||
| 886 | * Byte0 TWO & MULTI L 1 R M 1 Y0-2 Y0-1 Y0-0 | ||
| 887 | * Byte0 NEW L 1 X1-5 1 1 Y0-2 Y0-1 Y0-0 | ||
| 888 | * Byte1 Y0-10 Y0-9 Y0-8 Y0-7 Y0-6 Y0-5 Y0-4 Y0-3 | ||
| 889 | * Byte2 X0-11 1 X0-10 X0-9 X0-8 X0-7 X0-6 X0-5 | ||
| 890 | * Byte3 X1-11 1 X0-4 X0-3 1 X0-2 X0-1 X0-0 | ||
| 891 | * Byte4 TWO X1-10 TWO X1-9 X1-8 X1-7 X1-6 X1-5 X1-4 | ||
| 892 | * Byte4 MULTI X1-10 TWO X1-9 X1-8 X1-7 X1-6 Y1-5 1 | ||
| 893 | * Byte4 NEW X1-10 TWO X1-9 X1-8 X1-7 X1-6 0 0 | ||
| 894 | * Byte5 TWO & NEW Y1-10 0 Y1-9 Y1-8 Y1-7 Y1-6 Y1-5 Y1-4 | ||
| 895 | * Byte5 MULTI Y1-10 0 Y1-9 Y1-8 Y1-7 Y1-6 F-1 F-0 | ||
| 896 | * L: Left button | ||
| 897 | * R / M: Non-clickpads: Right / Middle button | ||
| 898 | * Clickpads: When > 2 fingers are down, and some fingers | ||
| 899 | * are in the button area, then the 2 coordinates reported | ||
| 900 | * are for fingers outside the button area and these report | ||
| 901 | * extra fingers being present in the right / left button | ||
| 902 | * area. Note these fingers are not added to the F field! | ||
| 903 | * so if a TWO packet is received and R = 1 then there are | ||
| 904 | * 3 fingers down, etc. | ||
| 905 | * TWO: 1: Two touches present, byte 0/4/5 are in TWO fmt | ||
| 906 | * 0: If byte 4 bit 0 is 1, then byte 0/4/5 are in MULTI fmt | ||
| 907 | * otherwise byte 0 bit 4 must be set and byte 0/4/5 are | ||
| 908 | * in NEW fmt | ||
| 909 | * F: Number of fingers - 3, 0 means 3 fingers, 1 means 4 ... | ||
| 910 | */ | ||
| 911 | |||
| 884 | mt[0].x = ((pkt[2] & 0x80) << 4); | 912 | mt[0].x = ((pkt[2] & 0x80) << 4); |
| 885 | mt[0].x |= ((pkt[2] & 0x3F) << 5); | 913 | mt[0].x |= ((pkt[2] & 0x3F) << 5); |
| 886 | mt[0].x |= ((pkt[3] & 0x30) >> 1); | 914 | mt[0].x |= ((pkt[3] & 0x30) >> 1); |
| @@ -919,18 +947,21 @@ static void alps_get_finger_coordinate_v7(struct input_mt_pos *mt, | |||
| 919 | 947 | ||
| 920 | static int alps_get_mt_count(struct input_mt_pos *mt) | 948 | static int alps_get_mt_count(struct input_mt_pos *mt) |
| 921 | { | 949 | { |
| 922 | int i; | 950 | int i, fingers = 0; |
| 923 | 951 | ||
| 924 | for (i = 0; i < MAX_TOUCHES && mt[i].x != 0 && mt[i].y != 0; i++) | 952 | for (i = 0; i < MAX_TOUCHES; i++) { |
| 925 | /* empty */; | 953 | if (mt[i].x != 0 || mt[i].y != 0) |
| 954 | fingers++; | ||
| 955 | } | ||
| 926 | 956 | ||
| 927 | return i; | 957 | return fingers; |
| 928 | } | 958 | } |
| 929 | 959 | ||
| 930 | static int alps_decode_packet_v7(struct alps_fields *f, | 960 | static int alps_decode_packet_v7(struct alps_fields *f, |
| 931 | unsigned char *p, | 961 | unsigned char *p, |
| 932 | struct psmouse *psmouse) | 962 | struct psmouse *psmouse) |
| 933 | { | 963 | { |
| 964 | struct alps_data *priv = psmouse->private; | ||
| 934 | unsigned char pkt_id; | 965 | unsigned char pkt_id; |
| 935 | 966 | ||
| 936 | pkt_id = alps_get_packet_id_v7(p); | 967 | pkt_id = alps_get_packet_id_v7(p); |
| @@ -938,19 +969,52 @@ static int alps_decode_packet_v7(struct alps_fields *f, | |||
| 938 | return 0; | 969 | return 0; |
| 939 | if (pkt_id == V7_PACKET_ID_UNKNOWN) | 970 | if (pkt_id == V7_PACKET_ID_UNKNOWN) |
| 940 | return -1; | 971 | return -1; |
| 972 | /* | ||
| 973 | * NEW packets are send to indicate a discontinuity in the finger | ||
| 974 | * coordinate reporting. Specifically a finger may have moved from | ||
| 975 | * slot 0 to 1 or vice versa. INPUT_MT_TRACK takes care of this for | ||
| 976 | * us. | ||
| 977 | * | ||
| 978 | * NEW packets have 3 problems: | ||
| 979 | * 1) They do not contain middle / right button info (on non clickpads) | ||
| 980 | * this can be worked around by preserving the old button state | ||
| 981 | * 2) They do not contain an accurate fingercount, and they are | ||
| 982 | * typically send when the number of fingers changes. We cannot use | ||
| 983 | * the old finger count as that may mismatch with the amount of | ||
| 984 | * touch coordinates we've available in the NEW packet | ||
| 985 | * 3) Their x data for the second touch is inaccurate leading to | ||
| 986 | * a possible jump of the x coordinate by 16 units when the first | ||
| 987 | * non NEW packet comes in | ||
| 988 | * Since problems 2 & 3 cannot be worked around, just ignore them. | ||
| 989 | */ | ||
| 990 | if (pkt_id == V7_PACKET_ID_NEW) | ||
| 991 | return 1; | ||
| 941 | 992 | ||
| 942 | alps_get_finger_coordinate_v7(f->mt, p, pkt_id); | 993 | alps_get_finger_coordinate_v7(f->mt, p, pkt_id); |
| 943 | 994 | ||
| 944 | if (pkt_id == V7_PACKET_ID_TWO || pkt_id == V7_PACKET_ID_MULTI) { | 995 | if (pkt_id == V7_PACKET_ID_TWO) |
| 945 | f->left = (p[0] & 0x80) >> 7; | 996 | f->fingers = alps_get_mt_count(f->mt); |
| 997 | else /* pkt_id == V7_PACKET_ID_MULTI */ | ||
| 998 | f->fingers = 3 + (p[5] & 0x03); | ||
| 999 | |||
| 1000 | f->left = (p[0] & 0x80) >> 7; | ||
| 1001 | if (priv->flags & ALPS_BUTTONPAD) { | ||
| 1002 | if (p[0] & 0x20) | ||
| 1003 | f->fingers++; | ||
| 1004 | if (p[0] & 0x10) | ||
| 1005 | f->fingers++; | ||
| 1006 | } else { | ||
| 946 | f->right = (p[0] & 0x20) >> 5; | 1007 | f->right = (p[0] & 0x20) >> 5; |
| 947 | f->middle = (p[0] & 0x10) >> 4; | 1008 | f->middle = (p[0] & 0x10) >> 4; |
| 948 | } | 1009 | } |
| 949 | 1010 | ||
| 950 | if (pkt_id == V7_PACKET_ID_TWO) | 1011 | /* Sometimes a single touch is reported in mt[1] rather then mt[0] */ |
| 951 | f->fingers = alps_get_mt_count(f->mt); | 1012 | if (f->fingers == 1 && f->mt[0].x == 0 && f->mt[0].y == 0) { |
| 952 | else if (pkt_id == V7_PACKET_ID_MULTI) | 1013 | f->mt[0].x = f->mt[1].x; |
| 953 | f->fingers = 3 + (p[5] & 0x03); | 1014 | f->mt[0].y = f->mt[1].y; |
| 1015 | f->mt[1].x = 0; | ||
| 1016 | f->mt[1].y = 0; | ||
| 1017 | } | ||
| 954 | 1018 | ||
| 955 | return 0; | 1019 | return 0; |
| 956 | } | 1020 | } |
diff --git a/drivers/input/mouse/trackpoint.c b/drivers/input/mouse/trackpoint.c index 30c8b6998808..354d47ecd66a 100644 --- a/drivers/input/mouse/trackpoint.c +++ b/drivers/input/mouse/trackpoint.c | |||
| @@ -227,6 +227,7 @@ TRACKPOINT_INT_ATTR(thresh, TP_THRESH, TP_DEF_THRESH); | |||
| 227 | TRACKPOINT_INT_ATTR(upthresh, TP_UP_THRESH, TP_DEF_UP_THRESH); | 227 | TRACKPOINT_INT_ATTR(upthresh, TP_UP_THRESH, TP_DEF_UP_THRESH); |
| 228 | TRACKPOINT_INT_ATTR(ztime, TP_Z_TIME, TP_DEF_Z_TIME); | 228 | TRACKPOINT_INT_ATTR(ztime, TP_Z_TIME, TP_DEF_Z_TIME); |
| 229 | TRACKPOINT_INT_ATTR(jenks, TP_JENKS_CURV, TP_DEF_JENKS_CURV); | 229 | TRACKPOINT_INT_ATTR(jenks, TP_JENKS_CURV, TP_DEF_JENKS_CURV); |
| 230 | TRACKPOINT_INT_ATTR(drift_time, TP_DRIFT_TIME, TP_DEF_DRIFT_TIME); | ||
| 230 | 231 | ||
| 231 | TRACKPOINT_BIT_ATTR(press_to_select, TP_TOGGLE_PTSON, TP_MASK_PTSON, 0, | 232 | TRACKPOINT_BIT_ATTR(press_to_select, TP_TOGGLE_PTSON, TP_MASK_PTSON, 0, |
| 232 | TP_DEF_PTSON); | 233 | TP_DEF_PTSON); |
| @@ -246,6 +247,7 @@ static struct attribute *trackpoint_attrs[] = { | |||
| 246 | &psmouse_attr_upthresh.dattr.attr, | 247 | &psmouse_attr_upthresh.dattr.attr, |
| 247 | &psmouse_attr_ztime.dattr.attr, | 248 | &psmouse_attr_ztime.dattr.attr, |
| 248 | &psmouse_attr_jenks.dattr.attr, | 249 | &psmouse_attr_jenks.dattr.attr, |
| 250 | &psmouse_attr_drift_time.dattr.attr, | ||
| 249 | &psmouse_attr_press_to_select.dattr.attr, | 251 | &psmouse_attr_press_to_select.dattr.attr, |
| 250 | &psmouse_attr_skipback.dattr.attr, | 252 | &psmouse_attr_skipback.dattr.attr, |
| 251 | &psmouse_attr_ext_dev.dattr.attr, | 253 | &psmouse_attr_ext_dev.dattr.attr, |
| @@ -312,6 +314,7 @@ static int trackpoint_sync(struct psmouse *psmouse, bool in_power_on_state) | |||
| 312 | TRACKPOINT_UPDATE(in_power_on_state, psmouse, tp, upthresh); | 314 | TRACKPOINT_UPDATE(in_power_on_state, psmouse, tp, upthresh); |
| 313 | TRACKPOINT_UPDATE(in_power_on_state, psmouse, tp, ztime); | 315 | TRACKPOINT_UPDATE(in_power_on_state, psmouse, tp, ztime); |
| 314 | TRACKPOINT_UPDATE(in_power_on_state, psmouse, tp, jenks); | 316 | TRACKPOINT_UPDATE(in_power_on_state, psmouse, tp, jenks); |
| 317 | TRACKPOINT_UPDATE(in_power_on_state, psmouse, tp, drift_time); | ||
| 315 | 318 | ||
| 316 | /* toggles */ | 319 | /* toggles */ |
| 317 | TRACKPOINT_UPDATE(in_power_on_state, psmouse, tp, press_to_select); | 320 | TRACKPOINT_UPDATE(in_power_on_state, psmouse, tp, press_to_select); |
| @@ -332,6 +335,7 @@ static void trackpoint_defaults(struct trackpoint_data *tp) | |||
| 332 | TRACKPOINT_SET_POWER_ON_DEFAULT(tp, upthresh); | 335 | TRACKPOINT_SET_POWER_ON_DEFAULT(tp, upthresh); |
| 333 | TRACKPOINT_SET_POWER_ON_DEFAULT(tp, ztime); | 336 | TRACKPOINT_SET_POWER_ON_DEFAULT(tp, ztime); |
| 334 | TRACKPOINT_SET_POWER_ON_DEFAULT(tp, jenks); | 337 | TRACKPOINT_SET_POWER_ON_DEFAULT(tp, jenks); |
| 338 | TRACKPOINT_SET_POWER_ON_DEFAULT(tp, drift_time); | ||
| 335 | TRACKPOINT_SET_POWER_ON_DEFAULT(tp, inertia); | 339 | TRACKPOINT_SET_POWER_ON_DEFAULT(tp, inertia); |
| 336 | 340 | ||
| 337 | /* toggles */ | 341 | /* toggles */ |
diff --git a/drivers/input/mouse/trackpoint.h b/drivers/input/mouse/trackpoint.h index ecd0547964a5..5617ed3a7d7a 100644 --- a/drivers/input/mouse/trackpoint.h +++ b/drivers/input/mouse/trackpoint.h | |||
| @@ -70,6 +70,9 @@ | |||
| 70 | #define TP_UP_THRESH 0x5A /* Used to generate a 'click' on Z-axis */ | 70 | #define TP_UP_THRESH 0x5A /* Used to generate a 'click' on Z-axis */ |
| 71 | #define TP_Z_TIME 0x5E /* How sharp of a press */ | 71 | #define TP_Z_TIME 0x5E /* How sharp of a press */ |
| 72 | #define TP_JENKS_CURV 0x5D /* Minimum curvature for double click */ | 72 | #define TP_JENKS_CURV 0x5D /* Minimum curvature for double click */ |
| 73 | #define TP_DRIFT_TIME 0x5F /* How long a 'hands off' condition */ | ||
| 74 | /* must last (x*107ms) for drift */ | ||
| 75 | /* correction to occur */ | ||
| 73 | 76 | ||
| 74 | /* | 77 | /* |
| 75 | * Toggling Flag bits | 78 | * Toggling Flag bits |
| @@ -120,6 +123,7 @@ | |||
| 120 | #define TP_DEF_UP_THRESH 0xFF | 123 | #define TP_DEF_UP_THRESH 0xFF |
| 121 | #define TP_DEF_Z_TIME 0x26 | 124 | #define TP_DEF_Z_TIME 0x26 |
| 122 | #define TP_DEF_JENKS_CURV 0x87 | 125 | #define TP_DEF_JENKS_CURV 0x87 |
| 126 | #define TP_DEF_DRIFT_TIME 0x05 | ||
| 123 | 127 | ||
| 124 | /* Toggles */ | 128 | /* Toggles */ |
| 125 | #define TP_DEF_MB 0x00 | 129 | #define TP_DEF_MB 0x00 |
| @@ -137,6 +141,7 @@ struct trackpoint_data | |||
| 137 | unsigned char draghys, mindrag; | 141 | unsigned char draghys, mindrag; |
| 138 | unsigned char thresh, upthresh; | 142 | unsigned char thresh, upthresh; |
| 139 | unsigned char ztime, jenks; | 143 | unsigned char ztime, jenks; |
| 144 | unsigned char drift_time; | ||
| 140 | 145 | ||
| 141 | /* toggles */ | 146 | /* toggles */ |
| 142 | unsigned char press_to_select; | 147 | unsigned char press_to_select; |
diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c index bb070206223c..95ee92a91bd2 100644 --- a/drivers/input/touchscreen/atmel_mxt_ts.c +++ b/drivers/input/touchscreen/atmel_mxt_ts.c | |||
| @@ -99,13 +99,9 @@ | |||
| 99 | #define MXT_T6_STATUS_COMSERR (1 << 2) | 99 | #define MXT_T6_STATUS_COMSERR (1 << 2) |
| 100 | 100 | ||
| 101 | /* MXT_GEN_POWER_T7 field */ | 101 | /* MXT_GEN_POWER_T7 field */ |
| 102 | struct t7_config { | 102 | #define MXT_POWER_IDLEACQINT 0 |
| 103 | u8 idle; | 103 | #define MXT_POWER_ACTVACQINT 1 |
| 104 | u8 active; | 104 | #define MXT_POWER_ACTV2IDLETO 2 |
| 105 | } __packed; | ||
| 106 | |||
| 107 | #define MXT_POWER_CFG_RUN 0 | ||
| 108 | #define MXT_POWER_CFG_DEEPSLEEP 1 | ||
| 109 | 105 | ||
| 110 | /* MXT_GEN_ACQUIRE_T8 field */ | 106 | /* MXT_GEN_ACQUIRE_T8 field */ |
| 111 | #define MXT_ACQUIRE_CHRGTIME 0 | 107 | #define MXT_ACQUIRE_CHRGTIME 0 |
| @@ -117,6 +113,7 @@ struct t7_config { | |||
| 117 | #define MXT_ACQUIRE_ATCHCALSTHR 7 | 113 | #define MXT_ACQUIRE_ATCHCALSTHR 7 |
| 118 | 114 | ||
| 119 | /* MXT_TOUCH_MULTI_T9 field */ | 115 | /* MXT_TOUCH_MULTI_T9 field */ |
| 116 | #define MXT_TOUCH_CTRL 0 | ||
| 120 | #define MXT_T9_ORIENT 9 | 117 | #define MXT_T9_ORIENT 9 |
| 121 | #define MXT_T9_RANGE 18 | 118 | #define MXT_T9_RANGE 18 |
| 122 | 119 | ||
| @@ -256,7 +253,6 @@ struct mxt_data { | |||
| 256 | bool update_input; | 253 | bool update_input; |
| 257 | u8 last_message_count; | 254 | u8 last_message_count; |
| 258 | u8 num_touchids; | 255 | u8 num_touchids; |
| 259 | struct t7_config t7_cfg; | ||
| 260 | 256 | ||
| 261 | /* Cached parameters from object table */ | 257 | /* Cached parameters from object table */ |
| 262 | u16 T5_address; | 258 | u16 T5_address; |
| @@ -672,6 +668,20 @@ static void mxt_proc_t6_messages(struct mxt_data *data, u8 *msg) | |||
| 672 | data->t6_status = status; | 668 | data->t6_status = status; |
| 673 | } | 669 | } |
| 674 | 670 | ||
| 671 | static int mxt_write_object(struct mxt_data *data, | ||
| 672 | u8 type, u8 offset, u8 val) | ||
| 673 | { | ||
| 674 | struct mxt_object *object; | ||
| 675 | u16 reg; | ||
| 676 | |||
| 677 | object = mxt_get_object(data, type); | ||
| 678 | if (!object || offset >= mxt_obj_size(object)) | ||
| 679 | return -EINVAL; | ||
| 680 | |||
| 681 | reg = object->start_address; | ||
| 682 | return mxt_write_reg(data->client, reg + offset, val); | ||
| 683 | } | ||
| 684 | |||
| 675 | static void mxt_input_button(struct mxt_data *data, u8 *message) | 685 | static void mxt_input_button(struct mxt_data *data, u8 *message) |
| 676 | { | 686 | { |
| 677 | struct input_dev *input = data->input_dev; | 687 | struct input_dev *input = data->input_dev; |
| @@ -1742,60 +1752,6 @@ err_free_object_table: | |||
| 1742 | return error; | 1752 | return error; |
| 1743 | } | 1753 | } |
| 1744 | 1754 | ||
| 1745 | static int mxt_set_t7_power_cfg(struct mxt_data *data, u8 sleep) | ||
| 1746 | { | ||
| 1747 | struct device *dev = &data->client->dev; | ||
| 1748 | int error; | ||
| 1749 | struct t7_config *new_config; | ||
| 1750 | struct t7_config deepsleep = { .active = 0, .idle = 0 }; | ||
| 1751 | |||
| 1752 | if (sleep == MXT_POWER_CFG_DEEPSLEEP) | ||
| 1753 | new_config = &deepsleep; | ||
| 1754 | else | ||
| 1755 | new_config = &data->t7_cfg; | ||
| 1756 | |||
| 1757 | error = __mxt_write_reg(data->client, data->T7_address, | ||
| 1758 | sizeof(data->t7_cfg), new_config); | ||
| 1759 | if (error) | ||
| 1760 | return error; | ||
| 1761 | |||
| 1762 | dev_dbg(dev, "Set T7 ACTV:%d IDLE:%d\n", | ||
| 1763 | new_config->active, new_config->idle); | ||
| 1764 | |||
| 1765 | return 0; | ||
| 1766 | } | ||
| 1767 | |||
| 1768 | static int mxt_init_t7_power_cfg(struct mxt_data *data) | ||
| 1769 | { | ||
| 1770 | struct device *dev = &data->client->dev; | ||
| 1771 | int error; | ||
| 1772 | bool retry = false; | ||
| 1773 | |||
| 1774 | recheck: | ||
| 1775 | error = __mxt_read_reg(data->client, data->T7_address, | ||
| 1776 | sizeof(data->t7_cfg), &data->t7_cfg); | ||
| 1777 | if (error) | ||
| 1778 | return error; | ||
| 1779 | |||
| 1780 | if (data->t7_cfg.active == 0 || data->t7_cfg.idle == 0) { | ||
| 1781 | if (!retry) { | ||
| 1782 | dev_dbg(dev, "T7 cfg zero, resetting\n"); | ||
| 1783 | mxt_soft_reset(data); | ||
| 1784 | retry = true; | ||
| 1785 | goto recheck; | ||
| 1786 | } else { | ||
| 1787 | dev_dbg(dev, "T7 cfg zero after reset, overriding\n"); | ||
| 1788 | data->t7_cfg.active = 20; | ||
| 1789 | data->t7_cfg.idle = 100; | ||
| 1790 | return mxt_set_t7_power_cfg(data, MXT_POWER_CFG_RUN); | ||
| 1791 | } | ||
| 1792 | } | ||
| 1793 | |||
| 1794 | dev_dbg(dev, "Initialized power cfg: ACTV %d, IDLE %d\n", | ||
| 1795 | data->t7_cfg.active, data->t7_cfg.idle); | ||
| 1796 | return 0; | ||
| 1797 | } | ||
| 1798 | |||
| 1799 | static int mxt_configure_objects(struct mxt_data *data, | 1755 | static int mxt_configure_objects(struct mxt_data *data, |
| 1800 | const struct firmware *cfg) | 1756 | const struct firmware *cfg) |
| 1801 | { | 1757 | { |
| @@ -1809,12 +1765,6 @@ static int mxt_configure_objects(struct mxt_data *data, | |||
| 1809 | dev_warn(dev, "Error %d updating config\n", error); | 1765 | dev_warn(dev, "Error %d updating config\n", error); |
| 1810 | } | 1766 | } |
| 1811 | 1767 | ||
| 1812 | error = mxt_init_t7_power_cfg(data); | ||
| 1813 | if (error) { | ||
| 1814 | dev_err(dev, "Failed to initialize power cfg\n"); | ||
| 1815 | return error; | ||
| 1816 | } | ||
| 1817 | |||
| 1818 | error = mxt_initialize_t9_input_device(data); | 1768 | error = mxt_initialize_t9_input_device(data); |
| 1819 | if (error) | 1769 | if (error) |
| 1820 | return error; | 1770 | return error; |
| @@ -2093,15 +2043,16 @@ static const struct attribute_group mxt_attr_group = { | |||
| 2093 | 2043 | ||
| 2094 | static void mxt_start(struct mxt_data *data) | 2044 | static void mxt_start(struct mxt_data *data) |
| 2095 | { | 2045 | { |
| 2096 | mxt_set_t7_power_cfg(data, MXT_POWER_CFG_RUN); | 2046 | /* Touch enable */ |
| 2097 | 2047 | mxt_write_object(data, | |
| 2098 | /* Recalibrate since chip has been in deep sleep */ | 2048 | MXT_TOUCH_MULTI_T9, MXT_TOUCH_CTRL, 0x83); |
| 2099 | mxt_t6_command(data, MXT_COMMAND_CALIBRATE, 1, false); | ||
| 2100 | } | 2049 | } |
| 2101 | 2050 | ||
| 2102 | static void mxt_stop(struct mxt_data *data) | 2051 | static void mxt_stop(struct mxt_data *data) |
| 2103 | { | 2052 | { |
| 2104 | mxt_set_t7_power_cfg(data, MXT_POWER_CFG_DEEPSLEEP); | 2053 | /* Touch disable */ |
| 2054 | mxt_write_object(data, | ||
| 2055 | MXT_TOUCH_MULTI_T9, MXT_TOUCH_CTRL, 0); | ||
| 2105 | } | 2056 | } |
| 2106 | 2057 | ||
| 2107 | static int mxt_input_open(struct input_dev *dev) | 2058 | static int mxt_input_open(struct input_dev *dev) |
| @@ -2266,6 +2217,8 @@ static int __maybe_unused mxt_resume(struct device *dev) | |||
| 2266 | struct mxt_data *data = i2c_get_clientdata(client); | 2217 | struct mxt_data *data = i2c_get_clientdata(client); |
| 2267 | struct input_dev *input_dev = data->input_dev; | 2218 | struct input_dev *input_dev = data->input_dev; |
| 2268 | 2219 | ||
| 2220 | mxt_soft_reset(data); | ||
| 2221 | |||
| 2269 | mutex_lock(&input_dev->mutex); | 2222 | mutex_lock(&input_dev->mutex); |
| 2270 | 2223 | ||
| 2271 | if (input_dev->users) | 2224 | if (input_dev->users) |
diff --git a/drivers/input/touchscreen/edt-ft5x06.c b/drivers/input/touchscreen/edt-ft5x06.c index 3793fcc7e5db..d4c24fb7704f 100644 --- a/drivers/input/touchscreen/edt-ft5x06.c +++ b/drivers/input/touchscreen/edt-ft5x06.c | |||
| @@ -850,9 +850,11 @@ static int edt_ft5x06_ts_identify(struct i2c_client *client, | |||
| 850 | } | 850 | } |
| 851 | 851 | ||
| 852 | #define EDT_ATTR_CHECKSET(name, reg) \ | 852 | #define EDT_ATTR_CHECKSET(name, reg) \ |
| 853 | do { \ | ||
| 853 | if (pdata->name >= edt_ft5x06_attr_##name.limit_low && \ | 854 | if (pdata->name >= edt_ft5x06_attr_##name.limit_low && \ |
| 854 | pdata->name <= edt_ft5x06_attr_##name.limit_high) \ | 855 | pdata->name <= edt_ft5x06_attr_##name.limit_high) \ |
| 855 | edt_ft5x06_register_write(tsdata, reg, pdata->name) | 856 | edt_ft5x06_register_write(tsdata, reg, pdata->name); \ |
| 857 | } while (0) | ||
| 856 | 858 | ||
| 857 | #define EDT_GET_PROP(name, reg) { \ | 859 | #define EDT_GET_PROP(name, reg) { \ |
| 858 | u32 val; \ | 860 | u32 val; \ |
diff --git a/drivers/md/dm-thin.c b/drivers/md/dm-thin.c index 8735543eacdb..493478989dbd 100644 --- a/drivers/md/dm-thin.c +++ b/drivers/md/dm-thin.c | |||
| @@ -1127,6 +1127,24 @@ static void schedule_external_copy(struct thin_c *tc, dm_block_t virt_block, | |||
| 1127 | schedule_zero(tc, virt_block, data_dest, cell, bio); | 1127 | schedule_zero(tc, virt_block, data_dest, cell, bio); |
| 1128 | } | 1128 | } |
| 1129 | 1129 | ||
| 1130 | static void set_pool_mode(struct pool *pool, enum pool_mode new_mode); | ||
| 1131 | |||
| 1132 | static void check_for_space(struct pool *pool) | ||
| 1133 | { | ||
| 1134 | int r; | ||
| 1135 | dm_block_t nr_free; | ||
| 1136 | |||
| 1137 | if (get_pool_mode(pool) != PM_OUT_OF_DATA_SPACE) | ||
| 1138 | return; | ||
| 1139 | |||
| 1140 | r = dm_pool_get_free_block_count(pool->pmd, &nr_free); | ||
| 1141 | if (r) | ||
| 1142 | return; | ||
| 1143 | |||
| 1144 | if (nr_free) | ||
| 1145 | set_pool_mode(pool, PM_WRITE); | ||
| 1146 | } | ||
| 1147 | |||
| 1130 | /* | 1148 | /* |
| 1131 | * A non-zero return indicates read_only or fail_io mode. | 1149 | * A non-zero return indicates read_only or fail_io mode. |
| 1132 | * Many callers don't care about the return value. | 1150 | * Many callers don't care about the return value. |
| @@ -1141,6 +1159,8 @@ static int commit(struct pool *pool) | |||
| 1141 | r = dm_pool_commit_metadata(pool->pmd); | 1159 | r = dm_pool_commit_metadata(pool->pmd); |
| 1142 | if (r) | 1160 | if (r) |
| 1143 | metadata_operation_failed(pool, "dm_pool_commit_metadata", r); | 1161 | metadata_operation_failed(pool, "dm_pool_commit_metadata", r); |
| 1162 | else | ||
| 1163 | check_for_space(pool); | ||
| 1144 | 1164 | ||
| 1145 | return r; | 1165 | return r; |
| 1146 | } | 1166 | } |
| @@ -1159,8 +1179,6 @@ static void check_low_water_mark(struct pool *pool, dm_block_t free_blocks) | |||
| 1159 | } | 1179 | } |
| 1160 | } | 1180 | } |
| 1161 | 1181 | ||
| 1162 | static void set_pool_mode(struct pool *pool, enum pool_mode new_mode); | ||
| 1163 | |||
| 1164 | static int alloc_data_block(struct thin_c *tc, dm_block_t *result) | 1182 | static int alloc_data_block(struct thin_c *tc, dm_block_t *result) |
| 1165 | { | 1183 | { |
| 1166 | int r; | 1184 | int r; |
| @@ -2155,7 +2173,7 @@ static void set_pool_mode(struct pool *pool, enum pool_mode new_mode) | |||
| 2155 | pool->process_cell = process_cell_read_only; | 2173 | pool->process_cell = process_cell_read_only; |
| 2156 | pool->process_discard_cell = process_discard_cell; | 2174 | pool->process_discard_cell = process_discard_cell; |
| 2157 | pool->process_prepared_mapping = process_prepared_mapping; | 2175 | pool->process_prepared_mapping = process_prepared_mapping; |
| 2158 | pool->process_prepared_discard = process_prepared_discard_passdown; | 2176 | pool->process_prepared_discard = process_prepared_discard; |
| 2159 | 2177 | ||
| 2160 | if (!pool->pf.error_if_no_space && no_space_timeout) | 2178 | if (!pool->pf.error_if_no_space && no_space_timeout) |
| 2161 | queue_delayed_work(pool->wq, &pool->no_space_timeout, no_space_timeout); | 2179 | queue_delayed_work(pool->wq, &pool->no_space_timeout, no_space_timeout); |
| @@ -3814,6 +3832,8 @@ static int thin_ctr(struct dm_target *ti, unsigned argc, char **argv) | |||
| 3814 | r = -EINVAL; | 3832 | r = -EINVAL; |
| 3815 | goto bad; | 3833 | goto bad; |
| 3816 | } | 3834 | } |
| 3835 | atomic_set(&tc->refcount, 1); | ||
| 3836 | init_completion(&tc->can_destroy); | ||
| 3817 | list_add_tail_rcu(&tc->list, &tc->pool->active_thins); | 3837 | list_add_tail_rcu(&tc->list, &tc->pool->active_thins); |
| 3818 | spin_unlock_irqrestore(&tc->pool->lock, flags); | 3838 | spin_unlock_irqrestore(&tc->pool->lock, flags); |
| 3819 | /* | 3839 | /* |
| @@ -3826,9 +3846,6 @@ static int thin_ctr(struct dm_target *ti, unsigned argc, char **argv) | |||
| 3826 | 3846 | ||
| 3827 | dm_put(pool_md); | 3847 | dm_put(pool_md); |
| 3828 | 3848 | ||
| 3829 | atomic_set(&tc->refcount, 1); | ||
| 3830 | init_completion(&tc->can_destroy); | ||
| 3831 | |||
| 3832 | return 0; | 3849 | return 0; |
| 3833 | 3850 | ||
| 3834 | bad: | 3851 | bad: |
diff --git a/drivers/md/dm.c b/drivers/md/dm.c index 4c06585bf165..b98cd9d84435 100644 --- a/drivers/md/dm.c +++ b/drivers/md/dm.c | |||
| @@ -899,7 +899,7 @@ static void disable_write_same(struct mapped_device *md) | |||
| 899 | 899 | ||
| 900 | static void clone_endio(struct bio *bio, int error) | 900 | static void clone_endio(struct bio *bio, int error) |
| 901 | { | 901 | { |
| 902 | int r = 0; | 902 | int r = error; |
| 903 | struct dm_target_io *tio = container_of(bio, struct dm_target_io, clone); | 903 | struct dm_target_io *tio = container_of(bio, struct dm_target_io, clone); |
| 904 | struct dm_io *io = tio->io; | 904 | struct dm_io *io = tio->io; |
| 905 | struct mapped_device *md = tio->io->md; | 905 | struct mapped_device *md = tio->io->md; |
diff --git a/drivers/mfd/stmpe.c b/drivers/mfd/stmpe.c index e2f9df1c0c36..2d7fae94c861 100644 --- a/drivers/mfd/stmpe.c +++ b/drivers/mfd/stmpe.c | |||
| @@ -519,6 +519,7 @@ static const u8 stmpe1601_regs[] = { | |||
| 519 | [STMPE_IDX_GPDR_LSB] = STMPE1601_REG_GPIO_SET_DIR_LSB, | 519 | [STMPE_IDX_GPDR_LSB] = STMPE1601_REG_GPIO_SET_DIR_LSB, |
| 520 | [STMPE_IDX_GPRER_LSB] = STMPE1601_REG_GPIO_RE_LSB, | 520 | [STMPE_IDX_GPRER_LSB] = STMPE1601_REG_GPIO_RE_LSB, |
| 521 | [STMPE_IDX_GPFER_LSB] = STMPE1601_REG_GPIO_FE_LSB, | 521 | [STMPE_IDX_GPFER_LSB] = STMPE1601_REG_GPIO_FE_LSB, |
| 522 | [STMPE_IDX_GPPUR_LSB] = STMPE1601_REG_GPIO_PU_LSB, | ||
| 522 | [STMPE_IDX_GPAFR_U_MSB] = STMPE1601_REG_GPIO_AF_U_MSB, | 523 | [STMPE_IDX_GPAFR_U_MSB] = STMPE1601_REG_GPIO_AF_U_MSB, |
| 523 | [STMPE_IDX_IEGPIOR_LSB] = STMPE1601_REG_INT_EN_GPIO_MASK_LSB, | 524 | [STMPE_IDX_IEGPIOR_LSB] = STMPE1601_REG_INT_EN_GPIO_MASK_LSB, |
| 524 | [STMPE_IDX_ISGPIOR_MSB] = STMPE1601_REG_INT_STA_GPIO_MSB, | 525 | [STMPE_IDX_ISGPIOR_MSB] = STMPE1601_REG_INT_STA_GPIO_MSB, |
| @@ -667,6 +668,7 @@ static const u8 stmpe1801_regs[] = { | |||
| 667 | [STMPE_IDX_GPDR_LSB] = STMPE1801_REG_GPIO_SET_DIR_LOW, | 668 | [STMPE_IDX_GPDR_LSB] = STMPE1801_REG_GPIO_SET_DIR_LOW, |
| 668 | [STMPE_IDX_GPRER_LSB] = STMPE1801_REG_GPIO_RE_LOW, | 669 | [STMPE_IDX_GPRER_LSB] = STMPE1801_REG_GPIO_RE_LOW, |
| 669 | [STMPE_IDX_GPFER_LSB] = STMPE1801_REG_GPIO_FE_LOW, | 670 | [STMPE_IDX_GPFER_LSB] = STMPE1801_REG_GPIO_FE_LOW, |
| 671 | [STMPE_IDX_GPPUR_LSB] = STMPE1801_REG_GPIO_PULL_UP_LOW, | ||
| 670 | [STMPE_IDX_IEGPIOR_LSB] = STMPE1801_REG_INT_EN_GPIO_MASK_LOW, | 672 | [STMPE_IDX_IEGPIOR_LSB] = STMPE1801_REG_INT_EN_GPIO_MASK_LOW, |
| 671 | [STMPE_IDX_ISGPIOR_LSB] = STMPE1801_REG_INT_STA_GPIO_LOW, | 673 | [STMPE_IDX_ISGPIOR_LSB] = STMPE1801_REG_INT_STA_GPIO_LOW, |
| 672 | }; | 674 | }; |
| @@ -750,6 +752,8 @@ static const u8 stmpe24xx_regs[] = { | |||
| 750 | [STMPE_IDX_GPDR_LSB] = STMPE24XX_REG_GPDR_LSB, | 752 | [STMPE_IDX_GPDR_LSB] = STMPE24XX_REG_GPDR_LSB, |
| 751 | [STMPE_IDX_GPRER_LSB] = STMPE24XX_REG_GPRER_LSB, | 753 | [STMPE_IDX_GPRER_LSB] = STMPE24XX_REG_GPRER_LSB, |
| 752 | [STMPE_IDX_GPFER_LSB] = STMPE24XX_REG_GPFER_LSB, | 754 | [STMPE_IDX_GPFER_LSB] = STMPE24XX_REG_GPFER_LSB, |
| 755 | [STMPE_IDX_GPPUR_LSB] = STMPE24XX_REG_GPPUR_LSB, | ||
| 756 | [STMPE_IDX_GPPDR_LSB] = STMPE24XX_REG_GPPDR_LSB, | ||
| 753 | [STMPE_IDX_GPAFR_U_MSB] = STMPE24XX_REG_GPAFR_U_MSB, | 757 | [STMPE_IDX_GPAFR_U_MSB] = STMPE24XX_REG_GPAFR_U_MSB, |
| 754 | [STMPE_IDX_IEGPIOR_LSB] = STMPE24XX_REG_IEGPIOR_LSB, | 758 | [STMPE_IDX_IEGPIOR_LSB] = STMPE24XX_REG_IEGPIOR_LSB, |
| 755 | [STMPE_IDX_ISGPIOR_MSB] = STMPE24XX_REG_ISGPIOR_MSB, | 759 | [STMPE_IDX_ISGPIOR_MSB] = STMPE24XX_REG_ISGPIOR_MSB, |
diff --git a/drivers/mfd/stmpe.h b/drivers/mfd/stmpe.h index bee0abf82040..84adb46b3e2f 100644 --- a/drivers/mfd/stmpe.h +++ b/drivers/mfd/stmpe.h | |||
| @@ -188,6 +188,7 @@ int stmpe_remove(struct stmpe *stmpe); | |||
| 188 | #define STMPE1601_REG_GPIO_ED_MSB 0x8A | 188 | #define STMPE1601_REG_GPIO_ED_MSB 0x8A |
| 189 | #define STMPE1601_REG_GPIO_RE_LSB 0x8D | 189 | #define STMPE1601_REG_GPIO_RE_LSB 0x8D |
| 190 | #define STMPE1601_REG_GPIO_FE_LSB 0x8F | 190 | #define STMPE1601_REG_GPIO_FE_LSB 0x8F |
| 191 | #define STMPE1601_REG_GPIO_PU_LSB 0x91 | ||
| 191 | #define STMPE1601_REG_GPIO_AF_U_MSB 0x92 | 192 | #define STMPE1601_REG_GPIO_AF_U_MSB 0x92 |
| 192 | 193 | ||
| 193 | #define STMPE1601_SYS_CTRL_ENABLE_GPIO (1 << 3) | 194 | #define STMPE1601_SYS_CTRL_ENABLE_GPIO (1 << 3) |
| @@ -276,6 +277,8 @@ int stmpe_remove(struct stmpe *stmpe); | |||
| 276 | #define STMPE24XX_REG_GPEDR_MSB 0x8C | 277 | #define STMPE24XX_REG_GPEDR_MSB 0x8C |
| 277 | #define STMPE24XX_REG_GPRER_LSB 0x91 | 278 | #define STMPE24XX_REG_GPRER_LSB 0x91 |
| 278 | #define STMPE24XX_REG_GPFER_LSB 0x94 | 279 | #define STMPE24XX_REG_GPFER_LSB 0x94 |
| 280 | #define STMPE24XX_REG_GPPUR_LSB 0x97 | ||
| 281 | #define STMPE24XX_REG_GPPDR_LSB 0x9a | ||
| 279 | #define STMPE24XX_REG_GPAFR_U_MSB 0x9B | 282 | #define STMPE24XX_REG_GPAFR_U_MSB 0x9B |
| 280 | 283 | ||
| 281 | #define STMPE24XX_SYS_CTRL_ENABLE_GPIO (1 << 3) | 284 | #define STMPE24XX_SYS_CTRL_ENABLE_GPIO (1 << 3) |
diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c index 02ad79229f65..7466ce098e60 100644 --- a/drivers/mmc/core/mmc.c +++ b/drivers/mmc/core/mmc.c | |||
| @@ -886,7 +886,7 @@ static int mmc_select_bus_width(struct mmc_card *card) | |||
| 886 | unsigned idx, bus_width = 0; | 886 | unsigned idx, bus_width = 0; |
| 887 | int err = 0; | 887 | int err = 0; |
| 888 | 888 | ||
| 889 | if (!mmc_can_ext_csd(card) && | 889 | if (!mmc_can_ext_csd(card) || |
| 890 | !(host->caps & (MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA))) | 890 | !(host->caps & (MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA))) |
| 891 | return 0; | 891 | return 0; |
| 892 | 892 | ||
diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index 184c434ae305..0dceba1a2ba1 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c | |||
| @@ -1648,7 +1648,7 @@ static int __bond_release_one(struct net_device *bond_dev, | |||
| 1648 | /* slave is not a slave or master is not master of this slave */ | 1648 | /* slave is not a slave or master is not master of this slave */ |
| 1649 | if (!(slave_dev->flags & IFF_SLAVE) || | 1649 | if (!(slave_dev->flags & IFF_SLAVE) || |
| 1650 | !netdev_has_upper_dev(slave_dev, bond_dev)) { | 1650 | !netdev_has_upper_dev(slave_dev, bond_dev)) { |
| 1651 | netdev_err(bond_dev, "cannot release %s\n", | 1651 | netdev_dbg(bond_dev, "cannot release %s\n", |
| 1652 | slave_dev->name); | 1652 | slave_dev->name); |
| 1653 | return -EINVAL; | 1653 | return -EINVAL; |
| 1654 | } | 1654 | } |
diff --git a/drivers/net/caif/caif_virtio.c b/drivers/net/caif/caif_virtio.c index a5fefb9059c5..b306210b02b7 100644 --- a/drivers/net/caif/caif_virtio.c +++ b/drivers/net/caif/caif_virtio.c | |||
| @@ -257,7 +257,6 @@ static int cfv_rx_poll(struct napi_struct *napi, int quota) | |||
| 257 | struct vringh_kiov *riov = &cfv->ctx.riov; | 257 | struct vringh_kiov *riov = &cfv->ctx.riov; |
| 258 | unsigned int skb_len; | 258 | unsigned int skb_len; |
| 259 | 259 | ||
| 260 | again: | ||
| 261 | do { | 260 | do { |
| 262 | skb = NULL; | 261 | skb = NULL; |
| 263 | 262 | ||
| @@ -322,7 +321,6 @@ exit: | |||
| 322 | napi_schedule_prep(napi)) { | 321 | napi_schedule_prep(napi)) { |
| 323 | vringh_notify_disable_kern(cfv->vr_rx); | 322 | vringh_notify_disable_kern(cfv->vr_rx); |
| 324 | __napi_schedule(napi); | 323 | __napi_schedule(napi); |
| 325 | goto again; | ||
| 326 | } | 324 | } |
| 327 | break; | 325 | break; |
| 328 | 326 | ||
diff --git a/drivers/net/ethernet/8390/ne2k-pci.c b/drivers/net/ethernet/8390/ne2k-pci.c index 89c8d9fc97de..57e97910c728 100644 --- a/drivers/net/ethernet/8390/ne2k-pci.c +++ b/drivers/net/ethernet/8390/ne2k-pci.c | |||
| @@ -246,13 +246,13 @@ static int ne2k_pci_init_one(struct pci_dev *pdev, | |||
| 246 | 246 | ||
| 247 | if (!ioaddr || ((pci_resource_flags (pdev, 0) & IORESOURCE_IO) == 0)) { | 247 | if (!ioaddr || ((pci_resource_flags (pdev, 0) & IORESOURCE_IO) == 0)) { |
| 248 | dev_err(&pdev->dev, "no I/O resource at PCI BAR #0\n"); | 248 | dev_err(&pdev->dev, "no I/O resource at PCI BAR #0\n"); |
| 249 | return -ENODEV; | 249 | goto err_out; |
| 250 | } | 250 | } |
| 251 | 251 | ||
| 252 | if (request_region (ioaddr, NE_IO_EXTENT, DRV_NAME) == NULL) { | 252 | if (request_region (ioaddr, NE_IO_EXTENT, DRV_NAME) == NULL) { |
| 253 | dev_err(&pdev->dev, "I/O resource 0x%x @ 0x%lx busy\n", | 253 | dev_err(&pdev->dev, "I/O resource 0x%x @ 0x%lx busy\n", |
| 254 | NE_IO_EXTENT, ioaddr); | 254 | NE_IO_EXTENT, ioaddr); |
| 255 | return -EBUSY; | 255 | goto err_out; |
| 256 | } | 256 | } |
| 257 | 257 | ||
| 258 | reg0 = inb(ioaddr); | 258 | reg0 = inb(ioaddr); |
| @@ -392,6 +392,8 @@ err_out_free_netdev: | |||
| 392 | free_netdev (dev); | 392 | free_netdev (dev); |
| 393 | err_out_free_res: | 393 | err_out_free_res: |
| 394 | release_region (ioaddr, NE_IO_EXTENT); | 394 | release_region (ioaddr, NE_IO_EXTENT); |
| 395 | err_out: | ||
| 396 | pci_disable_device(pdev); | ||
| 395 | return -ENODEV; | 397 | return -ENODEV; |
| 396 | } | 398 | } |
| 397 | 399 | ||
diff --git a/drivers/net/ethernet/Kconfig b/drivers/net/ethernet/Kconfig index df76050d0a9d..eadcb053807e 100644 --- a/drivers/net/ethernet/Kconfig +++ b/drivers/net/ethernet/Kconfig | |||
| @@ -156,18 +156,6 @@ source "drivers/net/ethernet/realtek/Kconfig" | |||
| 156 | source "drivers/net/ethernet/renesas/Kconfig" | 156 | source "drivers/net/ethernet/renesas/Kconfig" |
| 157 | source "drivers/net/ethernet/rdc/Kconfig" | 157 | source "drivers/net/ethernet/rdc/Kconfig" |
| 158 | source "drivers/net/ethernet/rocker/Kconfig" | 158 | source "drivers/net/ethernet/rocker/Kconfig" |
| 159 | |||
| 160 | config S6GMAC | ||
| 161 | tristate "S6105 GMAC ethernet support" | ||
| 162 | depends on XTENSA_VARIANT_S6000 | ||
| 163 | select PHYLIB | ||
| 164 | ---help--- | ||
| 165 | This driver supports the on chip ethernet device on the | ||
| 166 | S6105 xtensa processor. | ||
| 167 | |||
| 168 | To compile this driver as a module, choose M here. The module | ||
| 169 | will be called s6gmac. | ||
| 170 | |||
| 171 | source "drivers/net/ethernet/samsung/Kconfig" | 159 | source "drivers/net/ethernet/samsung/Kconfig" |
| 172 | source "drivers/net/ethernet/seeq/Kconfig" | 160 | source "drivers/net/ethernet/seeq/Kconfig" |
| 173 | source "drivers/net/ethernet/silan/Kconfig" | 161 | source "drivers/net/ethernet/silan/Kconfig" |
diff --git a/drivers/net/ethernet/Makefile b/drivers/net/ethernet/Makefile index bf56f8b36e90..1367afcd0a8b 100644 --- a/drivers/net/ethernet/Makefile +++ b/drivers/net/ethernet/Makefile | |||
| @@ -66,7 +66,6 @@ obj-$(CONFIG_NET_VENDOR_REALTEK) += realtek/ | |||
| 66 | obj-$(CONFIG_SH_ETH) += renesas/ | 66 | obj-$(CONFIG_SH_ETH) += renesas/ |
| 67 | obj-$(CONFIG_NET_VENDOR_RDC) += rdc/ | 67 | obj-$(CONFIG_NET_VENDOR_RDC) += rdc/ |
| 68 | obj-$(CONFIG_NET_VENDOR_ROCKER) += rocker/ | 68 | obj-$(CONFIG_NET_VENDOR_ROCKER) += rocker/ |
| 69 | obj-$(CONFIG_S6GMAC) += s6gmac.o | ||
| 70 | obj-$(CONFIG_NET_VENDOR_SAMSUNG) += samsung/ | 69 | obj-$(CONFIG_NET_VENDOR_SAMSUNG) += samsung/ |
| 71 | obj-$(CONFIG_NET_VENDOR_SEEQ) += seeq/ | 70 | obj-$(CONFIG_NET_VENDOR_SEEQ) += seeq/ |
| 72 | obj-$(CONFIG_NET_VENDOR_SILAN) += silan/ | 71 | obj-$(CONFIG_NET_VENDOR_SILAN) += silan/ |
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c index 9f5e38769a29..72eef9fc883e 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c | |||
| @@ -12553,9 +12553,11 @@ static int bnx2x_get_phys_port_id(struct net_device *netdev, | |||
| 12553 | return 0; | 12553 | return 0; |
| 12554 | } | 12554 | } |
| 12555 | 12555 | ||
| 12556 | static bool bnx2x_gso_check(struct sk_buff *skb, struct net_device *dev) | 12556 | static netdev_features_t bnx2x_features_check(struct sk_buff *skb, |
| 12557 | struct net_device *dev, | ||
| 12558 | netdev_features_t features) | ||
| 12557 | { | 12559 | { |
| 12558 | return vxlan_gso_check(skb); | 12560 | return vxlan_features_check(skb, features); |
| 12559 | } | 12561 | } |
| 12560 | 12562 | ||
| 12561 | static const struct net_device_ops bnx2x_netdev_ops = { | 12563 | static const struct net_device_ops bnx2x_netdev_ops = { |
| @@ -12589,7 +12591,7 @@ static const struct net_device_ops bnx2x_netdev_ops = { | |||
| 12589 | #endif | 12591 | #endif |
| 12590 | .ndo_get_phys_port_id = bnx2x_get_phys_port_id, | 12592 | .ndo_get_phys_port_id = bnx2x_get_phys_port_id, |
| 12591 | .ndo_set_vf_link_state = bnx2x_set_vf_link_state, | 12593 | .ndo_set_vf_link_state = bnx2x_set_vf_link_state, |
| 12592 | .ndo_gso_check = bnx2x_gso_check, | 12594 | .ndo_features_check = bnx2x_features_check, |
| 12593 | }; | 12595 | }; |
| 12594 | 12596 | ||
| 12595 | static int bnx2x_set_coherency_mask(struct bnx2x *bp) | 12597 | static int bnx2x_set_coherency_mask(struct bnx2x *bp) |
diff --git a/drivers/net/ethernet/broadcom/tg3.c b/drivers/net/ethernet/broadcom/tg3.c index bb48a610b72a..553dcd8a9df2 100644 --- a/drivers/net/ethernet/broadcom/tg3.c +++ b/drivers/net/ethernet/broadcom/tg3.c | |||
| @@ -17800,23 +17800,6 @@ static int tg3_init_one(struct pci_dev *pdev, | |||
| 17800 | goto err_out_apeunmap; | 17800 | goto err_out_apeunmap; |
| 17801 | } | 17801 | } |
| 17802 | 17802 | ||
| 17803 | /* | ||
| 17804 | * Reset chip in case UNDI or EFI driver did not shutdown | ||
| 17805 | * DMA self test will enable WDMAC and we'll see (spurious) | ||
| 17806 | * pending DMA on the PCI bus at that point. | ||
| 17807 | */ | ||
| 17808 | if ((tr32(HOSTCC_MODE) & HOSTCC_MODE_ENABLE) || | ||
| 17809 | (tr32(WDMAC_MODE) & WDMAC_MODE_ENABLE)) { | ||
| 17810 | tw32(MEMARB_MODE, MEMARB_MODE_ENABLE); | ||
| 17811 | tg3_halt(tp, RESET_KIND_SHUTDOWN, 1); | ||
| 17812 | } | ||
| 17813 | |||
| 17814 | err = tg3_test_dma(tp); | ||
| 17815 | if (err) { | ||
| 17816 | dev_err(&pdev->dev, "DMA engine test failed, aborting\n"); | ||
| 17817 | goto err_out_apeunmap; | ||
| 17818 | } | ||
| 17819 | |||
| 17820 | intmbx = MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW; | 17803 | intmbx = MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW; |
| 17821 | rcvmbx = MAILBOX_RCVRET_CON_IDX_0 + TG3_64BIT_REG_LOW; | 17804 | rcvmbx = MAILBOX_RCVRET_CON_IDX_0 + TG3_64BIT_REG_LOW; |
| 17822 | sndmbx = MAILBOX_SNDHOST_PROD_IDX_0 + TG3_64BIT_REG_LOW; | 17805 | sndmbx = MAILBOX_SNDHOST_PROD_IDX_0 + TG3_64BIT_REG_LOW; |
| @@ -17861,6 +17844,23 @@ static int tg3_init_one(struct pci_dev *pdev, | |||
| 17861 | sndmbx += 0xc; | 17844 | sndmbx += 0xc; |
| 17862 | } | 17845 | } |
| 17863 | 17846 | ||
| 17847 | /* | ||
| 17848 | * Reset chip in case UNDI or EFI driver did not shutdown | ||
| 17849 | * DMA self test will enable WDMAC and we'll see (spurious) | ||
| 17850 | * pending DMA on the PCI bus at that point. | ||
| 17851 | */ | ||
| 17852 | if ((tr32(HOSTCC_MODE) & HOSTCC_MODE_ENABLE) || | ||
| 17853 | (tr32(WDMAC_MODE) & WDMAC_MODE_ENABLE)) { | ||
| 17854 | tw32(MEMARB_MODE, MEMARB_MODE_ENABLE); | ||
| 17855 | tg3_halt(tp, RESET_KIND_SHUTDOWN, 1); | ||
| 17856 | } | ||
| 17857 | |||
| 17858 | err = tg3_test_dma(tp); | ||
| 17859 | if (err) { | ||
| 17860 | dev_err(&pdev->dev, "DMA engine test failed, aborting\n"); | ||
| 17861 | goto err_out_apeunmap; | ||
| 17862 | } | ||
| 17863 | |||
| 17864 | tg3_init_coal(tp); | 17864 | tg3_init_coal(tp); |
| 17865 | 17865 | ||
| 17866 | pci_set_drvdata(pdev, dev); | 17866 | pci_set_drvdata(pdev, dev); |
diff --git a/drivers/net/ethernet/brocade/bna/bnad_debugfs.c b/drivers/net/ethernet/brocade/bna/bnad_debugfs.c index 7d6aa8c87df8..619083a860a4 100644 --- a/drivers/net/ethernet/brocade/bna/bnad_debugfs.c +++ b/drivers/net/ethernet/brocade/bna/bnad_debugfs.c | |||
| @@ -172,7 +172,7 @@ bnad_get_debug_drvinfo(struct bnad *bnad, void *buffer, u32 len) | |||
| 172 | 172 | ||
| 173 | /* Retrieve flash partition info */ | 173 | /* Retrieve flash partition info */ |
| 174 | fcomp.comp_status = 0; | 174 | fcomp.comp_status = 0; |
| 175 | init_completion(&fcomp.comp); | 175 | reinit_completion(&fcomp.comp); |
| 176 | spin_lock_irqsave(&bnad->bna_lock, flags); | 176 | spin_lock_irqsave(&bnad->bna_lock, flags); |
| 177 | ret = bfa_nw_flash_get_attr(&bnad->bna.flash, &drvinfo->flash_attr, | 177 | ret = bfa_nw_flash_get_attr(&bnad->bna.flash, &drvinfo->flash_attr, |
| 178 | bnad_cb_completion, &fcomp); | 178 | bnad_cb_completion, &fcomp); |
diff --git a/drivers/net/ethernet/chelsio/cxgb4vf/adapter.h b/drivers/net/ethernet/chelsio/cxgb4vf/adapter.h index d00a751f0588..6049f70e110c 100644 --- a/drivers/net/ethernet/chelsio/cxgb4vf/adapter.h +++ b/drivers/net/ethernet/chelsio/cxgb4vf/adapter.h | |||
| @@ -96,6 +96,9 @@ struct port_info { | |||
| 96 | s16 xact_addr_filt; /* index of our MAC address filter */ | 96 | s16 xact_addr_filt; /* index of our MAC address filter */ |
| 97 | u16 rss_size; /* size of VI's RSS table slice */ | 97 | u16 rss_size; /* size of VI's RSS table slice */ |
| 98 | u8 pidx; /* index into adapter port[] */ | 98 | u8 pidx; /* index into adapter port[] */ |
| 99 | s8 mdio_addr; | ||
| 100 | u8 port_type; /* firmware port type */ | ||
| 101 | u8 mod_type; /* firmware module type */ | ||
| 99 | u8 port_id; /* physical port ID */ | 102 | u8 port_id; /* physical port ID */ |
| 100 | u8 nqsets; /* # of "Queue Sets" */ | 103 | u8 nqsets; /* # of "Queue Sets" */ |
| 101 | u8 first_qset; /* index of first "Queue Set" */ | 104 | u8 first_qset; /* index of first "Queue Set" */ |
| @@ -522,6 +525,7 @@ static inline struct adapter *netdev2adap(const struct net_device *dev) | |||
| 522 | * is "contracted" to provide for the common code. | 525 | * is "contracted" to provide for the common code. |
| 523 | */ | 526 | */ |
| 524 | void t4vf_os_link_changed(struct adapter *, int, int); | 527 | void t4vf_os_link_changed(struct adapter *, int, int); |
| 528 | void t4vf_os_portmod_changed(struct adapter *, int); | ||
| 525 | 529 | ||
| 526 | /* | 530 | /* |
| 527 | * SGE function prototype declarations. | 531 | * SGE function prototype declarations. |
diff --git a/drivers/net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c b/drivers/net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c index aa74ec34a467..2215d432a059 100644 --- a/drivers/net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c +++ b/drivers/net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c | |||
| @@ -44,6 +44,7 @@ | |||
| 44 | #include <linux/etherdevice.h> | 44 | #include <linux/etherdevice.h> |
| 45 | #include <linux/debugfs.h> | 45 | #include <linux/debugfs.h> |
| 46 | #include <linux/ethtool.h> | 46 | #include <linux/ethtool.h> |
| 47 | #include <linux/mdio.h> | ||
| 47 | 48 | ||
| 48 | #include "t4vf_common.h" | 49 | #include "t4vf_common.h" |
| 49 | #include "t4vf_defs.h" | 50 | #include "t4vf_defs.h" |
| @@ -210,6 +211,38 @@ void t4vf_os_link_changed(struct adapter *adapter, int pidx, int link_ok) | |||
| 210 | } | 211 | } |
| 211 | 212 | ||
| 212 | /* | 213 | /* |
| 214 | * THe port module type has changed on the indicated "port" (Virtual | ||
| 215 | * Interface). | ||
| 216 | */ | ||
| 217 | void t4vf_os_portmod_changed(struct adapter *adapter, int pidx) | ||
| 218 | { | ||
| 219 | static const char * const mod_str[] = { | ||
| 220 | NULL, "LR", "SR", "ER", "passive DA", "active DA", "LRM" | ||
| 221 | }; | ||
| 222 | const struct net_device *dev = adapter->port[pidx]; | ||
| 223 | const struct port_info *pi = netdev_priv(dev); | ||
| 224 | |||
| 225 | if (pi->mod_type == FW_PORT_MOD_TYPE_NONE) | ||
| 226 | dev_info(adapter->pdev_dev, "%s: port module unplugged\n", | ||
| 227 | dev->name); | ||
| 228 | else if (pi->mod_type < ARRAY_SIZE(mod_str)) | ||
| 229 | dev_info(adapter->pdev_dev, "%s: %s port module inserted\n", | ||
| 230 | dev->name, mod_str[pi->mod_type]); | ||
| 231 | else if (pi->mod_type == FW_PORT_MOD_TYPE_NOTSUPPORTED) | ||
| 232 | dev_info(adapter->pdev_dev, "%s: unsupported optical port " | ||
| 233 | "module inserted\n", dev->name); | ||
| 234 | else if (pi->mod_type == FW_PORT_MOD_TYPE_UNKNOWN) | ||
| 235 | dev_info(adapter->pdev_dev, "%s: unknown port module inserted," | ||
| 236 | "forcing TWINAX\n", dev->name); | ||
| 237 | else if (pi->mod_type == FW_PORT_MOD_TYPE_ERROR) | ||
| 238 | dev_info(adapter->pdev_dev, "%s: transceiver module error\n", | ||
| 239 | dev->name); | ||
| 240 | else | ||
| 241 | dev_info(adapter->pdev_dev, "%s: unknown module type %d " | ||
| 242 | "inserted\n", dev->name, pi->mod_type); | ||
| 243 | } | ||
| 244 | |||
| 245 | /* | ||
| 213 | * Net device operations. | 246 | * Net device operations. |
| 214 | * ====================== | 247 | * ====================== |
| 215 | */ | 248 | */ |
| @@ -1193,24 +1226,103 @@ static void cxgb4vf_poll_controller(struct net_device *dev) | |||
| 1193 | * state of the port to which we're linked. | 1226 | * state of the port to which we're linked. |
| 1194 | */ | 1227 | */ |
| 1195 | 1228 | ||
| 1196 | /* | 1229 | static unsigned int t4vf_from_fw_linkcaps(enum fw_port_type type, |
| 1197 | * Return current port link settings. | 1230 | unsigned int caps) |
| 1198 | */ | 1231 | { |
| 1199 | static int cxgb4vf_get_settings(struct net_device *dev, | 1232 | unsigned int v = 0; |
| 1200 | struct ethtool_cmd *cmd) | 1233 | |
| 1201 | { | 1234 | if (type == FW_PORT_TYPE_BT_SGMII || type == FW_PORT_TYPE_BT_XFI || |
| 1202 | const struct port_info *pi = netdev_priv(dev); | 1235 | type == FW_PORT_TYPE_BT_XAUI) { |
| 1236 | v |= SUPPORTED_TP; | ||
| 1237 | if (caps & FW_PORT_CAP_SPEED_100M) | ||
| 1238 | v |= SUPPORTED_100baseT_Full; | ||
| 1239 | if (caps & FW_PORT_CAP_SPEED_1G) | ||
| 1240 | v |= SUPPORTED_1000baseT_Full; | ||
| 1241 | if (caps & FW_PORT_CAP_SPEED_10G) | ||
| 1242 | v |= SUPPORTED_10000baseT_Full; | ||
| 1243 | } else if (type == FW_PORT_TYPE_KX4 || type == FW_PORT_TYPE_KX) { | ||
| 1244 | v |= SUPPORTED_Backplane; | ||
| 1245 | if (caps & FW_PORT_CAP_SPEED_1G) | ||
| 1246 | v |= SUPPORTED_1000baseKX_Full; | ||
| 1247 | if (caps & FW_PORT_CAP_SPEED_10G) | ||
| 1248 | v |= SUPPORTED_10000baseKX4_Full; | ||
| 1249 | } else if (type == FW_PORT_TYPE_KR) | ||
| 1250 | v |= SUPPORTED_Backplane | SUPPORTED_10000baseKR_Full; | ||
| 1251 | else if (type == FW_PORT_TYPE_BP_AP) | ||
| 1252 | v |= SUPPORTED_Backplane | SUPPORTED_10000baseR_FEC | | ||
| 1253 | SUPPORTED_10000baseKR_Full | SUPPORTED_1000baseKX_Full; | ||
| 1254 | else if (type == FW_PORT_TYPE_BP4_AP) | ||
| 1255 | v |= SUPPORTED_Backplane | SUPPORTED_10000baseR_FEC | | ||
| 1256 | SUPPORTED_10000baseKR_Full | SUPPORTED_1000baseKX_Full | | ||
| 1257 | SUPPORTED_10000baseKX4_Full; | ||
| 1258 | else if (type == FW_PORT_TYPE_FIBER_XFI || | ||
| 1259 | type == FW_PORT_TYPE_FIBER_XAUI || | ||
| 1260 | type == FW_PORT_TYPE_SFP || | ||
| 1261 | type == FW_PORT_TYPE_QSFP_10G || | ||
| 1262 | type == FW_PORT_TYPE_QSA) { | ||
| 1263 | v |= SUPPORTED_FIBRE; | ||
| 1264 | if (caps & FW_PORT_CAP_SPEED_1G) | ||
| 1265 | v |= SUPPORTED_1000baseT_Full; | ||
| 1266 | if (caps & FW_PORT_CAP_SPEED_10G) | ||
| 1267 | v |= SUPPORTED_10000baseT_Full; | ||
| 1268 | } else if (type == FW_PORT_TYPE_BP40_BA || | ||
| 1269 | type == FW_PORT_TYPE_QSFP) { | ||
| 1270 | v |= SUPPORTED_40000baseSR4_Full; | ||
| 1271 | v |= SUPPORTED_FIBRE; | ||
| 1272 | } | ||
| 1273 | |||
| 1274 | if (caps & FW_PORT_CAP_ANEG) | ||
| 1275 | v |= SUPPORTED_Autoneg; | ||
| 1276 | return v; | ||
| 1277 | } | ||
| 1278 | |||
| 1279 | static int cxgb4vf_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) | ||
| 1280 | { | ||
| 1281 | const struct port_info *p = netdev_priv(dev); | ||
| 1282 | |||
| 1283 | if (p->port_type == FW_PORT_TYPE_BT_SGMII || | ||
| 1284 | p->port_type == FW_PORT_TYPE_BT_XFI || | ||
| 1285 | p->port_type == FW_PORT_TYPE_BT_XAUI) | ||
| 1286 | cmd->port = PORT_TP; | ||
| 1287 | else if (p->port_type == FW_PORT_TYPE_FIBER_XFI || | ||
| 1288 | p->port_type == FW_PORT_TYPE_FIBER_XAUI) | ||
| 1289 | cmd->port = PORT_FIBRE; | ||
| 1290 | else if (p->port_type == FW_PORT_TYPE_SFP || | ||
| 1291 | p->port_type == FW_PORT_TYPE_QSFP_10G || | ||
| 1292 | p->port_type == FW_PORT_TYPE_QSA || | ||
| 1293 | p->port_type == FW_PORT_TYPE_QSFP) { | ||
| 1294 | if (p->mod_type == FW_PORT_MOD_TYPE_LR || | ||
| 1295 | p->mod_type == FW_PORT_MOD_TYPE_SR || | ||
| 1296 | p->mod_type == FW_PORT_MOD_TYPE_ER || | ||
| 1297 | p->mod_type == FW_PORT_MOD_TYPE_LRM) | ||
| 1298 | cmd->port = PORT_FIBRE; | ||
| 1299 | else if (p->mod_type == FW_PORT_MOD_TYPE_TWINAX_PASSIVE || | ||
| 1300 | p->mod_type == FW_PORT_MOD_TYPE_TWINAX_ACTIVE) | ||
| 1301 | cmd->port = PORT_DA; | ||
| 1302 | else | ||
| 1303 | cmd->port = PORT_OTHER; | ||
| 1304 | } else | ||
| 1305 | cmd->port = PORT_OTHER; | ||
| 1203 | 1306 | ||
| 1204 | cmd->supported = pi->link_cfg.supported; | 1307 | if (p->mdio_addr >= 0) { |
| 1205 | cmd->advertising = pi->link_cfg.advertising; | 1308 | cmd->phy_address = p->mdio_addr; |
| 1309 | cmd->transceiver = XCVR_EXTERNAL; | ||
| 1310 | cmd->mdio_support = p->port_type == FW_PORT_TYPE_BT_SGMII ? | ||
| 1311 | MDIO_SUPPORTS_C22 : MDIO_SUPPORTS_C45; | ||
| 1312 | } else { | ||
| 1313 | cmd->phy_address = 0; /* not really, but no better option */ | ||
| 1314 | cmd->transceiver = XCVR_INTERNAL; | ||
| 1315 | cmd->mdio_support = 0; | ||
| 1316 | } | ||
| 1317 | |||
| 1318 | cmd->supported = t4vf_from_fw_linkcaps(p->port_type, | ||
| 1319 | p->link_cfg.supported); | ||
| 1320 | cmd->advertising = t4vf_from_fw_linkcaps(p->port_type, | ||
| 1321 | p->link_cfg.advertising); | ||
| 1206 | ethtool_cmd_speed_set(cmd, | 1322 | ethtool_cmd_speed_set(cmd, |
| 1207 | netif_carrier_ok(dev) ? pi->link_cfg.speed : -1); | 1323 | netif_carrier_ok(dev) ? p->link_cfg.speed : 0); |
| 1208 | cmd->duplex = DUPLEX_FULL; | 1324 | cmd->duplex = DUPLEX_FULL; |
| 1209 | 1325 | cmd->autoneg = p->link_cfg.autoneg; | |
| 1210 | cmd->port = (cmd->supported & SUPPORTED_TP) ? PORT_TP : PORT_FIBRE; | ||
| 1211 | cmd->phy_address = pi->port_id; | ||
| 1212 | cmd->transceiver = XCVR_EXTERNAL; | ||
| 1213 | cmd->autoneg = pi->link_cfg.autoneg; | ||
| 1214 | cmd->maxtxpkt = 0; | 1326 | cmd->maxtxpkt = 0; |
| 1215 | cmd->maxrxpkt = 0; | 1327 | cmd->maxrxpkt = 0; |
| 1216 | return 0; | 1328 | return 0; |
diff --git a/drivers/net/ethernet/chelsio/cxgb4vf/t4vf_common.h b/drivers/net/ethernet/chelsio/cxgb4vf/t4vf_common.h index 8d3237f5e364..b9debb4f29a3 100644 --- a/drivers/net/ethernet/chelsio/cxgb4vf/t4vf_common.h +++ b/drivers/net/ethernet/chelsio/cxgb4vf/t4vf_common.h | |||
| @@ -230,7 +230,7 @@ struct adapter_params { | |||
| 230 | 230 | ||
| 231 | static inline bool is_10g_port(const struct link_config *lc) | 231 | static inline bool is_10g_port(const struct link_config *lc) |
| 232 | { | 232 | { |
| 233 | return (lc->supported & SUPPORTED_10000baseT_Full) != 0; | 233 | return (lc->supported & FW_PORT_CAP_SPEED_10G) != 0; |
| 234 | } | 234 | } |
| 235 | 235 | ||
| 236 | static inline bool is_x_10g_port(const struct link_config *lc) | 236 | static inline bool is_x_10g_port(const struct link_config *lc) |
diff --git a/drivers/net/ethernet/chelsio/cxgb4vf/t4vf_hw.c b/drivers/net/ethernet/chelsio/cxgb4vf/t4vf_hw.c index 02e8833b7797..21dc9a20308c 100644 --- a/drivers/net/ethernet/chelsio/cxgb4vf/t4vf_hw.c +++ b/drivers/net/ethernet/chelsio/cxgb4vf/t4vf_hw.c | |||
| @@ -245,6 +245,10 @@ static int hash_mac_addr(const u8 *addr) | |||
| 245 | return a & 0x3f; | 245 | return a & 0x3f; |
| 246 | } | 246 | } |
| 247 | 247 | ||
| 248 | #define ADVERT_MASK (FW_PORT_CAP_SPEED_100M | FW_PORT_CAP_SPEED_1G |\ | ||
| 249 | FW_PORT_CAP_SPEED_10G | FW_PORT_CAP_SPEED_40G | \ | ||
| 250 | FW_PORT_CAP_SPEED_100G | FW_PORT_CAP_ANEG) | ||
| 251 | |||
| 248 | /** | 252 | /** |
| 249 | * init_link_config - initialize a link's SW state | 253 | * init_link_config - initialize a link's SW state |
| 250 | * @lc: structure holding the link state | 254 | * @lc: structure holding the link state |
| @@ -259,8 +263,8 @@ static void init_link_config(struct link_config *lc, unsigned int caps) | |||
| 259 | lc->requested_speed = 0; | 263 | lc->requested_speed = 0; |
| 260 | lc->speed = 0; | 264 | lc->speed = 0; |
| 261 | lc->requested_fc = lc->fc = PAUSE_RX | PAUSE_TX; | 265 | lc->requested_fc = lc->fc = PAUSE_RX | PAUSE_TX; |
| 262 | if (lc->supported & SUPPORTED_Autoneg) { | 266 | if (lc->supported & FW_PORT_CAP_ANEG) { |
| 263 | lc->advertising = lc->supported; | 267 | lc->advertising = lc->supported & ADVERT_MASK; |
| 264 | lc->autoneg = AUTONEG_ENABLE; | 268 | lc->autoneg = AUTONEG_ENABLE; |
| 265 | lc->requested_fc |= PAUSE_AUTONEG; | 269 | lc->requested_fc |= PAUSE_AUTONEG; |
| 266 | } else { | 270 | } else { |
| @@ -280,7 +284,6 @@ int t4vf_port_init(struct adapter *adapter, int pidx) | |||
| 280 | struct fw_vi_cmd vi_cmd, vi_rpl; | 284 | struct fw_vi_cmd vi_cmd, vi_rpl; |
| 281 | struct fw_port_cmd port_cmd, port_rpl; | 285 | struct fw_port_cmd port_cmd, port_rpl; |
| 282 | int v; | 286 | int v; |
| 283 | u32 word; | ||
| 284 | 287 | ||
| 285 | /* | 288 | /* |
| 286 | * Execute a VI Read command to get our Virtual Interface information | 289 | * Execute a VI Read command to get our Virtual Interface information |
| @@ -319,19 +322,11 @@ int t4vf_port_init(struct adapter *adapter, int pidx) | |||
| 319 | if (v) | 322 | if (v) |
| 320 | return v; | 323 | return v; |
| 321 | 324 | ||
| 322 | v = 0; | 325 | v = be32_to_cpu(port_rpl.u.info.lstatus_to_modtype); |
| 323 | word = be16_to_cpu(port_rpl.u.info.pcap); | 326 | pi->port_type = FW_PORT_CMD_PTYPE_G(v); |
| 324 | if (word & FW_PORT_CAP_SPEED_100M) | 327 | pi->mod_type = FW_PORT_MOD_TYPE_NA; |
| 325 | v |= SUPPORTED_100baseT_Full; | 328 | |
| 326 | if (word & FW_PORT_CAP_SPEED_1G) | 329 | init_link_config(&pi->link_cfg, be16_to_cpu(port_rpl.u.info.pcap)); |
| 327 | v |= SUPPORTED_1000baseT_Full; | ||
| 328 | if (word & FW_PORT_CAP_SPEED_10G) | ||
| 329 | v |= SUPPORTED_10000baseT_Full; | ||
| 330 | if (word & FW_PORT_CAP_SPEED_40G) | ||
| 331 | v |= SUPPORTED_40000baseSR4_Full; | ||
| 332 | if (word & FW_PORT_CAP_ANEG) | ||
| 333 | v |= SUPPORTED_Autoneg; | ||
| 334 | init_link_config(&pi->link_cfg, v); | ||
| 335 | 330 | ||
| 336 | return 0; | 331 | return 0; |
| 337 | } | 332 | } |
| @@ -1491,7 +1486,7 @@ int t4vf_handle_fw_rpl(struct adapter *adapter, const __be64 *rpl) | |||
| 1491 | */ | 1486 | */ |
| 1492 | const struct fw_port_cmd *port_cmd = | 1487 | const struct fw_port_cmd *port_cmd = |
| 1493 | (const struct fw_port_cmd *)rpl; | 1488 | (const struct fw_port_cmd *)rpl; |
| 1494 | u32 word; | 1489 | u32 stat, mod; |
| 1495 | int action, port_id, link_ok, speed, fc, pidx; | 1490 | int action, port_id, link_ok, speed, fc, pidx; |
| 1496 | 1491 | ||
| 1497 | /* | 1492 | /* |
| @@ -1509,21 +1504,21 @@ int t4vf_handle_fw_rpl(struct adapter *adapter, const __be64 *rpl) | |||
| 1509 | port_id = FW_PORT_CMD_PORTID_G( | 1504 | port_id = FW_PORT_CMD_PORTID_G( |
| 1510 | be32_to_cpu(port_cmd->op_to_portid)); | 1505 | be32_to_cpu(port_cmd->op_to_portid)); |
| 1511 | 1506 | ||
| 1512 | word = be32_to_cpu(port_cmd->u.info.lstatus_to_modtype); | 1507 | stat = be32_to_cpu(port_cmd->u.info.lstatus_to_modtype); |
| 1513 | link_ok = (word & FW_PORT_CMD_LSTATUS_F) != 0; | 1508 | link_ok = (stat & FW_PORT_CMD_LSTATUS_F) != 0; |
| 1514 | speed = 0; | 1509 | speed = 0; |
| 1515 | fc = 0; | 1510 | fc = 0; |
| 1516 | if (word & FW_PORT_CMD_RXPAUSE_F) | 1511 | if (stat & FW_PORT_CMD_RXPAUSE_F) |
| 1517 | fc |= PAUSE_RX; | 1512 | fc |= PAUSE_RX; |
| 1518 | if (word & FW_PORT_CMD_TXPAUSE_F) | 1513 | if (stat & FW_PORT_CMD_TXPAUSE_F) |
| 1519 | fc |= PAUSE_TX; | 1514 | fc |= PAUSE_TX; |
| 1520 | if (word & FW_PORT_CMD_LSPEED_V(FW_PORT_CAP_SPEED_100M)) | 1515 | if (stat & FW_PORT_CMD_LSPEED_V(FW_PORT_CAP_SPEED_100M)) |
| 1521 | speed = 100; | 1516 | speed = 100; |
| 1522 | else if (word & FW_PORT_CMD_LSPEED_V(FW_PORT_CAP_SPEED_1G)) | 1517 | else if (stat & FW_PORT_CMD_LSPEED_V(FW_PORT_CAP_SPEED_1G)) |
| 1523 | speed = 1000; | 1518 | speed = 1000; |
| 1524 | else if (word & FW_PORT_CMD_LSPEED_V(FW_PORT_CAP_SPEED_10G)) | 1519 | else if (stat & FW_PORT_CMD_LSPEED_V(FW_PORT_CAP_SPEED_10G)) |
| 1525 | speed = 10000; | 1520 | speed = 10000; |
| 1526 | else if (word & FW_PORT_CMD_LSPEED_V(FW_PORT_CAP_SPEED_40G)) | 1521 | else if (stat & FW_PORT_CMD_LSPEED_V(FW_PORT_CAP_SPEED_40G)) |
| 1527 | speed = 40000; | 1522 | speed = 40000; |
| 1528 | 1523 | ||
| 1529 | /* | 1524 | /* |
| @@ -1540,12 +1535,21 @@ int t4vf_handle_fw_rpl(struct adapter *adapter, const __be64 *rpl) | |||
| 1540 | continue; | 1535 | continue; |
| 1541 | 1536 | ||
| 1542 | lc = &pi->link_cfg; | 1537 | lc = &pi->link_cfg; |
| 1538 | |||
| 1539 | mod = FW_PORT_CMD_MODTYPE_G(stat); | ||
| 1540 | if (mod != pi->mod_type) { | ||
| 1541 | pi->mod_type = mod; | ||
| 1542 | t4vf_os_portmod_changed(adapter, pidx); | ||
| 1543 | } | ||
| 1544 | |||
| 1543 | if (link_ok != lc->link_ok || speed != lc->speed || | 1545 | if (link_ok != lc->link_ok || speed != lc->speed || |
| 1544 | fc != lc->fc) { | 1546 | fc != lc->fc) { |
| 1545 | /* something changed */ | 1547 | /* something changed */ |
| 1546 | lc->link_ok = link_ok; | 1548 | lc->link_ok = link_ok; |
| 1547 | lc->speed = speed; | 1549 | lc->speed = speed; |
| 1548 | lc->fc = fc; | 1550 | lc->fc = fc; |
| 1551 | lc->supported = | ||
| 1552 | be16_to_cpu(port_cmd->u.info.pcap); | ||
| 1549 | t4vf_os_link_changed(adapter, pidx, link_ok); | 1553 | t4vf_os_link_changed(adapter, pidx, link_ok); |
| 1550 | } | 1554 | } |
| 1551 | } | 1555 | } |
diff --git a/drivers/net/ethernet/cisco/enic/enic_main.c b/drivers/net/ethernet/cisco/enic/enic_main.c index 868d0f605d60..705f334ebb85 100644 --- a/drivers/net/ethernet/cisco/enic/enic_main.c +++ b/drivers/net/ethernet/cisco/enic/enic_main.c | |||
| @@ -1060,10 +1060,14 @@ static void enic_rq_indicate_buf(struct vnic_rq *rq, | |||
| 1060 | PKT_HASH_TYPE_L4 : PKT_HASH_TYPE_L3); | 1060 | PKT_HASH_TYPE_L4 : PKT_HASH_TYPE_L3); |
| 1061 | } | 1061 | } |
| 1062 | 1062 | ||
| 1063 | if ((netdev->features & NETIF_F_RXCSUM) && !csum_not_calc) { | 1063 | /* Hardware does not provide whole packet checksum. It only |
| 1064 | skb->csum = htons(checksum); | 1064 | * provides pseudo checksum. Since hw validates the packet |
| 1065 | skb->ip_summed = CHECKSUM_COMPLETE; | 1065 | * checksum but not provide us the checksum value. use |
| 1066 | } | 1066 | * CHECSUM_UNNECESSARY. |
| 1067 | */ | ||
| 1068 | if ((netdev->features & NETIF_F_RXCSUM) && tcp_udp_csum_ok && | ||
| 1069 | ipv4_csum_ok) | ||
| 1070 | skb->ip_summed = CHECKSUM_UNNECESSARY; | ||
| 1067 | 1071 | ||
| 1068 | if (vlan_stripped) | 1072 | if (vlan_stripped) |
| 1069 | __vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), vlan_tci); | 1073 | __vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), vlan_tci); |
diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c index 196073110e32..41a0a5498da7 100644 --- a/drivers/net/ethernet/emulex/benet/be_main.c +++ b/drivers/net/ethernet/emulex/benet/be_main.c | |||
| @@ -4459,9 +4459,11 @@ done: | |||
| 4459 | adapter->vxlan_port_count--; | 4459 | adapter->vxlan_port_count--; |
| 4460 | } | 4460 | } |
| 4461 | 4461 | ||
| 4462 | static bool be_gso_check(struct sk_buff *skb, struct net_device *dev) | 4462 | static netdev_features_t be_features_check(struct sk_buff *skb, |
| 4463 | struct net_device *dev, | ||
| 4464 | netdev_features_t features) | ||
| 4463 | { | 4465 | { |
| 4464 | return vxlan_gso_check(skb); | 4466 | return vxlan_features_check(skb, features); |
| 4465 | } | 4467 | } |
| 4466 | #endif | 4468 | #endif |
| 4467 | 4469 | ||
| @@ -4492,7 +4494,7 @@ static const struct net_device_ops be_netdev_ops = { | |||
| 4492 | #ifdef CONFIG_BE2NET_VXLAN | 4494 | #ifdef CONFIG_BE2NET_VXLAN |
| 4493 | .ndo_add_vxlan_port = be_add_vxlan_port, | 4495 | .ndo_add_vxlan_port = be_add_vxlan_port, |
| 4494 | .ndo_del_vxlan_port = be_del_vxlan_port, | 4496 | .ndo_del_vxlan_port = be_del_vxlan_port, |
| 4495 | .ndo_gso_check = be_gso_check, | 4497 | .ndo_features_check = be_features_check, |
| 4496 | #endif | 4498 | #endif |
| 4497 | }; | 4499 | }; |
| 4498 | 4500 | ||
diff --git a/drivers/net/ethernet/mellanox/mlx4/en_netdev.c b/drivers/net/ethernet/mellanox/mlx4/en_netdev.c index 190cbd931f6b..d0d6dc1b8e46 100644 --- a/drivers/net/ethernet/mellanox/mlx4/en_netdev.c +++ b/drivers/net/ethernet/mellanox/mlx4/en_netdev.c | |||
| @@ -2365,9 +2365,11 @@ static void mlx4_en_del_vxlan_port(struct net_device *dev, | |||
| 2365 | queue_work(priv->mdev->workqueue, &priv->vxlan_del_task); | 2365 | queue_work(priv->mdev->workqueue, &priv->vxlan_del_task); |
| 2366 | } | 2366 | } |
| 2367 | 2367 | ||
| 2368 | static bool mlx4_en_gso_check(struct sk_buff *skb, struct net_device *dev) | 2368 | static netdev_features_t mlx4_en_features_check(struct sk_buff *skb, |
| 2369 | struct net_device *dev, | ||
| 2370 | netdev_features_t features) | ||
| 2369 | { | 2371 | { |
| 2370 | return vxlan_gso_check(skb); | 2372 | return vxlan_features_check(skb, features); |
| 2371 | } | 2373 | } |
| 2372 | #endif | 2374 | #endif |
| 2373 | 2375 | ||
| @@ -2400,7 +2402,7 @@ static const struct net_device_ops mlx4_netdev_ops = { | |||
| 2400 | #ifdef CONFIG_MLX4_EN_VXLAN | 2402 | #ifdef CONFIG_MLX4_EN_VXLAN |
| 2401 | .ndo_add_vxlan_port = mlx4_en_add_vxlan_port, | 2403 | .ndo_add_vxlan_port = mlx4_en_add_vxlan_port, |
| 2402 | .ndo_del_vxlan_port = mlx4_en_del_vxlan_port, | 2404 | .ndo_del_vxlan_port = mlx4_en_del_vxlan_port, |
| 2403 | .ndo_gso_check = mlx4_en_gso_check, | 2405 | .ndo_features_check = mlx4_en_features_check, |
| 2404 | #endif | 2406 | #endif |
| 2405 | }; | 2407 | }; |
| 2406 | 2408 | ||
| @@ -2434,7 +2436,7 @@ static const struct net_device_ops mlx4_netdev_ops_master = { | |||
| 2434 | #ifdef CONFIG_MLX4_EN_VXLAN | 2436 | #ifdef CONFIG_MLX4_EN_VXLAN |
| 2435 | .ndo_add_vxlan_port = mlx4_en_add_vxlan_port, | 2437 | .ndo_add_vxlan_port = mlx4_en_add_vxlan_port, |
| 2436 | .ndo_del_vxlan_port = mlx4_en_del_vxlan_port, | 2438 | .ndo_del_vxlan_port = mlx4_en_del_vxlan_port, |
| 2437 | .ndo_gso_check = mlx4_en_gso_check, | 2439 | .ndo_features_check = mlx4_en_features_check, |
| 2438 | #endif | 2440 | #endif |
| 2439 | }; | 2441 | }; |
| 2440 | 2442 | ||
diff --git a/drivers/net/ethernet/mellanox/mlx4/en_tx.c b/drivers/net/ethernet/mellanox/mlx4/en_tx.c index a308d41e4de0..e3357bf523df 100644 --- a/drivers/net/ethernet/mellanox/mlx4/en_tx.c +++ b/drivers/net/ethernet/mellanox/mlx4/en_tx.c | |||
| @@ -962,7 +962,17 @@ netdev_tx_t mlx4_en_xmit(struct sk_buff *skb, struct net_device *dev) | |||
| 962 | tx_desc->ctrl.owner_opcode = op_own; | 962 | tx_desc->ctrl.owner_opcode = op_own; |
| 963 | if (send_doorbell) { | 963 | if (send_doorbell) { |
| 964 | wmb(); | 964 | wmb(); |
| 965 | iowrite32(ring->doorbell_qpn, | 965 | /* Since there is no iowrite*_native() that writes the |
| 966 | * value as is, without byteswapping - using the one | ||
| 967 | * the doesn't do byteswapping in the relevant arch | ||
| 968 | * endianness. | ||
| 969 | */ | ||
| 970 | #if defined(__LITTLE_ENDIAN) | ||
| 971 | iowrite32( | ||
| 972 | #else | ||
| 973 | iowrite32be( | ||
| 974 | #endif | ||
| 975 | ring->doorbell_qpn, | ||
| 966 | ring->bf.uar->map + MLX4_SEND_DOORBELL); | 976 | ring->bf.uar->map + MLX4_SEND_DOORBELL); |
| 967 | } else { | 977 | } else { |
| 968 | ring->xmit_more++; | 978 | ring->xmit_more++; |
diff --git a/drivers/net/ethernet/micrel/ksz884x.c b/drivers/net/ethernet/micrel/ksz884x.c index f1ebed6c63b1..2fa6ae026e4f 100644 --- a/drivers/net/ethernet/micrel/ksz884x.c +++ b/drivers/net/ethernet/micrel/ksz884x.c | |||
| @@ -2303,12 +2303,6 @@ static inline int port_chk_force_flow_ctrl(struct ksz_hw *hw, int p) | |||
| 2303 | 2303 | ||
| 2304 | /* Spanning Tree */ | 2304 | /* Spanning Tree */ |
| 2305 | 2305 | ||
| 2306 | static inline void port_cfg_dis_learn(struct ksz_hw *hw, int p, int set) | ||
| 2307 | { | ||
| 2308 | port_cfg(hw, p, | ||
| 2309 | KS8842_PORT_CTRL_2_OFFSET, PORT_LEARN_DISABLE, set); | ||
| 2310 | } | ||
| 2311 | |||
| 2312 | static inline void port_cfg_rx(struct ksz_hw *hw, int p, int set) | 2306 | static inline void port_cfg_rx(struct ksz_hw *hw, int p, int set) |
| 2313 | { | 2307 | { |
| 2314 | port_cfg(hw, p, | 2308 | port_cfg(hw, p, |
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c index 1aa25b13ace1..9929b97cfb36 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c | |||
| @@ -505,9 +505,11 @@ static void qlcnic_del_vxlan_port(struct net_device *netdev, | |||
| 505 | adapter->flags |= QLCNIC_DEL_VXLAN_PORT; | 505 | adapter->flags |= QLCNIC_DEL_VXLAN_PORT; |
| 506 | } | 506 | } |
| 507 | 507 | ||
| 508 | static bool qlcnic_gso_check(struct sk_buff *skb, struct net_device *dev) | 508 | static netdev_features_t qlcnic_features_check(struct sk_buff *skb, |
| 509 | struct net_device *dev, | ||
| 510 | netdev_features_t features) | ||
| 509 | { | 511 | { |
| 510 | return vxlan_gso_check(skb); | 512 | return vxlan_features_check(skb, features); |
| 511 | } | 513 | } |
| 512 | #endif | 514 | #endif |
| 513 | 515 | ||
| @@ -532,7 +534,7 @@ static const struct net_device_ops qlcnic_netdev_ops = { | |||
| 532 | #ifdef CONFIG_QLCNIC_VXLAN | 534 | #ifdef CONFIG_QLCNIC_VXLAN |
| 533 | .ndo_add_vxlan_port = qlcnic_add_vxlan_port, | 535 | .ndo_add_vxlan_port = qlcnic_add_vxlan_port, |
| 534 | .ndo_del_vxlan_port = qlcnic_del_vxlan_port, | 536 | .ndo_del_vxlan_port = qlcnic_del_vxlan_port, |
| 535 | .ndo_gso_check = qlcnic_gso_check, | 537 | .ndo_features_check = qlcnic_features_check, |
| 536 | #endif | 538 | #endif |
| 537 | #ifdef CONFIG_NET_POLL_CONTROLLER | 539 | #ifdef CONFIG_NET_POLL_CONTROLLER |
| 538 | .ndo_poll_controller = qlcnic_poll_controller, | 540 | .ndo_poll_controller = qlcnic_poll_controller, |
diff --git a/drivers/net/ethernet/realtek/8139too.c b/drivers/net/ethernet/realtek/8139too.c index 6d0b9dfac313..78bb4ceb1cdd 100644 --- a/drivers/net/ethernet/realtek/8139too.c +++ b/drivers/net/ethernet/realtek/8139too.c | |||
| @@ -787,10 +787,10 @@ static struct net_device *rtl8139_init_board(struct pci_dev *pdev) | |||
| 787 | if (rc) | 787 | if (rc) |
| 788 | goto err_out; | 788 | goto err_out; |
| 789 | 789 | ||
| 790 | disable_dev_on_err = 1; | ||
| 790 | rc = pci_request_regions (pdev, DRV_NAME); | 791 | rc = pci_request_regions (pdev, DRV_NAME); |
| 791 | if (rc) | 792 | if (rc) |
| 792 | goto err_out; | 793 | goto err_out; |
| 793 | disable_dev_on_err = 1; | ||
| 794 | 794 | ||
| 795 | pci_set_master (pdev); | 795 | pci_set_master (pdev); |
| 796 | 796 | ||
| @@ -1110,6 +1110,7 @@ static int rtl8139_init_one(struct pci_dev *pdev, | |||
| 1110 | return 0; | 1110 | return 0; |
| 1111 | 1111 | ||
| 1112 | err_out: | 1112 | err_out: |
| 1113 | netif_napi_del(&tp->napi); | ||
| 1113 | __rtl8139_cleanup_dev (dev); | 1114 | __rtl8139_cleanup_dev (dev); |
| 1114 | pci_disable_device (pdev); | 1115 | pci_disable_device (pdev); |
| 1115 | return i; | 1116 | return i; |
| @@ -1124,6 +1125,7 @@ static void rtl8139_remove_one(struct pci_dev *pdev) | |||
| 1124 | assert (dev != NULL); | 1125 | assert (dev != NULL); |
| 1125 | 1126 | ||
| 1126 | cancel_delayed_work_sync(&tp->thread); | 1127 | cancel_delayed_work_sync(&tp->thread); |
| 1128 | netif_napi_del(&tp->napi); | ||
| 1127 | 1129 | ||
| 1128 | unregister_netdev (dev); | 1130 | unregister_netdev (dev); |
| 1129 | 1131 | ||
diff --git a/drivers/net/ethernet/s6gmac.c b/drivers/net/ethernet/s6gmac.c deleted file mode 100644 index f537cbea20e5..000000000000 --- a/drivers/net/ethernet/s6gmac.c +++ /dev/null | |||
| @@ -1,1058 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * Ethernet driver for S6105 on chip network device | ||
| 3 | * (c)2008 emlix GmbH http://www.emlix.com | ||
| 4 | * Authors: Oskar Schirmer <oskar@scara.com> | ||
| 5 | * Daniel Gloeckner <dg@emlix.com> | ||
| 6 | * | ||
| 7 | * This program is free software; you can redistribute it and/or | ||
| 8 | * modify it under the terms of the GNU General Public License | ||
| 9 | * as published by the Free Software Foundation; either version | ||
| 10 | * 2 of the License, or (at your option) any later version. | ||
| 11 | */ | ||
| 12 | #include <linux/kernel.h> | ||
| 13 | #include <linux/module.h> | ||
| 14 | #include <linux/interrupt.h> | ||
| 15 | #include <linux/types.h> | ||
| 16 | #include <linux/delay.h> | ||
| 17 | #include <linux/spinlock.h> | ||
| 18 | #include <linux/netdevice.h> | ||
| 19 | #include <linux/etherdevice.h> | ||
| 20 | #include <linux/if.h> | ||
| 21 | #include <linux/stddef.h> | ||
| 22 | #include <linux/mii.h> | ||
| 23 | #include <linux/phy.h> | ||
| 24 | #include <linux/platform_device.h> | ||
| 25 | #include <variant/hardware.h> | ||
| 26 | #include <variant/dmac.h> | ||
| 27 | |||
| 28 | #define DRV_NAME "s6gmac" | ||
| 29 | #define DRV_PRMT DRV_NAME ": " | ||
| 30 | |||
| 31 | |||
| 32 | /* register declarations */ | ||
| 33 | |||
| 34 | #define S6_GMAC_MACCONF1 0x000 | ||
| 35 | #define S6_GMAC_MACCONF1_TXENA 0 | ||
| 36 | #define S6_GMAC_MACCONF1_SYNCTX 1 | ||
| 37 | #define S6_GMAC_MACCONF1_RXENA 2 | ||
| 38 | #define S6_GMAC_MACCONF1_SYNCRX 3 | ||
| 39 | #define S6_GMAC_MACCONF1_TXFLOWCTRL 4 | ||
| 40 | #define S6_GMAC_MACCONF1_RXFLOWCTRL 5 | ||
| 41 | #define S6_GMAC_MACCONF1_LOOPBACK 8 | ||
| 42 | #define S6_GMAC_MACCONF1_RESTXFUNC 16 | ||
| 43 | #define S6_GMAC_MACCONF1_RESRXFUNC 17 | ||
| 44 | #define S6_GMAC_MACCONF1_RESTXMACCTRL 18 | ||
| 45 | #define S6_GMAC_MACCONF1_RESRXMACCTRL 19 | ||
| 46 | #define S6_GMAC_MACCONF1_SIMULRES 30 | ||
| 47 | #define S6_GMAC_MACCONF1_SOFTRES 31 | ||
| 48 | #define S6_GMAC_MACCONF2 0x004 | ||
| 49 | #define S6_GMAC_MACCONF2_FULL 0 | ||
| 50 | #define S6_GMAC_MACCONF2_CRCENA 1 | ||
| 51 | #define S6_GMAC_MACCONF2_PADCRCENA 2 | ||
| 52 | #define S6_GMAC_MACCONF2_LENGTHFCHK 4 | ||
| 53 | #define S6_GMAC_MACCONF2_HUGEFRAMENA 5 | ||
| 54 | #define S6_GMAC_MACCONF2_IFMODE 8 | ||
| 55 | #define S6_GMAC_MACCONF2_IFMODE_NIBBLE 1 | ||
| 56 | #define S6_GMAC_MACCONF2_IFMODE_BYTE 2 | ||
| 57 | #define S6_GMAC_MACCONF2_IFMODE_MASK 3 | ||
| 58 | #define S6_GMAC_MACCONF2_PREAMBLELEN 12 | ||
| 59 | #define S6_GMAC_MACCONF2_PREAMBLELEN_MASK 0x0F | ||
| 60 | #define S6_GMAC_MACIPGIFG 0x008 | ||
| 61 | #define S6_GMAC_MACIPGIFG_B2BINTERPGAP 0 | ||
| 62 | #define S6_GMAC_MACIPGIFG_B2BINTERPGAP_MASK 0x7F | ||
| 63 | #define S6_GMAC_MACIPGIFG_MINIFGENFORCE 8 | ||
| 64 | #define S6_GMAC_MACIPGIFG_B2BINTERPGAP2 16 | ||
| 65 | #define S6_GMAC_MACIPGIFG_B2BINTERPGAP1 24 | ||
| 66 | #define S6_GMAC_MACHALFDUPLEX 0x00C | ||
| 67 | #define S6_GMAC_MACHALFDUPLEX_COLLISWIN 0 | ||
| 68 | #define S6_GMAC_MACHALFDUPLEX_COLLISWIN_MASK 0x3F | ||
| 69 | #define S6_GMAC_MACHALFDUPLEX_RETXMAX 12 | ||
| 70 | #define S6_GMAC_MACHALFDUPLEX_RETXMAX_MASK 0x0F | ||
| 71 | #define S6_GMAC_MACHALFDUPLEX_EXCESSDEF 16 | ||
| 72 | #define S6_GMAC_MACHALFDUPLEX_NOBACKOFF 17 | ||
| 73 | #define S6_GMAC_MACHALFDUPLEX_BPNOBCKOF 18 | ||
| 74 | #define S6_GMAC_MACHALFDUPLEX_ALTBEBENA 19 | ||
| 75 | #define S6_GMAC_MACHALFDUPLEX_ALTBEBTRN 20 | ||
| 76 | #define S6_GMAC_MACHALFDUPLEX_ALTBEBTR_MASK 0x0F | ||
| 77 | #define S6_GMAC_MACMAXFRAMELEN 0x010 | ||
| 78 | #define S6_GMAC_MACMIICONF 0x020 | ||
| 79 | #define S6_GMAC_MACMIICONF_CSEL 0 | ||
| 80 | #define S6_GMAC_MACMIICONF_CSEL_DIV10 0 | ||
| 81 | #define S6_GMAC_MACMIICONF_CSEL_DIV12 1 | ||
| 82 | #define S6_GMAC_MACMIICONF_CSEL_DIV14 2 | ||
| 83 | #define S6_GMAC_MACMIICONF_CSEL_DIV18 3 | ||
| 84 | #define S6_GMAC_MACMIICONF_CSEL_DIV24 4 | ||
| 85 | #define S6_GMAC_MACMIICONF_CSEL_DIV34 5 | ||
| 86 | #define S6_GMAC_MACMIICONF_CSEL_DIV68 6 | ||
| 87 | #define S6_GMAC_MACMIICONF_CSEL_DIV168 7 | ||
| 88 | #define S6_GMAC_MACMIICONF_CSEL_MASK 7 | ||
| 89 | #define S6_GMAC_MACMIICONF_PREAMBLESUPR 4 | ||
| 90 | #define S6_GMAC_MACMIICONF_SCANAUTOINCR 5 | ||
| 91 | #define S6_GMAC_MACMIICMD 0x024 | ||
| 92 | #define S6_GMAC_MACMIICMD_READ 0 | ||
| 93 | #define S6_GMAC_MACMIICMD_SCAN 1 | ||
| 94 | #define S6_GMAC_MACMIIADDR 0x028 | ||
| 95 | #define S6_GMAC_MACMIIADDR_REG 0 | ||
| 96 | #define S6_GMAC_MACMIIADDR_REG_MASK 0x1F | ||
| 97 | #define S6_GMAC_MACMIIADDR_PHY 8 | ||
| 98 | #define S6_GMAC_MACMIIADDR_PHY_MASK 0x1F | ||
| 99 | #define S6_GMAC_MACMIICTRL 0x02C | ||
| 100 | #define S6_GMAC_MACMIISTAT 0x030 | ||
| 101 | #define S6_GMAC_MACMIIINDI 0x034 | ||
| 102 | #define S6_GMAC_MACMIIINDI_BUSY 0 | ||
| 103 | #define S6_GMAC_MACMIIINDI_SCAN 1 | ||
| 104 | #define S6_GMAC_MACMIIINDI_INVAL 2 | ||
| 105 | #define S6_GMAC_MACINTERFSTAT 0x03C | ||
| 106 | #define S6_GMAC_MACINTERFSTAT_LINKFAIL 3 | ||
| 107 | #define S6_GMAC_MACINTERFSTAT_EXCESSDEF 9 | ||
| 108 | #define S6_GMAC_MACSTATADDR1 0x040 | ||
| 109 | #define S6_GMAC_MACSTATADDR2 0x044 | ||
| 110 | |||
| 111 | #define S6_GMAC_FIFOCONF0 0x048 | ||
| 112 | #define S6_GMAC_FIFOCONF0_HSTRSTWT 0 | ||
| 113 | #define S6_GMAC_FIFOCONF0_HSTRSTSR 1 | ||
| 114 | #define S6_GMAC_FIFOCONF0_HSTRSTFR 2 | ||
| 115 | #define S6_GMAC_FIFOCONF0_HSTRSTST 3 | ||
| 116 | #define S6_GMAC_FIFOCONF0_HSTRSTFT 4 | ||
| 117 | #define S6_GMAC_FIFOCONF0_WTMENREQ 8 | ||
| 118 | #define S6_GMAC_FIFOCONF0_SRFENREQ 9 | ||
| 119 | #define S6_GMAC_FIFOCONF0_FRFENREQ 10 | ||
| 120 | #define S6_GMAC_FIFOCONF0_STFENREQ 11 | ||
| 121 | #define S6_GMAC_FIFOCONF0_FTFENREQ 12 | ||
| 122 | #define S6_GMAC_FIFOCONF0_WTMENRPLY 16 | ||
| 123 | #define S6_GMAC_FIFOCONF0_SRFENRPLY 17 | ||
| 124 | #define S6_GMAC_FIFOCONF0_FRFENRPLY 18 | ||
| 125 | #define S6_GMAC_FIFOCONF0_STFENRPLY 19 | ||
| 126 | #define S6_GMAC_FIFOCONF0_FTFENRPLY 20 | ||
| 127 | #define S6_GMAC_FIFOCONF1 0x04C | ||
| 128 | #define S6_GMAC_FIFOCONF2 0x050 | ||
| 129 | #define S6_GMAC_FIFOCONF2_CFGLWM 0 | ||
| 130 | #define S6_GMAC_FIFOCONF2_CFGHWM 16 | ||
| 131 | #define S6_GMAC_FIFOCONF3 0x054 | ||
| 132 | #define S6_GMAC_FIFOCONF3_CFGFTTH 0 | ||
| 133 | #define S6_GMAC_FIFOCONF3_CFGHWMFT 16 | ||
| 134 | #define S6_GMAC_FIFOCONF4 0x058 | ||
| 135 | #define S6_GMAC_FIFOCONF_RSV_PREVDROP 0 | ||
| 136 | #define S6_GMAC_FIFOCONF_RSV_RUNT 1 | ||
| 137 | #define S6_GMAC_FIFOCONF_RSV_FALSECAR 2 | ||
| 138 | #define S6_GMAC_FIFOCONF_RSV_CODEERR 3 | ||
| 139 | #define S6_GMAC_FIFOCONF_RSV_CRCERR 4 | ||
| 140 | #define S6_GMAC_FIFOCONF_RSV_LENGTHERR 5 | ||
| 141 | #define S6_GMAC_FIFOCONF_RSV_LENRANGE 6 | ||
| 142 | #define S6_GMAC_FIFOCONF_RSV_OK 7 | ||
| 143 | #define S6_GMAC_FIFOCONF_RSV_MULTICAST 8 | ||
| 144 | #define S6_GMAC_FIFOCONF_RSV_BROADCAST 9 | ||
| 145 | #define S6_GMAC_FIFOCONF_RSV_DRIBBLE 10 | ||
| 146 | #define S6_GMAC_FIFOCONF_RSV_CTRLFRAME 11 | ||
| 147 | #define S6_GMAC_FIFOCONF_RSV_PAUSECTRL 12 | ||
| 148 | #define S6_GMAC_FIFOCONF_RSV_UNOPCODE 13 | ||
| 149 | #define S6_GMAC_FIFOCONF_RSV_VLANTAG 14 | ||
| 150 | #define S6_GMAC_FIFOCONF_RSV_LONGEVENT 15 | ||
| 151 | #define S6_GMAC_FIFOCONF_RSV_TRUNCATED 16 | ||
| 152 | #define S6_GMAC_FIFOCONF_RSV_MASK 0x3FFFF | ||
| 153 | #define S6_GMAC_FIFOCONF5 0x05C | ||
| 154 | #define S6_GMAC_FIFOCONF5_DROPLT64 18 | ||
| 155 | #define S6_GMAC_FIFOCONF5_CFGBYTM 19 | ||
| 156 | #define S6_GMAC_FIFOCONF5_RXDROPSIZE 20 | ||
| 157 | #define S6_GMAC_FIFOCONF5_RXDROPSIZE_MASK 0xF | ||
| 158 | |||
| 159 | #define S6_GMAC_STAT_REGS 0x080 | ||
| 160 | #define S6_GMAC_STAT_SIZE_MIN 12 | ||
| 161 | #define S6_GMAC_STATTR64 0x080 | ||
| 162 | #define S6_GMAC_STATTR64_SIZE 18 | ||
| 163 | #define S6_GMAC_STATTR127 0x084 | ||
| 164 | #define S6_GMAC_STATTR127_SIZE 18 | ||
| 165 | #define S6_GMAC_STATTR255 0x088 | ||
| 166 | #define S6_GMAC_STATTR255_SIZE 18 | ||
| 167 | #define S6_GMAC_STATTR511 0x08C | ||
| 168 | #define S6_GMAC_STATTR511_SIZE 18 | ||
| 169 | #define S6_GMAC_STATTR1K 0x090 | ||
| 170 | #define S6_GMAC_STATTR1K_SIZE 18 | ||
| 171 | #define S6_GMAC_STATTRMAX 0x094 | ||
| 172 | #define S6_GMAC_STATTRMAX_SIZE 18 | ||
| 173 | #define S6_GMAC_STATTRMGV 0x098 | ||
| 174 | #define S6_GMAC_STATTRMGV_SIZE 18 | ||
| 175 | #define S6_GMAC_STATRBYT 0x09C | ||
| 176 | #define S6_GMAC_STATRBYT_SIZE 24 | ||
| 177 | #define S6_GMAC_STATRPKT 0x0A0 | ||
| 178 | #define S6_GMAC_STATRPKT_SIZE 18 | ||
| 179 | #define S6_GMAC_STATRFCS 0x0A4 | ||
| 180 | #define S6_GMAC_STATRFCS_SIZE 12 | ||
| 181 | #define S6_GMAC_STATRMCA 0x0A8 | ||
| 182 | #define S6_GMAC_STATRMCA_SIZE 18 | ||
| 183 | #define S6_GMAC_STATRBCA 0x0AC | ||
| 184 | #define S6_GMAC_STATRBCA_SIZE 22 | ||
| 185 | #define S6_GMAC_STATRXCF 0x0B0 | ||
| 186 | #define S6_GMAC_STATRXCF_SIZE 18 | ||
| 187 | #define S6_GMAC_STATRXPF 0x0B4 | ||
| 188 | #define S6_GMAC_STATRXPF_SIZE 12 | ||
| 189 | #define S6_GMAC_STATRXUO 0x0B8 | ||
| 190 | #define S6_GMAC_STATRXUO_SIZE 12 | ||
| 191 | #define S6_GMAC_STATRALN 0x0BC | ||
| 192 | #define S6_GMAC_STATRALN_SIZE 12 | ||
| 193 | #define S6_GMAC_STATRFLR 0x0C0 | ||
| 194 | #define S6_GMAC_STATRFLR_SIZE 16 | ||
| 195 | #define S6_GMAC_STATRCDE 0x0C4 | ||
| 196 | #define S6_GMAC_STATRCDE_SIZE 12 | ||
| 197 | #define S6_GMAC_STATRCSE 0x0C8 | ||
| 198 | #define S6_GMAC_STATRCSE_SIZE 12 | ||
| 199 | #define S6_GMAC_STATRUND 0x0CC | ||
| 200 | #define S6_GMAC_STATRUND_SIZE 12 | ||
| 201 | #define S6_GMAC_STATROVR 0x0D0 | ||
| 202 | #define S6_GMAC_STATROVR_SIZE 12 | ||
| 203 | #define S6_GMAC_STATRFRG 0x0D4 | ||
| 204 | #define S6_GMAC_STATRFRG_SIZE 12 | ||
| 205 | #define S6_GMAC_STATRJBR 0x0D8 | ||
| 206 | #define S6_GMAC_STATRJBR_SIZE 12 | ||
| 207 | #define S6_GMAC_STATRDRP 0x0DC | ||
| 208 | #define S6_GMAC_STATRDRP_SIZE 12 | ||
| 209 | #define S6_GMAC_STATTBYT 0x0E0 | ||
| 210 | #define S6_GMAC_STATTBYT_SIZE 24 | ||
| 211 | #define S6_GMAC_STATTPKT 0x0E4 | ||
| 212 | #define S6_GMAC_STATTPKT_SIZE 18 | ||
| 213 | #define S6_GMAC_STATTMCA 0x0E8 | ||
| 214 | #define S6_GMAC_STATTMCA_SIZE 18 | ||
| 215 | #define S6_GMAC_STATTBCA 0x0EC | ||
| 216 | #define S6_GMAC_STATTBCA_SIZE 18 | ||
| 217 | #define S6_GMAC_STATTXPF 0x0F0 | ||
| 218 | #define S6_GMAC_STATTXPF_SIZE 12 | ||
| 219 | #define S6_GMAC_STATTDFR 0x0F4 | ||
| 220 | #define S6_GMAC_STATTDFR_SIZE 12 | ||
| 221 | #define S6_GMAC_STATTEDF 0x0F8 | ||
| 222 | #define S6_GMAC_STATTEDF_SIZE 12 | ||
| 223 | #define S6_GMAC_STATTSCL 0x0FC | ||
| 224 | #define S6_GMAC_STATTSCL_SIZE 12 | ||
| 225 | #define S6_GMAC_STATTMCL 0x100 | ||
| 226 | #define S6_GMAC_STATTMCL_SIZE 12 | ||
| 227 | #define S6_GMAC_STATTLCL 0x104 | ||
| 228 | #define S6_GMAC_STATTLCL_SIZE 12 | ||
| 229 | #define S6_GMAC_STATTXCL 0x108 | ||
| 230 | #define S6_GMAC_STATTXCL_SIZE 12 | ||
| 231 | #define S6_GMAC_STATTNCL 0x10C | ||
| 232 | #define S6_GMAC_STATTNCL_SIZE 13 | ||
| 233 | #define S6_GMAC_STATTPFH 0x110 | ||
| 234 | #define S6_GMAC_STATTPFH_SIZE 12 | ||
| 235 | #define S6_GMAC_STATTDRP 0x114 | ||
| 236 | #define S6_GMAC_STATTDRP_SIZE 12 | ||
| 237 | #define S6_GMAC_STATTJBR 0x118 | ||
| 238 | #define S6_GMAC_STATTJBR_SIZE 12 | ||
| 239 | #define S6_GMAC_STATTFCS 0x11C | ||
| 240 | #define S6_GMAC_STATTFCS_SIZE 12 | ||
| 241 | #define S6_GMAC_STATTXCF 0x120 | ||
| 242 | #define S6_GMAC_STATTXCF_SIZE 12 | ||
| 243 | #define S6_GMAC_STATTOVR 0x124 | ||
| 244 | #define S6_GMAC_STATTOVR_SIZE 12 | ||
| 245 | #define S6_GMAC_STATTUND 0x128 | ||
| 246 | #define S6_GMAC_STATTUND_SIZE 12 | ||
| 247 | #define S6_GMAC_STATTFRG 0x12C | ||
| 248 | #define S6_GMAC_STATTFRG_SIZE 12 | ||
| 249 | #define S6_GMAC_STATCARRY(n) (0x130 + 4*(n)) | ||
| 250 | #define S6_GMAC_STATCARRYMSK(n) (0x138 + 4*(n)) | ||
| 251 | #define S6_GMAC_STATCARRY1_RDRP 0 | ||
| 252 | #define S6_GMAC_STATCARRY1_RJBR 1 | ||
| 253 | #define S6_GMAC_STATCARRY1_RFRG 2 | ||
| 254 | #define S6_GMAC_STATCARRY1_ROVR 3 | ||
| 255 | #define S6_GMAC_STATCARRY1_RUND 4 | ||
| 256 | #define S6_GMAC_STATCARRY1_RCSE 5 | ||
| 257 | #define S6_GMAC_STATCARRY1_RCDE 6 | ||
| 258 | #define S6_GMAC_STATCARRY1_RFLR 7 | ||
| 259 | #define S6_GMAC_STATCARRY1_RALN 8 | ||
| 260 | #define S6_GMAC_STATCARRY1_RXUO 9 | ||
| 261 | #define S6_GMAC_STATCARRY1_RXPF 10 | ||
| 262 | #define S6_GMAC_STATCARRY1_RXCF 11 | ||
| 263 | #define S6_GMAC_STATCARRY1_RBCA 12 | ||
| 264 | #define S6_GMAC_STATCARRY1_RMCA 13 | ||
| 265 | #define S6_GMAC_STATCARRY1_RFCS 14 | ||
| 266 | #define S6_GMAC_STATCARRY1_RPKT 15 | ||
| 267 | #define S6_GMAC_STATCARRY1_RBYT 16 | ||
| 268 | #define S6_GMAC_STATCARRY1_TRMGV 25 | ||
| 269 | #define S6_GMAC_STATCARRY1_TRMAX 26 | ||
| 270 | #define S6_GMAC_STATCARRY1_TR1K 27 | ||
| 271 | #define S6_GMAC_STATCARRY1_TR511 28 | ||
| 272 | #define S6_GMAC_STATCARRY1_TR255 29 | ||
| 273 | #define S6_GMAC_STATCARRY1_TR127 30 | ||
| 274 | #define S6_GMAC_STATCARRY1_TR64 31 | ||
| 275 | #define S6_GMAC_STATCARRY2_TDRP 0 | ||
| 276 | #define S6_GMAC_STATCARRY2_TPFH 1 | ||
| 277 | #define S6_GMAC_STATCARRY2_TNCL 2 | ||
| 278 | #define S6_GMAC_STATCARRY2_TXCL 3 | ||
| 279 | #define S6_GMAC_STATCARRY2_TLCL 4 | ||
| 280 | #define S6_GMAC_STATCARRY2_TMCL 5 | ||
| 281 | #define S6_GMAC_STATCARRY2_TSCL 6 | ||
| 282 | #define S6_GMAC_STATCARRY2_TEDF 7 | ||
| 283 | #define S6_GMAC_STATCARRY2_TDFR 8 | ||
| 284 | #define S6_GMAC_STATCARRY2_TXPF 9 | ||
| 285 | #define S6_GMAC_STATCARRY2_TBCA 10 | ||
| 286 | #define S6_GMAC_STATCARRY2_TMCA 11 | ||
| 287 | #define S6_GMAC_STATCARRY2_TPKT 12 | ||
| 288 | #define S6_GMAC_STATCARRY2_TBYT 13 | ||
| 289 | #define S6_GMAC_STATCARRY2_TFRG 14 | ||
| 290 | #define S6_GMAC_STATCARRY2_TUND 15 | ||
| 291 | #define S6_GMAC_STATCARRY2_TOVR 16 | ||
| 292 | #define S6_GMAC_STATCARRY2_TXCF 17 | ||
| 293 | #define S6_GMAC_STATCARRY2_TFCS 18 | ||
| 294 | #define S6_GMAC_STATCARRY2_TJBR 19 | ||
| 295 | |||
| 296 | #define S6_GMAC_HOST_PBLKCTRL 0x140 | ||
| 297 | #define S6_GMAC_HOST_PBLKCTRL_TXENA 0 | ||
| 298 | #define S6_GMAC_HOST_PBLKCTRL_RXENA 1 | ||
| 299 | #define S6_GMAC_HOST_PBLKCTRL_TXSRES 2 | ||
| 300 | #define S6_GMAC_HOST_PBLKCTRL_RXSRES 3 | ||
| 301 | #define S6_GMAC_HOST_PBLKCTRL_TXBSIZ 8 | ||
| 302 | #define S6_GMAC_HOST_PBLKCTRL_RXBSIZ 12 | ||
| 303 | #define S6_GMAC_HOST_PBLKCTRL_SIZ_16 4 | ||
| 304 | #define S6_GMAC_HOST_PBLKCTRL_SIZ_32 5 | ||
| 305 | #define S6_GMAC_HOST_PBLKCTRL_SIZ_64 6 | ||
| 306 | #define S6_GMAC_HOST_PBLKCTRL_SIZ_128 7 | ||
| 307 | #define S6_GMAC_HOST_PBLKCTRL_SIZ_MASK 0xF | ||
| 308 | #define S6_GMAC_HOST_PBLKCTRL_STATENA 16 | ||
| 309 | #define S6_GMAC_HOST_PBLKCTRL_STATAUTOZ 17 | ||
| 310 | #define S6_GMAC_HOST_PBLKCTRL_STATCLEAR 18 | ||
| 311 | #define S6_GMAC_HOST_PBLKCTRL_RGMII 19 | ||
| 312 | #define S6_GMAC_HOST_INTMASK 0x144 | ||
| 313 | #define S6_GMAC_HOST_INTSTAT 0x148 | ||
| 314 | #define S6_GMAC_HOST_INT_TXBURSTOVER 3 | ||
| 315 | #define S6_GMAC_HOST_INT_TXPREWOVER 4 | ||
| 316 | #define S6_GMAC_HOST_INT_RXBURSTUNDER 5 | ||
| 317 | #define S6_GMAC_HOST_INT_RXPOSTRFULL 6 | ||
| 318 | #define S6_GMAC_HOST_INT_RXPOSTRUNDER 7 | ||
| 319 | #define S6_GMAC_HOST_RXFIFOHWM 0x14C | ||
| 320 | #define S6_GMAC_HOST_CTRLFRAMXP 0x150 | ||
| 321 | #define S6_GMAC_HOST_DSTADDRLO(n) (0x160 + 8*(n)) | ||
| 322 | #define S6_GMAC_HOST_DSTADDRHI(n) (0x164 + 8*(n)) | ||
| 323 | #define S6_GMAC_HOST_DSTMASKLO(n) (0x180 + 8*(n)) | ||
| 324 | #define S6_GMAC_HOST_DSTMASKHI(n) (0x184 + 8*(n)) | ||
| 325 | |||
| 326 | #define S6_GMAC_BURST_PREWR 0x1B0 | ||
| 327 | #define S6_GMAC_BURST_PREWR_LEN 0 | ||
| 328 | #define S6_GMAC_BURST_PREWR_LEN_MASK ((1 << 20) - 1) | ||
| 329 | #define S6_GMAC_BURST_PREWR_CFE 20 | ||
| 330 | #define S6_GMAC_BURST_PREWR_PPE 21 | ||
| 331 | #define S6_GMAC_BURST_PREWR_FCS 22 | ||
| 332 | #define S6_GMAC_BURST_PREWR_PAD 23 | ||
| 333 | #define S6_GMAC_BURST_POSTRD 0x1D0 | ||
| 334 | #define S6_GMAC_BURST_POSTRD_LEN 0 | ||
| 335 | #define S6_GMAC_BURST_POSTRD_LEN_MASK ((1 << 20) - 1) | ||
| 336 | #define S6_GMAC_BURST_POSTRD_DROP 20 | ||
| 337 | |||
| 338 | |||
| 339 | /* data handling */ | ||
| 340 | |||
| 341 | #define S6_NUM_TX_SKB 8 /* must be larger than TX fifo size */ | ||
| 342 | #define S6_NUM_RX_SKB 16 | ||
| 343 | #define S6_MAX_FRLEN 1536 | ||
| 344 | |||
| 345 | struct s6gmac { | ||
| 346 | u32 reg; | ||
| 347 | u32 tx_dma; | ||
| 348 | u32 rx_dma; | ||
| 349 | u32 io; | ||
| 350 | u8 tx_chan; | ||
| 351 | u8 rx_chan; | ||
| 352 | spinlock_t lock; | ||
| 353 | u8 tx_skb_i, tx_skb_o; | ||
| 354 | u8 rx_skb_i, rx_skb_o; | ||
| 355 | struct sk_buff *tx_skb[S6_NUM_TX_SKB]; | ||
| 356 | struct sk_buff *rx_skb[S6_NUM_RX_SKB]; | ||
| 357 | unsigned long carry[sizeof(struct net_device_stats) / sizeof(long)]; | ||
| 358 | unsigned long stats[sizeof(struct net_device_stats) / sizeof(long)]; | ||
| 359 | struct phy_device *phydev; | ||
| 360 | struct { | ||
| 361 | struct mii_bus *bus; | ||
| 362 | int irq[PHY_MAX_ADDR]; | ||
| 363 | } mii; | ||
| 364 | struct { | ||
| 365 | unsigned int mbit; | ||
| 366 | u8 giga; | ||
| 367 | u8 isup; | ||
| 368 | u8 full; | ||
| 369 | } link; | ||
| 370 | }; | ||
| 371 | |||
| 372 | static void s6gmac_rx_fillfifo(struct net_device *dev) | ||
| 373 | { | ||
| 374 | struct s6gmac *pd = netdev_priv(dev); | ||
| 375 | struct sk_buff *skb; | ||
| 376 | while ((((u8)(pd->rx_skb_i - pd->rx_skb_o)) < S6_NUM_RX_SKB) && | ||
| 377 | (!s6dmac_fifo_full(pd->rx_dma, pd->rx_chan)) && | ||
| 378 | (skb = netdev_alloc_skb(dev, S6_MAX_FRLEN + 2))) { | ||
| 379 | pd->rx_skb[(pd->rx_skb_i++) % S6_NUM_RX_SKB] = skb; | ||
| 380 | s6dmac_put_fifo_cache(pd->rx_dma, pd->rx_chan, | ||
| 381 | pd->io, (u32)skb->data, S6_MAX_FRLEN); | ||
| 382 | } | ||
| 383 | } | ||
| 384 | |||
| 385 | static void s6gmac_rx_interrupt(struct net_device *dev) | ||
| 386 | { | ||
| 387 | struct s6gmac *pd = netdev_priv(dev); | ||
| 388 | u32 pfx; | ||
| 389 | struct sk_buff *skb; | ||
| 390 | while (((u8)(pd->rx_skb_i - pd->rx_skb_o)) > | ||
| 391 | s6dmac_pending_count(pd->rx_dma, pd->rx_chan)) { | ||
| 392 | skb = pd->rx_skb[(pd->rx_skb_o++) % S6_NUM_RX_SKB]; | ||
| 393 | pfx = readl(pd->reg + S6_GMAC_BURST_POSTRD); | ||
| 394 | if (pfx & (1 << S6_GMAC_BURST_POSTRD_DROP)) { | ||
| 395 | dev_kfree_skb_irq(skb); | ||
| 396 | } else { | ||
| 397 | skb_put(skb, (pfx >> S6_GMAC_BURST_POSTRD_LEN) | ||
| 398 | & S6_GMAC_BURST_POSTRD_LEN_MASK); | ||
| 399 | skb->protocol = eth_type_trans(skb, dev); | ||
| 400 | skb->ip_summed = CHECKSUM_UNNECESSARY; | ||
| 401 | netif_rx(skb); | ||
| 402 | } | ||
| 403 | } | ||
| 404 | } | ||
| 405 | |||
| 406 | static void s6gmac_tx_interrupt(struct net_device *dev) | ||
| 407 | { | ||
| 408 | struct s6gmac *pd = netdev_priv(dev); | ||
| 409 | while (((u8)(pd->tx_skb_i - pd->tx_skb_o)) > | ||
| 410 | s6dmac_pending_count(pd->tx_dma, pd->tx_chan)) { | ||
| 411 | dev_kfree_skb_irq(pd->tx_skb[(pd->tx_skb_o++) % S6_NUM_TX_SKB]); | ||
| 412 | } | ||
| 413 | if (!s6dmac_fifo_full(pd->tx_dma, pd->tx_chan)) | ||
| 414 | netif_wake_queue(dev); | ||
| 415 | } | ||
| 416 | |||
| 417 | struct s6gmac_statinf { | ||
| 418 | unsigned reg_size : 4; /* 0: unused */ | ||
| 419 | unsigned reg_off : 6; | ||
| 420 | unsigned net_index : 6; | ||
| 421 | }; | ||
| 422 | |||
| 423 | #define S6_STATS_B (8 * sizeof(u32)) | ||
| 424 | #define S6_STATS_C(b, r, f) [b] = { \ | ||
| 425 | BUILD_BUG_ON_ZERO(r##_SIZE < S6_GMAC_STAT_SIZE_MIN) + \ | ||
| 426 | BUILD_BUG_ON_ZERO((r##_SIZE - (S6_GMAC_STAT_SIZE_MIN - 1)) \ | ||
| 427 | >= (1<<4)) + \ | ||
| 428 | r##_SIZE - (S6_GMAC_STAT_SIZE_MIN - 1), \ | ||
| 429 | BUILD_BUG_ON_ZERO(((unsigned)((r - S6_GMAC_STAT_REGS) / sizeof(u32))) \ | ||
| 430 | >= ((1<<6)-1)) + \ | ||
| 431 | (r - S6_GMAC_STAT_REGS) / sizeof(u32), \ | ||
| 432 | BUILD_BUG_ON_ZERO((offsetof(struct net_device_stats, f)) \ | ||
| 433 | % sizeof(unsigned long)) + \ | ||
| 434 | BUILD_BUG_ON_ZERO((((unsigned)(offsetof(struct net_device_stats, f)) \ | ||
| 435 | / sizeof(unsigned long)) >= (1<<6))) + \ | ||
| 436 | BUILD_BUG_ON_ZERO((sizeof(((struct net_device_stats *)0)->f) \ | ||
| 437 | != sizeof(unsigned long))) + \ | ||
| 438 | (offsetof(struct net_device_stats, f)) / sizeof(unsigned long)}, | ||
| 439 | |||
| 440 | static const struct s6gmac_statinf statinf[2][S6_STATS_B] = { { | ||
| 441 | S6_STATS_C(S6_GMAC_STATCARRY1_RBYT, S6_GMAC_STATRBYT, rx_bytes) | ||
| 442 | S6_STATS_C(S6_GMAC_STATCARRY1_RPKT, S6_GMAC_STATRPKT, rx_packets) | ||
| 443 | S6_STATS_C(S6_GMAC_STATCARRY1_RFCS, S6_GMAC_STATRFCS, rx_crc_errors) | ||
| 444 | S6_STATS_C(S6_GMAC_STATCARRY1_RMCA, S6_GMAC_STATRMCA, multicast) | ||
| 445 | S6_STATS_C(S6_GMAC_STATCARRY1_RALN, S6_GMAC_STATRALN, rx_frame_errors) | ||
| 446 | S6_STATS_C(S6_GMAC_STATCARRY1_RFLR, S6_GMAC_STATRFLR, rx_length_errors) | ||
| 447 | S6_STATS_C(S6_GMAC_STATCARRY1_RCDE, S6_GMAC_STATRCDE, rx_missed_errors) | ||
| 448 | S6_STATS_C(S6_GMAC_STATCARRY1_RUND, S6_GMAC_STATRUND, rx_length_errors) | ||
| 449 | S6_STATS_C(S6_GMAC_STATCARRY1_ROVR, S6_GMAC_STATROVR, rx_length_errors) | ||
| 450 | S6_STATS_C(S6_GMAC_STATCARRY1_RFRG, S6_GMAC_STATRFRG, rx_crc_errors) | ||
| 451 | S6_STATS_C(S6_GMAC_STATCARRY1_RJBR, S6_GMAC_STATRJBR, rx_crc_errors) | ||
| 452 | S6_STATS_C(S6_GMAC_STATCARRY1_RDRP, S6_GMAC_STATRDRP, rx_dropped) | ||
| 453 | }, { | ||
| 454 | S6_STATS_C(S6_GMAC_STATCARRY2_TBYT, S6_GMAC_STATTBYT, tx_bytes) | ||
| 455 | S6_STATS_C(S6_GMAC_STATCARRY2_TPKT, S6_GMAC_STATTPKT, tx_packets) | ||
| 456 | S6_STATS_C(S6_GMAC_STATCARRY2_TEDF, S6_GMAC_STATTEDF, tx_aborted_errors) | ||
| 457 | S6_STATS_C(S6_GMAC_STATCARRY2_TXCL, S6_GMAC_STATTXCL, tx_aborted_errors) | ||
| 458 | S6_STATS_C(S6_GMAC_STATCARRY2_TNCL, S6_GMAC_STATTNCL, collisions) | ||
| 459 | S6_STATS_C(S6_GMAC_STATCARRY2_TDRP, S6_GMAC_STATTDRP, tx_dropped) | ||
| 460 | S6_STATS_C(S6_GMAC_STATCARRY2_TJBR, S6_GMAC_STATTJBR, tx_errors) | ||
| 461 | S6_STATS_C(S6_GMAC_STATCARRY2_TFCS, S6_GMAC_STATTFCS, tx_errors) | ||
| 462 | S6_STATS_C(S6_GMAC_STATCARRY2_TOVR, S6_GMAC_STATTOVR, tx_errors) | ||
| 463 | S6_STATS_C(S6_GMAC_STATCARRY2_TUND, S6_GMAC_STATTUND, tx_errors) | ||
| 464 | S6_STATS_C(S6_GMAC_STATCARRY2_TFRG, S6_GMAC_STATTFRG, tx_errors) | ||
| 465 | } }; | ||
| 466 | |||
| 467 | static void s6gmac_stats_collect(struct s6gmac *pd, | ||
| 468 | const struct s6gmac_statinf *inf) | ||
| 469 | { | ||
| 470 | int b; | ||
| 471 | for (b = 0; b < S6_STATS_B; b++) { | ||
| 472 | if (inf[b].reg_size) { | ||
| 473 | pd->stats[inf[b].net_index] += | ||
| 474 | readl(pd->reg + S6_GMAC_STAT_REGS | ||
| 475 | + sizeof(u32) * inf[b].reg_off); | ||
| 476 | } | ||
| 477 | } | ||
| 478 | } | ||
| 479 | |||
| 480 | static void s6gmac_stats_carry(struct s6gmac *pd, | ||
| 481 | const struct s6gmac_statinf *inf, u32 mask) | ||
| 482 | { | ||
| 483 | int b; | ||
| 484 | while (mask) { | ||
| 485 | b = fls(mask) - 1; | ||
| 486 | mask &= ~(1 << b); | ||
| 487 | pd->carry[inf[b].net_index] += (1 << inf[b].reg_size); | ||
| 488 | } | ||
| 489 | } | ||
| 490 | |||
| 491 | static inline u32 s6gmac_stats_pending(struct s6gmac *pd, int carry) | ||
| 492 | { | ||
| 493 | int r = readl(pd->reg + S6_GMAC_STATCARRY(carry)) & | ||
| 494 | ~readl(pd->reg + S6_GMAC_STATCARRYMSK(carry)); | ||
| 495 | return r; | ||
| 496 | } | ||
| 497 | |||
| 498 | static inline void s6gmac_stats_interrupt(struct s6gmac *pd, int carry) | ||
| 499 | { | ||
| 500 | u32 mask; | ||
| 501 | mask = s6gmac_stats_pending(pd, carry); | ||
| 502 | if (mask) { | ||
| 503 | writel(mask, pd->reg + S6_GMAC_STATCARRY(carry)); | ||
| 504 | s6gmac_stats_carry(pd, &statinf[carry][0], mask); | ||
| 505 | } | ||
| 506 | } | ||
| 507 | |||
| 508 | static irqreturn_t s6gmac_interrupt(int irq, void *dev_id) | ||
| 509 | { | ||
| 510 | struct net_device *dev = (struct net_device *)dev_id; | ||
| 511 | struct s6gmac *pd = netdev_priv(dev); | ||
| 512 | if (!dev) | ||
| 513 | return IRQ_NONE; | ||
| 514 | spin_lock(&pd->lock); | ||
| 515 | if (s6dmac_termcnt_irq(pd->rx_dma, pd->rx_chan)) | ||
| 516 | s6gmac_rx_interrupt(dev); | ||
| 517 | s6gmac_rx_fillfifo(dev); | ||
| 518 | if (s6dmac_termcnt_irq(pd->tx_dma, pd->tx_chan)) | ||
| 519 | s6gmac_tx_interrupt(dev); | ||
| 520 | s6gmac_stats_interrupt(pd, 0); | ||
| 521 | s6gmac_stats_interrupt(pd, 1); | ||
| 522 | spin_unlock(&pd->lock); | ||
| 523 | return IRQ_HANDLED; | ||
| 524 | } | ||
| 525 | |||
| 526 | static inline void s6gmac_set_dstaddr(struct s6gmac *pd, int n, | ||
| 527 | u32 addrlo, u32 addrhi, u32 masklo, u32 maskhi) | ||
| 528 | { | ||
| 529 | writel(addrlo, pd->reg + S6_GMAC_HOST_DSTADDRLO(n)); | ||
| 530 | writel(addrhi, pd->reg + S6_GMAC_HOST_DSTADDRHI(n)); | ||
| 531 | writel(masklo, pd->reg + S6_GMAC_HOST_DSTMASKLO(n)); | ||
| 532 | writel(maskhi, pd->reg + S6_GMAC_HOST_DSTMASKHI(n)); | ||
| 533 | } | ||
| 534 | |||
| 535 | static inline void s6gmac_stop_device(struct net_device *dev) | ||
| 536 | { | ||
| 537 | struct s6gmac *pd = netdev_priv(dev); | ||
| 538 | writel(0, pd->reg + S6_GMAC_MACCONF1); | ||
| 539 | } | ||
| 540 | |||
| 541 | static inline void s6gmac_init_device(struct net_device *dev) | ||
| 542 | { | ||
| 543 | struct s6gmac *pd = netdev_priv(dev); | ||
| 544 | int is_rgmii = !!(pd->phydev->supported | ||
| 545 | & (SUPPORTED_1000baseT_Full | SUPPORTED_1000baseT_Half)); | ||
| 546 | #if 0 | ||
| 547 | writel(1 << S6_GMAC_MACCONF1_SYNCTX | | ||
| 548 | 1 << S6_GMAC_MACCONF1_SYNCRX | | ||
| 549 | 1 << S6_GMAC_MACCONF1_TXFLOWCTRL | | ||
| 550 | 1 << S6_GMAC_MACCONF1_RXFLOWCTRL | | ||
| 551 | 1 << S6_GMAC_MACCONF1_RESTXFUNC | | ||
| 552 | 1 << S6_GMAC_MACCONF1_RESRXFUNC | | ||
| 553 | 1 << S6_GMAC_MACCONF1_RESTXMACCTRL | | ||
| 554 | 1 << S6_GMAC_MACCONF1_RESRXMACCTRL, | ||
| 555 | pd->reg + S6_GMAC_MACCONF1); | ||
| 556 | #endif | ||
| 557 | writel(1 << S6_GMAC_MACCONF1_SOFTRES, pd->reg + S6_GMAC_MACCONF1); | ||
| 558 | udelay(1000); | ||
| 559 | writel(1 << S6_GMAC_MACCONF1_TXENA | 1 << S6_GMAC_MACCONF1_RXENA, | ||
| 560 | pd->reg + S6_GMAC_MACCONF1); | ||
| 561 | writel(1 << S6_GMAC_HOST_PBLKCTRL_TXSRES | | ||
| 562 | 1 << S6_GMAC_HOST_PBLKCTRL_RXSRES, | ||
| 563 | pd->reg + S6_GMAC_HOST_PBLKCTRL); | ||
| 564 | writel(S6_GMAC_HOST_PBLKCTRL_SIZ_128 << S6_GMAC_HOST_PBLKCTRL_TXBSIZ | | ||
| 565 | S6_GMAC_HOST_PBLKCTRL_SIZ_128 << S6_GMAC_HOST_PBLKCTRL_RXBSIZ | | ||
| 566 | 1 << S6_GMAC_HOST_PBLKCTRL_STATENA | | ||
| 567 | 1 << S6_GMAC_HOST_PBLKCTRL_STATCLEAR | | ||
| 568 | is_rgmii << S6_GMAC_HOST_PBLKCTRL_RGMII, | ||
| 569 | pd->reg + S6_GMAC_HOST_PBLKCTRL); | ||
| 570 | writel(1 << S6_GMAC_MACCONF1_TXENA | | ||
| 571 | 1 << S6_GMAC_MACCONF1_RXENA | | ||
| 572 | (dev->flags & IFF_LOOPBACK ? 1 : 0) | ||
| 573 | << S6_GMAC_MACCONF1_LOOPBACK, | ||
| 574 | pd->reg + S6_GMAC_MACCONF1); | ||
| 575 | writel(dev->mtu && (dev->mtu < (S6_MAX_FRLEN - ETH_HLEN-ETH_FCS_LEN)) ? | ||
| 576 | dev->mtu+ETH_HLEN+ETH_FCS_LEN : S6_MAX_FRLEN, | ||
| 577 | pd->reg + S6_GMAC_MACMAXFRAMELEN); | ||
| 578 | writel((pd->link.full ? 1 : 0) << S6_GMAC_MACCONF2_FULL | | ||
| 579 | 1 << S6_GMAC_MACCONF2_PADCRCENA | | ||
| 580 | 1 << S6_GMAC_MACCONF2_LENGTHFCHK | | ||
| 581 | (pd->link.giga ? | ||
| 582 | S6_GMAC_MACCONF2_IFMODE_BYTE : | ||
| 583 | S6_GMAC_MACCONF2_IFMODE_NIBBLE) | ||
| 584 | << S6_GMAC_MACCONF2_IFMODE | | ||
| 585 | 7 << S6_GMAC_MACCONF2_PREAMBLELEN, | ||
| 586 | pd->reg + S6_GMAC_MACCONF2); | ||
| 587 | writel(0, pd->reg + S6_GMAC_MACSTATADDR1); | ||
| 588 | writel(0, pd->reg + S6_GMAC_MACSTATADDR2); | ||
| 589 | writel(1 << S6_GMAC_FIFOCONF0_WTMENREQ | | ||
| 590 | 1 << S6_GMAC_FIFOCONF0_SRFENREQ | | ||
| 591 | 1 << S6_GMAC_FIFOCONF0_FRFENREQ | | ||
| 592 | 1 << S6_GMAC_FIFOCONF0_STFENREQ | | ||
| 593 | 1 << S6_GMAC_FIFOCONF0_FTFENREQ, | ||
| 594 | pd->reg + S6_GMAC_FIFOCONF0); | ||
| 595 | writel(128 << S6_GMAC_FIFOCONF3_CFGFTTH | | ||
| 596 | 128 << S6_GMAC_FIFOCONF3_CFGHWMFT, | ||
| 597 | pd->reg + S6_GMAC_FIFOCONF3); | ||
| 598 | writel((S6_GMAC_FIFOCONF_RSV_MASK & ~( | ||
| 599 | 1 << S6_GMAC_FIFOCONF_RSV_RUNT | | ||
| 600 | 1 << S6_GMAC_FIFOCONF_RSV_CRCERR | | ||
| 601 | 1 << S6_GMAC_FIFOCONF_RSV_OK | | ||
| 602 | 1 << S6_GMAC_FIFOCONF_RSV_DRIBBLE | | ||
| 603 | 1 << S6_GMAC_FIFOCONF_RSV_CTRLFRAME | | ||
| 604 | 1 << S6_GMAC_FIFOCONF_RSV_PAUSECTRL | | ||
| 605 | 1 << S6_GMAC_FIFOCONF_RSV_UNOPCODE | | ||
| 606 | 1 << S6_GMAC_FIFOCONF_RSV_TRUNCATED)) | | ||
| 607 | 1 << S6_GMAC_FIFOCONF5_DROPLT64 | | ||
| 608 | pd->link.giga << S6_GMAC_FIFOCONF5_CFGBYTM | | ||
| 609 | 1 << S6_GMAC_FIFOCONF5_RXDROPSIZE, | ||
| 610 | pd->reg + S6_GMAC_FIFOCONF5); | ||
| 611 | writel(1 << S6_GMAC_FIFOCONF_RSV_RUNT | | ||
| 612 | 1 << S6_GMAC_FIFOCONF_RSV_CRCERR | | ||
| 613 | 1 << S6_GMAC_FIFOCONF_RSV_DRIBBLE | | ||
| 614 | 1 << S6_GMAC_FIFOCONF_RSV_CTRLFRAME | | ||
| 615 | 1 << S6_GMAC_FIFOCONF_RSV_PAUSECTRL | | ||
| 616 | 1 << S6_GMAC_FIFOCONF_RSV_UNOPCODE | | ||
| 617 | 1 << S6_GMAC_FIFOCONF_RSV_TRUNCATED, | ||
| 618 | pd->reg + S6_GMAC_FIFOCONF4); | ||
| 619 | s6gmac_set_dstaddr(pd, 0, | ||
| 620 | 0xFFFFFFFF, 0x0000FFFF, 0xFFFFFFFF, 0x0000FFFF); | ||
| 621 | s6gmac_set_dstaddr(pd, 1, | ||
| 622 | dev->dev_addr[5] | | ||
| 623 | dev->dev_addr[4] << 8 | | ||
| 624 | dev->dev_addr[3] << 16 | | ||
| 625 | dev->dev_addr[2] << 24, | ||
| 626 | dev->dev_addr[1] | | ||
| 627 | dev->dev_addr[0] << 8, | ||
| 628 | 0xFFFFFFFF, 0x0000FFFF); | ||
| 629 | s6gmac_set_dstaddr(pd, 2, | ||
| 630 | 0x00000000, 0x00000100, 0x00000000, 0x00000100); | ||
| 631 | s6gmac_set_dstaddr(pd, 3, | ||
| 632 | 0x00000000, 0x00000000, 0x00000000, 0x00000000); | ||
| 633 | writel(1 << S6_GMAC_HOST_PBLKCTRL_TXENA | | ||
| 634 | 1 << S6_GMAC_HOST_PBLKCTRL_RXENA | | ||
| 635 | S6_GMAC_HOST_PBLKCTRL_SIZ_128 << S6_GMAC_HOST_PBLKCTRL_TXBSIZ | | ||
| 636 | S6_GMAC_HOST_PBLKCTRL_SIZ_128 << S6_GMAC_HOST_PBLKCTRL_RXBSIZ | | ||
| 637 | 1 << S6_GMAC_HOST_PBLKCTRL_STATENA | | ||
| 638 | 1 << S6_GMAC_HOST_PBLKCTRL_STATCLEAR | | ||
| 639 | is_rgmii << S6_GMAC_HOST_PBLKCTRL_RGMII, | ||
| 640 | pd->reg + S6_GMAC_HOST_PBLKCTRL); | ||
| 641 | } | ||
| 642 | |||
| 643 | static void s6mii_enable(struct s6gmac *pd) | ||
| 644 | { | ||
| 645 | writel(readl(pd->reg + S6_GMAC_MACCONF1) & | ||
| 646 | ~(1 << S6_GMAC_MACCONF1_SOFTRES), | ||
| 647 | pd->reg + S6_GMAC_MACCONF1); | ||
| 648 | writel((readl(pd->reg + S6_GMAC_MACMIICONF) | ||
| 649 | & ~(S6_GMAC_MACMIICONF_CSEL_MASK << S6_GMAC_MACMIICONF_CSEL)) | ||
| 650 | | (S6_GMAC_MACMIICONF_CSEL_DIV168 << S6_GMAC_MACMIICONF_CSEL), | ||
| 651 | pd->reg + S6_GMAC_MACMIICONF); | ||
| 652 | } | ||
| 653 | |||
| 654 | static int s6mii_busy(struct s6gmac *pd, int tmo) | ||
| 655 | { | ||
| 656 | while (readl(pd->reg + S6_GMAC_MACMIIINDI)) { | ||
| 657 | if (--tmo == 0) | ||
| 658 | return -ETIME; | ||
| 659 | udelay(64); | ||
| 660 | } | ||
| 661 | return 0; | ||
| 662 | } | ||
| 663 | |||
| 664 | static int s6mii_read(struct mii_bus *bus, int phy_addr, int regnum) | ||
| 665 | { | ||
| 666 | struct s6gmac *pd = bus->priv; | ||
| 667 | s6mii_enable(pd); | ||
| 668 | if (s6mii_busy(pd, 256)) | ||
| 669 | return -ETIME; | ||
| 670 | writel(phy_addr << S6_GMAC_MACMIIADDR_PHY | | ||
| 671 | regnum << S6_GMAC_MACMIIADDR_REG, | ||
| 672 | pd->reg + S6_GMAC_MACMIIADDR); | ||
| 673 | writel(1 << S6_GMAC_MACMIICMD_READ, pd->reg + S6_GMAC_MACMIICMD); | ||
| 674 | writel(0, pd->reg + S6_GMAC_MACMIICMD); | ||
| 675 | if (s6mii_busy(pd, 256)) | ||
| 676 | return -ETIME; | ||
| 677 | return (u16)readl(pd->reg + S6_GMAC_MACMIISTAT); | ||
| 678 | } | ||
| 679 | |||
| 680 | static int s6mii_write(struct mii_bus *bus, int phy_addr, int regnum, u16 value) | ||
| 681 | { | ||
| 682 | struct s6gmac *pd = bus->priv; | ||
| 683 | s6mii_enable(pd); | ||
| 684 | if (s6mii_busy(pd, 256)) | ||
| 685 | return -ETIME; | ||
| 686 | writel(phy_addr << S6_GMAC_MACMIIADDR_PHY | | ||
| 687 | regnum << S6_GMAC_MACMIIADDR_REG, | ||
| 688 | pd->reg + S6_GMAC_MACMIIADDR); | ||
| 689 | writel(value, pd->reg + S6_GMAC_MACMIICTRL); | ||
| 690 | if (s6mii_busy(pd, 256)) | ||
| 691 | return -ETIME; | ||
| 692 | return 0; | ||
| 693 | } | ||
| 694 | |||
| 695 | static int s6mii_reset(struct mii_bus *bus) | ||
| 696 | { | ||
| 697 | struct s6gmac *pd = bus->priv; | ||
| 698 | s6mii_enable(pd); | ||
| 699 | if (s6mii_busy(pd, PHY_INIT_TIMEOUT)) | ||
| 700 | return -ETIME; | ||
| 701 | return 0; | ||
| 702 | } | ||
| 703 | |||
| 704 | static void s6gmac_set_rgmii_txclock(struct s6gmac *pd) | ||
| 705 | { | ||
| 706 | u32 pllsel = readl(S6_REG_GREG1 + S6_GREG1_PLLSEL); | ||
| 707 | pllsel &= ~(S6_GREG1_PLLSEL_GMAC_MASK << S6_GREG1_PLLSEL_GMAC); | ||
| 708 | switch (pd->link.mbit) { | ||
| 709 | case 10: | ||
| 710 | pllsel |= S6_GREG1_PLLSEL_GMAC_2500KHZ << S6_GREG1_PLLSEL_GMAC; | ||
| 711 | break; | ||
| 712 | case 100: | ||
| 713 | pllsel |= S6_GREG1_PLLSEL_GMAC_25MHZ << S6_GREG1_PLLSEL_GMAC; | ||
| 714 | break; | ||
| 715 | case 1000: | ||
| 716 | pllsel |= S6_GREG1_PLLSEL_GMAC_125MHZ << S6_GREG1_PLLSEL_GMAC; | ||
| 717 | break; | ||
| 718 | default: | ||
| 719 | return; | ||
| 720 | } | ||
| 721 | writel(pllsel, S6_REG_GREG1 + S6_GREG1_PLLSEL); | ||
| 722 | } | ||
| 723 | |||
| 724 | static inline void s6gmac_linkisup(struct net_device *dev, int isup) | ||
| 725 | { | ||
| 726 | struct s6gmac *pd = netdev_priv(dev); | ||
| 727 | struct phy_device *phydev = pd->phydev; | ||
| 728 | |||
| 729 | pd->link.full = phydev->duplex; | ||
| 730 | pd->link.giga = (phydev->speed == 1000); | ||
| 731 | if (pd->link.mbit != phydev->speed) { | ||
| 732 | pd->link.mbit = phydev->speed; | ||
| 733 | s6gmac_set_rgmii_txclock(pd); | ||
| 734 | } | ||
| 735 | pd->link.isup = isup; | ||
| 736 | if (isup) | ||
| 737 | netif_carrier_on(dev); | ||
| 738 | phy_print_status(phydev); | ||
| 739 | } | ||
| 740 | |||
| 741 | static void s6gmac_adjust_link(struct net_device *dev) | ||
| 742 | { | ||
| 743 | struct s6gmac *pd = netdev_priv(dev); | ||
| 744 | struct phy_device *phydev = pd->phydev; | ||
| 745 | if (pd->link.isup && | ||
| 746 | (!phydev->link || | ||
| 747 | (pd->link.mbit != phydev->speed) || | ||
| 748 | (pd->link.full != phydev->duplex))) { | ||
| 749 | pd->link.isup = 0; | ||
| 750 | netif_tx_disable(dev); | ||
| 751 | if (!phydev->link) { | ||
| 752 | netif_carrier_off(dev); | ||
| 753 | phy_print_status(phydev); | ||
| 754 | } | ||
| 755 | } | ||
| 756 | if (!pd->link.isup && phydev->link) { | ||
| 757 | if (pd->link.full != phydev->duplex) { | ||
| 758 | u32 maccfg = readl(pd->reg + S6_GMAC_MACCONF2); | ||
| 759 | if (phydev->duplex) | ||
| 760 | maccfg |= 1 << S6_GMAC_MACCONF2_FULL; | ||
| 761 | else | ||
| 762 | maccfg &= ~(1 << S6_GMAC_MACCONF2_FULL); | ||
| 763 | writel(maccfg, pd->reg + S6_GMAC_MACCONF2); | ||
| 764 | } | ||
| 765 | |||
| 766 | if (pd->link.giga != (phydev->speed == 1000)) { | ||
| 767 | u32 fifocfg = readl(pd->reg + S6_GMAC_FIFOCONF5); | ||
| 768 | u32 maccfg = readl(pd->reg + S6_GMAC_MACCONF2); | ||
| 769 | maccfg &= ~(S6_GMAC_MACCONF2_IFMODE_MASK | ||
| 770 | << S6_GMAC_MACCONF2_IFMODE); | ||
| 771 | if (phydev->speed == 1000) { | ||
| 772 | fifocfg |= 1 << S6_GMAC_FIFOCONF5_CFGBYTM; | ||
| 773 | maccfg |= S6_GMAC_MACCONF2_IFMODE_BYTE | ||
| 774 | << S6_GMAC_MACCONF2_IFMODE; | ||
| 775 | } else { | ||
| 776 | fifocfg &= ~(1 << S6_GMAC_FIFOCONF5_CFGBYTM); | ||
| 777 | maccfg |= S6_GMAC_MACCONF2_IFMODE_NIBBLE | ||
| 778 | << S6_GMAC_MACCONF2_IFMODE; | ||
| 779 | } | ||
| 780 | writel(fifocfg, pd->reg + S6_GMAC_FIFOCONF5); | ||
| 781 | writel(maccfg, pd->reg + S6_GMAC_MACCONF2); | ||
| 782 | } | ||
| 783 | |||
| 784 | if (!s6dmac_fifo_full(pd->tx_dma, pd->tx_chan)) | ||
| 785 | netif_wake_queue(dev); | ||
| 786 | s6gmac_linkisup(dev, 1); | ||
| 787 | } | ||
| 788 | } | ||
| 789 | |||
| 790 | static inline int s6gmac_phy_start(struct net_device *dev) | ||
| 791 | { | ||
| 792 | struct s6gmac *pd = netdev_priv(dev); | ||
| 793 | int i = 0; | ||
| 794 | struct phy_device *p = NULL; | ||
| 795 | while ((i < PHY_MAX_ADDR) && (!(p = pd->mii.bus->phy_map[i]))) | ||
| 796 | i++; | ||
| 797 | p = phy_connect(dev, dev_name(&p->dev), &s6gmac_adjust_link, | ||
| 798 | PHY_INTERFACE_MODE_RGMII); | ||
| 799 | if (IS_ERR(p)) { | ||
| 800 | printk(KERN_ERR "%s: Could not attach to PHY\n", dev->name); | ||
| 801 | return PTR_ERR(p); | ||
| 802 | } | ||
| 803 | p->supported &= PHY_GBIT_FEATURES; | ||
| 804 | p->advertising = p->supported; | ||
| 805 | pd->phydev = p; | ||
| 806 | return 0; | ||
| 807 | } | ||
| 808 | |||
| 809 | static inline void s6gmac_init_stats(struct net_device *dev) | ||
| 810 | { | ||
| 811 | struct s6gmac *pd = netdev_priv(dev); | ||
| 812 | u32 mask; | ||
| 813 | mask = 1 << S6_GMAC_STATCARRY1_RDRP | | ||
| 814 | 1 << S6_GMAC_STATCARRY1_RJBR | | ||
| 815 | 1 << S6_GMAC_STATCARRY1_RFRG | | ||
| 816 | 1 << S6_GMAC_STATCARRY1_ROVR | | ||
| 817 | 1 << S6_GMAC_STATCARRY1_RUND | | ||
| 818 | 1 << S6_GMAC_STATCARRY1_RCDE | | ||
| 819 | 1 << S6_GMAC_STATCARRY1_RFLR | | ||
| 820 | 1 << S6_GMAC_STATCARRY1_RALN | | ||
| 821 | 1 << S6_GMAC_STATCARRY1_RMCA | | ||
| 822 | 1 << S6_GMAC_STATCARRY1_RFCS | | ||
| 823 | 1 << S6_GMAC_STATCARRY1_RPKT | | ||
| 824 | 1 << S6_GMAC_STATCARRY1_RBYT; | ||
| 825 | writel(mask, pd->reg + S6_GMAC_STATCARRY(0)); | ||
| 826 | writel(~mask, pd->reg + S6_GMAC_STATCARRYMSK(0)); | ||
| 827 | mask = 1 << S6_GMAC_STATCARRY2_TDRP | | ||
| 828 | 1 << S6_GMAC_STATCARRY2_TNCL | | ||
| 829 | 1 << S6_GMAC_STATCARRY2_TXCL | | ||
| 830 | 1 << S6_GMAC_STATCARRY2_TEDF | | ||
| 831 | 1 << S6_GMAC_STATCARRY2_TPKT | | ||
| 832 | 1 << S6_GMAC_STATCARRY2_TBYT | | ||
| 833 | 1 << S6_GMAC_STATCARRY2_TFRG | | ||
| 834 | 1 << S6_GMAC_STATCARRY2_TUND | | ||
| 835 | 1 << S6_GMAC_STATCARRY2_TOVR | | ||
| 836 | 1 << S6_GMAC_STATCARRY2_TFCS | | ||
| 837 | 1 << S6_GMAC_STATCARRY2_TJBR; | ||
| 838 | writel(mask, pd->reg + S6_GMAC_STATCARRY(1)); | ||
| 839 | writel(~mask, pd->reg + S6_GMAC_STATCARRYMSK(1)); | ||
| 840 | } | ||
| 841 | |||
| 842 | static inline void s6gmac_init_dmac(struct net_device *dev) | ||
| 843 | { | ||
| 844 | struct s6gmac *pd = netdev_priv(dev); | ||
| 845 | s6dmac_disable_chan(pd->tx_dma, pd->tx_chan); | ||
| 846 | s6dmac_disable_chan(pd->rx_dma, pd->rx_chan); | ||
| 847 | s6dmac_disable_error_irqs(pd->tx_dma, 1 << S6_HIFDMA_GMACTX); | ||
| 848 | s6dmac_disable_error_irqs(pd->rx_dma, 1 << S6_HIFDMA_GMACRX); | ||
| 849 | } | ||
| 850 | |||
| 851 | static int s6gmac_tx(struct sk_buff *skb, struct net_device *dev) | ||
| 852 | { | ||
| 853 | struct s6gmac *pd = netdev_priv(dev); | ||
| 854 | unsigned long flags; | ||
| 855 | |||
| 856 | spin_lock_irqsave(&pd->lock, flags); | ||
| 857 | writel(skb->len << S6_GMAC_BURST_PREWR_LEN | | ||
| 858 | 0 << S6_GMAC_BURST_PREWR_CFE | | ||
| 859 | 1 << S6_GMAC_BURST_PREWR_PPE | | ||
| 860 | 1 << S6_GMAC_BURST_PREWR_FCS | | ||
| 861 | ((skb->len < ETH_ZLEN) ? 1 : 0) << S6_GMAC_BURST_PREWR_PAD, | ||
| 862 | pd->reg + S6_GMAC_BURST_PREWR); | ||
| 863 | s6dmac_put_fifo_cache(pd->tx_dma, pd->tx_chan, | ||
| 864 | (u32)skb->data, pd->io, skb->len); | ||
| 865 | if (s6dmac_fifo_full(pd->tx_dma, pd->tx_chan)) | ||
| 866 | netif_stop_queue(dev); | ||
| 867 | if (((u8)(pd->tx_skb_i - pd->tx_skb_o)) >= S6_NUM_TX_SKB) { | ||
| 868 | printk(KERN_ERR "GMAC BUG: skb tx ring overflow [%x, %x]\n", | ||
| 869 | pd->tx_skb_o, pd->tx_skb_i); | ||
| 870 | BUG(); | ||
| 871 | } | ||
| 872 | pd->tx_skb[(pd->tx_skb_i++) % S6_NUM_TX_SKB] = skb; | ||
| 873 | spin_unlock_irqrestore(&pd->lock, flags); | ||
| 874 | return 0; | ||
| 875 | } | ||
| 876 | |||
| 877 | static void s6gmac_tx_timeout(struct net_device *dev) | ||
| 878 | { | ||
| 879 | struct s6gmac *pd = netdev_priv(dev); | ||
| 880 | unsigned long flags; | ||
| 881 | spin_lock_irqsave(&pd->lock, flags); | ||
| 882 | s6gmac_tx_interrupt(dev); | ||
| 883 | spin_unlock_irqrestore(&pd->lock, flags); | ||
| 884 | } | ||
| 885 | |||
| 886 | static int s6gmac_open(struct net_device *dev) | ||
| 887 | { | ||
| 888 | struct s6gmac *pd = netdev_priv(dev); | ||
| 889 | unsigned long flags; | ||
| 890 | phy_read_status(pd->phydev); | ||
| 891 | spin_lock_irqsave(&pd->lock, flags); | ||
| 892 | pd->link.mbit = 0; | ||
| 893 | s6gmac_linkisup(dev, pd->phydev->link); | ||
| 894 | s6gmac_init_device(dev); | ||
| 895 | s6gmac_init_stats(dev); | ||
| 896 | s6gmac_init_dmac(dev); | ||
| 897 | s6gmac_rx_fillfifo(dev); | ||
| 898 | s6dmac_enable_chan(pd->rx_dma, pd->rx_chan, | ||
| 899 | 2, 1, 0, 1, 0, 0, 0, 7, -1, 2, 0, 1); | ||
| 900 | s6dmac_enable_chan(pd->tx_dma, pd->tx_chan, | ||
| 901 | 2, 0, 1, 0, 0, 0, 0, 7, -1, 2, 0, 1); | ||
| 902 | writel(0 << S6_GMAC_HOST_INT_TXBURSTOVER | | ||
| 903 | 0 << S6_GMAC_HOST_INT_TXPREWOVER | | ||
| 904 | 0 << S6_GMAC_HOST_INT_RXBURSTUNDER | | ||
| 905 | 0 << S6_GMAC_HOST_INT_RXPOSTRFULL | | ||
| 906 | 0 << S6_GMAC_HOST_INT_RXPOSTRUNDER, | ||
| 907 | pd->reg + S6_GMAC_HOST_INTMASK); | ||
| 908 | spin_unlock_irqrestore(&pd->lock, flags); | ||
| 909 | phy_start(pd->phydev); | ||
| 910 | netif_start_queue(dev); | ||
| 911 | return 0; | ||
| 912 | } | ||
| 913 | |||
| 914 | static int s6gmac_stop(struct net_device *dev) | ||
| 915 | { | ||
| 916 | struct s6gmac *pd = netdev_priv(dev); | ||
| 917 | unsigned long flags; | ||
| 918 | netif_stop_queue(dev); | ||
| 919 | phy_stop(pd->phydev); | ||
| 920 | spin_lock_irqsave(&pd->lock, flags); | ||
| 921 | s6gmac_init_dmac(dev); | ||
| 922 | s6gmac_stop_device(dev); | ||
| 923 | while (pd->tx_skb_i != pd->tx_skb_o) | ||
| 924 | dev_kfree_skb(pd->tx_skb[(pd->tx_skb_o++) % S6_NUM_TX_SKB]); | ||
| 925 | while (pd->rx_skb_i != pd->rx_skb_o) | ||
| 926 | dev_kfree_skb(pd->rx_skb[(pd->rx_skb_o++) % S6_NUM_RX_SKB]); | ||
| 927 | spin_unlock_irqrestore(&pd->lock, flags); | ||
| 928 | return 0; | ||
| 929 | } | ||
| 930 | |||
| 931 | static struct net_device_stats *s6gmac_stats(struct net_device *dev) | ||
| 932 | { | ||
| 933 | struct s6gmac *pd = netdev_priv(dev); | ||
| 934 | struct net_device_stats *st = (struct net_device_stats *)&pd->stats; | ||
| 935 | int i; | ||
| 936 | do { | ||
| 937 | unsigned long flags; | ||
| 938 | spin_lock_irqsave(&pd->lock, flags); | ||
| 939 | for (i = 0; i < ARRAY_SIZE(pd->stats); i++) | ||
| 940 | pd->stats[i] = | ||
| 941 | pd->carry[i] << (S6_GMAC_STAT_SIZE_MIN - 1); | ||
| 942 | s6gmac_stats_collect(pd, &statinf[0][0]); | ||
| 943 | s6gmac_stats_collect(pd, &statinf[1][0]); | ||
| 944 | i = s6gmac_stats_pending(pd, 0) | | ||
| 945 | s6gmac_stats_pending(pd, 1); | ||
| 946 | spin_unlock_irqrestore(&pd->lock, flags); | ||
| 947 | } while (i); | ||
| 948 | st->rx_errors = st->rx_crc_errors + | ||
| 949 | st->rx_frame_errors + | ||
| 950 | st->rx_length_errors + | ||
| 951 | st->rx_missed_errors; | ||
| 952 | st->tx_errors += st->tx_aborted_errors; | ||
| 953 | return st; | ||
| 954 | } | ||
| 955 | |||
| 956 | static int s6gmac_probe(struct platform_device *pdev) | ||
| 957 | { | ||
| 958 | struct net_device *dev; | ||
| 959 | struct s6gmac *pd; | ||
| 960 | int res; | ||
| 961 | unsigned long i; | ||
| 962 | struct mii_bus *mb; | ||
| 963 | |||
| 964 | dev = alloc_etherdev(sizeof(*pd)); | ||
| 965 | if (!dev) | ||
| 966 | return -ENOMEM; | ||
| 967 | |||
| 968 | dev->open = s6gmac_open; | ||
| 969 | dev->stop = s6gmac_stop; | ||
| 970 | dev->hard_start_xmit = s6gmac_tx; | ||
| 971 | dev->tx_timeout = s6gmac_tx_timeout; | ||
| 972 | dev->watchdog_timeo = HZ; | ||
| 973 | dev->get_stats = s6gmac_stats; | ||
| 974 | dev->irq = platform_get_irq(pdev, 0); | ||
| 975 | pd = netdev_priv(dev); | ||
| 976 | memset(pd, 0, sizeof(*pd)); | ||
| 977 | spin_lock_init(&pd->lock); | ||
| 978 | pd->reg = platform_get_resource(pdev, IORESOURCE_MEM, 0)->start; | ||
| 979 | i = platform_get_resource(pdev, IORESOURCE_DMA, 0)->start; | ||
| 980 | pd->tx_dma = DMA_MASK_DMAC(i); | ||
| 981 | pd->tx_chan = DMA_INDEX_CHNL(i); | ||
| 982 | i = platform_get_resource(pdev, IORESOURCE_DMA, 1)->start; | ||
| 983 | pd->rx_dma = DMA_MASK_DMAC(i); | ||
| 984 | pd->rx_chan = DMA_INDEX_CHNL(i); | ||
| 985 | pd->io = platform_get_resource(pdev, IORESOURCE_IO, 0)->start; | ||
| 986 | res = request_irq(dev->irq, s6gmac_interrupt, 0, dev->name, dev); | ||
| 987 | if (res) { | ||
| 988 | printk(KERN_ERR DRV_PRMT "irq request failed: %d\n", dev->irq); | ||
| 989 | goto errirq; | ||
| 990 | } | ||
| 991 | res = register_netdev(dev); | ||
| 992 | if (res) { | ||
| 993 | printk(KERN_ERR DRV_PRMT "error registering device %s\n", | ||
| 994 | dev->name); | ||
| 995 | goto errdev; | ||
| 996 | } | ||
| 997 | mb = mdiobus_alloc(); | ||
| 998 | if (!mb) { | ||
| 999 | printk(KERN_ERR DRV_PRMT "error allocating mii bus\n"); | ||
| 1000 | res = -ENOMEM; | ||
| 1001 | goto errmii; | ||
| 1002 | } | ||
| 1003 | mb->name = "s6gmac_mii"; | ||
| 1004 | mb->read = s6mii_read; | ||
| 1005 | mb->write = s6mii_write; | ||
| 1006 | mb->reset = s6mii_reset; | ||
| 1007 | mb->priv = pd; | ||
| 1008 | snprintf(mb->id, MII_BUS_ID_SIZE, "%s-%x", pdev->name, pdev->id); | ||
| 1009 | mb->phy_mask = ~(1 << 0); | ||
| 1010 | mb->irq = &pd->mii.irq[0]; | ||
| 1011 | for (i = 0; i < PHY_MAX_ADDR; i++) { | ||
| 1012 | int n = platform_get_irq(pdev, i + 1); | ||
| 1013 | if (n < 0) | ||
| 1014 | n = PHY_POLL; | ||
| 1015 | pd->mii.irq[i] = n; | ||
| 1016 | } | ||
| 1017 | mdiobus_register(mb); | ||
| 1018 | pd->mii.bus = mb; | ||
| 1019 | res = s6gmac_phy_start(dev); | ||
| 1020 | if (res) | ||
| 1021 | return res; | ||
| 1022 | platform_set_drvdata(pdev, dev); | ||
| 1023 | return 0; | ||
| 1024 | errmii: | ||
| 1025 | unregister_netdev(dev); | ||
| 1026 | errdev: | ||
| 1027 | free_irq(dev->irq, dev); | ||
| 1028 | errirq: | ||
| 1029 | free_netdev(dev); | ||
| 1030 | return res; | ||
| 1031 | } | ||
| 1032 | |||
| 1033 | static int s6gmac_remove(struct platform_device *pdev) | ||
| 1034 | { | ||
| 1035 | struct net_device *dev = platform_get_drvdata(pdev); | ||
| 1036 | if (dev) { | ||
| 1037 | struct s6gmac *pd = netdev_priv(dev); | ||
| 1038 | mdiobus_unregister(pd->mii.bus); | ||
| 1039 | unregister_netdev(dev); | ||
| 1040 | free_irq(dev->irq, dev); | ||
| 1041 | free_netdev(dev); | ||
| 1042 | } | ||
| 1043 | return 0; | ||
| 1044 | } | ||
| 1045 | |||
| 1046 | static struct platform_driver s6gmac_driver = { | ||
| 1047 | .probe = s6gmac_probe, | ||
| 1048 | .remove = s6gmac_remove, | ||
| 1049 | .driver = { | ||
| 1050 | .name = "s6gmac", | ||
| 1051 | }, | ||
| 1052 | }; | ||
| 1053 | |||
| 1054 | module_platform_driver(s6gmac_driver); | ||
| 1055 | |||
| 1056 | MODULE_LICENSE("GPL"); | ||
| 1057 | MODULE_DESCRIPTION("S6105 on chip Ethernet driver"); | ||
| 1058 | MODULE_AUTHOR("Oskar Schirmer <oskar@scara.com>"); | ||
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c index 118a427d1942..8c6b7c1651e5 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | |||
| @@ -1671,7 +1671,7 @@ static void stmmac_init_tx_coalesce(struct stmmac_priv *priv) | |||
| 1671 | * 0 on success and an appropriate (-)ve integer as defined in errno.h | 1671 | * 0 on success and an appropriate (-)ve integer as defined in errno.h |
| 1672 | * file on failure. | 1672 | * file on failure. |
| 1673 | */ | 1673 | */ |
| 1674 | static int stmmac_hw_setup(struct net_device *dev) | 1674 | static int stmmac_hw_setup(struct net_device *dev, bool init_ptp) |
| 1675 | { | 1675 | { |
| 1676 | struct stmmac_priv *priv = netdev_priv(dev); | 1676 | struct stmmac_priv *priv = netdev_priv(dev); |
| 1677 | int ret; | 1677 | int ret; |
| @@ -1708,9 +1708,11 @@ static int stmmac_hw_setup(struct net_device *dev) | |||
| 1708 | 1708 | ||
| 1709 | stmmac_mmc_setup(priv); | 1709 | stmmac_mmc_setup(priv); |
| 1710 | 1710 | ||
| 1711 | ret = stmmac_init_ptp(priv); | 1711 | if (init_ptp) { |
| 1712 | if (ret && ret != -EOPNOTSUPP) | 1712 | ret = stmmac_init_ptp(priv); |
| 1713 | pr_warn("%s: failed PTP initialisation\n", __func__); | 1713 | if (ret && ret != -EOPNOTSUPP) |
| 1714 | pr_warn("%s: failed PTP initialisation\n", __func__); | ||
| 1715 | } | ||
| 1714 | 1716 | ||
| 1715 | #ifdef CONFIG_DEBUG_FS | 1717 | #ifdef CONFIG_DEBUG_FS |
| 1716 | ret = stmmac_init_fs(dev); | 1718 | ret = stmmac_init_fs(dev); |
| @@ -1787,7 +1789,7 @@ static int stmmac_open(struct net_device *dev) | |||
| 1787 | goto init_error; | 1789 | goto init_error; |
| 1788 | } | 1790 | } |
| 1789 | 1791 | ||
| 1790 | ret = stmmac_hw_setup(dev); | 1792 | ret = stmmac_hw_setup(dev, true); |
| 1791 | if (ret < 0) { | 1793 | if (ret < 0) { |
| 1792 | pr_err("%s: Hw setup failed\n", __func__); | 1794 | pr_err("%s: Hw setup failed\n", __func__); |
| 1793 | goto init_error; | 1795 | goto init_error; |
| @@ -3036,7 +3038,7 @@ int stmmac_resume(struct net_device *ndev) | |||
| 3036 | netif_device_attach(ndev); | 3038 | netif_device_attach(ndev); |
| 3037 | 3039 | ||
| 3038 | init_dma_desc_rings(ndev, GFP_ATOMIC); | 3040 | init_dma_desc_rings(ndev, GFP_ATOMIC); |
| 3039 | stmmac_hw_setup(ndev); | 3041 | stmmac_hw_setup(ndev, false); |
| 3040 | stmmac_init_tx_coalesce(priv); | 3042 | stmmac_init_tx_coalesce(priv); |
| 3041 | 3043 | ||
| 3042 | napi_enable(&priv->napi); | 3044 | napi_enable(&priv->napi); |
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c index 4032b170fe24..3039de2465ba 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c | |||
| @@ -430,7 +430,6 @@ static struct platform_driver stmmac_pltfr_driver = { | |||
| 430 | .remove = stmmac_pltfr_remove, | 430 | .remove = stmmac_pltfr_remove, |
| 431 | .driver = { | 431 | .driver = { |
| 432 | .name = STMMAC_RESOURCE_NAME, | 432 | .name = STMMAC_RESOURCE_NAME, |
| 433 | .owner = THIS_MODULE, | ||
| 434 | .pm = &stmmac_pltfr_pm_ops, | 433 | .pm = &stmmac_pltfr_pm_ops, |
| 435 | .of_match_table = of_match_ptr(stmmac_dt_ids), | 434 | .of_match_table = of_match_ptr(stmmac_dt_ids), |
| 436 | }, | 435 | }, |
diff --git a/drivers/net/ethernet/sun/sunvnet.c b/drivers/net/ethernet/sun/sunvnet.c index 45c408ef67d0..d2835bf7b4fb 100644 --- a/drivers/net/ethernet/sun/sunvnet.c +++ b/drivers/net/ethernet/sun/sunvnet.c | |||
| @@ -1201,6 +1201,7 @@ static int vnet_handle_offloads(struct vnet_port *port, struct sk_buff *skb) | |||
| 1201 | segs = skb_gso_segment(skb, dev->features & ~NETIF_F_TSO); | 1201 | segs = skb_gso_segment(skb, dev->features & ~NETIF_F_TSO); |
| 1202 | if (IS_ERR(segs)) { | 1202 | if (IS_ERR(segs)) { |
| 1203 | dev->stats.tx_dropped++; | 1203 | dev->stats.tx_dropped++; |
| 1204 | dev_kfree_skb_any(skb); | ||
| 1204 | return NETDEV_TX_OK; | 1205 | return NETDEV_TX_OK; |
| 1205 | } | 1206 | } |
| 1206 | 1207 | ||
diff --git a/drivers/net/ethernet/xilinx/xilinx_axienet.h b/drivers/net/ethernet/xilinx/xilinx_axienet.h index 44b8d2bad8c3..4c9b4fa1d3c1 100644 --- a/drivers/net/ethernet/xilinx/xilinx_axienet.h +++ b/drivers/net/ethernet/xilinx/xilinx_axienet.h | |||
| @@ -388,7 +388,6 @@ struct axidma_bd { | |||
| 388 | * @dma_err_tasklet: Tasklet structure to process Axi DMA errors | 388 | * @dma_err_tasklet: Tasklet structure to process Axi DMA errors |
| 389 | * @tx_irq: Axidma TX IRQ number | 389 | * @tx_irq: Axidma TX IRQ number |
| 390 | * @rx_irq: Axidma RX IRQ number | 390 | * @rx_irq: Axidma RX IRQ number |
| 391 | * @temac_type: axienet type to identify between soft and hard temac | ||
| 392 | * @phy_type: Phy type to identify between MII/GMII/RGMII/SGMII/1000 Base-X | 391 | * @phy_type: Phy type to identify between MII/GMII/RGMII/SGMII/1000 Base-X |
| 393 | * @options: AxiEthernet option word | 392 | * @options: AxiEthernet option word |
| 394 | * @last_link: Phy link state in which the PHY was negotiated earlier | 393 | * @last_link: Phy link state in which the PHY was negotiated earlier |
| @@ -431,7 +430,6 @@ struct axienet_local { | |||
| 431 | 430 | ||
| 432 | int tx_irq; | 431 | int tx_irq; |
| 433 | int rx_irq; | 432 | int rx_irq; |
| 434 | u32 temac_type; | ||
| 435 | u32 phy_type; | 433 | u32 phy_type; |
| 436 | 434 | ||
| 437 | u32 options; /* Current options word */ | 435 | u32 options; /* Current options word */ |
diff --git a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c index 4ea2d4e6f1d1..c18a0c637c44 100644 --- a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c +++ b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c | |||
| @@ -1555,10 +1555,6 @@ static int axienet_of_probe(struct platform_device *op) | |||
| 1555 | if ((be32_to_cpup(p)) >= 0x4000) | 1555 | if ((be32_to_cpup(p)) >= 0x4000) |
| 1556 | lp->jumbo_support = 1; | 1556 | lp->jumbo_support = 1; |
| 1557 | } | 1557 | } |
| 1558 | p = (__be32 *) of_get_property(op->dev.of_node, "xlnx,temac-type", | ||
| 1559 | NULL); | ||
| 1560 | if (p) | ||
| 1561 | lp->temac_type = be32_to_cpup(p); | ||
| 1562 | p = (__be32 *) of_get_property(op->dev.of_node, "xlnx,phy-type", NULL); | 1558 | p = (__be32 *) of_get_property(op->dev.of_node, "xlnx,phy-type", NULL); |
| 1563 | if (p) | 1559 | if (p) |
| 1564 | lp->phy_type = be32_to_cpup(p); | 1560 | lp->phy_type = be32_to_cpup(p); |
diff --git a/drivers/net/hyperv/hyperv_net.h b/drivers/net/hyperv/hyperv_net.h index 2f48f790c9b4..384ca4f4de4a 100644 --- a/drivers/net/hyperv/hyperv_net.h +++ b/drivers/net/hyperv/hyperv_net.h | |||
| @@ -590,6 +590,7 @@ struct nvsp_message { | |||
| 590 | 590 | ||
| 591 | 591 | ||
| 592 | #define NETVSC_RECEIVE_BUFFER_ID 0xcafe | 592 | #define NETVSC_RECEIVE_BUFFER_ID 0xcafe |
| 593 | #define NETVSC_SEND_BUFFER_ID 0 | ||
| 593 | 594 | ||
| 594 | #define NETVSC_PACKET_SIZE 4096 | 595 | #define NETVSC_PACKET_SIZE 4096 |
| 595 | 596 | ||
diff --git a/drivers/net/hyperv/netvsc.c b/drivers/net/hyperv/netvsc.c index dd867e6cabd6..9f49c0129a78 100644 --- a/drivers/net/hyperv/netvsc.c +++ b/drivers/net/hyperv/netvsc.c | |||
| @@ -161,8 +161,8 @@ static int netvsc_destroy_buf(struct netvsc_device *net_device) | |||
| 161 | 161 | ||
| 162 | /* Deal with the send buffer we may have setup. | 162 | /* Deal with the send buffer we may have setup. |
| 163 | * If we got a send section size, it means we received a | 163 | * If we got a send section size, it means we received a |
| 164 | * SendsendBufferComplete msg (ie sent | 164 | * NVSP_MSG1_TYPE_SEND_SEND_BUF_COMPLETE msg (ie sent |
| 165 | * NvspMessage1TypeSendReceiveBuffer msg) therefore, we need | 165 | * NVSP_MSG1_TYPE_SEND_SEND_BUF msg) therefore, we need |
| 166 | * to send a revoke msg here | 166 | * to send a revoke msg here |
| 167 | */ | 167 | */ |
| 168 | if (net_device->send_section_size) { | 168 | if (net_device->send_section_size) { |
| @@ -172,7 +172,8 @@ static int netvsc_destroy_buf(struct netvsc_device *net_device) | |||
| 172 | 172 | ||
| 173 | revoke_packet->hdr.msg_type = | 173 | revoke_packet->hdr.msg_type = |
| 174 | NVSP_MSG1_TYPE_REVOKE_SEND_BUF; | 174 | NVSP_MSG1_TYPE_REVOKE_SEND_BUF; |
| 175 | revoke_packet->msg.v1_msg.revoke_recv_buf.id = 0; | 175 | revoke_packet->msg.v1_msg.revoke_send_buf.id = |
| 176 | NETVSC_SEND_BUFFER_ID; | ||
| 176 | 177 | ||
| 177 | ret = vmbus_sendpacket(net_device->dev->channel, | 178 | ret = vmbus_sendpacket(net_device->dev->channel, |
| 178 | revoke_packet, | 179 | revoke_packet, |
| @@ -204,7 +205,7 @@ static int netvsc_destroy_buf(struct netvsc_device *net_device) | |||
| 204 | net_device->send_buf_gpadl_handle = 0; | 205 | net_device->send_buf_gpadl_handle = 0; |
| 205 | } | 206 | } |
| 206 | if (net_device->send_buf) { | 207 | if (net_device->send_buf) { |
| 207 | /* Free up the receive buffer */ | 208 | /* Free up the send buffer */ |
| 208 | vfree(net_device->send_buf); | 209 | vfree(net_device->send_buf); |
| 209 | net_device->send_buf = NULL; | 210 | net_device->send_buf = NULL; |
| 210 | } | 211 | } |
| @@ -339,9 +340,9 @@ static int netvsc_init_buf(struct hv_device *device) | |||
| 339 | init_packet = &net_device->channel_init_pkt; | 340 | init_packet = &net_device->channel_init_pkt; |
| 340 | memset(init_packet, 0, sizeof(struct nvsp_message)); | 341 | memset(init_packet, 0, sizeof(struct nvsp_message)); |
| 341 | init_packet->hdr.msg_type = NVSP_MSG1_TYPE_SEND_SEND_BUF; | 342 | init_packet->hdr.msg_type = NVSP_MSG1_TYPE_SEND_SEND_BUF; |
| 342 | init_packet->msg.v1_msg.send_recv_buf.gpadl_handle = | 343 | init_packet->msg.v1_msg.send_send_buf.gpadl_handle = |
| 343 | net_device->send_buf_gpadl_handle; | 344 | net_device->send_buf_gpadl_handle; |
| 344 | init_packet->msg.v1_msg.send_recv_buf.id = 0; | 345 | init_packet->msg.v1_msg.send_send_buf.id = NETVSC_SEND_BUFFER_ID; |
| 345 | 346 | ||
| 346 | /* Send the gpadl notification request */ | 347 | /* Send the gpadl notification request */ |
| 347 | ret = vmbus_sendpacket(device->channel, init_packet, | 348 | ret = vmbus_sendpacket(device->channel, init_packet, |
| @@ -364,7 +365,7 @@ static int netvsc_init_buf(struct hv_device *device) | |||
| 364 | netdev_err(ndev, "Unable to complete send buffer " | 365 | netdev_err(ndev, "Unable to complete send buffer " |
| 365 | "initialization with NetVsp - status %d\n", | 366 | "initialization with NetVsp - status %d\n", |
| 366 | init_packet->msg.v1_msg. | 367 | init_packet->msg.v1_msg. |
| 367 | send_recv_buf_complete.status); | 368 | send_send_buf_complete.status); |
| 368 | ret = -EINVAL; | 369 | ret = -EINVAL; |
| 369 | goto cleanup; | 370 | goto cleanup; |
| 370 | } | 371 | } |
diff --git a/drivers/net/phy/micrel.c b/drivers/net/phy/micrel.c index c530de1e63f5..3ad8ca76196d 100644 --- a/drivers/net/phy/micrel.c +++ b/drivers/net/phy/micrel.c | |||
| @@ -88,6 +88,7 @@ struct kszphy_priv { | |||
| 88 | 88 | ||
| 89 | static const struct kszphy_type ksz8021_type = { | 89 | static const struct kszphy_type ksz8021_type = { |
| 90 | .led_mode_reg = MII_KSZPHY_CTRL_2, | 90 | .led_mode_reg = MII_KSZPHY_CTRL_2, |
| 91 | .has_broadcast_disable = true, | ||
| 91 | .has_rmii_ref_clk_sel = true, | 92 | .has_rmii_ref_clk_sel = true, |
| 92 | }; | 93 | }; |
| 93 | 94 | ||
| @@ -258,19 +259,6 @@ static int kszphy_config_init(struct phy_device *phydev) | |||
| 258 | return 0; | 259 | return 0; |
| 259 | } | 260 | } |
| 260 | 261 | ||
| 261 | static int ksz8021_config_init(struct phy_device *phydev) | ||
| 262 | { | ||
| 263 | int rc; | ||
| 264 | |||
| 265 | rc = kszphy_config_init(phydev); | ||
| 266 | if (rc) | ||
| 267 | return rc; | ||
| 268 | |||
| 269 | rc = kszphy_broadcast_disable(phydev); | ||
| 270 | |||
| 271 | return rc < 0 ? rc : 0; | ||
| 272 | } | ||
| 273 | |||
| 274 | static int ksz9021_load_values_from_of(struct phy_device *phydev, | 262 | static int ksz9021_load_values_from_of(struct phy_device *phydev, |
| 275 | struct device_node *of_node, u16 reg, | 263 | struct device_node *of_node, u16 reg, |
| 276 | char *field1, char *field2, | 264 | char *field1, char *field2, |
| @@ -584,7 +572,7 @@ static struct phy_driver ksphy_driver[] = { | |||
| 584 | .flags = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT, | 572 | .flags = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT, |
| 585 | .driver_data = &ksz8021_type, | 573 | .driver_data = &ksz8021_type, |
| 586 | .probe = kszphy_probe, | 574 | .probe = kszphy_probe, |
| 587 | .config_init = ksz8021_config_init, | 575 | .config_init = kszphy_config_init, |
| 588 | .config_aneg = genphy_config_aneg, | 576 | .config_aneg = genphy_config_aneg, |
| 589 | .read_status = genphy_read_status, | 577 | .read_status = genphy_read_status, |
| 590 | .ack_interrupt = kszphy_ack_interrupt, | 578 | .ack_interrupt = kszphy_ack_interrupt, |
| @@ -601,7 +589,7 @@ static struct phy_driver ksphy_driver[] = { | |||
| 601 | .flags = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT, | 589 | .flags = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT, |
| 602 | .driver_data = &ksz8021_type, | 590 | .driver_data = &ksz8021_type, |
| 603 | .probe = kszphy_probe, | 591 | .probe = kszphy_probe, |
| 604 | .config_init = ksz8021_config_init, | 592 | .config_init = kszphy_config_init, |
| 605 | .config_aneg = genphy_config_aneg, | 593 | .config_aneg = genphy_config_aneg, |
| 606 | .read_status = genphy_read_status, | 594 | .read_status = genphy_read_status, |
| 607 | .ack_interrupt = kszphy_ack_interrupt, | 595 | .ack_interrupt = kszphy_ack_interrupt, |
diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c index b8bd7191572d..5ca97713bfb3 100644 --- a/drivers/net/virtio_net.c +++ b/drivers/net/virtio_net.c | |||
| @@ -760,7 +760,6 @@ static int virtnet_poll(struct napi_struct *napi, int budget) | |||
| 760 | container_of(napi, struct receive_queue, napi); | 760 | container_of(napi, struct receive_queue, napi); |
| 761 | unsigned int r, received = 0; | 761 | unsigned int r, received = 0; |
| 762 | 762 | ||
| 763 | again: | ||
| 764 | received += virtnet_receive(rq, budget - received); | 763 | received += virtnet_receive(rq, budget - received); |
| 765 | 764 | ||
| 766 | /* Out of packets? */ | 765 | /* Out of packets? */ |
| @@ -771,7 +770,6 @@ again: | |||
| 771 | napi_schedule_prep(napi)) { | 770 | napi_schedule_prep(napi)) { |
| 772 | virtqueue_disable_cb(rq->vq); | 771 | virtqueue_disable_cb(rq->vq); |
| 773 | __napi_schedule(napi); | 772 | __napi_schedule(napi); |
| 774 | goto again; | ||
| 775 | } | 773 | } |
| 776 | } | 774 | } |
| 777 | 775 | ||
diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c index 49d9f2291998..7fbd89fbe107 100644 --- a/drivers/net/vxlan.c +++ b/drivers/net/vxlan.c | |||
| @@ -1579,8 +1579,10 @@ static int vxlan6_xmit_skb(struct vxlan_sock *vs, | |||
| 1579 | bool udp_sum = !udp_get_no_check6_tx(vs->sock->sk); | 1579 | bool udp_sum = !udp_get_no_check6_tx(vs->sock->sk); |
| 1580 | 1580 | ||
| 1581 | skb = udp_tunnel_handle_offloads(skb, udp_sum); | 1581 | skb = udp_tunnel_handle_offloads(skb, udp_sum); |
| 1582 | if (IS_ERR(skb)) | 1582 | if (IS_ERR(skb)) { |
| 1583 | return -EINVAL; | 1583 | err = -EINVAL; |
| 1584 | goto err; | ||
| 1585 | } | ||
| 1584 | 1586 | ||
| 1585 | skb_scrub_packet(skb, xnet); | 1587 | skb_scrub_packet(skb, xnet); |
| 1586 | 1588 | ||
| @@ -1590,12 +1592,16 @@ static int vxlan6_xmit_skb(struct vxlan_sock *vs, | |||
| 1590 | 1592 | ||
| 1591 | /* Need space for new headers (invalidates iph ptr) */ | 1593 | /* Need space for new headers (invalidates iph ptr) */ |
| 1592 | err = skb_cow_head(skb, min_headroom); | 1594 | err = skb_cow_head(skb, min_headroom); |
| 1593 | if (unlikely(err)) | 1595 | if (unlikely(err)) { |
| 1594 | return err; | 1596 | kfree_skb(skb); |
| 1597 | goto err; | ||
| 1598 | } | ||
| 1595 | 1599 | ||
| 1596 | skb = vlan_hwaccel_push_inside(skb); | 1600 | skb = vlan_hwaccel_push_inside(skb); |
| 1597 | if (WARN_ON(!skb)) | 1601 | if (WARN_ON(!skb)) { |
| 1598 | return -ENOMEM; | 1602 | err = -ENOMEM; |
| 1603 | goto err; | ||
| 1604 | } | ||
| 1599 | 1605 | ||
| 1600 | vxh = (struct vxlanhdr *) __skb_push(skb, sizeof(*vxh)); | 1606 | vxh = (struct vxlanhdr *) __skb_push(skb, sizeof(*vxh)); |
| 1601 | vxh->vx_flags = htonl(VXLAN_FLAGS); | 1607 | vxh->vx_flags = htonl(VXLAN_FLAGS); |
| @@ -1606,6 +1612,9 @@ static int vxlan6_xmit_skb(struct vxlan_sock *vs, | |||
| 1606 | udp_tunnel6_xmit_skb(vs->sock, dst, skb, dev, saddr, daddr, prio, | 1612 | udp_tunnel6_xmit_skb(vs->sock, dst, skb, dev, saddr, daddr, prio, |
| 1607 | ttl, src_port, dst_port); | 1613 | ttl, src_port, dst_port); |
| 1608 | return 0; | 1614 | return 0; |
| 1615 | err: | ||
| 1616 | dst_release(dst); | ||
| 1617 | return err; | ||
| 1609 | } | 1618 | } |
| 1610 | #endif | 1619 | #endif |
| 1611 | 1620 | ||
| @@ -1621,7 +1630,7 @@ int vxlan_xmit_skb(struct vxlan_sock *vs, | |||
| 1621 | 1630 | ||
| 1622 | skb = udp_tunnel_handle_offloads(skb, udp_sum); | 1631 | skb = udp_tunnel_handle_offloads(skb, udp_sum); |
| 1623 | if (IS_ERR(skb)) | 1632 | if (IS_ERR(skb)) |
| 1624 | return -EINVAL; | 1633 | return PTR_ERR(skb); |
| 1625 | 1634 | ||
| 1626 | min_headroom = LL_RESERVED_SPACE(rt->dst.dev) + rt->dst.header_len | 1635 | min_headroom = LL_RESERVED_SPACE(rt->dst.dev) + rt->dst.header_len |
| 1627 | + VXLAN_HLEN + sizeof(struct iphdr) | 1636 | + VXLAN_HLEN + sizeof(struct iphdr) |
| @@ -1629,8 +1638,10 @@ int vxlan_xmit_skb(struct vxlan_sock *vs, | |||
| 1629 | 1638 | ||
| 1630 | /* Need space for new headers (invalidates iph ptr) */ | 1639 | /* Need space for new headers (invalidates iph ptr) */ |
| 1631 | err = skb_cow_head(skb, min_headroom); | 1640 | err = skb_cow_head(skb, min_headroom); |
| 1632 | if (unlikely(err)) | 1641 | if (unlikely(err)) { |
| 1642 | kfree_skb(skb); | ||
| 1633 | return err; | 1643 | return err; |
| 1644 | } | ||
| 1634 | 1645 | ||
| 1635 | skb = vlan_hwaccel_push_inside(skb); | 1646 | skb = vlan_hwaccel_push_inside(skb); |
| 1636 | if (WARN_ON(!skb)) | 1647 | if (WARN_ON(!skb)) |
| @@ -1776,9 +1787,12 @@ static void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev, | |||
| 1776 | tos, ttl, df, src_port, dst_port, | 1787 | tos, ttl, df, src_port, dst_port, |
| 1777 | htonl(vni << 8), | 1788 | htonl(vni << 8), |
| 1778 | !net_eq(vxlan->net, dev_net(vxlan->dev))); | 1789 | !net_eq(vxlan->net, dev_net(vxlan->dev))); |
| 1779 | 1790 | if (err < 0) { | |
| 1780 | if (err < 0) | 1791 | /* skb is already freed. */ |
| 1792 | skb = NULL; | ||
| 1781 | goto rt_tx_error; | 1793 | goto rt_tx_error; |
| 1794 | } | ||
| 1795 | |||
| 1782 | iptunnel_xmit_stats(err, &dev->stats, dev->tstats); | 1796 | iptunnel_xmit_stats(err, &dev->stats, dev->tstats); |
| 1783 | #if IS_ENABLED(CONFIG_IPV6) | 1797 | #if IS_ENABLED(CONFIG_IPV6) |
| 1784 | } else { | 1798 | } else { |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c index 3c06e9365949..9880dae2a569 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c | |||
| @@ -1070,7 +1070,7 @@ static int brcmf_ops_sdio_probe(struct sdio_func *func, | |||
| 1070 | */ | 1070 | */ |
| 1071 | if ((sdio_get_host_pm_caps(sdiodev->func[1]) & MMC_PM_KEEP_POWER) && | 1071 | if ((sdio_get_host_pm_caps(sdiodev->func[1]) & MMC_PM_KEEP_POWER) && |
| 1072 | ((sdio_get_host_pm_caps(sdiodev->func[1]) & MMC_PM_WAKE_SDIO_IRQ) || | 1072 | ((sdio_get_host_pm_caps(sdiodev->func[1]) & MMC_PM_WAKE_SDIO_IRQ) || |
| 1073 | (sdiodev->pdata->oob_irq_supported))) | 1073 | (sdiodev->pdata && sdiodev->pdata->oob_irq_supported))) |
| 1074 | bus_if->wowl_supported = true; | 1074 | bus_if->wowl_supported = true; |
| 1075 | #endif | 1075 | #endif |
| 1076 | 1076 | ||
| @@ -1167,7 +1167,7 @@ static int brcmf_ops_sdio_resume(struct device *dev) | |||
| 1167 | struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv.sdio; | 1167 | struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv.sdio; |
| 1168 | 1168 | ||
| 1169 | brcmf_dbg(SDIO, "Enter\n"); | 1169 | brcmf_dbg(SDIO, "Enter\n"); |
| 1170 | if (sdiodev->pdata->oob_irq_supported) | 1170 | if (sdiodev->pdata && sdiodev->pdata->oob_irq_supported) |
| 1171 | disable_irq_wake(sdiodev->pdata->oob_irq_nr); | 1171 | disable_irq_wake(sdiodev->pdata->oob_irq_nr); |
| 1172 | brcmf_sdio_wd_timer(sdiodev->bus, BRCMF_WD_POLL_MS); | 1172 | brcmf_sdio_wd_timer(sdiodev->bus, BRCMF_WD_POLL_MS); |
| 1173 | atomic_set(&sdiodev->suspend, false); | 1173 | atomic_set(&sdiodev->suspend, false); |
diff --git a/drivers/net/wireless/ipw2x00/Kconfig b/drivers/net/wireless/ipw2x00/Kconfig index 91c0cb3c368e..21de4fe6cf2d 100644 --- a/drivers/net/wireless/ipw2x00/Kconfig +++ b/drivers/net/wireless/ipw2x00/Kconfig | |||
| @@ -65,7 +65,8 @@ config IPW2100_DEBUG | |||
| 65 | 65 | ||
| 66 | config IPW2200 | 66 | config IPW2200 |
| 67 | tristate "Intel PRO/Wireless 2200BG and 2915ABG Network Connection" | 67 | tristate "Intel PRO/Wireless 2200BG and 2915ABG Network Connection" |
| 68 | depends on PCI && CFG80211 && CFG80211_WEXT | 68 | depends on PCI && CFG80211 |
| 69 | select CFG80211_WEXT | ||
| 69 | select WIRELESS_EXT | 70 | select WIRELESS_EXT |
| 70 | select WEXT_SPY | 71 | select WEXT_SPY |
| 71 | select WEXT_PRIV | 72 | select WEXT_PRIV |
diff --git a/drivers/net/wireless/iwlwifi/iwl-drv.c b/drivers/net/wireless/iwlwifi/iwl-drv.c index 38de1513e4de..850b85a47806 100644 --- a/drivers/net/wireless/iwlwifi/iwl-drv.c +++ b/drivers/net/wireless/iwlwifi/iwl-drv.c | |||
| @@ -1323,10 +1323,10 @@ static void iwl_req_fw_callback(const struct firmware *ucode_raw, void *context) | |||
| 1323 | 1323 | ||
| 1324 | try_again: | 1324 | try_again: |
| 1325 | /* try next, if any */ | 1325 | /* try next, if any */ |
| 1326 | kfree(pieces); | ||
| 1327 | release_firmware(ucode_raw); | 1326 | release_firmware(ucode_raw); |
| 1328 | if (iwl_request_firmware(drv, false)) | 1327 | if (iwl_request_firmware(drv, false)) |
| 1329 | goto out_unbind; | 1328 | goto out_unbind; |
| 1329 | kfree(pieces); | ||
| 1330 | return; | 1330 | return; |
| 1331 | 1331 | ||
| 1332 | out_free_fw: | 1332 | out_free_fw: |
diff --git a/drivers/net/wireless/iwlwifi/iwl-fh.h b/drivers/net/wireless/iwlwifi/iwl-fh.h index 9564ae173d06..1f7f15eb86da 100644 --- a/drivers/net/wireless/iwlwifi/iwl-fh.h +++ b/drivers/net/wireless/iwlwifi/iwl-fh.h | |||
| @@ -310,6 +310,7 @@ static inline unsigned int FH_MEM_CBBC_QUEUE(unsigned int chnl) | |||
| 310 | #define FH_RSSR_CHNL0_RX_STATUS_CHNL_IDLE (0x01000000) | 310 | #define FH_RSSR_CHNL0_RX_STATUS_CHNL_IDLE (0x01000000) |
| 311 | 311 | ||
| 312 | #define FH_MEM_TFDIB_REG1_ADDR_BITSHIFT 28 | 312 | #define FH_MEM_TFDIB_REG1_ADDR_BITSHIFT 28 |
| 313 | #define FH_MEM_TB_MAX_LENGTH (0x00020000) | ||
| 313 | 314 | ||
| 314 | /* TFDB Area - TFDs buffer table */ | 315 | /* TFDB Area - TFDs buffer table */ |
| 315 | #define FH_MEM_TFDIB_DRAM_ADDR_LSB_MSK (0xFFFFFFFF) | 316 | #define FH_MEM_TFDIB_DRAM_ADDR_LSB_MSK (0xFFFFFFFF) |
diff --git a/drivers/net/wireless/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/iwlwifi/mvm/mac80211.c index 31a5b3f4266c..e880f9d4717b 100644 --- a/drivers/net/wireless/iwlwifi/mvm/mac80211.c +++ b/drivers/net/wireless/iwlwifi/mvm/mac80211.c | |||
| @@ -1004,8 +1004,13 @@ void __iwl_mvm_mac_stop(struct iwl_mvm *mvm) | |||
| 1004 | { | 1004 | { |
| 1005 | lockdep_assert_held(&mvm->mutex); | 1005 | lockdep_assert_held(&mvm->mutex); |
| 1006 | 1006 | ||
| 1007 | /* disallow low power states when the FW is down */ | 1007 | /* |
| 1008 | iwl_mvm_ref(mvm, IWL_MVM_REF_UCODE_DOWN); | 1008 | * Disallow low power states when the FW is down by taking |
| 1009 | * the UCODE_DOWN ref. in case of ongoing hw restart the | ||
| 1010 | * ref is already taken, so don't take it again. | ||
| 1011 | */ | ||
| 1012 | if (!test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status)) | ||
| 1013 | iwl_mvm_ref(mvm, IWL_MVM_REF_UCODE_DOWN); | ||
| 1009 | 1014 | ||
| 1010 | /* async_handlers_wk is now blocked */ | 1015 | /* async_handlers_wk is now blocked */ |
| 1011 | 1016 | ||
| @@ -1023,6 +1028,12 @@ void __iwl_mvm_mac_stop(struct iwl_mvm *mvm) | |||
| 1023 | /* the fw is stopped, the aux sta is dead: clean up driver state */ | 1028 | /* the fw is stopped, the aux sta is dead: clean up driver state */ |
| 1024 | iwl_mvm_del_aux_sta(mvm); | 1029 | iwl_mvm_del_aux_sta(mvm); |
| 1025 | 1030 | ||
| 1031 | /* | ||
| 1032 | * Clear IN_HW_RESTART flag when stopping the hw (as restart_complete() | ||
| 1033 | * won't be called in this case). | ||
| 1034 | */ | ||
| 1035 | clear_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status); | ||
| 1036 | |||
| 1026 | mvm->ucode_loaded = false; | 1037 | mvm->ucode_loaded = false; |
| 1027 | } | 1038 | } |
| 1028 | 1039 | ||
diff --git a/drivers/net/wireless/iwlwifi/pcie/drv.c b/drivers/net/wireless/iwlwifi/pcie/drv.c index 3ee8e3848876..2f0c4b170344 100644 --- a/drivers/net/wireless/iwlwifi/pcie/drv.c +++ b/drivers/net/wireless/iwlwifi/pcie/drv.c | |||
| @@ -367,7 +367,11 @@ static const struct pci_device_id iwl_hw_card_ids[] = { | |||
| 367 | 367 | ||
| 368 | /* 3165 Series */ | 368 | /* 3165 Series */ |
| 369 | {IWL_PCI_DEVICE(0x3165, 0x4010, iwl3165_2ac_cfg)}, | 369 | {IWL_PCI_DEVICE(0x3165, 0x4010, iwl3165_2ac_cfg)}, |
| 370 | {IWL_PCI_DEVICE(0x3165, 0x4012, iwl3165_2ac_cfg)}, | ||
| 371 | {IWL_PCI_DEVICE(0x3165, 0x4110, iwl3165_2ac_cfg)}, | ||
| 370 | {IWL_PCI_DEVICE(0x3165, 0x4210, iwl3165_2ac_cfg)}, | 372 | {IWL_PCI_DEVICE(0x3165, 0x4210, iwl3165_2ac_cfg)}, |
| 373 | {IWL_PCI_DEVICE(0x3165, 0x4410, iwl3165_2ac_cfg)}, | ||
| 374 | {IWL_PCI_DEVICE(0x3165, 0x4510, iwl3165_2ac_cfg)}, | ||
| 371 | 375 | ||
| 372 | /* 7265 Series */ | 376 | /* 7265 Series */ |
| 373 | {IWL_PCI_DEVICE(0x095A, 0x5010, iwl7265_2ac_cfg)}, | 377 | {IWL_PCI_DEVICE(0x095A, 0x5010, iwl7265_2ac_cfg)}, |
diff --git a/drivers/net/wireless/iwlwifi/pcie/trans.c b/drivers/net/wireless/iwlwifi/pcie/trans.c index 5d79a1f44b8e..523fe0c88dcb 100644 --- a/drivers/net/wireless/iwlwifi/pcie/trans.c +++ b/drivers/net/wireless/iwlwifi/pcie/trans.c | |||
| @@ -614,7 +614,7 @@ static int iwl_pcie_load_section(struct iwl_trans *trans, u8 section_num, | |||
| 614 | { | 614 | { |
| 615 | u8 *v_addr; | 615 | u8 *v_addr; |
| 616 | dma_addr_t p_addr; | 616 | dma_addr_t p_addr; |
| 617 | u32 offset, chunk_sz = section->len; | 617 | u32 offset, chunk_sz = min_t(u32, FH_MEM_TB_MAX_LENGTH, section->len); |
| 618 | int ret = 0; | 618 | int ret = 0; |
| 619 | 619 | ||
| 620 | IWL_DEBUG_FW(trans, "[%d] uCode section being loaded...\n", | 620 | IWL_DEBUG_FW(trans, "[%d] uCode section being loaded...\n", |
| @@ -1012,16 +1012,21 @@ static void iwl_trans_pcie_stop_device(struct iwl_trans *trans) | |||
| 1012 | /* Stop the device, and put it in low power state */ | 1012 | /* Stop the device, and put it in low power state */ |
| 1013 | iwl_pcie_apm_stop(trans); | 1013 | iwl_pcie_apm_stop(trans); |
| 1014 | 1014 | ||
| 1015 | /* Upon stop, the APM issues an interrupt if HW RF kill is set. | 1015 | /* stop and reset the on-board processor */ |
| 1016 | * Clean again the interrupt here | 1016 | iwl_write32(trans, CSR_RESET, CSR_RESET_REG_FLAG_SW_RESET); |
| 1017 | udelay(20); | ||
| 1018 | |||
| 1019 | /* | ||
| 1020 | * Upon stop, the APM issues an interrupt if HW RF kill is set. | ||
| 1021 | * This is a bug in certain verions of the hardware. | ||
| 1022 | * Certain devices also keep sending HW RF kill interrupt all | ||
| 1023 | * the time, unless the interrupt is ACKed even if the interrupt | ||
| 1024 | * should be masked. Re-ACK all the interrupts here. | ||
| 1017 | */ | 1025 | */ |
| 1018 | spin_lock(&trans_pcie->irq_lock); | 1026 | spin_lock(&trans_pcie->irq_lock); |
| 1019 | iwl_disable_interrupts(trans); | 1027 | iwl_disable_interrupts(trans); |
| 1020 | spin_unlock(&trans_pcie->irq_lock); | 1028 | spin_unlock(&trans_pcie->irq_lock); |
| 1021 | 1029 | ||
| 1022 | /* stop and reset the on-board processor */ | ||
| 1023 | iwl_write32(trans, CSR_RESET, CSR_RESET_REG_FLAG_SW_RESET); | ||
| 1024 | udelay(20); | ||
| 1025 | 1030 | ||
| 1026 | /* clear all status bits */ | 1031 | /* clear all status bits */ |
| 1027 | clear_bit(STATUS_SYNC_HCMD_ACTIVE, &trans->status); | 1032 | clear_bit(STATUS_SYNC_HCMD_ACTIVE, &trans->status); |
diff --git a/drivers/powercap/intel_rapl.c b/drivers/powercap/intel_rapl.c index c71443c4f265..97b5e4ee1ca4 100644 --- a/drivers/powercap/intel_rapl.c +++ b/drivers/powercap/intel_rapl.c | |||
| @@ -1041,6 +1041,7 @@ static const struct x86_cpu_id rapl_ids[] = { | |||
| 1041 | RAPL_CPU(0x45, rapl_defaults_core),/* Haswell ULT */ | 1041 | RAPL_CPU(0x45, rapl_defaults_core),/* Haswell ULT */ |
| 1042 | RAPL_CPU(0x4C, rapl_defaults_atom),/* Braswell */ | 1042 | RAPL_CPU(0x4C, rapl_defaults_atom),/* Braswell */ |
| 1043 | RAPL_CPU(0x4A, rapl_defaults_atom),/* Tangier */ | 1043 | RAPL_CPU(0x4A, rapl_defaults_atom),/* Tangier */ |
| 1044 | RAPL_CPU(0x56, rapl_defaults_core),/* Future Xeon */ | ||
| 1044 | RAPL_CPU(0x5A, rapl_defaults_atom),/* Annidale */ | 1045 | RAPL_CPU(0x5A, rapl_defaults_atom),/* Annidale */ |
| 1045 | {} | 1046 | {} |
| 1046 | }; | 1047 | }; |
diff --git a/drivers/regulator/s2mps11.c b/drivers/regulator/s2mps11.c index c1444c3d84c2..2809ae0d6bcd 100644 --- a/drivers/regulator/s2mps11.c +++ b/drivers/regulator/s2mps11.c | |||
| @@ -570,7 +570,7 @@ static struct regulator_ops s2mps14_reg_ops = { | |||
| 570 | .enable_mask = S2MPS14_ENABLE_MASK \ | 570 | .enable_mask = S2MPS14_ENABLE_MASK \ |
| 571 | } | 571 | } |
| 572 | 572 | ||
| 573 | #define regulator_desc_s2mps14_buck(num, min, step) { \ | 573 | #define regulator_desc_s2mps14_buck(num, min, step, min_sel) { \ |
| 574 | .name = "BUCK"#num, \ | 574 | .name = "BUCK"#num, \ |
| 575 | .id = S2MPS14_BUCK##num, \ | 575 | .id = S2MPS14_BUCK##num, \ |
| 576 | .ops = &s2mps14_reg_ops, \ | 576 | .ops = &s2mps14_reg_ops, \ |
| @@ -579,7 +579,7 @@ static struct regulator_ops s2mps14_reg_ops = { | |||
| 579 | .min_uV = min, \ | 579 | .min_uV = min, \ |
| 580 | .uV_step = step, \ | 580 | .uV_step = step, \ |
| 581 | .n_voltages = S2MPS14_BUCK_N_VOLTAGES, \ | 581 | .n_voltages = S2MPS14_BUCK_N_VOLTAGES, \ |
| 582 | .linear_min_sel = S2MPS14_BUCK1235_START_SEL, \ | 582 | .linear_min_sel = min_sel, \ |
| 583 | .ramp_delay = S2MPS14_BUCK_RAMP_DELAY, \ | 583 | .ramp_delay = S2MPS14_BUCK_RAMP_DELAY, \ |
| 584 | .vsel_reg = S2MPS14_REG_B1CTRL2 + (num - 1) * 2, \ | 584 | .vsel_reg = S2MPS14_REG_B1CTRL2 + (num - 1) * 2, \ |
| 585 | .vsel_mask = S2MPS14_BUCK_VSEL_MASK, \ | 585 | .vsel_mask = S2MPS14_BUCK_VSEL_MASK, \ |
| @@ -613,11 +613,16 @@ static const struct regulator_desc s2mps14_regulators[] = { | |||
| 613 | regulator_desc_s2mps14_ldo(23, MIN_800_MV, STEP_25_MV), | 613 | regulator_desc_s2mps14_ldo(23, MIN_800_MV, STEP_25_MV), |
| 614 | regulator_desc_s2mps14_ldo(24, MIN_1800_MV, STEP_25_MV), | 614 | regulator_desc_s2mps14_ldo(24, MIN_1800_MV, STEP_25_MV), |
| 615 | regulator_desc_s2mps14_ldo(25, MIN_1800_MV, STEP_25_MV), | 615 | regulator_desc_s2mps14_ldo(25, MIN_1800_MV, STEP_25_MV), |
| 616 | regulator_desc_s2mps14_buck(1, MIN_600_MV, STEP_6_25_MV), | 616 | regulator_desc_s2mps14_buck(1, MIN_600_MV, STEP_6_25_MV, |
| 617 | regulator_desc_s2mps14_buck(2, MIN_600_MV, STEP_6_25_MV), | 617 | S2MPS14_BUCK1235_START_SEL), |
| 618 | regulator_desc_s2mps14_buck(3, MIN_600_MV, STEP_6_25_MV), | 618 | regulator_desc_s2mps14_buck(2, MIN_600_MV, STEP_6_25_MV, |
| 619 | regulator_desc_s2mps14_buck(4, MIN_1400_MV, STEP_12_5_MV), | 619 | S2MPS14_BUCK1235_START_SEL), |
| 620 | regulator_desc_s2mps14_buck(5, MIN_600_MV, STEP_6_25_MV), | 620 | regulator_desc_s2mps14_buck(3, MIN_600_MV, STEP_6_25_MV, |
| 621 | S2MPS14_BUCK1235_START_SEL), | ||
| 622 | regulator_desc_s2mps14_buck(4, MIN_1400_MV, STEP_12_5_MV, | ||
| 623 | S2MPS14_BUCK4_START_SEL), | ||
| 624 | regulator_desc_s2mps14_buck(5, MIN_600_MV, STEP_6_25_MV, | ||
| 625 | S2MPS14_BUCK1235_START_SEL), | ||
| 621 | }; | 626 | }; |
| 622 | 627 | ||
| 623 | static int s2mps14_pmic_enable_ext_control(struct s2mps11_info *s2mps11, | 628 | static int s2mps14_pmic_enable_ext_control(struct s2mps11_info *s2mps11, |
diff --git a/drivers/scsi/fnic/fnic.h b/drivers/scsi/fnic/fnic.h index 3b73b96619e2..26270c351624 100644 --- a/drivers/scsi/fnic/fnic.h +++ b/drivers/scsi/fnic/fnic.h | |||
| @@ -39,7 +39,7 @@ | |||
| 39 | 39 | ||
| 40 | #define DRV_NAME "fnic" | 40 | #define DRV_NAME "fnic" |
| 41 | #define DRV_DESCRIPTION "Cisco FCoE HBA Driver" | 41 | #define DRV_DESCRIPTION "Cisco FCoE HBA Driver" |
| 42 | #define DRV_VERSION "1.6.0.16" | 42 | #define DRV_VERSION "1.6.0.17" |
| 43 | #define PFX DRV_NAME ": " | 43 | #define PFX DRV_NAME ": " |
| 44 | #define DFX DRV_NAME "%d: " | 44 | #define DFX DRV_NAME "%d: " |
| 45 | 45 | ||
diff --git a/drivers/scsi/fnic/fnic_scsi.c b/drivers/scsi/fnic/fnic_scsi.c index 2097de42a147..155b286f1a9d 100644 --- a/drivers/scsi/fnic/fnic_scsi.c +++ b/drivers/scsi/fnic/fnic_scsi.c | |||
| @@ -1892,6 +1892,21 @@ int fnic_abort_cmd(struct scsi_cmnd *sc) | |||
| 1892 | goto fnic_abort_cmd_end; | 1892 | goto fnic_abort_cmd_end; |
| 1893 | } | 1893 | } |
| 1894 | 1894 | ||
| 1895 | /* IO out of order */ | ||
| 1896 | |||
| 1897 | if (!(CMD_FLAGS(sc) & (FNIC_IO_ABORTED | FNIC_IO_DONE))) { | ||
| 1898 | spin_unlock_irqrestore(io_lock, flags); | ||
| 1899 | FNIC_SCSI_DBG(KERN_DEBUG, fnic->lport->host, | ||
| 1900 | "Issuing Host reset due to out of order IO\n"); | ||
| 1901 | |||
| 1902 | if (fnic_host_reset(sc) == FAILED) { | ||
| 1903 | FNIC_SCSI_DBG(KERN_DEBUG, fnic->lport->host, | ||
| 1904 | "fnic_host_reset failed.\n"); | ||
| 1905 | } | ||
| 1906 | ret = FAILED; | ||
| 1907 | goto fnic_abort_cmd_end; | ||
| 1908 | } | ||
| 1909 | |||
| 1895 | CMD_STATE(sc) = FNIC_IOREQ_ABTS_COMPLETE; | 1910 | CMD_STATE(sc) = FNIC_IOREQ_ABTS_COMPLETE; |
| 1896 | 1911 | ||
| 1897 | /* | 1912 | /* |
diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c index e42fff6e8c10..8afb01604d51 100644 --- a/drivers/scsi/scsi_error.c +++ b/drivers/scsi/scsi_error.c | |||
| @@ -1041,7 +1041,7 @@ retry: | |||
| 1041 | } | 1041 | } |
| 1042 | /* signal not to enter either branch of the if () below */ | 1042 | /* signal not to enter either branch of the if () below */ |
| 1043 | timeleft = 0; | 1043 | timeleft = 0; |
| 1044 | rtn = NEEDS_RETRY; | 1044 | rtn = FAILED; |
| 1045 | } else { | 1045 | } else { |
| 1046 | timeleft = wait_for_completion_timeout(&done, timeout); | 1046 | timeleft = wait_for_completion_timeout(&done, timeout); |
| 1047 | rtn = SUCCESS; | 1047 | rtn = SUCCESS; |
| @@ -1081,7 +1081,7 @@ retry: | |||
| 1081 | rtn = FAILED; | 1081 | rtn = FAILED; |
| 1082 | break; | 1082 | break; |
| 1083 | } | 1083 | } |
| 1084 | } else if (!rtn) { | 1084 | } else if (rtn != FAILED) { |
| 1085 | scsi_abort_eh_cmnd(scmd); | 1085 | scsi_abort_eh_cmnd(scmd); |
| 1086 | rtn = FAILED; | 1086 | rtn = FAILED; |
| 1087 | } | 1087 | } |
diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index fedab3c21ddf..399516925d80 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c | |||
| @@ -2623,8 +2623,9 @@ static void sd_read_block_limits(struct scsi_disk *sdkp) | |||
| 2623 | sd_config_discard(sdkp, SD_LBP_WS16); | 2623 | sd_config_discard(sdkp, SD_LBP_WS16); |
| 2624 | 2624 | ||
| 2625 | } else { /* LBP VPD page tells us what to use */ | 2625 | } else { /* LBP VPD page tells us what to use */ |
| 2626 | 2626 | if (sdkp->lbpu && sdkp->max_unmap_blocks && !sdkp->lbprz) | |
| 2627 | if (sdkp->lbpws) | 2627 | sd_config_discard(sdkp, SD_LBP_UNMAP); |
| 2628 | else if (sdkp->lbpws) | ||
| 2628 | sd_config_discard(sdkp, SD_LBP_WS16); | 2629 | sd_config_discard(sdkp, SD_LBP_WS16); |
| 2629 | else if (sdkp->lbpws10) | 2630 | else if (sdkp->lbpws10) |
| 2630 | sd_config_discard(sdkp, SD_LBP_WS10); | 2631 | sd_config_discard(sdkp, SD_LBP_WS10); |
diff --git a/drivers/spi/spi-img-spfi.c b/drivers/spi/spi-img-spfi.c index b410499cddca..aad6683db81b 100644 --- a/drivers/spi/spi-img-spfi.c +++ b/drivers/spi/spi-img-spfi.c | |||
| @@ -341,7 +341,7 @@ static int img_spfi_start_dma(struct spi_master *master, | |||
| 341 | default: | 341 | default: |
| 342 | rxconf.src_addr = spfi->phys + SPFI_RX_8BIT_VALID_DATA; | 342 | rxconf.src_addr = spfi->phys + SPFI_RX_8BIT_VALID_DATA; |
| 343 | rxconf.src_addr_width = 1; | 343 | rxconf.src_addr_width = 1; |
| 344 | rxconf.src_maxburst = 1; | 344 | rxconf.src_maxburst = 4; |
| 345 | } | 345 | } |
| 346 | dmaengine_slave_config(spfi->rx_ch, &rxconf); | 346 | dmaengine_slave_config(spfi->rx_ch, &rxconf); |
| 347 | 347 | ||
| @@ -368,7 +368,7 @@ static int img_spfi_start_dma(struct spi_master *master, | |||
| 368 | default: | 368 | default: |
| 369 | txconf.dst_addr = spfi->phys + SPFI_TX_8BIT_VALID_DATA; | 369 | txconf.dst_addr = spfi->phys + SPFI_TX_8BIT_VALID_DATA; |
| 370 | txconf.dst_addr_width = 1; | 370 | txconf.dst_addr_width = 1; |
| 371 | txconf.dst_maxburst = 1; | 371 | txconf.dst_maxburst = 4; |
| 372 | break; | 372 | break; |
| 373 | } | 373 | } |
| 374 | dmaengine_slave_config(spfi->tx_ch, &txconf); | 374 | dmaengine_slave_config(spfi->tx_ch, &txconf); |
| @@ -390,14 +390,14 @@ static int img_spfi_start_dma(struct spi_master *master, | |||
| 390 | dma_async_issue_pending(spfi->rx_ch); | 390 | dma_async_issue_pending(spfi->rx_ch); |
| 391 | } | 391 | } |
| 392 | 392 | ||
| 393 | spfi_start(spfi); | ||
| 394 | |||
| 393 | if (xfer->tx_buf) { | 395 | if (xfer->tx_buf) { |
| 394 | spfi->tx_dma_busy = true; | 396 | spfi->tx_dma_busy = true; |
| 395 | dmaengine_submit(txdesc); | 397 | dmaengine_submit(txdesc); |
| 396 | dma_async_issue_pending(spfi->tx_ch); | 398 | dma_async_issue_pending(spfi->tx_ch); |
| 397 | } | 399 | } |
| 398 | 400 | ||
| 399 | spfi_start(spfi); | ||
| 400 | |||
| 401 | return 1; | 401 | return 1; |
| 402 | 402 | ||
| 403 | stop_dma: | 403 | stop_dma: |
diff --git a/drivers/spi/spi-sh-msiof.c b/drivers/spi/spi-sh-msiof.c index 239be7cbe5a8..96a5fc0878d8 100644 --- a/drivers/spi/spi-sh-msiof.c +++ b/drivers/spi/spi-sh-msiof.c | |||
| @@ -480,6 +480,8 @@ static int sh_msiof_spi_setup(struct spi_device *spi) | |||
| 480 | struct device_node *np = spi->master->dev.of_node; | 480 | struct device_node *np = spi->master->dev.of_node; |
| 481 | struct sh_msiof_spi_priv *p = spi_master_get_devdata(spi->master); | 481 | struct sh_msiof_spi_priv *p = spi_master_get_devdata(spi->master); |
| 482 | 482 | ||
| 483 | pm_runtime_get_sync(&p->pdev->dev); | ||
| 484 | |||
| 483 | if (!np) { | 485 | if (!np) { |
| 484 | /* | 486 | /* |
| 485 | * Use spi->controller_data for CS (same strategy as spi_gpio), | 487 | * Use spi->controller_data for CS (same strategy as spi_gpio), |
| @@ -498,6 +500,9 @@ static int sh_msiof_spi_setup(struct spi_device *spi) | |||
| 498 | if (spi->cs_gpio >= 0) | 500 | if (spi->cs_gpio >= 0) |
| 499 | gpio_set_value(spi->cs_gpio, !(spi->mode & SPI_CS_HIGH)); | 501 | gpio_set_value(spi->cs_gpio, !(spi->mode & SPI_CS_HIGH)); |
| 500 | 502 | ||
| 503 | |||
| 504 | pm_runtime_put_sync(&p->pdev->dev); | ||
| 505 | |||
| 501 | return 0; | 506 | return 0; |
| 502 | } | 507 | } |
| 503 | 508 | ||
diff --git a/drivers/staging/lustre/lustre/llite/namei.c b/drivers/staging/lustre/lustre/llite/namei.c index 1bf891bd321a..4f361b77c749 100644 --- a/drivers/staging/lustre/lustre/llite/namei.c +++ b/drivers/staging/lustre/lustre/llite/namei.c | |||
| @@ -264,7 +264,7 @@ int ll_md_blocking_ast(struct ldlm_lock *lock, struct ldlm_lock_desc *desc, | |||
| 264 | 264 | ||
| 265 | if ((bits & (MDS_INODELOCK_LOOKUP | MDS_INODELOCK_PERM)) && | 265 | if ((bits & (MDS_INODELOCK_LOOKUP | MDS_INODELOCK_PERM)) && |
| 266 | inode->i_sb->s_root != NULL && | 266 | inode->i_sb->s_root != NULL && |
| 267 | is_root_inode(inode)) | 267 | !is_root_inode(inode)) |
| 268 | ll_invalidate_aliases(inode); | 268 | ll_invalidate_aliases(inode); |
| 269 | 269 | ||
| 270 | iput(inode); | 270 | iput(inode); |
diff --git a/drivers/thermal/cpu_cooling.c b/drivers/thermal/cpu_cooling.c index ad09e51ffae4..f65f0d109fc8 100644 --- a/drivers/thermal/cpu_cooling.c +++ b/drivers/thermal/cpu_cooling.c | |||
| @@ -4,6 +4,8 @@ | |||
| 4 | * Copyright (C) 2012 Samsung Electronics Co., Ltd(http://www.samsung.com) | 4 | * Copyright (C) 2012 Samsung Electronics Co., Ltd(http://www.samsung.com) |
| 5 | * Copyright (C) 2012 Amit Daniel <amit.kachhap@linaro.org> | 5 | * Copyright (C) 2012 Amit Daniel <amit.kachhap@linaro.org> |
| 6 | * | 6 | * |
| 7 | * Copyright (C) 2014 Viresh Kumar <viresh.kumar@linaro.org> | ||
| 8 | * | ||
| 7 | * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | 9 | * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| 8 | * This program is free software; you can redistribute it and/or modify | 10 | * This program is free software; you can redistribute it and/or modify |
| 9 | * it under the terms of the GNU General Public License as published by | 11 | * it under the terms of the GNU General Public License as published by |
| @@ -28,6 +30,20 @@ | |||
| 28 | #include <linux/cpu.h> | 30 | #include <linux/cpu.h> |
| 29 | #include <linux/cpu_cooling.h> | 31 | #include <linux/cpu_cooling.h> |
| 30 | 32 | ||
| 33 | /* | ||
| 34 | * Cooling state <-> CPUFreq frequency | ||
| 35 | * | ||
| 36 | * Cooling states are translated to frequencies throughout this driver and this | ||
| 37 | * is the relation between them. | ||
| 38 | * | ||
| 39 | * Highest cooling state corresponds to lowest possible frequency. | ||
| 40 | * | ||
| 41 | * i.e. | ||
| 42 | * level 0 --> 1st Max Freq | ||
| 43 | * level 1 --> 2nd Max Freq | ||
| 44 | * ... | ||
| 45 | */ | ||
| 46 | |||
| 31 | /** | 47 | /** |
| 32 | * struct cpufreq_cooling_device - data for cooling device with cpufreq | 48 | * struct cpufreq_cooling_device - data for cooling device with cpufreq |
| 33 | * @id: unique integer value corresponding to each cpufreq_cooling_device | 49 | * @id: unique integer value corresponding to each cpufreq_cooling_device |
| @@ -38,25 +54,27 @@ | |||
| 38 | * cooling devices. | 54 | * cooling devices. |
| 39 | * @cpufreq_val: integer value representing the absolute value of the clipped | 55 | * @cpufreq_val: integer value representing the absolute value of the clipped |
| 40 | * frequency. | 56 | * frequency. |
| 57 | * @max_level: maximum cooling level. One less than total number of valid | ||
| 58 | * cpufreq frequencies. | ||
| 41 | * @allowed_cpus: all the cpus involved for this cpufreq_cooling_device. | 59 | * @allowed_cpus: all the cpus involved for this cpufreq_cooling_device. |
| 60 | * @node: list_head to link all cpufreq_cooling_device together. | ||
| 42 | * | 61 | * |
| 43 | * This structure is required for keeping information of each | 62 | * This structure is required for keeping information of each registered |
| 44 | * cpufreq_cooling_device registered. In order to prevent corruption of this a | 63 | * cpufreq_cooling_device. |
| 45 | * mutex lock cooling_cpufreq_lock is used. | ||
| 46 | */ | 64 | */ |
| 47 | struct cpufreq_cooling_device { | 65 | struct cpufreq_cooling_device { |
| 48 | int id; | 66 | int id; |
| 49 | struct thermal_cooling_device *cool_dev; | 67 | struct thermal_cooling_device *cool_dev; |
| 50 | unsigned int cpufreq_state; | 68 | unsigned int cpufreq_state; |
| 51 | unsigned int cpufreq_val; | 69 | unsigned int cpufreq_val; |
| 70 | unsigned int max_level; | ||
| 71 | unsigned int *freq_table; /* In descending order */ | ||
| 52 | struct cpumask allowed_cpus; | 72 | struct cpumask allowed_cpus; |
| 53 | struct list_head node; | 73 | struct list_head node; |
| 54 | }; | 74 | }; |
| 55 | static DEFINE_IDR(cpufreq_idr); | 75 | static DEFINE_IDR(cpufreq_idr); |
| 56 | static DEFINE_MUTEX(cooling_cpufreq_lock); | 76 | static DEFINE_MUTEX(cooling_cpufreq_lock); |
| 57 | 77 | ||
| 58 | static unsigned int cpufreq_dev_count; | ||
| 59 | |||
| 60 | static LIST_HEAD(cpufreq_dev_list); | 78 | static LIST_HEAD(cpufreq_dev_list); |
| 61 | 79 | ||
| 62 | /** | 80 | /** |
| @@ -98,120 +116,30 @@ static void release_idr(struct idr *idr, int id) | |||
| 98 | /* Below code defines functions to be used for cpufreq as cooling device */ | 116 | /* Below code defines functions to be used for cpufreq as cooling device */ |
| 99 | 117 | ||
| 100 | /** | 118 | /** |
| 101 | * is_cpufreq_valid - function to check frequency transitioning capability. | 119 | * get_level: Find the level for a particular frequency |
| 102 | * @cpu: cpu for which check is needed. | 120 | * @cpufreq_dev: cpufreq_dev for which the property is required |
| 121 | * @freq: Frequency | ||
| 103 | * | 122 | * |
| 104 | * This function will check the current state of the system if | 123 | * Return: level on success, THERMAL_CSTATE_INVALID on error. |
| 105 | * it is capable of changing the frequency for a given @cpu. | ||
| 106 | * | ||
| 107 | * Return: 0 if the system is not currently capable of changing | ||
| 108 | * the frequency of given cpu. !0 in case the frequency is changeable. | ||
| 109 | */ | 124 | */ |
| 110 | static int is_cpufreq_valid(int cpu) | 125 | static unsigned long get_level(struct cpufreq_cooling_device *cpufreq_dev, |
| 126 | unsigned int freq) | ||
| 111 | { | 127 | { |
| 112 | struct cpufreq_policy policy; | 128 | unsigned long level; |
| 113 | |||
| 114 | return !cpufreq_get_policy(&policy, cpu); | ||
| 115 | } | ||
| 116 | |||
| 117 | enum cpufreq_cooling_property { | ||
| 118 | GET_LEVEL, | ||
| 119 | GET_FREQ, | ||
| 120 | GET_MAXL, | ||
| 121 | }; | ||
| 122 | |||
| 123 | /** | ||
| 124 | * get_property - fetch a property of interest for a give cpu. | ||
| 125 | * @cpu: cpu for which the property is required | ||
| 126 | * @input: query parameter | ||
| 127 | * @output: query return | ||
| 128 | * @property: type of query (frequency, level, max level) | ||
| 129 | * | ||
| 130 | * This is the common function to | ||
| 131 | * 1. get maximum cpu cooling states | ||
| 132 | * 2. translate frequency to cooling state | ||
| 133 | * 3. translate cooling state to frequency | ||
| 134 | * Note that the code may be not in good shape | ||
| 135 | * but it is written in this way in order to: | ||
| 136 | * a) reduce duplicate code as most of the code can be shared. | ||
| 137 | * b) make sure the logic is consistent when translating between | ||
| 138 | * cooling states and frequencies. | ||
| 139 | * | ||
| 140 | * Return: 0 on success, -EINVAL when invalid parameters are passed. | ||
| 141 | */ | ||
| 142 | static int get_property(unsigned int cpu, unsigned long input, | ||
| 143 | unsigned int *output, | ||
| 144 | enum cpufreq_cooling_property property) | ||
| 145 | { | ||
| 146 | int i; | ||
| 147 | unsigned long max_level = 0, level = 0; | ||
| 148 | unsigned int freq = CPUFREQ_ENTRY_INVALID; | ||
| 149 | int descend = -1; | ||
| 150 | struct cpufreq_frequency_table *pos, *table = | ||
| 151 | cpufreq_frequency_get_table(cpu); | ||
| 152 | |||
| 153 | if (!output) | ||
| 154 | return -EINVAL; | ||
| 155 | |||
| 156 | if (!table) | ||
| 157 | return -EINVAL; | ||
| 158 | |||
| 159 | cpufreq_for_each_valid_entry(pos, table) { | ||
| 160 | /* ignore duplicate entry */ | ||
| 161 | if (freq == pos->frequency) | ||
| 162 | continue; | ||
| 163 | |||
| 164 | /* get the frequency order */ | ||
| 165 | if (freq != CPUFREQ_ENTRY_INVALID && descend == -1) | ||
| 166 | descend = freq > pos->frequency; | ||
| 167 | |||
| 168 | freq = pos->frequency; | ||
| 169 | max_level++; | ||
| 170 | } | ||
| 171 | |||
| 172 | /* No valid cpu frequency entry */ | ||
| 173 | if (max_level == 0) | ||
| 174 | return -EINVAL; | ||
| 175 | 129 | ||
| 176 | /* max_level is an index, not a counter */ | 130 | for (level = 0; level <= cpufreq_dev->max_level; level++) { |
| 177 | max_level--; | 131 | if (freq == cpufreq_dev->freq_table[level]) |
| 132 | return level; | ||
| 178 | 133 | ||
| 179 | /* get max level */ | 134 | if (freq > cpufreq_dev->freq_table[level]) |
| 180 | if (property == GET_MAXL) { | 135 | break; |
| 181 | *output = (unsigned int)max_level; | ||
| 182 | return 0; | ||
| 183 | } | 136 | } |
| 184 | 137 | ||
| 185 | if (property == GET_FREQ) | 138 | return THERMAL_CSTATE_INVALID; |
| 186 | level = descend ? input : (max_level - input); | ||
| 187 | |||
| 188 | i = 0; | ||
| 189 | cpufreq_for_each_valid_entry(pos, table) { | ||
| 190 | /* ignore duplicate entry */ | ||
| 191 | if (freq == pos->frequency) | ||
| 192 | continue; | ||
| 193 | |||
| 194 | /* now we have a valid frequency entry */ | ||
| 195 | freq = pos->frequency; | ||
| 196 | |||
| 197 | if (property == GET_LEVEL && (unsigned int)input == freq) { | ||
| 198 | /* get level by frequency */ | ||
| 199 | *output = descend ? i : (max_level - i); | ||
| 200 | return 0; | ||
| 201 | } | ||
| 202 | if (property == GET_FREQ && level == i) { | ||
| 203 | /* get frequency by level */ | ||
| 204 | *output = freq; | ||
| 205 | return 0; | ||
| 206 | } | ||
| 207 | i++; | ||
| 208 | } | ||
| 209 | |||
| 210 | return -EINVAL; | ||
| 211 | } | 139 | } |
| 212 | 140 | ||
| 213 | /** | 141 | /** |
| 214 | * cpufreq_cooling_get_level - for a give cpu, return the cooling level. | 142 | * cpufreq_cooling_get_level - for a given cpu, return the cooling level. |
| 215 | * @cpu: cpu for which the level is required | 143 | * @cpu: cpu for which the level is required |
| 216 | * @freq: the frequency of interest | 144 | * @freq: the frequency of interest |
| 217 | * | 145 | * |
| @@ -223,77 +151,21 @@ static int get_property(unsigned int cpu, unsigned long input, | |||
| 223 | */ | 151 | */ |
| 224 | unsigned long cpufreq_cooling_get_level(unsigned int cpu, unsigned int freq) | 152 | unsigned long cpufreq_cooling_get_level(unsigned int cpu, unsigned int freq) |
| 225 | { | 153 | { |
| 226 | unsigned int val; | 154 | struct cpufreq_cooling_device *cpufreq_dev; |
| 227 | |||
| 228 | if (get_property(cpu, (unsigned long)freq, &val, GET_LEVEL)) | ||
| 229 | return THERMAL_CSTATE_INVALID; | ||
| 230 | |||
| 231 | return (unsigned long)val; | ||
| 232 | } | ||
| 233 | EXPORT_SYMBOL_GPL(cpufreq_cooling_get_level); | ||
| 234 | |||
| 235 | /** | ||
| 236 | * get_cpu_frequency - get the absolute value of frequency from level. | ||
| 237 | * @cpu: cpu for which frequency is fetched. | ||
| 238 | * @level: cooling level | ||
| 239 | * | ||
| 240 | * This function matches cooling level with frequency. Based on a cooling level | ||
| 241 | * of frequency, equals cooling state of cpu cooling device, it will return | ||
| 242 | * the corresponding frequency. | ||
| 243 | * e.g level=0 --> 1st MAX FREQ, level=1 ---> 2nd MAX FREQ, .... etc | ||
| 244 | * | ||
| 245 | * Return: 0 on error, the corresponding frequency otherwise. | ||
| 246 | */ | ||
| 247 | static unsigned int get_cpu_frequency(unsigned int cpu, unsigned long level) | ||
| 248 | { | ||
| 249 | int ret = 0; | ||
| 250 | unsigned int freq; | ||
| 251 | |||
| 252 | ret = get_property(cpu, level, &freq, GET_FREQ); | ||
| 253 | if (ret) | ||
| 254 | return 0; | ||
| 255 | |||
| 256 | return freq; | ||
| 257 | } | ||
| 258 | |||
| 259 | /** | ||
| 260 | * cpufreq_apply_cooling - function to apply frequency clipping. | ||
| 261 | * @cpufreq_device: cpufreq_cooling_device pointer containing frequency | ||
| 262 | * clipping data. | ||
| 263 | * @cooling_state: value of the cooling state. | ||
| 264 | * | ||
| 265 | * Function used to make sure the cpufreq layer is aware of current thermal | ||
| 266 | * limits. The limits are applied by updating the cpufreq policy. | ||
| 267 | * | ||
| 268 | * Return: 0 on success, an error code otherwise (-EINVAL in case wrong | ||
| 269 | * cooling state). | ||
| 270 | */ | ||
| 271 | static int cpufreq_apply_cooling(struct cpufreq_cooling_device *cpufreq_device, | ||
| 272 | unsigned long cooling_state) | ||
| 273 | { | ||
| 274 | unsigned int cpuid, clip_freq; | ||
| 275 | struct cpumask *mask = &cpufreq_device->allowed_cpus; | ||
| 276 | unsigned int cpu = cpumask_any(mask); | ||
| 277 | |||
| 278 | |||
| 279 | /* Check if the old cooling action is same as new cooling action */ | ||
| 280 | if (cpufreq_device->cpufreq_state == cooling_state) | ||
| 281 | return 0; | ||
| 282 | |||
| 283 | clip_freq = get_cpu_frequency(cpu, cooling_state); | ||
| 284 | if (!clip_freq) | ||
| 285 | return -EINVAL; | ||
| 286 | |||
| 287 | cpufreq_device->cpufreq_state = cooling_state; | ||
| 288 | cpufreq_device->cpufreq_val = clip_freq; | ||
| 289 | 155 | ||
| 290 | for_each_cpu(cpuid, mask) { | 156 | mutex_lock(&cooling_cpufreq_lock); |
| 291 | if (is_cpufreq_valid(cpuid)) | 157 | list_for_each_entry(cpufreq_dev, &cpufreq_dev_list, node) { |
| 292 | cpufreq_update_policy(cpuid); | 158 | if (cpumask_test_cpu(cpu, &cpufreq_dev->allowed_cpus)) { |
| 159 | mutex_unlock(&cooling_cpufreq_lock); | ||
| 160 | return get_level(cpufreq_dev, freq); | ||
| 161 | } | ||
| 293 | } | 162 | } |
| 163 | mutex_unlock(&cooling_cpufreq_lock); | ||
| 294 | 164 | ||
| 295 | return 0; | 165 | pr_err("%s: cpu:%d not part of any cooling device\n", __func__, cpu); |
| 166 | return THERMAL_CSTATE_INVALID; | ||
| 296 | } | 167 | } |
| 168 | EXPORT_SYMBOL_GPL(cpufreq_cooling_get_level); | ||
| 297 | 169 | ||
| 298 | /** | 170 | /** |
| 299 | * cpufreq_thermal_notifier - notifier callback for cpufreq policy change. | 171 | * cpufreq_thermal_notifier - notifier callback for cpufreq policy change. |
| @@ -323,11 +195,6 @@ static int cpufreq_thermal_notifier(struct notifier_block *nb, | |||
| 323 | &cpufreq_dev->allowed_cpus)) | 195 | &cpufreq_dev->allowed_cpus)) |
| 324 | continue; | 196 | continue; |
| 325 | 197 | ||
| 326 | if (!cpufreq_dev->cpufreq_val) | ||
| 327 | cpufreq_dev->cpufreq_val = get_cpu_frequency( | ||
| 328 | cpumask_any(&cpufreq_dev->allowed_cpus), | ||
| 329 | cpufreq_dev->cpufreq_state); | ||
| 330 | |||
| 331 | max_freq = cpufreq_dev->cpufreq_val; | 198 | max_freq = cpufreq_dev->cpufreq_val; |
| 332 | 199 | ||
| 333 | if (policy->max != max_freq) | 200 | if (policy->max != max_freq) |
| @@ -354,19 +221,9 @@ static int cpufreq_get_max_state(struct thermal_cooling_device *cdev, | |||
| 354 | unsigned long *state) | 221 | unsigned long *state) |
| 355 | { | 222 | { |
| 356 | struct cpufreq_cooling_device *cpufreq_device = cdev->devdata; | 223 | struct cpufreq_cooling_device *cpufreq_device = cdev->devdata; |
| 357 | struct cpumask *mask = &cpufreq_device->allowed_cpus; | ||
| 358 | unsigned int cpu; | ||
| 359 | unsigned int count = 0; | ||
| 360 | int ret; | ||
| 361 | |||
| 362 | cpu = cpumask_any(mask); | ||
| 363 | |||
| 364 | ret = get_property(cpu, 0, &count, GET_MAXL); | ||
| 365 | 224 | ||
| 366 | if (count > 0) | 225 | *state = cpufreq_device->max_level; |
| 367 | *state = count; | 226 | return 0; |
| 368 | |||
| 369 | return ret; | ||
| 370 | } | 227 | } |
| 371 | 228 | ||
| 372 | /** | 229 | /** |
| @@ -403,8 +260,24 @@ static int cpufreq_set_cur_state(struct thermal_cooling_device *cdev, | |||
| 403 | unsigned long state) | 260 | unsigned long state) |
| 404 | { | 261 | { |
| 405 | struct cpufreq_cooling_device *cpufreq_device = cdev->devdata; | 262 | struct cpufreq_cooling_device *cpufreq_device = cdev->devdata; |
| 263 | unsigned int cpu = cpumask_any(&cpufreq_device->allowed_cpus); | ||
| 264 | unsigned int clip_freq; | ||
| 265 | |||
| 266 | /* Request state should be less than max_level */ | ||
| 267 | if (WARN_ON(state > cpufreq_device->max_level)) | ||
| 268 | return -EINVAL; | ||
| 269 | |||
| 270 | /* Check if the old cooling action is same as new cooling action */ | ||
| 271 | if (cpufreq_device->cpufreq_state == state) | ||
| 272 | return 0; | ||
| 406 | 273 | ||
| 407 | return cpufreq_apply_cooling(cpufreq_device, state); | 274 | clip_freq = cpufreq_device->freq_table[state]; |
| 275 | cpufreq_device->cpufreq_state = state; | ||
| 276 | cpufreq_device->cpufreq_val = clip_freq; | ||
| 277 | |||
| 278 | cpufreq_update_policy(cpu); | ||
| 279 | |||
| 280 | return 0; | ||
| 408 | } | 281 | } |
| 409 | 282 | ||
| 410 | /* Bind cpufreq callbacks to thermal cooling device ops */ | 283 | /* Bind cpufreq callbacks to thermal cooling device ops */ |
| @@ -419,10 +292,25 @@ static struct notifier_block thermal_cpufreq_notifier_block = { | |||
| 419 | .notifier_call = cpufreq_thermal_notifier, | 292 | .notifier_call = cpufreq_thermal_notifier, |
| 420 | }; | 293 | }; |
| 421 | 294 | ||
| 295 | static unsigned int find_next_max(struct cpufreq_frequency_table *table, | ||
| 296 | unsigned int prev_max) | ||
| 297 | { | ||
| 298 | struct cpufreq_frequency_table *pos; | ||
| 299 | unsigned int max = 0; | ||
| 300 | |||
| 301 | cpufreq_for_each_valid_entry(pos, table) { | ||
| 302 | if (pos->frequency > max && pos->frequency < prev_max) | ||
| 303 | max = pos->frequency; | ||
| 304 | } | ||
| 305 | |||
| 306 | return max; | ||
| 307 | } | ||
| 308 | |||
| 422 | /** | 309 | /** |
| 423 | * __cpufreq_cooling_register - helper function to create cpufreq cooling device | 310 | * __cpufreq_cooling_register - helper function to create cpufreq cooling device |
| 424 | * @np: a valid struct device_node to the cooling device device tree node | 311 | * @np: a valid struct device_node to the cooling device device tree node |
| 425 | * @clip_cpus: cpumask of cpus where the frequency constraints will happen. | 312 | * @clip_cpus: cpumask of cpus where the frequency constraints will happen. |
| 313 | * Normally this should be same as cpufreq policy->related_cpus. | ||
| 426 | * | 314 | * |
| 427 | * This interface function registers the cpufreq cooling device with the name | 315 | * This interface function registers the cpufreq cooling device with the name |
| 428 | * "thermal-cpufreq-%x". This api can support multiple instances of cpufreq | 316 | * "thermal-cpufreq-%x". This api can support multiple instances of cpufreq |
| @@ -437,37 +325,42 @@ __cpufreq_cooling_register(struct device_node *np, | |||
| 437 | const struct cpumask *clip_cpus) | 325 | const struct cpumask *clip_cpus) |
| 438 | { | 326 | { |
| 439 | struct thermal_cooling_device *cool_dev; | 327 | struct thermal_cooling_device *cool_dev; |
| 440 | struct cpufreq_cooling_device *cpufreq_dev = NULL; | 328 | struct cpufreq_cooling_device *cpufreq_dev; |
| 441 | unsigned int min = 0, max = 0; | ||
| 442 | char dev_name[THERMAL_NAME_LENGTH]; | 329 | char dev_name[THERMAL_NAME_LENGTH]; |
| 443 | int ret = 0, i; | 330 | struct cpufreq_frequency_table *pos, *table; |
| 444 | struct cpufreq_policy policy; | 331 | unsigned int freq, i; |
| 332 | int ret; | ||
| 445 | 333 | ||
| 446 | /* Verify that all the clip cpus have same freq_min, freq_max limit */ | 334 | table = cpufreq_frequency_get_table(cpumask_first(clip_cpus)); |
| 447 | for_each_cpu(i, clip_cpus) { | 335 | if (!table) { |
| 448 | /* continue if cpufreq policy not found and not return error */ | 336 | pr_debug("%s: CPUFreq table not found\n", __func__); |
| 449 | if (!cpufreq_get_policy(&policy, i)) | 337 | return ERR_PTR(-EPROBE_DEFER); |
| 450 | continue; | ||
| 451 | if (min == 0 && max == 0) { | ||
| 452 | min = policy.cpuinfo.min_freq; | ||
| 453 | max = policy.cpuinfo.max_freq; | ||
| 454 | } else { | ||
| 455 | if (min != policy.cpuinfo.min_freq || | ||
| 456 | max != policy.cpuinfo.max_freq) | ||
| 457 | return ERR_PTR(-EINVAL); | ||
| 458 | } | ||
| 459 | } | 338 | } |
| 460 | cpufreq_dev = kzalloc(sizeof(struct cpufreq_cooling_device), | 339 | |
| 461 | GFP_KERNEL); | 340 | cpufreq_dev = kzalloc(sizeof(*cpufreq_dev), GFP_KERNEL); |
| 462 | if (!cpufreq_dev) | 341 | if (!cpufreq_dev) |
| 463 | return ERR_PTR(-ENOMEM); | 342 | return ERR_PTR(-ENOMEM); |
| 464 | 343 | ||
| 344 | /* Find max levels */ | ||
| 345 | cpufreq_for_each_valid_entry(pos, table) | ||
| 346 | cpufreq_dev->max_level++; | ||
| 347 | |||
| 348 | cpufreq_dev->freq_table = kmalloc(sizeof(*cpufreq_dev->freq_table) * | ||
| 349 | cpufreq_dev->max_level, GFP_KERNEL); | ||
| 350 | if (!cpufreq_dev->freq_table) { | ||
| 351 | cool_dev = ERR_PTR(-ENOMEM); | ||
| 352 | goto free_cdev; | ||
| 353 | } | ||
| 354 | |||
| 355 | /* max_level is an index, not a counter */ | ||
| 356 | cpufreq_dev->max_level--; | ||
| 357 | |||
| 465 | cpumask_copy(&cpufreq_dev->allowed_cpus, clip_cpus); | 358 | cpumask_copy(&cpufreq_dev->allowed_cpus, clip_cpus); |
| 466 | 359 | ||
| 467 | ret = get_idr(&cpufreq_idr, &cpufreq_dev->id); | 360 | ret = get_idr(&cpufreq_idr, &cpufreq_dev->id); |
| 468 | if (ret) { | 361 | if (ret) { |
| 469 | kfree(cpufreq_dev); | 362 | cool_dev = ERR_PTR(ret); |
| 470 | return ERR_PTR(-EINVAL); | 363 | goto free_table; |
| 471 | } | 364 | } |
| 472 | 365 | ||
| 473 | snprintf(dev_name, sizeof(dev_name), "thermal-cpufreq-%d", | 366 | snprintf(dev_name, sizeof(dev_name), "thermal-cpufreq-%d", |
| @@ -475,25 +368,44 @@ __cpufreq_cooling_register(struct device_node *np, | |||
| 475 | 368 | ||
| 476 | cool_dev = thermal_of_cooling_device_register(np, dev_name, cpufreq_dev, | 369 | cool_dev = thermal_of_cooling_device_register(np, dev_name, cpufreq_dev, |
| 477 | &cpufreq_cooling_ops); | 370 | &cpufreq_cooling_ops); |
| 478 | if (IS_ERR(cool_dev)) { | 371 | if (IS_ERR(cool_dev)) |
| 479 | release_idr(&cpufreq_idr, cpufreq_dev->id); | 372 | goto remove_idr; |
| 480 | kfree(cpufreq_dev); | 373 | |
| 481 | return cool_dev; | 374 | /* Fill freq-table in descending order of frequencies */ |
| 375 | for (i = 0, freq = -1; i <= cpufreq_dev->max_level; i++) { | ||
| 376 | freq = find_next_max(table, freq); | ||
| 377 | cpufreq_dev->freq_table[i] = freq; | ||
| 378 | |||
| 379 | /* Warn for duplicate entries */ | ||
| 380 | if (!freq) | ||
| 381 | pr_warn("%s: table has duplicate entries\n", __func__); | ||
| 382 | else | ||
| 383 | pr_debug("%s: freq:%u KHz\n", __func__, freq); | ||
| 482 | } | 384 | } |
| 385 | |||
| 386 | cpufreq_dev->cpufreq_val = cpufreq_dev->freq_table[0]; | ||
| 483 | cpufreq_dev->cool_dev = cool_dev; | 387 | cpufreq_dev->cool_dev = cool_dev; |
| 484 | cpufreq_dev->cpufreq_state = 0; | 388 | |
| 485 | mutex_lock(&cooling_cpufreq_lock); | 389 | mutex_lock(&cooling_cpufreq_lock); |
| 486 | 390 | ||
| 487 | /* Register the notifier for first cpufreq cooling device */ | 391 | /* Register the notifier for first cpufreq cooling device */ |
| 488 | if (cpufreq_dev_count == 0) | 392 | if (list_empty(&cpufreq_dev_list)) |
| 489 | cpufreq_register_notifier(&thermal_cpufreq_notifier_block, | 393 | cpufreq_register_notifier(&thermal_cpufreq_notifier_block, |
| 490 | CPUFREQ_POLICY_NOTIFIER); | 394 | CPUFREQ_POLICY_NOTIFIER); |
| 491 | cpufreq_dev_count++; | ||
| 492 | list_add(&cpufreq_dev->node, &cpufreq_dev_list); | 395 | list_add(&cpufreq_dev->node, &cpufreq_dev_list); |
| 493 | 396 | ||
| 494 | mutex_unlock(&cooling_cpufreq_lock); | 397 | mutex_unlock(&cooling_cpufreq_lock); |
| 495 | 398 | ||
| 496 | return cool_dev; | 399 | return cool_dev; |
| 400 | |||
| 401 | remove_idr: | ||
| 402 | release_idr(&cpufreq_idr, cpufreq_dev->id); | ||
| 403 | free_table: | ||
| 404 | kfree(cpufreq_dev->freq_table); | ||
| 405 | free_cdev: | ||
| 406 | kfree(cpufreq_dev); | ||
| 407 | |||
| 408 | return cool_dev; | ||
| 497 | } | 409 | } |
| 498 | 410 | ||
| 499 | /** | 411 | /** |
| @@ -554,16 +466,16 @@ void cpufreq_cooling_unregister(struct thermal_cooling_device *cdev) | |||
| 554 | cpufreq_dev = cdev->devdata; | 466 | cpufreq_dev = cdev->devdata; |
| 555 | mutex_lock(&cooling_cpufreq_lock); | 467 | mutex_lock(&cooling_cpufreq_lock); |
| 556 | list_del(&cpufreq_dev->node); | 468 | list_del(&cpufreq_dev->node); |
| 557 | cpufreq_dev_count--; | ||
| 558 | 469 | ||
| 559 | /* Unregister the notifier for the last cpufreq cooling device */ | 470 | /* Unregister the notifier for the last cpufreq cooling device */ |
| 560 | if (cpufreq_dev_count == 0) | 471 | if (list_empty(&cpufreq_dev_list)) |
| 561 | cpufreq_unregister_notifier(&thermal_cpufreq_notifier_block, | 472 | cpufreq_unregister_notifier(&thermal_cpufreq_notifier_block, |
| 562 | CPUFREQ_POLICY_NOTIFIER); | 473 | CPUFREQ_POLICY_NOTIFIER); |
| 563 | mutex_unlock(&cooling_cpufreq_lock); | 474 | mutex_unlock(&cooling_cpufreq_lock); |
| 564 | 475 | ||
| 565 | thermal_cooling_device_unregister(cpufreq_dev->cool_dev); | 476 | thermal_cooling_device_unregister(cpufreq_dev->cool_dev); |
| 566 | release_idr(&cpufreq_idr, cpufreq_dev->id); | 477 | release_idr(&cpufreq_idr, cpufreq_dev->id); |
| 478 | kfree(cpufreq_dev->freq_table); | ||
| 567 | kfree(cpufreq_dev); | 479 | kfree(cpufreq_dev); |
| 568 | } | 480 | } |
| 569 | EXPORT_SYMBOL_GPL(cpufreq_cooling_unregister); | 481 | EXPORT_SYMBOL_GPL(cpufreq_cooling_unregister); |
diff --git a/drivers/thermal/db8500_cpufreq_cooling.c b/drivers/thermal/db8500_cpufreq_cooling.c index 000d53e934a0..607b62c7e611 100644 --- a/drivers/thermal/db8500_cpufreq_cooling.c +++ b/drivers/thermal/db8500_cpufreq_cooling.c | |||
| @@ -18,7 +18,6 @@ | |||
| 18 | */ | 18 | */ |
| 19 | 19 | ||
| 20 | #include <linux/cpu_cooling.h> | 20 | #include <linux/cpu_cooling.h> |
| 21 | #include <linux/cpufreq.h> | ||
| 22 | #include <linux/err.h> | 21 | #include <linux/err.h> |
| 23 | #include <linux/module.h> | 22 | #include <linux/module.h> |
| 24 | #include <linux/of.h> | 23 | #include <linux/of.h> |
| @@ -28,18 +27,17 @@ | |||
| 28 | static int db8500_cpufreq_cooling_probe(struct platform_device *pdev) | 27 | static int db8500_cpufreq_cooling_probe(struct platform_device *pdev) |
| 29 | { | 28 | { |
| 30 | struct thermal_cooling_device *cdev; | 29 | struct thermal_cooling_device *cdev; |
| 31 | struct cpumask mask_val; | ||
| 32 | |||
| 33 | /* make sure cpufreq driver has been initialized */ | ||
| 34 | if (!cpufreq_frequency_get_table(0)) | ||
| 35 | return -EPROBE_DEFER; | ||
| 36 | |||
| 37 | cpumask_set_cpu(0, &mask_val); | ||
| 38 | cdev = cpufreq_cooling_register(&mask_val); | ||
| 39 | 30 | ||
| 31 | cdev = cpufreq_cooling_register(cpu_present_mask); | ||
| 40 | if (IS_ERR(cdev)) { | 32 | if (IS_ERR(cdev)) { |
| 41 | dev_err(&pdev->dev, "Failed to register cooling device\n"); | 33 | int ret = PTR_ERR(cdev); |
| 42 | return PTR_ERR(cdev); | 34 | |
| 35 | if (ret != -EPROBE_DEFER) | ||
| 36 | dev_err(&pdev->dev, | ||
| 37 | "Failed to register cooling device %d\n", | ||
| 38 | ret); | ||
| 39 | |||
| 40 | return ret; | ||
| 43 | } | 41 | } |
| 44 | 42 | ||
| 45 | platform_set_drvdata(pdev, cdev); | 43 | platform_set_drvdata(pdev, cdev); |
diff --git a/drivers/thermal/imx_thermal.c b/drivers/thermal/imx_thermal.c index 88b32f942dcf..c1188ac053c9 100644 --- a/drivers/thermal/imx_thermal.c +++ b/drivers/thermal/imx_thermal.c | |||
| @@ -9,7 +9,6 @@ | |||
| 9 | 9 | ||
| 10 | #include <linux/clk.h> | 10 | #include <linux/clk.h> |
| 11 | #include <linux/cpu_cooling.h> | 11 | #include <linux/cpu_cooling.h> |
| 12 | #include <linux/cpufreq.h> | ||
| 13 | #include <linux/delay.h> | 12 | #include <linux/delay.h> |
| 14 | #include <linux/device.h> | 13 | #include <linux/device.h> |
| 15 | #include <linux/init.h> | 14 | #include <linux/init.h> |
| @@ -454,15 +453,10 @@ static int imx_thermal_probe(struct platform_device *pdev) | |||
| 454 | const struct of_device_id *of_id = | 453 | const struct of_device_id *of_id = |
| 455 | of_match_device(of_imx_thermal_match, &pdev->dev); | 454 | of_match_device(of_imx_thermal_match, &pdev->dev); |
| 456 | struct imx_thermal_data *data; | 455 | struct imx_thermal_data *data; |
| 457 | struct cpumask clip_cpus; | ||
| 458 | struct regmap *map; | 456 | struct regmap *map; |
| 459 | int measure_freq; | 457 | int measure_freq; |
| 460 | int ret; | 458 | int ret; |
| 461 | 459 | ||
| 462 | if (!cpufreq_get_current_driver()) { | ||
| 463 | dev_dbg(&pdev->dev, "no cpufreq driver!"); | ||
| 464 | return -EPROBE_DEFER; | ||
| 465 | } | ||
| 466 | data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL); | 460 | data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL); |
| 467 | if (!data) | 461 | if (!data) |
| 468 | return -ENOMEM; | 462 | return -ENOMEM; |
| @@ -516,12 +510,13 @@ static int imx_thermal_probe(struct platform_device *pdev) | |||
| 516 | regmap_write(map, MISC0 + REG_SET, MISC0_REFTOP_SELBIASOFF); | 510 | regmap_write(map, MISC0 + REG_SET, MISC0_REFTOP_SELBIASOFF); |
| 517 | regmap_write(map, TEMPSENSE0 + REG_SET, TEMPSENSE0_POWER_DOWN); | 511 | regmap_write(map, TEMPSENSE0 + REG_SET, TEMPSENSE0_POWER_DOWN); |
| 518 | 512 | ||
| 519 | cpumask_set_cpu(0, &clip_cpus); | 513 | data->cdev = cpufreq_cooling_register(cpu_present_mask); |
| 520 | data->cdev = cpufreq_cooling_register(&clip_cpus); | ||
| 521 | if (IS_ERR(data->cdev)) { | 514 | if (IS_ERR(data->cdev)) { |
| 522 | ret = PTR_ERR(data->cdev); | 515 | ret = PTR_ERR(data->cdev); |
| 523 | dev_err(&pdev->dev, | 516 | if (ret != -EPROBE_DEFER) |
| 524 | "failed to register cpufreq cooling device: %d\n", ret); | 517 | dev_err(&pdev->dev, |
| 518 | "failed to register cpufreq cooling device: %d\n", | ||
| 519 | ret); | ||
| 525 | return ret; | 520 | return ret; |
| 526 | } | 521 | } |
| 527 | 522 | ||
diff --git a/drivers/thermal/int340x_thermal/Makefile b/drivers/thermal/int340x_thermal/Makefile index ffe40bffaf1a..d4413698a85f 100644 --- a/drivers/thermal/int340x_thermal/Makefile +++ b/drivers/thermal/int340x_thermal/Makefile | |||
| @@ -1,4 +1,5 @@ | |||
| 1 | obj-$(CONFIG_INT340X_THERMAL) += int3400_thermal.o | 1 | obj-$(CONFIG_INT340X_THERMAL) += int3400_thermal.o |
| 2 | obj-$(CONFIG_INT340X_THERMAL) += int3402_thermal.o | 2 | obj-$(CONFIG_INT340X_THERMAL) += int3402_thermal.o |
| 3 | obj-$(CONFIG_INT340X_THERMAL) += int3403_thermal.o | 3 | obj-$(CONFIG_INT340X_THERMAL) += int3403_thermal.o |
| 4 | obj-$(CONFIG_INT340X_THERMAL) += processor_thermal_device.o | ||
| 4 | obj-$(CONFIG_ACPI_THERMAL_REL) += acpi_thermal_rel.o | 5 | obj-$(CONFIG_ACPI_THERMAL_REL) += acpi_thermal_rel.o |
diff --git a/drivers/thermal/int340x_thermal/acpi_thermal_rel.c b/drivers/thermal/int340x_thermal/acpi_thermal_rel.c index e4e61b3fb11e..231cabc16e16 100644 --- a/drivers/thermal/int340x_thermal/acpi_thermal_rel.c +++ b/drivers/thermal/int340x_thermal/acpi_thermal_rel.c | |||
| @@ -82,7 +82,7 @@ int acpi_parse_trt(acpi_handle handle, int *trt_count, struct trt **trtp, | |||
| 82 | struct acpi_buffer trt_format = { sizeof("RRNNNNNN"), "RRNNNNNN" }; | 82 | struct acpi_buffer trt_format = { sizeof("RRNNNNNN"), "RRNNNNNN" }; |
| 83 | 83 | ||
| 84 | if (!acpi_has_method(handle, "_TRT")) | 84 | if (!acpi_has_method(handle, "_TRT")) |
| 85 | return 0; | 85 | return -ENODEV; |
| 86 | 86 | ||
| 87 | status = acpi_evaluate_object(handle, "_TRT", NULL, &buffer); | 87 | status = acpi_evaluate_object(handle, "_TRT", NULL, &buffer); |
| 88 | if (ACPI_FAILURE(status)) | 88 | if (ACPI_FAILURE(status)) |
| @@ -167,7 +167,7 @@ int acpi_parse_art(acpi_handle handle, int *art_count, struct art **artp, | |||
| 167 | sizeof("RRNNNNNNNNNNN"), "RRNNNNNNNNNNN" }; | 167 | sizeof("RRNNNNNNNNNNN"), "RRNNNNNNNNNNN" }; |
| 168 | 168 | ||
| 169 | if (!acpi_has_method(handle, "_ART")) | 169 | if (!acpi_has_method(handle, "_ART")) |
| 170 | return 0; | 170 | return -ENODEV; |
| 171 | 171 | ||
| 172 | status = acpi_evaluate_object(handle, "_ART", NULL, &buffer); | 172 | status = acpi_evaluate_object(handle, "_ART", NULL, &buffer); |
| 173 | if (ACPI_FAILURE(status)) | 173 | if (ACPI_FAILURE(status)) |
| @@ -321,8 +321,8 @@ static long acpi_thermal_rel_ioctl(struct file *f, unsigned int cmd, | |||
| 321 | unsigned long length = 0; | 321 | unsigned long length = 0; |
| 322 | int count = 0; | 322 | int count = 0; |
| 323 | char __user *arg = (void __user *)__arg; | 323 | char __user *arg = (void __user *)__arg; |
| 324 | struct trt *trts; | 324 | struct trt *trts = NULL; |
| 325 | struct art *arts; | 325 | struct art *arts = NULL; |
| 326 | 326 | ||
| 327 | switch (cmd) { | 327 | switch (cmd) { |
| 328 | case ACPI_THERMAL_GET_TRT_COUNT: | 328 | case ACPI_THERMAL_GET_TRT_COUNT: |
diff --git a/drivers/thermal/int340x_thermal/int3400_thermal.c b/drivers/thermal/int340x_thermal/int3400_thermal.c index dcb306ea14a4..65a98a97df07 100644 --- a/drivers/thermal/int340x_thermal/int3400_thermal.c +++ b/drivers/thermal/int340x_thermal/int3400_thermal.c | |||
| @@ -335,7 +335,6 @@ static struct platform_driver int3400_thermal_driver = { | |||
| 335 | .remove = int3400_thermal_remove, | 335 | .remove = int3400_thermal_remove, |
| 336 | .driver = { | 336 | .driver = { |
| 337 | .name = "int3400 thermal", | 337 | .name = "int3400 thermal", |
| 338 | .owner = THIS_MODULE, | ||
| 339 | .acpi_match_table = ACPI_PTR(int3400_thermal_match), | 338 | .acpi_match_table = ACPI_PTR(int3400_thermal_match), |
| 340 | }, | 339 | }, |
| 341 | }; | 340 | }; |
diff --git a/drivers/thermal/int340x_thermal/int3402_thermal.c b/drivers/thermal/int340x_thermal/int3402_thermal.c index a5d08c14ba24..c5cbc3af3a05 100644 --- a/drivers/thermal/int340x_thermal/int3402_thermal.c +++ b/drivers/thermal/int340x_thermal/int3402_thermal.c | |||
| @@ -231,7 +231,6 @@ static struct platform_driver int3402_thermal_driver = { | |||
| 231 | .remove = int3402_thermal_remove, | 231 | .remove = int3402_thermal_remove, |
| 232 | .driver = { | 232 | .driver = { |
| 233 | .name = "int3402 thermal", | 233 | .name = "int3402 thermal", |
| 234 | .owner = THIS_MODULE, | ||
| 235 | .acpi_match_table = int3402_thermal_match, | 234 | .acpi_match_table = int3402_thermal_match, |
| 236 | }, | 235 | }, |
| 237 | }; | 236 | }; |
diff --git a/drivers/thermal/int340x_thermal/int3403_thermal.c b/drivers/thermal/int340x_thermal/int3403_thermal.c index 1bfa6a69e77a..0faf500d8a77 100644 --- a/drivers/thermal/int340x_thermal/int3403_thermal.c +++ b/drivers/thermal/int340x_thermal/int3403_thermal.c | |||
| @@ -301,6 +301,8 @@ static int int3403_sensor_remove(struct int3403_priv *priv) | |||
| 301 | { | 301 | { |
| 302 | struct int3403_sensor *obj = priv->priv; | 302 | struct int3403_sensor *obj = priv->priv; |
| 303 | 303 | ||
| 304 | acpi_remove_notify_handler(priv->adev->handle, | ||
| 305 | ACPI_DEVICE_NOTIFY, int3403_notify); | ||
| 304 | thermal_zone_device_unregister(obj->tzone); | 306 | thermal_zone_device_unregister(obj->tzone); |
| 305 | return 0; | 307 | return 0; |
| 306 | } | 308 | } |
| @@ -369,6 +371,7 @@ static int int3403_cdev_add(struct int3403_priv *priv) | |||
| 369 | p = buf.pointer; | 371 | p = buf.pointer; |
| 370 | if (!p || (p->type != ACPI_TYPE_PACKAGE)) { | 372 | if (!p || (p->type != ACPI_TYPE_PACKAGE)) { |
| 371 | printk(KERN_WARNING "Invalid PPSS data\n"); | 373 | printk(KERN_WARNING "Invalid PPSS data\n"); |
| 374 | kfree(buf.pointer); | ||
| 372 | return -EFAULT; | 375 | return -EFAULT; |
| 373 | } | 376 | } |
| 374 | 377 | ||
| @@ -381,6 +384,7 @@ static int int3403_cdev_add(struct int3403_priv *priv) | |||
| 381 | 384 | ||
| 382 | priv->priv = obj; | 385 | priv->priv = obj; |
| 383 | 386 | ||
| 387 | kfree(buf.pointer); | ||
| 384 | /* TODO: add ACPI notification support */ | 388 | /* TODO: add ACPI notification support */ |
| 385 | 389 | ||
| 386 | return result; | 390 | return result; |
diff --git a/drivers/thermal/int340x_thermal/processor_thermal_device.c b/drivers/thermal/int340x_thermal/processor_thermal_device.c new file mode 100644 index 000000000000..31bb553aac26 --- /dev/null +++ b/drivers/thermal/int340x_thermal/processor_thermal_device.c | |||
| @@ -0,0 +1,309 @@ | |||
| 1 | /* | ||
| 2 | * processor_thermal_device.c | ||
| 3 | * Copyright (c) 2014, Intel Corporation. | ||
| 4 | * | ||
| 5 | * This program is free software; you can redistribute it and/or modify it | ||
| 6 | * under the terms and conditions of the GNU General Public License, | ||
| 7 | * version 2, as published by the Free Software Foundation. | ||
| 8 | * | ||
| 9 | * This program is distributed in the hope it will be useful, but WITHOUT | ||
| 10 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
| 11 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
| 12 | * more details. | ||
| 13 | * | ||
| 14 | */ | ||
| 15 | #include <linux/kernel.h> | ||
| 16 | #include <linux/module.h> | ||
| 17 | #include <linux/init.h> | ||
| 18 | #include <linux/pci.h> | ||
| 19 | #include <linux/platform_device.h> | ||
| 20 | #include <linux/acpi.h> | ||
| 21 | |||
| 22 | /* Broadwell-U/HSB thermal reporting device */ | ||
| 23 | #define PCI_DEVICE_ID_PROC_BDW_THERMAL 0x1603 | ||
| 24 | #define PCI_DEVICE_ID_PROC_HSB_THERMAL 0x0A03 | ||
| 25 | |||
| 26 | /* Braswell thermal reporting device */ | ||
| 27 | #define PCI_DEVICE_ID_PROC_BSW_THERMAL 0x22DC | ||
| 28 | |||
| 29 | struct power_config { | ||
| 30 | u32 index; | ||
| 31 | u32 min_uw; | ||
| 32 | u32 max_uw; | ||
| 33 | u32 tmin_us; | ||
| 34 | u32 tmax_us; | ||
| 35 | u32 step_uw; | ||
| 36 | }; | ||
| 37 | |||
| 38 | struct proc_thermal_device { | ||
| 39 | struct device *dev; | ||
| 40 | struct acpi_device *adev; | ||
| 41 | struct power_config power_limits[2]; | ||
| 42 | }; | ||
| 43 | |||
| 44 | enum proc_thermal_emum_mode_type { | ||
| 45 | PROC_THERMAL_NONE, | ||
| 46 | PROC_THERMAL_PCI, | ||
| 47 | PROC_THERMAL_PLATFORM_DEV | ||
| 48 | }; | ||
| 49 | |||
| 50 | /* | ||
| 51 | * We can have only one type of enumeration, PCI or Platform, | ||
| 52 | * not both. So we don't need instance specific data. | ||
| 53 | */ | ||
| 54 | static enum proc_thermal_emum_mode_type proc_thermal_emum_mode = | ||
| 55 | PROC_THERMAL_NONE; | ||
| 56 | |||
| 57 | #define POWER_LIMIT_SHOW(index, suffix) \ | ||
| 58 | static ssize_t power_limit_##index##_##suffix##_show(struct device *dev, \ | ||
| 59 | struct device_attribute *attr, \ | ||
| 60 | char *buf) \ | ||
| 61 | { \ | ||
| 62 | struct pci_dev *pci_dev; \ | ||
| 63 | struct platform_device *pdev; \ | ||
| 64 | struct proc_thermal_device *proc_dev; \ | ||
| 65 | \ | ||
| 66 | if (proc_thermal_emum_mode == PROC_THERMAL_PLATFORM_DEV) { \ | ||
| 67 | pdev = to_platform_device(dev); \ | ||
| 68 | proc_dev = platform_get_drvdata(pdev); \ | ||
| 69 | } else { \ | ||
| 70 | pci_dev = to_pci_dev(dev); \ | ||
| 71 | proc_dev = pci_get_drvdata(pci_dev); \ | ||
| 72 | } \ | ||
| 73 | return sprintf(buf, "%lu\n",\ | ||
| 74 | (unsigned long)proc_dev->power_limits[index].suffix * 1000); \ | ||
| 75 | } | ||
| 76 | |||
| 77 | POWER_LIMIT_SHOW(0, min_uw) | ||
| 78 | POWER_LIMIT_SHOW(0, max_uw) | ||
| 79 | POWER_LIMIT_SHOW(0, step_uw) | ||
| 80 | POWER_LIMIT_SHOW(0, tmin_us) | ||
| 81 | POWER_LIMIT_SHOW(0, tmax_us) | ||
| 82 | |||
| 83 | POWER_LIMIT_SHOW(1, min_uw) | ||
| 84 | POWER_LIMIT_SHOW(1, max_uw) | ||
| 85 | POWER_LIMIT_SHOW(1, step_uw) | ||
| 86 | POWER_LIMIT_SHOW(1, tmin_us) | ||
| 87 | POWER_LIMIT_SHOW(1, tmax_us) | ||
| 88 | |||
| 89 | static DEVICE_ATTR_RO(power_limit_0_min_uw); | ||
| 90 | static DEVICE_ATTR_RO(power_limit_0_max_uw); | ||
| 91 | static DEVICE_ATTR_RO(power_limit_0_step_uw); | ||
| 92 | static DEVICE_ATTR_RO(power_limit_0_tmin_us); | ||
| 93 | static DEVICE_ATTR_RO(power_limit_0_tmax_us); | ||
| 94 | |||
| 95 | static DEVICE_ATTR_RO(power_limit_1_min_uw); | ||
| 96 | static DEVICE_ATTR_RO(power_limit_1_max_uw); | ||
| 97 | static DEVICE_ATTR_RO(power_limit_1_step_uw); | ||
| 98 | static DEVICE_ATTR_RO(power_limit_1_tmin_us); | ||
| 99 | static DEVICE_ATTR_RO(power_limit_1_tmax_us); | ||
| 100 | |||
| 101 | static struct attribute *power_limit_attrs[] = { | ||
| 102 | &dev_attr_power_limit_0_min_uw.attr, | ||
| 103 | &dev_attr_power_limit_1_min_uw.attr, | ||
| 104 | &dev_attr_power_limit_0_max_uw.attr, | ||
| 105 | &dev_attr_power_limit_1_max_uw.attr, | ||
| 106 | &dev_attr_power_limit_0_step_uw.attr, | ||
| 107 | &dev_attr_power_limit_1_step_uw.attr, | ||
| 108 | &dev_attr_power_limit_0_tmin_us.attr, | ||
| 109 | &dev_attr_power_limit_1_tmin_us.attr, | ||
| 110 | &dev_attr_power_limit_0_tmax_us.attr, | ||
| 111 | &dev_attr_power_limit_1_tmax_us.attr, | ||
| 112 | NULL | ||
| 113 | }; | ||
| 114 | |||
| 115 | static struct attribute_group power_limit_attribute_group = { | ||
| 116 | .attrs = power_limit_attrs, | ||
| 117 | .name = "power_limits" | ||
| 118 | }; | ||
| 119 | |||
| 120 | static int proc_thermal_add(struct device *dev, | ||
| 121 | struct proc_thermal_device **priv) | ||
| 122 | { | ||
| 123 | struct proc_thermal_device *proc_priv; | ||
| 124 | struct acpi_device *adev; | ||
| 125 | acpi_status status; | ||
| 126 | struct acpi_buffer buf = { ACPI_ALLOCATE_BUFFER, NULL }; | ||
| 127 | union acpi_object *elements, *ppcc; | ||
| 128 | union acpi_object *p; | ||
| 129 | int i; | ||
| 130 | int ret; | ||
| 131 | |||
| 132 | adev = ACPI_COMPANION(dev); | ||
| 133 | |||
| 134 | status = acpi_evaluate_object(adev->handle, "PPCC", NULL, &buf); | ||
| 135 | if (ACPI_FAILURE(status)) | ||
| 136 | return -ENODEV; | ||
| 137 | |||
| 138 | p = buf.pointer; | ||
| 139 | if (!p || (p->type != ACPI_TYPE_PACKAGE)) { | ||
| 140 | dev_err(dev, "Invalid PPCC data\n"); | ||
| 141 | ret = -EFAULT; | ||
| 142 | goto free_buffer; | ||
| 143 | } | ||
| 144 | if (!p->package.count) { | ||
| 145 | dev_err(dev, "Invalid PPCC package size\n"); | ||
| 146 | ret = -EFAULT; | ||
| 147 | goto free_buffer; | ||
| 148 | } | ||
| 149 | |||
| 150 | proc_priv = devm_kzalloc(dev, sizeof(*proc_priv), GFP_KERNEL); | ||
| 151 | if (!proc_priv) { | ||
| 152 | ret = -ENOMEM; | ||
| 153 | goto free_buffer; | ||
| 154 | } | ||
| 155 | |||
| 156 | proc_priv->dev = dev; | ||
| 157 | proc_priv->adev = adev; | ||
| 158 | |||
| 159 | for (i = 0; i < min((int)p->package.count - 1, 2); ++i) { | ||
| 160 | elements = &(p->package.elements[i+1]); | ||
| 161 | if (elements->type != ACPI_TYPE_PACKAGE || | ||
| 162 | elements->package.count != 6) { | ||
| 163 | ret = -EFAULT; | ||
| 164 | goto free_buffer; | ||
| 165 | } | ||
| 166 | ppcc = elements->package.elements; | ||
| 167 | proc_priv->power_limits[i].index = ppcc[0].integer.value; | ||
| 168 | proc_priv->power_limits[i].min_uw = ppcc[1].integer.value; | ||
| 169 | proc_priv->power_limits[i].max_uw = ppcc[2].integer.value; | ||
| 170 | proc_priv->power_limits[i].tmin_us = ppcc[3].integer.value; | ||
| 171 | proc_priv->power_limits[i].tmax_us = ppcc[4].integer.value; | ||
| 172 | proc_priv->power_limits[i].step_uw = ppcc[5].integer.value; | ||
| 173 | } | ||
| 174 | |||
| 175 | *priv = proc_priv; | ||
| 176 | |||
| 177 | ret = sysfs_create_group(&dev->kobj, | ||
| 178 | &power_limit_attribute_group); | ||
| 179 | |||
| 180 | free_buffer: | ||
| 181 | kfree(buf.pointer); | ||
| 182 | |||
| 183 | return ret; | ||
| 184 | } | ||
| 185 | |||
| 186 | void proc_thermal_remove(struct proc_thermal_device *proc_priv) | ||
| 187 | { | ||
| 188 | sysfs_remove_group(&proc_priv->dev->kobj, | ||
| 189 | &power_limit_attribute_group); | ||
| 190 | } | ||
| 191 | |||
| 192 | static int int3401_add(struct platform_device *pdev) | ||
| 193 | { | ||
| 194 | struct proc_thermal_device *proc_priv; | ||
| 195 | int ret; | ||
| 196 | |||
| 197 | if (proc_thermal_emum_mode == PROC_THERMAL_PCI) { | ||
| 198 | dev_err(&pdev->dev, "error: enumerated as PCI dev\n"); | ||
| 199 | return -ENODEV; | ||
| 200 | } | ||
| 201 | |||
| 202 | ret = proc_thermal_add(&pdev->dev, &proc_priv); | ||
| 203 | if (ret) | ||
| 204 | return ret; | ||
| 205 | |||
| 206 | platform_set_drvdata(pdev, proc_priv); | ||
| 207 | proc_thermal_emum_mode = PROC_THERMAL_PLATFORM_DEV; | ||
| 208 | |||
| 209 | return 0; | ||
| 210 | } | ||
| 211 | |||
| 212 | static int int3401_remove(struct platform_device *pdev) | ||
| 213 | { | ||
| 214 | proc_thermal_remove(platform_get_drvdata(pdev)); | ||
| 215 | |||
| 216 | return 0; | ||
| 217 | } | ||
| 218 | |||
| 219 | static int proc_thermal_pci_probe(struct pci_dev *pdev, | ||
| 220 | const struct pci_device_id *unused) | ||
| 221 | { | ||
| 222 | struct proc_thermal_device *proc_priv; | ||
| 223 | int ret; | ||
| 224 | |||
| 225 | if (proc_thermal_emum_mode == PROC_THERMAL_PLATFORM_DEV) { | ||
| 226 | dev_err(&pdev->dev, "error: enumerated as platform dev\n"); | ||
| 227 | return -ENODEV; | ||
| 228 | } | ||
| 229 | |||
| 230 | ret = pci_enable_device(pdev); | ||
| 231 | if (ret < 0) { | ||
| 232 | dev_err(&pdev->dev, "error: could not enable device\n"); | ||
| 233 | return ret; | ||
| 234 | } | ||
| 235 | |||
| 236 | ret = proc_thermal_add(&pdev->dev, &proc_priv); | ||
| 237 | if (ret) { | ||
| 238 | pci_disable_device(pdev); | ||
| 239 | return ret; | ||
| 240 | } | ||
| 241 | |||
| 242 | pci_set_drvdata(pdev, proc_priv); | ||
| 243 | proc_thermal_emum_mode = PROC_THERMAL_PCI; | ||
| 244 | |||
| 245 | return 0; | ||
| 246 | } | ||
| 247 | |||
| 248 | static void proc_thermal_pci_remove(struct pci_dev *pdev) | ||
| 249 | { | ||
| 250 | proc_thermal_remove(pci_get_drvdata(pdev)); | ||
| 251 | pci_disable_device(pdev); | ||
| 252 | } | ||
| 253 | |||
| 254 | static const struct pci_device_id proc_thermal_pci_ids[] = { | ||
| 255 | { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_PROC_BDW_THERMAL)}, | ||
| 256 | { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_PROC_HSB_THERMAL)}, | ||
| 257 | { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_PROC_BSW_THERMAL)}, | ||
| 258 | { 0, }, | ||
| 259 | }; | ||
| 260 | |||
| 261 | MODULE_DEVICE_TABLE(pci, proc_thermal_pci_ids); | ||
| 262 | |||
| 263 | static struct pci_driver proc_thermal_pci_driver = { | ||
| 264 | .name = "proc_thermal", | ||
| 265 | .probe = proc_thermal_pci_probe, | ||
| 266 | .remove = proc_thermal_pci_remove, | ||
| 267 | .id_table = proc_thermal_pci_ids, | ||
| 268 | }; | ||
| 269 | |||
| 270 | static const struct acpi_device_id int3401_device_ids[] = { | ||
| 271 | {"INT3401", 0}, | ||
| 272 | {"", 0}, | ||
| 273 | }; | ||
| 274 | MODULE_DEVICE_TABLE(acpi, int3401_device_ids); | ||
| 275 | |||
| 276 | static struct platform_driver int3401_driver = { | ||
| 277 | .probe = int3401_add, | ||
| 278 | .remove = int3401_remove, | ||
| 279 | .driver = { | ||
| 280 | .name = "int3401 thermal", | ||
| 281 | .acpi_match_table = int3401_device_ids, | ||
| 282 | }, | ||
| 283 | }; | ||
| 284 | |||
| 285 | static int __init proc_thermal_init(void) | ||
| 286 | { | ||
| 287 | int ret; | ||
| 288 | |||
| 289 | ret = platform_driver_register(&int3401_driver); | ||
| 290 | if (ret) | ||
| 291 | return ret; | ||
| 292 | |||
| 293 | ret = pci_register_driver(&proc_thermal_pci_driver); | ||
| 294 | |||
| 295 | return ret; | ||
| 296 | } | ||
| 297 | |||
| 298 | static void __exit proc_thermal_exit(void) | ||
| 299 | { | ||
| 300 | platform_driver_unregister(&int3401_driver); | ||
| 301 | pci_unregister_driver(&proc_thermal_pci_driver); | ||
| 302 | } | ||
| 303 | |||
| 304 | module_init(proc_thermal_init); | ||
| 305 | module_exit(proc_thermal_exit); | ||
| 306 | |||
| 307 | MODULE_AUTHOR("Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com>"); | ||
| 308 | MODULE_DESCRIPTION("Processor Thermal Reporting Device Driver"); | ||
| 309 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/thermal/intel_powerclamp.c b/drivers/thermal/intel_powerclamp.c index e98b4249187c..6ceebd659dd4 100644 --- a/drivers/thermal/intel_powerclamp.c +++ b/drivers/thermal/intel_powerclamp.c | |||
| @@ -688,6 +688,7 @@ static const struct x86_cpu_id intel_powerclamp_ids[] = { | |||
| 688 | { X86_VENDOR_INTEL, 6, 0x45}, | 688 | { X86_VENDOR_INTEL, 6, 0x45}, |
| 689 | { X86_VENDOR_INTEL, 6, 0x46}, | 689 | { X86_VENDOR_INTEL, 6, 0x46}, |
| 690 | { X86_VENDOR_INTEL, 6, 0x4c}, | 690 | { X86_VENDOR_INTEL, 6, 0x4c}, |
| 691 | { X86_VENDOR_INTEL, 6, 0x56}, | ||
| 691 | {} | 692 | {} |
| 692 | }; | 693 | }; |
| 693 | MODULE_DEVICE_TABLE(x86cpu, intel_powerclamp_ids); | 694 | MODULE_DEVICE_TABLE(x86cpu, intel_powerclamp_ids); |
diff --git a/drivers/thermal/rockchip_thermal.c b/drivers/thermal/rockchip_thermal.c index 1bcddfc60e91..9c6ce548e363 100644 --- a/drivers/thermal/rockchip_thermal.c +++ b/drivers/thermal/rockchip_thermal.c | |||
| @@ -677,7 +677,6 @@ static SIMPLE_DEV_PM_OPS(rockchip_thermal_pm_ops, | |||
| 677 | static struct platform_driver rockchip_thermal_driver = { | 677 | static struct platform_driver rockchip_thermal_driver = { |
| 678 | .driver = { | 678 | .driver = { |
| 679 | .name = "rockchip-thermal", | 679 | .name = "rockchip-thermal", |
| 680 | .owner = THIS_MODULE, | ||
| 681 | .pm = &rockchip_thermal_pm_ops, | 680 | .pm = &rockchip_thermal_pm_ops, |
| 682 | .of_match_table = of_rockchip_thermal_match, | 681 | .of_match_table = of_rockchip_thermal_match, |
| 683 | }, | 682 | }, |
diff --git a/drivers/thermal/samsung/Kconfig b/drivers/thermal/samsung/Kconfig index f760389a204c..c43306ecc0ab 100644 --- a/drivers/thermal/samsung/Kconfig +++ b/drivers/thermal/samsung/Kconfig | |||
| @@ -1,6 +1,6 @@ | |||
| 1 | config EXYNOS_THERMAL | 1 | config EXYNOS_THERMAL |
| 2 | tristate "Exynos thermal management unit driver" | 2 | tristate "Exynos thermal management unit driver" |
| 3 | depends on ARCH_HAS_BANDGAP && OF | 3 | depends on OF |
| 4 | help | 4 | help |
| 5 | If you say yes here you get support for the TMU (Thermal Management | 5 | If you say yes here you get support for the TMU (Thermal Management |
| 6 | Unit) driver for SAMSUNG EXYNOS series of SoCs. This driver initialises | 6 | Unit) driver for SAMSUNG EXYNOS series of SoCs. This driver initialises |
diff --git a/drivers/thermal/samsung/exynos_thermal_common.c b/drivers/thermal/samsung/exynos_thermal_common.c index b6be572704a4..6dc3815cc73f 100644 --- a/drivers/thermal/samsung/exynos_thermal_common.c +++ b/drivers/thermal/samsung/exynos_thermal_common.c | |||
| @@ -347,7 +347,6 @@ void exynos_report_trigger(struct thermal_sensor_conf *conf) | |||
| 347 | int exynos_register_thermal(struct thermal_sensor_conf *sensor_conf) | 347 | int exynos_register_thermal(struct thermal_sensor_conf *sensor_conf) |
| 348 | { | 348 | { |
| 349 | int ret; | 349 | int ret; |
| 350 | struct cpumask mask_val; | ||
| 351 | struct exynos_thermal_zone *th_zone; | 350 | struct exynos_thermal_zone *th_zone; |
| 352 | 351 | ||
| 353 | if (!sensor_conf || !sensor_conf->read_temperature) { | 352 | if (!sensor_conf || !sensor_conf->read_temperature) { |
| @@ -367,13 +366,14 @@ int exynos_register_thermal(struct thermal_sensor_conf *sensor_conf) | |||
| 367 | * sensor | 366 | * sensor |
| 368 | */ | 367 | */ |
| 369 | if (sensor_conf->cooling_data.freq_clip_count > 0) { | 368 | if (sensor_conf->cooling_data.freq_clip_count > 0) { |
| 370 | cpumask_set_cpu(0, &mask_val); | ||
| 371 | th_zone->cool_dev[th_zone->cool_dev_size] = | 369 | th_zone->cool_dev[th_zone->cool_dev_size] = |
| 372 | cpufreq_cooling_register(&mask_val); | 370 | cpufreq_cooling_register(cpu_present_mask); |
| 373 | if (IS_ERR(th_zone->cool_dev[th_zone->cool_dev_size])) { | 371 | if (IS_ERR(th_zone->cool_dev[th_zone->cool_dev_size])) { |
| 374 | dev_err(sensor_conf->dev, | 372 | ret = PTR_ERR(th_zone->cool_dev[th_zone->cool_dev_size]); |
| 375 | "Failed to register cpufreq cooling device\n"); | 373 | if (ret != -EPROBE_DEFER) |
| 376 | ret = -EINVAL; | 374 | dev_err(sensor_conf->dev, |
| 375 | "Failed to register cpufreq cooling device: %d\n", | ||
| 376 | ret); | ||
| 377 | goto err_unregister; | 377 | goto err_unregister; |
| 378 | } | 378 | } |
| 379 | th_zone->cool_dev_size++; | 379 | th_zone->cool_dev_size++; |
diff --git a/drivers/thermal/samsung/exynos_tmu.c b/drivers/thermal/samsung/exynos_tmu.c index d44d91d681d4..d2f1e62a4232 100644 --- a/drivers/thermal/samsung/exynos_tmu.c +++ b/drivers/thermal/samsung/exynos_tmu.c | |||
| @@ -927,7 +927,10 @@ static int exynos_tmu_probe(struct platform_device *pdev) | |||
| 927 | /* Register the sensor with thermal management interface */ | 927 | /* Register the sensor with thermal management interface */ |
| 928 | ret = exynos_register_thermal(sensor_conf); | 928 | ret = exynos_register_thermal(sensor_conf); |
| 929 | if (ret) { | 929 | if (ret) { |
| 930 | dev_err(&pdev->dev, "Failed to register thermal interface\n"); | 930 | if (ret != -EPROBE_DEFER) |
| 931 | dev_err(&pdev->dev, | ||
| 932 | "Failed to register thermal interface: %d\n", | ||
| 933 | ret); | ||
| 931 | goto err_clk; | 934 | goto err_clk; |
| 932 | } | 935 | } |
| 933 | data->reg_conf = sensor_conf; | 936 | data->reg_conf = sensor_conf; |
diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c index 84fdf0792e27..87e0b0782023 100644 --- a/drivers/thermal/thermal_core.c +++ b/drivers/thermal/thermal_core.c | |||
| @@ -930,7 +930,7 @@ int thermal_zone_bind_cooling_device(struct thermal_zone_device *tz, | |||
| 930 | struct thermal_zone_device *pos1; | 930 | struct thermal_zone_device *pos1; |
| 931 | struct thermal_cooling_device *pos2; | 931 | struct thermal_cooling_device *pos2; |
| 932 | unsigned long max_state; | 932 | unsigned long max_state; |
| 933 | int result; | 933 | int result, ret; |
| 934 | 934 | ||
| 935 | if (trip >= tz->trips || (trip < 0 && trip != THERMAL_TRIPS_NONE)) | 935 | if (trip >= tz->trips || (trip < 0 && trip != THERMAL_TRIPS_NONE)) |
| 936 | return -EINVAL; | 936 | return -EINVAL; |
| @@ -947,7 +947,9 @@ int thermal_zone_bind_cooling_device(struct thermal_zone_device *tz, | |||
| 947 | if (tz != pos1 || cdev != pos2) | 947 | if (tz != pos1 || cdev != pos2) |
| 948 | return -EINVAL; | 948 | return -EINVAL; |
| 949 | 949 | ||
| 950 | cdev->ops->get_max_state(cdev, &max_state); | 950 | ret = cdev->ops->get_max_state(cdev, &max_state); |
| 951 | if (ret) | ||
| 952 | return ret; | ||
| 951 | 953 | ||
| 952 | /* lower default 0, upper default max_state */ | 954 | /* lower default 0, upper default max_state */ |
| 953 | lower = lower == THERMAL_NO_LIMIT ? 0 : lower; | 955 | lower = lower == THERMAL_NO_LIMIT ? 0 : lower; |
diff --git a/drivers/thermal/ti-soc-thermal/ti-thermal-common.c b/drivers/thermal/ti-soc-thermal/ti-thermal-common.c index 5fd03865e396..3fb054a10f6a 100644 --- a/drivers/thermal/ti-soc-thermal/ti-thermal-common.c +++ b/drivers/thermal/ti-soc-thermal/ti-thermal-common.c | |||
| @@ -28,7 +28,6 @@ | |||
| 28 | #include <linux/kernel.h> | 28 | #include <linux/kernel.h> |
| 29 | #include <linux/workqueue.h> | 29 | #include <linux/workqueue.h> |
| 30 | #include <linux/thermal.h> | 30 | #include <linux/thermal.h> |
| 31 | #include <linux/cpufreq.h> | ||
| 32 | #include <linux/cpumask.h> | 31 | #include <linux/cpumask.h> |
| 33 | #include <linux/cpu_cooling.h> | 32 | #include <linux/cpu_cooling.h> |
| 34 | #include <linux/of.h> | 33 | #include <linux/of.h> |
| @@ -407,17 +406,17 @@ int ti_thermal_register_cpu_cooling(struct ti_bandgap *bgp, int id) | |||
| 407 | if (!data) | 406 | if (!data) |
| 408 | return -EINVAL; | 407 | return -EINVAL; |
| 409 | 408 | ||
| 410 | if (!cpufreq_get_current_driver()) { | ||
| 411 | dev_dbg(bgp->dev, "no cpufreq driver yet\n"); | ||
| 412 | return -EPROBE_DEFER; | ||
| 413 | } | ||
| 414 | |||
| 415 | /* Register cooling device */ | 409 | /* Register cooling device */ |
| 416 | data->cool_dev = cpufreq_cooling_register(cpu_present_mask); | 410 | data->cool_dev = cpufreq_cooling_register(cpu_present_mask); |
| 417 | if (IS_ERR(data->cool_dev)) { | 411 | if (IS_ERR(data->cool_dev)) { |
| 418 | dev_err(bgp->dev, | 412 | int ret = PTR_ERR(data->cool_dev); |
| 419 | "Failed to register cpufreq cooling device\n"); | 413 | |
| 420 | return PTR_ERR(data->cool_dev); | 414 | if (ret != -EPROBE_DEFER) |
| 415 | dev_err(bgp->dev, | ||
| 416 | "Failed to register cpu cooling device %d\n", | ||
| 417 | ret); | ||
| 418 | |||
| 419 | return ret; | ||
| 421 | } | 420 | } |
| 422 | ti_bandgap_set_sensor_data(bgp, id, data); | 421 | ti_bandgap_set_sensor_data(bgp, id, data); |
| 423 | 422 | ||
diff --git a/drivers/vhost/vhost.c b/drivers/vhost/vhost.c index ed71b5347a76..cb807d0ea498 100644 --- a/drivers/vhost/vhost.c +++ b/drivers/vhost/vhost.c | |||
| @@ -713,9 +713,13 @@ long vhost_vring_ioctl(struct vhost_dev *d, int ioctl, void __user *argp) | |||
| 713 | r = -EFAULT; | 713 | r = -EFAULT; |
| 714 | break; | 714 | break; |
| 715 | } | 715 | } |
| 716 | if ((a.avail_user_addr & (sizeof *vq->avail->ring - 1)) || | 716 | |
| 717 | (a.used_user_addr & (sizeof *vq->used->ring - 1)) || | 717 | /* Make sure it's safe to cast pointers to vring types. */ |
| 718 | (a.log_guest_addr & (sizeof *vq->used->ring - 1))) { | 718 | BUILD_BUG_ON(__alignof__ *vq->avail > VRING_AVAIL_ALIGN_SIZE); |
| 719 | BUILD_BUG_ON(__alignof__ *vq->used > VRING_USED_ALIGN_SIZE); | ||
| 720 | if ((a.avail_user_addr & (VRING_AVAIL_ALIGN_SIZE - 1)) || | ||
| 721 | (a.used_user_addr & (VRING_USED_ALIGN_SIZE - 1)) || | ||
| 722 | (a.log_guest_addr & (sizeof(u64) - 1))) { | ||
| 719 | r = -EINVAL; | 723 | r = -EINVAL; |
| 720 | break; | 724 | break; |
| 721 | } | 725 | } |
diff --git a/drivers/video/fbdev/core/fb_defio.c b/drivers/video/fbdev/core/fb_defio.c index 900aa4ecd617..d6cab1fd9a47 100644 --- a/drivers/video/fbdev/core/fb_defio.c +++ b/drivers/video/fbdev/core/fb_defio.c | |||
| @@ -83,9 +83,10 @@ int fb_deferred_io_fsync(struct file *file, loff_t start, loff_t end, int datasy | |||
| 83 | cancel_delayed_work_sync(&info->deferred_work); | 83 | cancel_delayed_work_sync(&info->deferred_work); |
| 84 | 84 | ||
| 85 | /* Run it immediately */ | 85 | /* Run it immediately */ |
| 86 | err = schedule_delayed_work(&info->deferred_work, 0); | 86 | schedule_delayed_work(&info->deferred_work, 0); |
| 87 | mutex_unlock(&inode->i_mutex); | 87 | mutex_unlock(&inode->i_mutex); |
| 88 | return err; | 88 | |
| 89 | return 0; | ||
| 89 | } | 90 | } |
| 90 | EXPORT_SYMBOL_GPL(fb_deferred_io_fsync); | 91 | EXPORT_SYMBOL_GPL(fb_deferred_io_fsync); |
| 91 | 92 | ||
diff --git a/drivers/video/fbdev/omap2/dss/hdmi_pll.c b/drivers/video/fbdev/omap2/dss/hdmi_pll.c index 87accdb59c81..ac83ef5cfd7d 100644 --- a/drivers/video/fbdev/omap2/dss/hdmi_pll.c +++ b/drivers/video/fbdev/omap2/dss/hdmi_pll.c | |||
| @@ -132,7 +132,6 @@ static const struct dss_pll_hw dss_omap4_hdmi_pll_hw = { | |||
| 132 | .mX_max = 127, | 132 | .mX_max = 127, |
| 133 | .fint_min = 500000, | 133 | .fint_min = 500000, |
| 134 | .fint_max = 2500000, | 134 | .fint_max = 2500000, |
| 135 | .clkdco_max = 1800000000, | ||
| 136 | 135 | ||
| 137 | .clkdco_min = 500000000, | 136 | .clkdco_min = 500000000, |
| 138 | .clkdco_low = 1000000000, | 137 | .clkdco_low = 1000000000, |
| @@ -156,7 +155,6 @@ static const struct dss_pll_hw dss_omap5_hdmi_pll_hw = { | |||
| 156 | .mX_max = 127, | 155 | .mX_max = 127, |
| 157 | .fint_min = 620000, | 156 | .fint_min = 620000, |
| 158 | .fint_max = 2500000, | 157 | .fint_max = 2500000, |
| 159 | .clkdco_max = 1800000000, | ||
| 160 | 158 | ||
| 161 | .clkdco_min = 750000000, | 159 | .clkdco_min = 750000000, |
| 162 | .clkdco_low = 1500000000, | 160 | .clkdco_low = 1500000000, |
diff --git a/drivers/video/fbdev/omap2/dss/pll.c b/drivers/video/fbdev/omap2/dss/pll.c index 50bc62c5d367..335ffac224b9 100644 --- a/drivers/video/fbdev/omap2/dss/pll.c +++ b/drivers/video/fbdev/omap2/dss/pll.c | |||
| @@ -97,7 +97,8 @@ int dss_pll_enable(struct dss_pll *pll) | |||
| 97 | return 0; | 97 | return 0; |
| 98 | 98 | ||
| 99 | err_enable: | 99 | err_enable: |
| 100 | regulator_disable(pll->regulator); | 100 | if (pll->regulator) |
| 101 | regulator_disable(pll->regulator); | ||
| 101 | err_reg: | 102 | err_reg: |
| 102 | clk_disable_unprepare(pll->clkin); | 103 | clk_disable_unprepare(pll->clkin); |
| 103 | return r; | 104 | return r; |
diff --git a/drivers/video/fbdev/omap2/dss/sdi.c b/drivers/video/fbdev/omap2/dss/sdi.c index d51a983075bc..5c2ccab5a958 100644 --- a/drivers/video/fbdev/omap2/dss/sdi.c +++ b/drivers/video/fbdev/omap2/dss/sdi.c | |||
| @@ -342,6 +342,8 @@ static void sdi_init_output(struct platform_device *pdev) | |||
| 342 | out->output_type = OMAP_DISPLAY_TYPE_SDI; | 342 | out->output_type = OMAP_DISPLAY_TYPE_SDI; |
| 343 | out->name = "sdi.0"; | 343 | out->name = "sdi.0"; |
| 344 | out->dispc_channel = OMAP_DSS_CHANNEL_LCD; | 344 | out->dispc_channel = OMAP_DSS_CHANNEL_LCD; |
| 345 | /* We have SDI only on OMAP3, where it's on port 1 */ | ||
| 346 | out->port_num = 1; | ||
| 345 | out->ops.sdi = &sdi_ops; | 347 | out->ops.sdi = &sdi_ops; |
| 346 | out->owner = THIS_MODULE; | 348 | out->owner = THIS_MODULE; |
| 347 | 349 | ||
diff --git a/drivers/video/logo/logo.c b/drivers/video/logo/logo.c index 940cd196eef5..10fbfd8ab963 100644 --- a/drivers/video/logo/logo.c +++ b/drivers/video/logo/logo.c | |||
| @@ -21,6 +21,21 @@ static bool nologo; | |||
| 21 | module_param(nologo, bool, 0); | 21 | module_param(nologo, bool, 0); |
| 22 | MODULE_PARM_DESC(nologo, "Disables startup logo"); | 22 | MODULE_PARM_DESC(nologo, "Disables startup logo"); |
| 23 | 23 | ||
| 24 | /* | ||
| 25 | * Logos are located in the initdata, and will be freed in kernel_init. | ||
| 26 | * Use late_init to mark the logos as freed to prevent any further use. | ||
| 27 | */ | ||
| 28 | |||
| 29 | static bool logos_freed; | ||
| 30 | |||
| 31 | static int __init fb_logo_late_init(void) | ||
| 32 | { | ||
| 33 | logos_freed = true; | ||
| 34 | return 0; | ||
| 35 | } | ||
| 36 | |||
| 37 | late_initcall(fb_logo_late_init); | ||
| 38 | |||
| 24 | /* logo's are marked __initdata. Use __init_refok to tell | 39 | /* logo's are marked __initdata. Use __init_refok to tell |
| 25 | * modpost that it is intended that this function uses data | 40 | * modpost that it is intended that this function uses data |
| 26 | * marked __initdata. | 41 | * marked __initdata. |
| @@ -29,7 +44,7 @@ const struct linux_logo * __init_refok fb_find_logo(int depth) | |||
| 29 | { | 44 | { |
| 30 | const struct linux_logo *logo = NULL; | 45 | const struct linux_logo *logo = NULL; |
| 31 | 46 | ||
| 32 | if (nologo) | 47 | if (nologo || logos_freed) |
| 33 | return NULL; | 48 | return NULL; |
| 34 | 49 | ||
| 35 | if (depth >= 1) { | 50 | if (depth >= 1) { |
diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h index 6e139111fdb2..22b289a3b1c4 100644 --- a/fs/cifs/cifsglob.h +++ b/fs/cifs/cifsglob.h | |||
| @@ -661,16 +661,16 @@ set_credits(struct TCP_Server_Info *server, const int val) | |||
| 661 | server->ops->set_credits(server, val); | 661 | server->ops->set_credits(server, val); |
| 662 | } | 662 | } |
| 663 | 663 | ||
| 664 | static inline __u64 | 664 | static inline __le64 |
| 665 | get_next_mid64(struct TCP_Server_Info *server) | 665 | get_next_mid64(struct TCP_Server_Info *server) |
| 666 | { | 666 | { |
| 667 | return server->ops->get_next_mid(server); | 667 | return cpu_to_le64(server->ops->get_next_mid(server)); |
| 668 | } | 668 | } |
| 669 | 669 | ||
| 670 | static inline __le16 | 670 | static inline __le16 |
| 671 | get_next_mid(struct TCP_Server_Info *server) | 671 | get_next_mid(struct TCP_Server_Info *server) |
| 672 | { | 672 | { |
| 673 | __u16 mid = get_next_mid64(server); | 673 | __u16 mid = server->ops->get_next_mid(server); |
| 674 | /* | 674 | /* |
| 675 | * The value in the SMB header should be little endian for easy | 675 | * The value in the SMB header should be little endian for easy |
| 676 | * on-the-wire decoding. | 676 | * on-the-wire decoding. |
diff --git a/fs/cifs/netmisc.c b/fs/cifs/netmisc.c index b333ff60781d..abae6dd2c6b9 100644 --- a/fs/cifs/netmisc.c +++ b/fs/cifs/netmisc.c | |||
| @@ -926,6 +926,7 @@ cifs_NTtimeToUnix(__le64 ntutc) | |||
| 926 | 926 | ||
| 927 | /* Subtract the NTFS time offset, then convert to 1s intervals. */ | 927 | /* Subtract the NTFS time offset, then convert to 1s intervals. */ |
| 928 | s64 t = le64_to_cpu(ntutc) - NTFS_TIME_OFFSET; | 928 | s64 t = le64_to_cpu(ntutc) - NTFS_TIME_OFFSET; |
| 929 | u64 abs_t; | ||
| 929 | 930 | ||
| 930 | /* | 931 | /* |
| 931 | * Unfortunately can not use normal 64 bit division on 32 bit arch, but | 932 | * Unfortunately can not use normal 64 bit division on 32 bit arch, but |
| @@ -933,13 +934,14 @@ cifs_NTtimeToUnix(__le64 ntutc) | |||
| 933 | * to special case them | 934 | * to special case them |
| 934 | */ | 935 | */ |
| 935 | if (t < 0) { | 936 | if (t < 0) { |
| 936 | t = -t; | 937 | abs_t = -t; |
| 937 | ts.tv_nsec = (long)(do_div(t, 10000000) * 100); | 938 | ts.tv_nsec = (long)(do_div(abs_t, 10000000) * 100); |
| 938 | ts.tv_nsec = -ts.tv_nsec; | 939 | ts.tv_nsec = -ts.tv_nsec; |
| 939 | ts.tv_sec = -t; | 940 | ts.tv_sec = -abs_t; |
| 940 | } else { | 941 | } else { |
| 941 | ts.tv_nsec = (long)do_div(t, 10000000) * 100; | 942 | abs_t = t; |
| 942 | ts.tv_sec = t; | 943 | ts.tv_nsec = (long)do_div(abs_t, 10000000) * 100; |
| 944 | ts.tv_sec = abs_t; | ||
| 943 | } | 945 | } |
| 944 | 946 | ||
| 945 | return ts; | 947 | return ts; |
diff --git a/fs/cifs/readdir.c b/fs/cifs/readdir.c index 8eaf20a80649..c295338e0a98 100644 --- a/fs/cifs/readdir.c +++ b/fs/cifs/readdir.c | |||
| @@ -69,7 +69,8 @@ static inline void dump_cifs_file_struct(struct file *file, char *label) | |||
| 69 | * Attempt to preload the dcache with the results from the FIND_FIRST/NEXT | 69 | * Attempt to preload the dcache with the results from the FIND_FIRST/NEXT |
| 70 | * | 70 | * |
| 71 | * Find the dentry that matches "name". If there isn't one, create one. If it's | 71 | * Find the dentry that matches "name". If there isn't one, create one. If it's |
| 72 | * a negative dentry or the uniqueid changed, then drop it and recreate it. | 72 | * a negative dentry or the uniqueid or filetype(mode) changed, |
| 73 | * then drop it and recreate it. | ||
| 73 | */ | 74 | */ |
| 74 | static void | 75 | static void |
| 75 | cifs_prime_dcache(struct dentry *parent, struct qstr *name, | 76 | cifs_prime_dcache(struct dentry *parent, struct qstr *name, |
| @@ -97,8 +98,11 @@ cifs_prime_dcache(struct dentry *parent, struct qstr *name, | |||
| 97 | if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM)) | 98 | if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM)) |
| 98 | fattr->cf_uniqueid = CIFS_I(inode)->uniqueid; | 99 | fattr->cf_uniqueid = CIFS_I(inode)->uniqueid; |
| 99 | 100 | ||
| 100 | /* update inode in place if i_ino didn't change */ | 101 | /* update inode in place |
| 101 | if (CIFS_I(inode)->uniqueid == fattr->cf_uniqueid) { | 102 | * if both i_ino and i_mode didn't change */ |
| 103 | if (CIFS_I(inode)->uniqueid == fattr->cf_uniqueid && | ||
| 104 | (inode->i_mode & S_IFMT) == | ||
| 105 | (fattr->cf_mode & S_IFMT)) { | ||
| 102 | cifs_fattr_to_inode(inode, fattr); | 106 | cifs_fattr_to_inode(inode, fattr); |
| 103 | goto out; | 107 | goto out; |
| 104 | } | 108 | } |
diff --git a/fs/cifs/smb2misc.c b/fs/cifs/smb2misc.c index f1cefc9763ed..689f035915cf 100644 --- a/fs/cifs/smb2misc.c +++ b/fs/cifs/smb2misc.c | |||
| @@ -32,12 +32,14 @@ | |||
| 32 | static int | 32 | static int |
| 33 | check_smb2_hdr(struct smb2_hdr *hdr, __u64 mid) | 33 | check_smb2_hdr(struct smb2_hdr *hdr, __u64 mid) |
| 34 | { | 34 | { |
| 35 | __u64 wire_mid = le64_to_cpu(hdr->MessageId); | ||
| 36 | |||
| 35 | /* | 37 | /* |
| 36 | * Make sure that this really is an SMB, that it is a response, | 38 | * Make sure that this really is an SMB, that it is a response, |
| 37 | * and that the message ids match. | 39 | * and that the message ids match. |
| 38 | */ | 40 | */ |
| 39 | if ((*(__le32 *)hdr->ProtocolId == SMB2_PROTO_NUMBER) && | 41 | if ((*(__le32 *)hdr->ProtocolId == SMB2_PROTO_NUMBER) && |
| 40 | (mid == hdr->MessageId)) { | 42 | (mid == wire_mid)) { |
| 41 | if (hdr->Flags & SMB2_FLAGS_SERVER_TO_REDIR) | 43 | if (hdr->Flags & SMB2_FLAGS_SERVER_TO_REDIR) |
| 42 | return 0; | 44 | return 0; |
| 43 | else { | 45 | else { |
| @@ -51,11 +53,11 @@ check_smb2_hdr(struct smb2_hdr *hdr, __u64 mid) | |||
| 51 | if (*(__le32 *)hdr->ProtocolId != SMB2_PROTO_NUMBER) | 53 | if (*(__le32 *)hdr->ProtocolId != SMB2_PROTO_NUMBER) |
| 52 | cifs_dbg(VFS, "Bad protocol string signature header %x\n", | 54 | cifs_dbg(VFS, "Bad protocol string signature header %x\n", |
| 53 | *(unsigned int *) hdr->ProtocolId); | 55 | *(unsigned int *) hdr->ProtocolId); |
| 54 | if (mid != hdr->MessageId) | 56 | if (mid != wire_mid) |
| 55 | cifs_dbg(VFS, "Mids do not match: %llu and %llu\n", | 57 | cifs_dbg(VFS, "Mids do not match: %llu and %llu\n", |
| 56 | mid, hdr->MessageId); | 58 | mid, wire_mid); |
| 57 | } | 59 | } |
| 58 | cifs_dbg(VFS, "Bad SMB detected. The Mid=%llu\n", hdr->MessageId); | 60 | cifs_dbg(VFS, "Bad SMB detected. The Mid=%llu\n", wire_mid); |
| 59 | return 1; | 61 | return 1; |
| 60 | } | 62 | } |
| 61 | 63 | ||
| @@ -95,7 +97,7 @@ smb2_check_message(char *buf, unsigned int length) | |||
| 95 | { | 97 | { |
| 96 | struct smb2_hdr *hdr = (struct smb2_hdr *)buf; | 98 | struct smb2_hdr *hdr = (struct smb2_hdr *)buf; |
| 97 | struct smb2_pdu *pdu = (struct smb2_pdu *)hdr; | 99 | struct smb2_pdu *pdu = (struct smb2_pdu *)hdr; |
| 98 | __u64 mid = hdr->MessageId; | 100 | __u64 mid = le64_to_cpu(hdr->MessageId); |
| 99 | __u32 len = get_rfc1002_length(buf); | 101 | __u32 len = get_rfc1002_length(buf); |
| 100 | __u32 clc_len; /* calculated length */ | 102 | __u32 clc_len; /* calculated length */ |
| 101 | int command; | 103 | int command; |
diff --git a/fs/cifs/smb2ops.c b/fs/cifs/smb2ops.c index 93fd0586f9ec..96b5d40a2ece 100644 --- a/fs/cifs/smb2ops.c +++ b/fs/cifs/smb2ops.c | |||
| @@ -176,10 +176,11 @@ smb2_find_mid(struct TCP_Server_Info *server, char *buf) | |||
| 176 | { | 176 | { |
| 177 | struct mid_q_entry *mid; | 177 | struct mid_q_entry *mid; |
| 178 | struct smb2_hdr *hdr = (struct smb2_hdr *)buf; | 178 | struct smb2_hdr *hdr = (struct smb2_hdr *)buf; |
| 179 | __u64 wire_mid = le64_to_cpu(hdr->MessageId); | ||
| 179 | 180 | ||
| 180 | spin_lock(&GlobalMid_Lock); | 181 | spin_lock(&GlobalMid_Lock); |
| 181 | list_for_each_entry(mid, &server->pending_mid_q, qhead) { | 182 | list_for_each_entry(mid, &server->pending_mid_q, qhead) { |
| 182 | if ((mid->mid == hdr->MessageId) && | 183 | if ((mid->mid == wire_mid) && |
| 183 | (mid->mid_state == MID_REQUEST_SUBMITTED) && | 184 | (mid->mid_state == MID_REQUEST_SUBMITTED) && |
| 184 | (mid->command == hdr->Command)) { | 185 | (mid->command == hdr->Command)) { |
| 185 | spin_unlock(&GlobalMid_Lock); | 186 | spin_unlock(&GlobalMid_Lock); |
diff --git a/fs/cifs/smb2pdu.h b/fs/cifs/smb2pdu.h index ce858477002a..70867d54fb8b 100644 --- a/fs/cifs/smb2pdu.h +++ b/fs/cifs/smb2pdu.h | |||
| @@ -110,7 +110,7 @@ struct smb2_hdr { | |||
| 110 | __le16 CreditRequest; /* CreditResponse */ | 110 | __le16 CreditRequest; /* CreditResponse */ |
| 111 | __le32 Flags; | 111 | __le32 Flags; |
| 112 | __le32 NextCommand; | 112 | __le32 NextCommand; |
| 113 | __u64 MessageId; /* opaque - so can stay little endian */ | 113 | __le64 MessageId; |
| 114 | __le32 ProcessId; | 114 | __le32 ProcessId; |
| 115 | __u32 TreeId; /* opaque - so do not make little endian */ | 115 | __u32 TreeId; /* opaque - so do not make little endian */ |
| 116 | __u64 SessionId; /* opaque - so do not make little endian */ | 116 | __u64 SessionId; /* opaque - so do not make little endian */ |
diff --git a/fs/cifs/smb2transport.c b/fs/cifs/smb2transport.c index 5111e7272db6..d4c5b6f109a7 100644 --- a/fs/cifs/smb2transport.c +++ b/fs/cifs/smb2transport.c | |||
| @@ -490,7 +490,7 @@ smb2_mid_entry_alloc(const struct smb2_hdr *smb_buffer, | |||
| 490 | return temp; | 490 | return temp; |
| 491 | else { | 491 | else { |
| 492 | memset(temp, 0, sizeof(struct mid_q_entry)); | 492 | memset(temp, 0, sizeof(struct mid_q_entry)); |
| 493 | temp->mid = smb_buffer->MessageId; /* always LE */ | 493 | temp->mid = le64_to_cpu(smb_buffer->MessageId); |
| 494 | temp->pid = current->pid; | 494 | temp->pid = current->pid; |
| 495 | temp->command = smb_buffer->Command; /* Always LE */ | 495 | temp->command = smb_buffer->Command; /* Always LE */ |
| 496 | temp->when_alloc = jiffies; | 496 | temp->when_alloc = jiffies; |
diff --git a/fs/isofs/rock.c b/fs/isofs/rock.c index bb63254ed848..735d7522a3a9 100644 --- a/fs/isofs/rock.c +++ b/fs/isofs/rock.c | |||
| @@ -362,6 +362,9 @@ repeat: | |||
| 362 | rs.cont_size = isonum_733(rr->u.CE.size); | 362 | rs.cont_size = isonum_733(rr->u.CE.size); |
| 363 | break; | 363 | break; |
| 364 | case SIG('E', 'R'): | 364 | case SIG('E', 'R'): |
| 365 | /* Invalid length of ER tag id? */ | ||
| 366 | if (rr->u.ER.len_id + offsetof(struct rock_ridge, u.ER.data) > rr->len) | ||
| 367 | goto out; | ||
| 365 | ISOFS_SB(inode->i_sb)->s_rock = 1; | 368 | ISOFS_SB(inode->i_sb)->s_rock = 1; |
| 366 | printk(KERN_DEBUG "ISO 9660 Extensions: "); | 369 | printk(KERN_DEBUG "ISO 9660 Extensions: "); |
| 367 | { | 370 | { |
diff --git a/fs/udf/dir.c b/fs/udf/dir.c index a012c51caffd..05e90edd1992 100644 --- a/fs/udf/dir.c +++ b/fs/udf/dir.c | |||
| @@ -57,6 +57,7 @@ static int udf_readdir(struct file *file, struct dir_context *ctx) | |||
| 57 | sector_t offset; | 57 | sector_t offset; |
| 58 | int i, num, ret = 0; | 58 | int i, num, ret = 0; |
| 59 | struct extent_position epos = { NULL, 0, {0, 0} }; | 59 | struct extent_position epos = { NULL, 0, {0, 0} }; |
| 60 | struct super_block *sb = dir->i_sb; | ||
| 60 | 61 | ||
| 61 | if (ctx->pos == 0) { | 62 | if (ctx->pos == 0) { |
| 62 | if (!dir_emit_dot(file, ctx)) | 63 | if (!dir_emit_dot(file, ctx)) |
| @@ -76,16 +77,16 @@ static int udf_readdir(struct file *file, struct dir_context *ctx) | |||
| 76 | if (nf_pos == 0) | 77 | if (nf_pos == 0) |
| 77 | nf_pos = udf_ext0_offset(dir); | 78 | nf_pos = udf_ext0_offset(dir); |
| 78 | 79 | ||
| 79 | fibh.soffset = fibh.eoffset = nf_pos & (dir->i_sb->s_blocksize - 1); | 80 | fibh.soffset = fibh.eoffset = nf_pos & (sb->s_blocksize - 1); |
| 80 | if (iinfo->i_alloc_type != ICBTAG_FLAG_AD_IN_ICB) { | 81 | if (iinfo->i_alloc_type != ICBTAG_FLAG_AD_IN_ICB) { |
| 81 | if (inode_bmap(dir, nf_pos >> dir->i_sb->s_blocksize_bits, | 82 | if (inode_bmap(dir, nf_pos >> sb->s_blocksize_bits, |
| 82 | &epos, &eloc, &elen, &offset) | 83 | &epos, &eloc, &elen, &offset) |
| 83 | != (EXT_RECORDED_ALLOCATED >> 30)) { | 84 | != (EXT_RECORDED_ALLOCATED >> 30)) { |
| 84 | ret = -ENOENT; | 85 | ret = -ENOENT; |
| 85 | goto out; | 86 | goto out; |
| 86 | } | 87 | } |
| 87 | block = udf_get_lb_pblock(dir->i_sb, &eloc, offset); | 88 | block = udf_get_lb_pblock(sb, &eloc, offset); |
| 88 | if ((++offset << dir->i_sb->s_blocksize_bits) < elen) { | 89 | if ((++offset << sb->s_blocksize_bits) < elen) { |
| 89 | if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_SHORT) | 90 | if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_SHORT) |
| 90 | epos.offset -= sizeof(struct short_ad); | 91 | epos.offset -= sizeof(struct short_ad); |
| 91 | else if (iinfo->i_alloc_type == | 92 | else if (iinfo->i_alloc_type == |
| @@ -95,18 +96,18 @@ static int udf_readdir(struct file *file, struct dir_context *ctx) | |||
| 95 | offset = 0; | 96 | offset = 0; |
| 96 | } | 97 | } |
| 97 | 98 | ||
| 98 | if (!(fibh.sbh = fibh.ebh = udf_tread(dir->i_sb, block))) { | 99 | if (!(fibh.sbh = fibh.ebh = udf_tread(sb, block))) { |
| 99 | ret = -EIO; | 100 | ret = -EIO; |
| 100 | goto out; | 101 | goto out; |
| 101 | } | 102 | } |
| 102 | 103 | ||
| 103 | if (!(offset & ((16 >> (dir->i_sb->s_blocksize_bits - 9)) - 1))) { | 104 | if (!(offset & ((16 >> (sb->s_blocksize_bits - 9)) - 1))) { |
| 104 | i = 16 >> (dir->i_sb->s_blocksize_bits - 9); | 105 | i = 16 >> (sb->s_blocksize_bits - 9); |
| 105 | if (i + offset > (elen >> dir->i_sb->s_blocksize_bits)) | 106 | if (i + offset > (elen >> sb->s_blocksize_bits)) |
| 106 | i = (elen >> dir->i_sb->s_blocksize_bits) - offset; | 107 | i = (elen >> sb->s_blocksize_bits) - offset; |
| 107 | for (num = 0; i > 0; i--) { | 108 | for (num = 0; i > 0; i--) { |
| 108 | block = udf_get_lb_pblock(dir->i_sb, &eloc, offset + i); | 109 | block = udf_get_lb_pblock(sb, &eloc, offset + i); |
| 109 | tmp = udf_tgetblk(dir->i_sb, block); | 110 | tmp = udf_tgetblk(sb, block); |
| 110 | if (tmp && !buffer_uptodate(tmp) && !buffer_locked(tmp)) | 111 | if (tmp && !buffer_uptodate(tmp) && !buffer_locked(tmp)) |
| 111 | bha[num++] = tmp; | 112 | bha[num++] = tmp; |
| 112 | else | 113 | else |
| @@ -152,12 +153,12 @@ static int udf_readdir(struct file *file, struct dir_context *ctx) | |||
| 152 | } | 153 | } |
| 153 | 154 | ||
| 154 | if ((cfi.fileCharacteristics & FID_FILE_CHAR_DELETED) != 0) { | 155 | if ((cfi.fileCharacteristics & FID_FILE_CHAR_DELETED) != 0) { |
| 155 | if (!UDF_QUERY_FLAG(dir->i_sb, UDF_FLAG_UNDELETE)) | 156 | if (!UDF_QUERY_FLAG(sb, UDF_FLAG_UNDELETE)) |
| 156 | continue; | 157 | continue; |
| 157 | } | 158 | } |
| 158 | 159 | ||
| 159 | if ((cfi.fileCharacteristics & FID_FILE_CHAR_HIDDEN) != 0) { | 160 | if ((cfi.fileCharacteristics & FID_FILE_CHAR_HIDDEN) != 0) { |
| 160 | if (!UDF_QUERY_FLAG(dir->i_sb, UDF_FLAG_UNHIDE)) | 161 | if (!UDF_QUERY_FLAG(sb, UDF_FLAG_UNHIDE)) |
| 161 | continue; | 162 | continue; |
| 162 | } | 163 | } |
| 163 | 164 | ||
| @@ -167,12 +168,12 @@ static int udf_readdir(struct file *file, struct dir_context *ctx) | |||
| 167 | continue; | 168 | continue; |
| 168 | } | 169 | } |
| 169 | 170 | ||
| 170 | flen = udf_get_filename(dir->i_sb, nameptr, fname, lfi); | 171 | flen = udf_get_filename(sb, nameptr, lfi, fname, UDF_NAME_LEN); |
| 171 | if (!flen) | 172 | if (!flen) |
| 172 | continue; | 173 | continue; |
| 173 | 174 | ||
| 174 | tloc = lelb_to_cpu(cfi.icb.extLocation); | 175 | tloc = lelb_to_cpu(cfi.icb.extLocation); |
| 175 | iblock = udf_get_lb_pblock(dir->i_sb, &tloc, 0); | 176 | iblock = udf_get_lb_pblock(sb, &tloc, 0); |
| 176 | if (!dir_emit(ctx, fname, flen, iblock, DT_UNKNOWN)) | 177 | if (!dir_emit(ctx, fname, flen, iblock, DT_UNKNOWN)) |
| 177 | goto out; | 178 | goto out; |
| 178 | } /* end while */ | 179 | } /* end while */ |
diff --git a/fs/udf/inode.c b/fs/udf/inode.c index c9b4df5810d5..5bc71d9a674a 100644 --- a/fs/udf/inode.c +++ b/fs/udf/inode.c | |||
| @@ -1489,6 +1489,20 @@ reread: | |||
| 1489 | } | 1489 | } |
| 1490 | inode->i_generation = iinfo->i_unique; | 1490 | inode->i_generation = iinfo->i_unique; |
| 1491 | 1491 | ||
| 1492 | /* Sanity checks for files in ICB so that we don't get confused later */ | ||
| 1493 | if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB) { | ||
| 1494 | /* | ||
| 1495 | * For file in ICB data is stored in allocation descriptor | ||
| 1496 | * so sizes should match | ||
| 1497 | */ | ||
| 1498 | if (iinfo->i_lenAlloc != inode->i_size) | ||
| 1499 | goto out; | ||
| 1500 | /* File in ICB has to fit in there... */ | ||
| 1501 | if (inode->i_size > inode->i_sb->s_blocksize - | ||
| 1502 | udf_file_entry_alloc_offset(inode)) | ||
| 1503 | goto out; | ||
| 1504 | } | ||
| 1505 | |||
| 1492 | switch (fe->icbTag.fileType) { | 1506 | switch (fe->icbTag.fileType) { |
| 1493 | case ICBTAG_FILE_TYPE_DIRECTORY: | 1507 | case ICBTAG_FILE_TYPE_DIRECTORY: |
| 1494 | inode->i_op = &udf_dir_inode_operations; | 1508 | inode->i_op = &udf_dir_inode_operations; |
diff --git a/fs/udf/namei.c b/fs/udf/namei.c index c12e260fd6c4..33b246b82c98 100644 --- a/fs/udf/namei.c +++ b/fs/udf/namei.c | |||
| @@ -159,18 +159,19 @@ static struct fileIdentDesc *udf_find_entry(struct inode *dir, | |||
| 159 | struct udf_inode_info *dinfo = UDF_I(dir); | 159 | struct udf_inode_info *dinfo = UDF_I(dir); |
| 160 | int isdotdot = child->len == 2 && | 160 | int isdotdot = child->len == 2 && |
| 161 | child->name[0] == '.' && child->name[1] == '.'; | 161 | child->name[0] == '.' && child->name[1] == '.'; |
| 162 | struct super_block *sb = dir->i_sb; | ||
| 162 | 163 | ||
| 163 | size = udf_ext0_offset(dir) + dir->i_size; | 164 | size = udf_ext0_offset(dir) + dir->i_size; |
| 164 | f_pos = udf_ext0_offset(dir); | 165 | f_pos = udf_ext0_offset(dir); |
| 165 | 166 | ||
| 166 | fibh->sbh = fibh->ebh = NULL; | 167 | fibh->sbh = fibh->ebh = NULL; |
| 167 | fibh->soffset = fibh->eoffset = f_pos & (dir->i_sb->s_blocksize - 1); | 168 | fibh->soffset = fibh->eoffset = f_pos & (sb->s_blocksize - 1); |
| 168 | if (dinfo->i_alloc_type != ICBTAG_FLAG_AD_IN_ICB) { | 169 | if (dinfo->i_alloc_type != ICBTAG_FLAG_AD_IN_ICB) { |
| 169 | if (inode_bmap(dir, f_pos >> dir->i_sb->s_blocksize_bits, &epos, | 170 | if (inode_bmap(dir, f_pos >> sb->s_blocksize_bits, &epos, |
| 170 | &eloc, &elen, &offset) != (EXT_RECORDED_ALLOCATED >> 30)) | 171 | &eloc, &elen, &offset) != (EXT_RECORDED_ALLOCATED >> 30)) |
| 171 | goto out_err; | 172 | goto out_err; |
| 172 | block = udf_get_lb_pblock(dir->i_sb, &eloc, offset); | 173 | block = udf_get_lb_pblock(sb, &eloc, offset); |
| 173 | if ((++offset << dir->i_sb->s_blocksize_bits) < elen) { | 174 | if ((++offset << sb->s_blocksize_bits) < elen) { |
| 174 | if (dinfo->i_alloc_type == ICBTAG_FLAG_AD_SHORT) | 175 | if (dinfo->i_alloc_type == ICBTAG_FLAG_AD_SHORT) |
| 175 | epos.offset -= sizeof(struct short_ad); | 176 | epos.offset -= sizeof(struct short_ad); |
| 176 | else if (dinfo->i_alloc_type == ICBTAG_FLAG_AD_LONG) | 177 | else if (dinfo->i_alloc_type == ICBTAG_FLAG_AD_LONG) |
| @@ -178,7 +179,7 @@ static struct fileIdentDesc *udf_find_entry(struct inode *dir, | |||
| 178 | } else | 179 | } else |
| 179 | offset = 0; | 180 | offset = 0; |
| 180 | 181 | ||
| 181 | fibh->sbh = fibh->ebh = udf_tread(dir->i_sb, block); | 182 | fibh->sbh = fibh->ebh = udf_tread(sb, block); |
| 182 | if (!fibh->sbh) | 183 | if (!fibh->sbh) |
| 183 | goto out_err; | 184 | goto out_err; |
| 184 | } | 185 | } |
| @@ -217,12 +218,12 @@ static struct fileIdentDesc *udf_find_entry(struct inode *dir, | |||
| 217 | } | 218 | } |
| 218 | 219 | ||
| 219 | if ((cfi->fileCharacteristics & FID_FILE_CHAR_DELETED) != 0) { | 220 | if ((cfi->fileCharacteristics & FID_FILE_CHAR_DELETED) != 0) { |
| 220 | if (!UDF_QUERY_FLAG(dir->i_sb, UDF_FLAG_UNDELETE)) | 221 | if (!UDF_QUERY_FLAG(sb, UDF_FLAG_UNDELETE)) |
| 221 | continue; | 222 | continue; |
| 222 | } | 223 | } |
| 223 | 224 | ||
| 224 | if ((cfi->fileCharacteristics & FID_FILE_CHAR_HIDDEN) != 0) { | 225 | if ((cfi->fileCharacteristics & FID_FILE_CHAR_HIDDEN) != 0) { |
| 225 | if (!UDF_QUERY_FLAG(dir->i_sb, UDF_FLAG_UNHIDE)) | 226 | if (!UDF_QUERY_FLAG(sb, UDF_FLAG_UNHIDE)) |
| 226 | continue; | 227 | continue; |
| 227 | } | 228 | } |
| 228 | 229 | ||
| @@ -233,7 +234,7 @@ static struct fileIdentDesc *udf_find_entry(struct inode *dir, | |||
| 233 | if (!lfi) | 234 | if (!lfi) |
| 234 | continue; | 235 | continue; |
| 235 | 236 | ||
| 236 | flen = udf_get_filename(dir->i_sb, nameptr, fname, lfi); | 237 | flen = udf_get_filename(sb, nameptr, lfi, fname, UDF_NAME_LEN); |
| 237 | if (flen && udf_match(flen, fname, child->len, child->name)) | 238 | if (flen && udf_match(flen, fname, child->len, child->name)) |
| 238 | goto out_ok; | 239 | goto out_ok; |
| 239 | } | 240 | } |
diff --git a/fs/udf/symlink.c b/fs/udf/symlink.c index 6fb7945c1e6e..ac10ca939f26 100644 --- a/fs/udf/symlink.c +++ b/fs/udf/symlink.c | |||
| @@ -30,49 +30,73 @@ | |||
| 30 | #include <linux/buffer_head.h> | 30 | #include <linux/buffer_head.h> |
| 31 | #include "udf_i.h" | 31 | #include "udf_i.h" |
| 32 | 32 | ||
| 33 | static void udf_pc_to_char(struct super_block *sb, unsigned char *from, | 33 | static int udf_pc_to_char(struct super_block *sb, unsigned char *from, |
| 34 | int fromlen, unsigned char *to) | 34 | int fromlen, unsigned char *to, int tolen) |
| 35 | { | 35 | { |
| 36 | struct pathComponent *pc; | 36 | struct pathComponent *pc; |
| 37 | int elen = 0; | 37 | int elen = 0; |
| 38 | int comp_len; | ||
| 38 | unsigned char *p = to; | 39 | unsigned char *p = to; |
| 39 | 40 | ||
| 41 | /* Reserve one byte for terminating \0 */ | ||
| 42 | tolen--; | ||
| 40 | while (elen < fromlen) { | 43 | while (elen < fromlen) { |
| 41 | pc = (struct pathComponent *)(from + elen); | 44 | pc = (struct pathComponent *)(from + elen); |
| 45 | elen += sizeof(struct pathComponent); | ||
| 42 | switch (pc->componentType) { | 46 | switch (pc->componentType) { |
| 43 | case 1: | 47 | case 1: |
| 44 | /* | 48 | /* |
| 45 | * Symlink points to some place which should be agreed | 49 | * Symlink points to some place which should be agreed |
| 46 | * upon between originator and receiver of the media. Ignore. | 50 | * upon between originator and receiver of the media. Ignore. |
| 47 | */ | 51 | */ |
| 48 | if (pc->lengthComponentIdent > 0) | 52 | if (pc->lengthComponentIdent > 0) { |
| 53 | elen += pc->lengthComponentIdent; | ||
| 49 | break; | 54 | break; |
| 55 | } | ||
| 50 | /* Fall through */ | 56 | /* Fall through */ |
| 51 | case 2: | 57 | case 2: |
| 58 | if (tolen == 0) | ||
| 59 | return -ENAMETOOLONG; | ||
| 52 | p = to; | 60 | p = to; |
| 53 | *p++ = '/'; | 61 | *p++ = '/'; |
| 62 | tolen--; | ||
| 54 | break; | 63 | break; |
| 55 | case 3: | 64 | case 3: |
| 65 | if (tolen < 3) | ||
| 66 | return -ENAMETOOLONG; | ||
| 56 | memcpy(p, "../", 3); | 67 | memcpy(p, "../", 3); |
| 57 | p += 3; | 68 | p += 3; |
| 69 | tolen -= 3; | ||
| 58 | break; | 70 | break; |
| 59 | case 4: | 71 | case 4: |
| 72 | if (tolen < 2) | ||
| 73 | return -ENAMETOOLONG; | ||
| 60 | memcpy(p, "./", 2); | 74 | memcpy(p, "./", 2); |
| 61 | p += 2; | 75 | p += 2; |
| 76 | tolen -= 2; | ||
| 62 | /* that would be . - just ignore */ | 77 | /* that would be . - just ignore */ |
| 63 | break; | 78 | break; |
| 64 | case 5: | 79 | case 5: |
| 65 | p += udf_get_filename(sb, pc->componentIdent, p, | 80 | elen += pc->lengthComponentIdent; |
| 66 | pc->lengthComponentIdent); | 81 | if (elen > fromlen) |
| 82 | return -EIO; | ||
| 83 | comp_len = udf_get_filename(sb, pc->componentIdent, | ||
| 84 | pc->lengthComponentIdent, | ||
| 85 | p, tolen); | ||
| 86 | p += comp_len; | ||
| 87 | tolen -= comp_len; | ||
| 88 | if (tolen == 0) | ||
| 89 | return -ENAMETOOLONG; | ||
| 67 | *p++ = '/'; | 90 | *p++ = '/'; |
| 91 | tolen--; | ||
| 68 | break; | 92 | break; |
| 69 | } | 93 | } |
| 70 | elen += sizeof(struct pathComponent) + pc->lengthComponentIdent; | ||
| 71 | } | 94 | } |
| 72 | if (p > to + 1) | 95 | if (p > to + 1) |
| 73 | p[-1] = '\0'; | 96 | p[-1] = '\0'; |
| 74 | else | 97 | else |
| 75 | p[0] = '\0'; | 98 | p[0] = '\0'; |
| 99 | return 0; | ||
| 76 | } | 100 | } |
| 77 | 101 | ||
| 78 | static int udf_symlink_filler(struct file *file, struct page *page) | 102 | static int udf_symlink_filler(struct file *file, struct page *page) |
| @@ -80,11 +104,17 @@ static int udf_symlink_filler(struct file *file, struct page *page) | |||
| 80 | struct inode *inode = page->mapping->host; | 104 | struct inode *inode = page->mapping->host; |
| 81 | struct buffer_head *bh = NULL; | 105 | struct buffer_head *bh = NULL; |
| 82 | unsigned char *symlink; | 106 | unsigned char *symlink; |
| 83 | int err = -EIO; | 107 | int err; |
| 84 | unsigned char *p = kmap(page); | 108 | unsigned char *p = kmap(page); |
| 85 | struct udf_inode_info *iinfo; | 109 | struct udf_inode_info *iinfo; |
| 86 | uint32_t pos; | 110 | uint32_t pos; |
| 87 | 111 | ||
| 112 | /* We don't support symlinks longer than one block */ | ||
| 113 | if (inode->i_size > inode->i_sb->s_blocksize) { | ||
| 114 | err = -ENAMETOOLONG; | ||
| 115 | goto out_unmap; | ||
| 116 | } | ||
| 117 | |||
| 88 | iinfo = UDF_I(inode); | 118 | iinfo = UDF_I(inode); |
| 89 | pos = udf_block_map(inode, 0); | 119 | pos = udf_block_map(inode, 0); |
| 90 | 120 | ||
| @@ -94,14 +124,18 @@ static int udf_symlink_filler(struct file *file, struct page *page) | |||
| 94 | } else { | 124 | } else { |
| 95 | bh = sb_bread(inode->i_sb, pos); | 125 | bh = sb_bread(inode->i_sb, pos); |
| 96 | 126 | ||
| 97 | if (!bh) | 127 | if (!bh) { |
| 98 | goto out; | 128 | err = -EIO; |
| 129 | goto out_unlock_inode; | ||
| 130 | } | ||
| 99 | 131 | ||
| 100 | symlink = bh->b_data; | 132 | symlink = bh->b_data; |
| 101 | } | 133 | } |
| 102 | 134 | ||
| 103 | udf_pc_to_char(inode->i_sb, symlink, inode->i_size, p); | 135 | err = udf_pc_to_char(inode->i_sb, symlink, inode->i_size, p, PAGE_SIZE); |
| 104 | brelse(bh); | 136 | brelse(bh); |
| 137 | if (err) | ||
| 138 | goto out_unlock_inode; | ||
| 105 | 139 | ||
| 106 | up_read(&iinfo->i_data_sem); | 140 | up_read(&iinfo->i_data_sem); |
| 107 | SetPageUptodate(page); | 141 | SetPageUptodate(page); |
| @@ -109,9 +143,10 @@ static int udf_symlink_filler(struct file *file, struct page *page) | |||
| 109 | unlock_page(page); | 143 | unlock_page(page); |
| 110 | return 0; | 144 | return 0; |
| 111 | 145 | ||
| 112 | out: | 146 | out_unlock_inode: |
| 113 | up_read(&iinfo->i_data_sem); | 147 | up_read(&iinfo->i_data_sem); |
| 114 | SetPageError(page); | 148 | SetPageError(page); |
| 149 | out_unmap: | ||
| 115 | kunmap(page); | 150 | kunmap(page); |
| 116 | unlock_page(page); | 151 | unlock_page(page); |
| 117 | return err; | 152 | return err; |
diff --git a/fs/udf/udfdecl.h b/fs/udf/udfdecl.h index 1cc3c993ebd0..47bb3f5ca360 100644 --- a/fs/udf/udfdecl.h +++ b/fs/udf/udfdecl.h | |||
| @@ -211,7 +211,8 @@ udf_get_lb_pblock(struct super_block *sb, struct kernel_lb_addr *loc, | |||
| 211 | } | 211 | } |
| 212 | 212 | ||
| 213 | /* unicode.c */ | 213 | /* unicode.c */ |
| 214 | extern int udf_get_filename(struct super_block *, uint8_t *, uint8_t *, int); | 214 | extern int udf_get_filename(struct super_block *, uint8_t *, int, uint8_t *, |
| 215 | int); | ||
| 215 | extern int udf_put_filename(struct super_block *, const uint8_t *, uint8_t *, | 216 | extern int udf_put_filename(struct super_block *, const uint8_t *, uint8_t *, |
| 216 | int); | 217 | int); |
| 217 | extern int udf_build_ustr(struct ustr *, dstring *, int); | 218 | extern int udf_build_ustr(struct ustr *, dstring *, int); |
diff --git a/fs/udf/unicode.c b/fs/udf/unicode.c index afd470e588ff..b84fee372734 100644 --- a/fs/udf/unicode.c +++ b/fs/udf/unicode.c | |||
| @@ -28,7 +28,8 @@ | |||
| 28 | 28 | ||
| 29 | #include "udf_sb.h" | 29 | #include "udf_sb.h" |
| 30 | 30 | ||
| 31 | static int udf_translate_to_linux(uint8_t *, uint8_t *, int, uint8_t *, int); | 31 | static int udf_translate_to_linux(uint8_t *, int, uint8_t *, int, uint8_t *, |
| 32 | int); | ||
| 32 | 33 | ||
| 33 | static int udf_char_to_ustr(struct ustr *dest, const uint8_t *src, int strlen) | 34 | static int udf_char_to_ustr(struct ustr *dest, const uint8_t *src, int strlen) |
| 34 | { | 35 | { |
| @@ -333,8 +334,8 @@ try_again: | |||
| 333 | return u_len + 1; | 334 | return u_len + 1; |
| 334 | } | 335 | } |
| 335 | 336 | ||
| 336 | int udf_get_filename(struct super_block *sb, uint8_t *sname, uint8_t *dname, | 337 | int udf_get_filename(struct super_block *sb, uint8_t *sname, int slen, |
| 337 | int flen) | 338 | uint8_t *dname, int dlen) |
| 338 | { | 339 | { |
| 339 | struct ustr *filename, *unifilename; | 340 | struct ustr *filename, *unifilename; |
| 340 | int len = 0; | 341 | int len = 0; |
| @@ -347,7 +348,7 @@ int udf_get_filename(struct super_block *sb, uint8_t *sname, uint8_t *dname, | |||
| 347 | if (!unifilename) | 348 | if (!unifilename) |
| 348 | goto out1; | 349 | goto out1; |
| 349 | 350 | ||
| 350 | if (udf_build_ustr_exact(unifilename, sname, flen)) | 351 | if (udf_build_ustr_exact(unifilename, sname, slen)) |
| 351 | goto out2; | 352 | goto out2; |
| 352 | 353 | ||
| 353 | if (UDF_QUERY_FLAG(sb, UDF_FLAG_UTF8)) { | 354 | if (UDF_QUERY_FLAG(sb, UDF_FLAG_UTF8)) { |
| @@ -366,7 +367,8 @@ int udf_get_filename(struct super_block *sb, uint8_t *sname, uint8_t *dname, | |||
| 366 | } else | 367 | } else |
| 367 | goto out2; | 368 | goto out2; |
| 368 | 369 | ||
| 369 | len = udf_translate_to_linux(dname, filename->u_name, filename->u_len, | 370 | len = udf_translate_to_linux(dname, dlen, |
| 371 | filename->u_name, filename->u_len, | ||
| 370 | unifilename->u_name, unifilename->u_len); | 372 | unifilename->u_name, unifilename->u_len); |
| 371 | out2: | 373 | out2: |
| 372 | kfree(unifilename); | 374 | kfree(unifilename); |
| @@ -403,10 +405,12 @@ int udf_put_filename(struct super_block *sb, const uint8_t *sname, | |||
| 403 | #define EXT_MARK '.' | 405 | #define EXT_MARK '.' |
| 404 | #define CRC_MARK '#' | 406 | #define CRC_MARK '#' |
| 405 | #define EXT_SIZE 5 | 407 | #define EXT_SIZE 5 |
| 408 | /* Number of chars we need to store generated CRC to make filename unique */ | ||
| 409 | #define CRC_LEN 5 | ||
| 406 | 410 | ||
| 407 | static int udf_translate_to_linux(uint8_t *newName, uint8_t *udfName, | 411 | static int udf_translate_to_linux(uint8_t *newName, int newLen, |
| 408 | int udfLen, uint8_t *fidName, | 412 | uint8_t *udfName, int udfLen, |
| 409 | int fidNameLen) | 413 | uint8_t *fidName, int fidNameLen) |
| 410 | { | 414 | { |
| 411 | int index, newIndex = 0, needsCRC = 0; | 415 | int index, newIndex = 0, needsCRC = 0; |
| 412 | int extIndex = 0, newExtIndex = 0, hasExt = 0; | 416 | int extIndex = 0, newExtIndex = 0, hasExt = 0; |
| @@ -439,7 +443,7 @@ static int udf_translate_to_linux(uint8_t *newName, uint8_t *udfName, | |||
| 439 | newExtIndex = newIndex; | 443 | newExtIndex = newIndex; |
| 440 | } | 444 | } |
| 441 | } | 445 | } |
| 442 | if (newIndex < 256) | 446 | if (newIndex < newLen) |
| 443 | newName[newIndex++] = curr; | 447 | newName[newIndex++] = curr; |
| 444 | else | 448 | else |
| 445 | needsCRC = 1; | 449 | needsCRC = 1; |
| @@ -467,13 +471,13 @@ static int udf_translate_to_linux(uint8_t *newName, uint8_t *udfName, | |||
| 467 | } | 471 | } |
| 468 | ext[localExtIndex++] = curr; | 472 | ext[localExtIndex++] = curr; |
| 469 | } | 473 | } |
| 470 | maxFilenameLen = 250 - localExtIndex; | 474 | maxFilenameLen = newLen - CRC_LEN - localExtIndex; |
| 471 | if (newIndex > maxFilenameLen) | 475 | if (newIndex > maxFilenameLen) |
| 472 | newIndex = maxFilenameLen; | 476 | newIndex = maxFilenameLen; |
| 473 | else | 477 | else |
| 474 | newIndex = newExtIndex; | 478 | newIndex = newExtIndex; |
| 475 | } else if (newIndex > 250) | 479 | } else if (newIndex > newLen - CRC_LEN) |
| 476 | newIndex = 250; | 480 | newIndex = newLen - CRC_LEN; |
| 477 | newName[newIndex++] = CRC_MARK; | 481 | newName[newIndex++] = CRC_MARK; |
| 478 | valueCRC = crc_itu_t(0, fidName, fidNameLen); | 482 | valueCRC = crc_itu_t(0, fidName, fidNameLen); |
| 479 | newName[newIndex++] = hex_asc_upper_hi(valueCRC >> 8); | 483 | newName[newIndex++] = hex_asc_upper_hi(valueCRC >> 8); |
diff --git a/include/drm/drmP.h b/include/drm/drmP.h index 8ba35c622e22..e1b2e8b98af7 100644 --- a/include/drm/drmP.h +++ b/include/drm/drmP.h | |||
| @@ -901,11 +901,15 @@ extern int drm_vblank_init(struct drm_device *dev, int num_crtcs); | |||
| 901 | extern int drm_wait_vblank(struct drm_device *dev, void *data, | 901 | extern int drm_wait_vblank(struct drm_device *dev, void *data, |
| 902 | struct drm_file *filp); | 902 | struct drm_file *filp); |
| 903 | extern u32 drm_vblank_count(struct drm_device *dev, int crtc); | 903 | extern u32 drm_vblank_count(struct drm_device *dev, int crtc); |
| 904 | extern u32 drm_crtc_vblank_count(struct drm_crtc *crtc); | ||
| 904 | extern u32 drm_vblank_count_and_time(struct drm_device *dev, int crtc, | 905 | extern u32 drm_vblank_count_and_time(struct drm_device *dev, int crtc, |
| 905 | struct timeval *vblanktime); | 906 | struct timeval *vblanktime); |
| 906 | extern void drm_send_vblank_event(struct drm_device *dev, int crtc, | 907 | extern void drm_send_vblank_event(struct drm_device *dev, int crtc, |
| 907 | struct drm_pending_vblank_event *e); | 908 | struct drm_pending_vblank_event *e); |
| 909 | extern void drm_crtc_send_vblank_event(struct drm_crtc *crtc, | ||
| 910 | struct drm_pending_vblank_event *e); | ||
| 908 | extern bool drm_handle_vblank(struct drm_device *dev, int crtc); | 911 | extern bool drm_handle_vblank(struct drm_device *dev, int crtc); |
| 912 | extern bool drm_crtc_handle_vblank(struct drm_crtc *crtc); | ||
| 909 | extern int drm_vblank_get(struct drm_device *dev, int crtc); | 913 | extern int drm_vblank_get(struct drm_device *dev, int crtc); |
| 910 | extern void drm_vblank_put(struct drm_device *dev, int crtc); | 914 | extern void drm_vblank_put(struct drm_device *dev, int crtc); |
| 911 | extern int drm_crtc_vblank_get(struct drm_crtc *crtc); | 915 | extern int drm_crtc_vblank_get(struct drm_crtc *crtc); |
diff --git a/include/drm/drm_gem.h b/include/drm/drm_gem.h index 780511a459c0..1e6ae1458f7a 100644 --- a/include/drm/drm_gem.h +++ b/include/drm/drm_gem.h | |||
| @@ -119,13 +119,6 @@ struct drm_gem_object { | |||
| 119 | * simply leave it as NULL. | 119 | * simply leave it as NULL. |
| 120 | */ | 120 | */ |
| 121 | struct dma_buf_attachment *import_attach; | 121 | struct dma_buf_attachment *import_attach; |
| 122 | |||
| 123 | /** | ||
| 124 | * dumb - created as dumb buffer | ||
| 125 | * Whether the gem object was created using the dumb buffer interface | ||
| 126 | * as such it may not be used for GPU rendering. | ||
| 127 | */ | ||
| 128 | bool dumb; | ||
| 129 | }; | 122 | }; |
| 130 | 123 | ||
| 131 | void drm_gem_object_release(struct drm_gem_object *obj); | 124 | void drm_gem_object_release(struct drm_gem_object *obj); |
diff --git a/include/dt-bindings/thermal/thermal.h b/include/dt-bindings/thermal/thermal.h index 59822a995858..b5e6b0069ac7 100644 --- a/include/dt-bindings/thermal/thermal.h +++ b/include/dt-bindings/thermal/thermal.h | |||
| @@ -11,7 +11,7 @@ | |||
| 11 | #define _DT_BINDINGS_THERMAL_THERMAL_H | 11 | #define _DT_BINDINGS_THERMAL_THERMAL_H |
| 12 | 12 | ||
| 13 | /* On cooling devices upper and lower limits */ | 13 | /* On cooling devices upper and lower limits */ |
| 14 | #define THERMAL_NO_LIMIT (-1UL) | 14 | #define THERMAL_NO_LIMIT (~0) |
| 15 | 15 | ||
| 16 | #endif | 16 | #endif |
| 17 | 17 | ||
diff --git a/include/linux/audit.h b/include/linux/audit.h index 0c04917c2f12..af84234e1f6e 100644 --- a/include/linux/audit.h +++ b/include/linux/audit.h | |||
| @@ -47,6 +47,7 @@ struct sk_buff; | |||
| 47 | 47 | ||
| 48 | struct audit_krule { | 48 | struct audit_krule { |
| 49 | int vers_ops; | 49 | int vers_ops; |
| 50 | u32 pflags; | ||
| 50 | u32 flags; | 51 | u32 flags; |
| 51 | u32 listnr; | 52 | u32 listnr; |
| 52 | u32 action; | 53 | u32 action; |
| @@ -64,6 +65,9 @@ struct audit_krule { | |||
| 64 | u64 prio; | 65 | u64 prio; |
| 65 | }; | 66 | }; |
| 66 | 67 | ||
| 68 | /* Flag to indicate legacy AUDIT_LOGINUID unset usage */ | ||
| 69 | #define AUDIT_LOGINUID_LEGACY 0x1 | ||
| 70 | |||
| 67 | struct audit_field { | 71 | struct audit_field { |
| 68 | u32 type; | 72 | u32 type; |
| 69 | union { | 73 | union { |
diff --git a/include/linux/cpu_cooling.h b/include/linux/cpu_cooling.h index c303d383def1..bd955270d5aa 100644 --- a/include/linux/cpu_cooling.h +++ b/include/linux/cpu_cooling.h | |||
| @@ -50,7 +50,7 @@ static inline struct thermal_cooling_device * | |||
| 50 | of_cpufreq_cooling_register(struct device_node *np, | 50 | of_cpufreq_cooling_register(struct device_node *np, |
| 51 | const struct cpumask *clip_cpus) | 51 | const struct cpumask *clip_cpus) |
| 52 | { | 52 | { |
| 53 | return NULL; | 53 | return ERR_PTR(-ENOSYS); |
| 54 | } | 54 | } |
| 55 | #endif | 55 | #endif |
| 56 | 56 | ||
| @@ -65,13 +65,13 @@ unsigned long cpufreq_cooling_get_level(unsigned int cpu, unsigned int freq); | |||
| 65 | static inline struct thermal_cooling_device * | 65 | static inline struct thermal_cooling_device * |
| 66 | cpufreq_cooling_register(const struct cpumask *clip_cpus) | 66 | cpufreq_cooling_register(const struct cpumask *clip_cpus) |
| 67 | { | 67 | { |
| 68 | return NULL; | 68 | return ERR_PTR(-ENOSYS); |
| 69 | } | 69 | } |
| 70 | static inline struct thermal_cooling_device * | 70 | static inline struct thermal_cooling_device * |
| 71 | of_cpufreq_cooling_register(struct device_node *np, | 71 | of_cpufreq_cooling_register(struct device_node *np, |
| 72 | const struct cpumask *clip_cpus) | 72 | const struct cpumask *clip_cpus) |
| 73 | { | 73 | { |
| 74 | return NULL; | 74 | return ERR_PTR(-ENOSYS); |
| 75 | } | 75 | } |
| 76 | static inline | 76 | static inline |
| 77 | void cpufreq_cooling_unregister(struct thermal_cooling_device *cdev) | 77 | void cpufreq_cooling_unregister(struct thermal_cooling_device *cdev) |
diff --git a/include/linux/cpuidle.h b/include/linux/cpuidle.h index a07e087f54b2..ab70f3bc44ad 100644 --- a/include/linux/cpuidle.h +++ b/include/linux/cpuidle.h | |||
| @@ -53,7 +53,6 @@ struct cpuidle_state { | |||
| 53 | }; | 53 | }; |
| 54 | 54 | ||
| 55 | /* Idle State Flags */ | 55 | /* Idle State Flags */ |
| 56 | #define CPUIDLE_FLAG_TIME_INVALID (0x01) /* is residency time measurable? */ | ||
| 57 | #define CPUIDLE_FLAG_COUPLED (0x02) /* state applies to multiple cpus */ | 56 | #define CPUIDLE_FLAG_COUPLED (0x02) /* state applies to multiple cpus */ |
| 58 | #define CPUIDLE_FLAG_TIMER_STOP (0x04) /* timer is stopped on this state */ | 57 | #define CPUIDLE_FLAG_TIMER_STOP (0x04) /* timer is stopped on this state */ |
| 59 | 58 | ||
| @@ -89,8 +88,6 @@ DECLARE_PER_CPU(struct cpuidle_device, cpuidle_dev); | |||
| 89 | /** | 88 | /** |
| 90 | * cpuidle_get_last_residency - retrieves the last state's residency time | 89 | * cpuidle_get_last_residency - retrieves the last state's residency time |
| 91 | * @dev: the target CPU | 90 | * @dev: the target CPU |
| 92 | * | ||
| 93 | * NOTE: this value is invalid if CPUIDLE_FLAG_TIME_INVALID is set | ||
| 94 | */ | 91 | */ |
| 95 | static inline int cpuidle_get_last_residency(struct cpuidle_device *dev) | 92 | static inline int cpuidle_get_last_residency(struct cpuidle_device *dev) |
| 96 | { | 93 | { |
diff --git a/include/linux/kprobes.h b/include/linux/kprobes.h index 5297f9fa0ef2..1ab54754a86d 100644 --- a/include/linux/kprobes.h +++ b/include/linux/kprobes.h | |||
| @@ -308,7 +308,8 @@ struct optimized_kprobe { | |||
| 308 | /* Architecture dependent functions for direct jump optimization */ | 308 | /* Architecture dependent functions for direct jump optimization */ |
| 309 | extern int arch_prepared_optinsn(struct arch_optimized_insn *optinsn); | 309 | extern int arch_prepared_optinsn(struct arch_optimized_insn *optinsn); |
| 310 | extern int arch_check_optimized_kprobe(struct optimized_kprobe *op); | 310 | extern int arch_check_optimized_kprobe(struct optimized_kprobe *op); |
| 311 | extern int arch_prepare_optimized_kprobe(struct optimized_kprobe *op); | 311 | extern int arch_prepare_optimized_kprobe(struct optimized_kprobe *op, |
| 312 | struct kprobe *orig); | ||
| 312 | extern void arch_remove_optimized_kprobe(struct optimized_kprobe *op); | 313 | extern void arch_remove_optimized_kprobe(struct optimized_kprobe *op); |
| 313 | extern void arch_optimize_kprobes(struct list_head *oplist); | 314 | extern void arch_optimize_kprobes(struct list_head *oplist); |
| 314 | extern void arch_unoptimize_kprobes(struct list_head *oplist, | 315 | extern void arch_unoptimize_kprobes(struct list_head *oplist, |
diff --git a/include/linux/mfd/stmpe.h b/include/linux/mfd/stmpe.h index 575a86c7fcbd..f742b6717d52 100644 --- a/include/linux/mfd/stmpe.h +++ b/include/linux/mfd/stmpe.h | |||
| @@ -50,6 +50,8 @@ enum { | |||
| 50 | STMPE_IDX_GPEDR_MSB, | 50 | STMPE_IDX_GPEDR_MSB, |
| 51 | STMPE_IDX_GPRER_LSB, | 51 | STMPE_IDX_GPRER_LSB, |
| 52 | STMPE_IDX_GPFER_LSB, | 52 | STMPE_IDX_GPFER_LSB, |
| 53 | STMPE_IDX_GPPUR_LSB, | ||
| 54 | STMPE_IDX_GPPDR_LSB, | ||
| 53 | STMPE_IDX_GPAFR_U_MSB, | 55 | STMPE_IDX_GPAFR_U_MSB, |
| 54 | STMPE_IDX_IEGPIOR_LSB, | 56 | STMPE_IDX_IEGPIOR_LSB, |
| 55 | STMPE_IDX_ISGPIOR_LSB, | 57 | STMPE_IDX_ISGPIOR_LSB, |
| @@ -113,24 +115,6 @@ extern int stmpe_set_altfunc(struct stmpe *stmpe, u32 pins, | |||
| 113 | extern int stmpe_enable(struct stmpe *stmpe, unsigned int blocks); | 115 | extern int stmpe_enable(struct stmpe *stmpe, unsigned int blocks); |
| 114 | extern int stmpe_disable(struct stmpe *stmpe, unsigned int blocks); | 116 | extern int stmpe_disable(struct stmpe *stmpe, unsigned int blocks); |
| 115 | 117 | ||
| 116 | struct matrix_keymap_data; | ||
| 117 | |||
| 118 | /** | ||
| 119 | * struct stmpe_keypad_platform_data - STMPE keypad platform data | ||
| 120 | * @keymap_data: key map table and size | ||
| 121 | * @debounce_ms: debounce interval, in ms. Maximum is | ||
| 122 | * %STMPE_KEYPAD_MAX_DEBOUNCE. | ||
| 123 | * @scan_count: number of key scanning cycles to confirm key data. | ||
| 124 | * Maximum is %STMPE_KEYPAD_MAX_SCAN_COUNT. | ||
| 125 | * @no_autorepeat: disable key autorepeat | ||
| 126 | */ | ||
| 127 | struct stmpe_keypad_platform_data { | ||
| 128 | const struct matrix_keymap_data *keymap_data; | ||
| 129 | unsigned int debounce_ms; | ||
| 130 | unsigned int scan_count; | ||
| 131 | bool no_autorepeat; | ||
| 132 | }; | ||
| 133 | |||
| 134 | #define STMPE_GPIO_NOREQ_811_TOUCH (0xf0) | 118 | #define STMPE_GPIO_NOREQ_811_TOUCH (0xf0) |
| 135 | 119 | ||
| 136 | /** | 120 | /** |
| @@ -199,7 +183,6 @@ struct stmpe_ts_platform_data { | |||
| 199 | * @irq_gpio: gpio number over which irq will be requested (significant only if | 183 | * @irq_gpio: gpio number over which irq will be requested (significant only if |
| 200 | * irq_over_gpio is true) | 184 | * irq_over_gpio is true) |
| 201 | * @gpio: GPIO-specific platform data | 185 | * @gpio: GPIO-specific platform data |
| 202 | * @keypad: keypad-specific platform data | ||
| 203 | * @ts: touchscreen-specific platform data | 186 | * @ts: touchscreen-specific platform data |
| 204 | */ | 187 | */ |
| 205 | struct stmpe_platform_data { | 188 | struct stmpe_platform_data { |
| @@ -212,7 +195,6 @@ struct stmpe_platform_data { | |||
| 212 | int autosleep_timeout; | 195 | int autosleep_timeout; |
| 213 | 196 | ||
| 214 | struct stmpe_gpio_platform_data *gpio; | 197 | struct stmpe_gpio_platform_data *gpio; |
| 215 | struct stmpe_keypad_platform_data *keypad; | ||
| 216 | struct stmpe_ts_platform_data *ts; | 198 | struct stmpe_ts_platform_data *ts; |
| 217 | }; | 199 | }; |
| 218 | 200 | ||
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index c31f74d76ebd..679e6e90aa4c 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h | |||
| @@ -1012,12 +1012,15 @@ typedef u16 (*select_queue_fallback_t)(struct net_device *dev, | |||
| 1012 | * Callback to use for xmit over the accelerated station. This | 1012 | * Callback to use for xmit over the accelerated station. This |
| 1013 | * is used in place of ndo_start_xmit on accelerated net | 1013 | * is used in place of ndo_start_xmit on accelerated net |
| 1014 | * devices. | 1014 | * devices. |
| 1015 | * bool (*ndo_gso_check) (struct sk_buff *skb, | 1015 | * netdev_features_t (*ndo_features_check) (struct sk_buff *skb, |
| 1016 | * struct net_device *dev); | 1016 | * struct net_device *dev |
| 1017 | * netdev_features_t features); | ||
| 1017 | * Called by core transmit path to determine if device is capable of | 1018 | * Called by core transmit path to determine if device is capable of |
| 1018 | * performing GSO on a packet. The device returns true if it is | 1019 | * performing offload operations on a given packet. This is to give |
| 1019 | * able to GSO the packet, false otherwise. If the return value is | 1020 | * the device an opportunity to implement any restrictions that cannot |
| 1020 | * false the stack will do software GSO. | 1021 | * be otherwise expressed by feature flags. The check is called with |
| 1022 | * the set of features that the stack has calculated and it returns | ||
| 1023 | * those the driver believes to be appropriate. | ||
| 1021 | * | 1024 | * |
| 1022 | * int (*ndo_switch_parent_id_get)(struct net_device *dev, | 1025 | * int (*ndo_switch_parent_id_get)(struct net_device *dev, |
| 1023 | * struct netdev_phys_item_id *psid); | 1026 | * struct netdev_phys_item_id *psid); |
| @@ -1178,8 +1181,9 @@ struct net_device_ops { | |||
| 1178 | struct net_device *dev, | 1181 | struct net_device *dev, |
| 1179 | void *priv); | 1182 | void *priv); |
| 1180 | int (*ndo_get_lock_subclass)(struct net_device *dev); | 1183 | int (*ndo_get_lock_subclass)(struct net_device *dev); |
| 1181 | bool (*ndo_gso_check) (struct sk_buff *skb, | 1184 | netdev_features_t (*ndo_features_check) (struct sk_buff *skb, |
| 1182 | struct net_device *dev); | 1185 | struct net_device *dev, |
| 1186 | netdev_features_t features); | ||
| 1183 | #ifdef CONFIG_NET_SWITCHDEV | 1187 | #ifdef CONFIG_NET_SWITCHDEV |
| 1184 | int (*ndo_switch_parent_id_get)(struct net_device *dev, | 1188 | int (*ndo_switch_parent_id_get)(struct net_device *dev, |
| 1185 | struct netdev_phys_item_id *psid); | 1189 | struct netdev_phys_item_id *psid); |
| @@ -3611,8 +3615,6 @@ static inline bool netif_needs_gso(struct net_device *dev, struct sk_buff *skb, | |||
| 3611 | netdev_features_t features) | 3615 | netdev_features_t features) |
| 3612 | { | 3616 | { |
| 3613 | return skb_is_gso(skb) && (!skb_gso_ok(skb, features) || | 3617 | return skb_is_gso(skb) && (!skb_gso_ok(skb, features) || |
| 3614 | (dev->netdev_ops->ndo_gso_check && | ||
| 3615 | !dev->netdev_ops->ndo_gso_check(skb, dev)) || | ||
| 3616 | unlikely((skb->ip_summed != CHECKSUM_PARTIAL) && | 3618 | unlikely((skb->ip_summed != CHECKSUM_PARTIAL) && |
| 3617 | (skb->ip_summed != CHECKSUM_UNNECESSARY))); | 3619 | (skb->ip_summed != CHECKSUM_UNNECESSARY))); |
| 3618 | } | 3620 | } |
diff --git a/include/linux/netlink.h b/include/linux/netlink.h index 9e572daa15d5..02fc86d2348e 100644 --- a/include/linux/netlink.h +++ b/include/linux/netlink.h | |||
| @@ -46,8 +46,8 @@ struct netlink_kernel_cfg { | |||
| 46 | unsigned int flags; | 46 | unsigned int flags; |
| 47 | void (*input)(struct sk_buff *skb); | 47 | void (*input)(struct sk_buff *skb); |
| 48 | struct mutex *cb_mutex; | 48 | struct mutex *cb_mutex; |
| 49 | int (*bind)(int group); | 49 | int (*bind)(struct net *net, int group); |
| 50 | void (*unbind)(int group); | 50 | void (*unbind)(struct net *net, int group); |
| 51 | bool (*compare)(struct net *net, struct sock *sk); | 51 | bool (*compare)(struct net *net, struct sock *sk); |
| 52 | }; | 52 | }; |
| 53 | 53 | ||
diff --git a/include/linux/pagemap.h b/include/linux/pagemap.h index 7ea069cd3257..4b3736f7065c 100644 --- a/include/linux/pagemap.h +++ b/include/linux/pagemap.h | |||
| @@ -251,7 +251,7 @@ pgoff_t page_cache_prev_hole(struct address_space *mapping, | |||
| 251 | #define FGP_NOWAIT 0x00000020 | 251 | #define FGP_NOWAIT 0x00000020 |
| 252 | 252 | ||
| 253 | struct page *pagecache_get_page(struct address_space *mapping, pgoff_t offset, | 253 | struct page *pagecache_get_page(struct address_space *mapping, pgoff_t offset, |
| 254 | int fgp_flags, gfp_t cache_gfp_mask, gfp_t radix_gfp_mask); | 254 | int fgp_flags, gfp_t cache_gfp_mask); |
| 255 | 255 | ||
| 256 | /** | 256 | /** |
| 257 | * find_get_page - find and get a page reference | 257 | * find_get_page - find and get a page reference |
| @@ -266,13 +266,13 @@ struct page *pagecache_get_page(struct address_space *mapping, pgoff_t offset, | |||
| 266 | static inline struct page *find_get_page(struct address_space *mapping, | 266 | static inline struct page *find_get_page(struct address_space *mapping, |
| 267 | pgoff_t offset) | 267 | pgoff_t offset) |
| 268 | { | 268 | { |
| 269 | return pagecache_get_page(mapping, offset, 0, 0, 0); | 269 | return pagecache_get_page(mapping, offset, 0, 0); |
| 270 | } | 270 | } |
| 271 | 271 | ||
| 272 | static inline struct page *find_get_page_flags(struct address_space *mapping, | 272 | static inline struct page *find_get_page_flags(struct address_space *mapping, |
| 273 | pgoff_t offset, int fgp_flags) | 273 | pgoff_t offset, int fgp_flags) |
| 274 | { | 274 | { |
| 275 | return pagecache_get_page(mapping, offset, fgp_flags, 0, 0); | 275 | return pagecache_get_page(mapping, offset, fgp_flags, 0); |
| 276 | } | 276 | } |
| 277 | 277 | ||
| 278 | /** | 278 | /** |
| @@ -292,7 +292,7 @@ static inline struct page *find_get_page_flags(struct address_space *mapping, | |||
| 292 | static inline struct page *find_lock_page(struct address_space *mapping, | 292 | static inline struct page *find_lock_page(struct address_space *mapping, |
| 293 | pgoff_t offset) | 293 | pgoff_t offset) |
| 294 | { | 294 | { |
| 295 | return pagecache_get_page(mapping, offset, FGP_LOCK, 0, 0); | 295 | return pagecache_get_page(mapping, offset, FGP_LOCK, 0); |
| 296 | } | 296 | } |
| 297 | 297 | ||
| 298 | /** | 298 | /** |
| @@ -319,7 +319,7 @@ static inline struct page *find_or_create_page(struct address_space *mapping, | |||
| 319 | { | 319 | { |
| 320 | return pagecache_get_page(mapping, offset, | 320 | return pagecache_get_page(mapping, offset, |
| 321 | FGP_LOCK|FGP_ACCESSED|FGP_CREAT, | 321 | FGP_LOCK|FGP_ACCESSED|FGP_CREAT, |
| 322 | gfp_mask, gfp_mask & GFP_RECLAIM_MASK); | 322 | gfp_mask); |
| 323 | } | 323 | } |
| 324 | 324 | ||
| 325 | /** | 325 | /** |
| @@ -340,8 +340,7 @@ static inline struct page *grab_cache_page_nowait(struct address_space *mapping, | |||
| 340 | { | 340 | { |
| 341 | return pagecache_get_page(mapping, index, | 341 | return pagecache_get_page(mapping, index, |
| 342 | FGP_LOCK|FGP_CREAT|FGP_NOFS|FGP_NOWAIT, | 342 | FGP_LOCK|FGP_CREAT|FGP_NOFS|FGP_NOWAIT, |
| 343 | mapping_gfp_mask(mapping), | 343 | mapping_gfp_mask(mapping)); |
| 344 | GFP_NOFS); | ||
| 345 | } | 344 | } |
| 346 | 345 | ||
| 347 | struct page *find_get_entry(struct address_space *mapping, pgoff_t offset); | 346 | struct page *find_get_entry(struct address_space *mapping, pgoff_t offset); |
diff --git a/include/linux/pm_domain.h b/include/linux/pm_domain.h index 6cd20d5e651b..a9edab2c787a 100644 --- a/include/linux/pm_domain.h +++ b/include/linux/pm_domain.h | |||
| @@ -271,6 +271,8 @@ typedef struct generic_pm_domain *(*genpd_xlate_t)(struct of_phandle_args *args, | |||
| 271 | int __of_genpd_add_provider(struct device_node *np, genpd_xlate_t xlate, | 271 | int __of_genpd_add_provider(struct device_node *np, genpd_xlate_t xlate, |
| 272 | void *data); | 272 | void *data); |
| 273 | void of_genpd_del_provider(struct device_node *np); | 273 | void of_genpd_del_provider(struct device_node *np); |
| 274 | struct generic_pm_domain *of_genpd_get_from_provider( | ||
| 275 | struct of_phandle_args *genpdspec); | ||
| 274 | 276 | ||
| 275 | struct generic_pm_domain *__of_genpd_xlate_simple( | 277 | struct generic_pm_domain *__of_genpd_xlate_simple( |
| 276 | struct of_phandle_args *genpdspec, | 278 | struct of_phandle_args *genpdspec, |
| @@ -288,6 +290,12 @@ static inline int __of_genpd_add_provider(struct device_node *np, | |||
| 288 | } | 290 | } |
| 289 | static inline void of_genpd_del_provider(struct device_node *np) {} | 291 | static inline void of_genpd_del_provider(struct device_node *np) {} |
| 290 | 292 | ||
| 293 | static inline struct generic_pm_domain *of_genpd_get_from_provider( | ||
| 294 | struct of_phandle_args *genpdspec) | ||
| 295 | { | ||
| 296 | return NULL; | ||
| 297 | } | ||
| 298 | |||
| 291 | #define __of_genpd_xlate_simple NULL | 299 | #define __of_genpd_xlate_simple NULL |
| 292 | #define __of_genpd_xlate_onecell NULL | 300 | #define __of_genpd_xlate_onecell NULL |
| 293 | 301 | ||
diff --git a/include/linux/thermal.h b/include/linux/thermal.h index c611a02fbc51..fc52e307efab 100644 --- a/include/linux/thermal.h +++ b/include/linux/thermal.h | |||
| @@ -38,7 +38,7 @@ | |||
| 38 | #define THERMAL_CSTATE_INVALID -1UL | 38 | #define THERMAL_CSTATE_INVALID -1UL |
| 39 | 39 | ||
| 40 | /* No upper/lower limit requirement */ | 40 | /* No upper/lower limit requirement */ |
| 41 | #define THERMAL_NO_LIMIT THERMAL_CSTATE_INVALID | 41 | #define THERMAL_NO_LIMIT ((u32)~0) |
| 42 | 42 | ||
| 43 | /* Unit conversion macros */ | 43 | /* Unit conversion macros */ |
| 44 | #define KELVIN_TO_CELSIUS(t) (long)(((long)t-2732 >= 0) ? \ | 44 | #define KELVIN_TO_CELSIUS(t) (long)(((long)t-2732 >= 0) ? \ |
diff --git a/include/net/genetlink.h b/include/net/genetlink.h index af10c2cf8a1d..84125088c309 100644 --- a/include/net/genetlink.h +++ b/include/net/genetlink.h | |||
| @@ -31,6 +31,9 @@ struct genl_info; | |||
| 31 | * do additional, common, filtering and return an error | 31 | * do additional, common, filtering and return an error |
| 32 | * @post_doit: called after an operation's doit callback, it may | 32 | * @post_doit: called after an operation's doit callback, it may |
| 33 | * undo operations done by pre_doit, for example release locks | 33 | * undo operations done by pre_doit, for example release locks |
| 34 | * @mcast_bind: a socket bound to the given multicast group (which | ||
| 35 | * is given as the offset into the groups array) | ||
| 36 | * @mcast_unbind: a socket was unbound from the given multicast group | ||
| 34 | * @attrbuf: buffer to store parsed attributes | 37 | * @attrbuf: buffer to store parsed attributes |
| 35 | * @family_list: family list | 38 | * @family_list: family list |
| 36 | * @mcgrps: multicast groups used by this family (private) | 39 | * @mcgrps: multicast groups used by this family (private) |
| @@ -53,6 +56,8 @@ struct genl_family { | |||
| 53 | void (*post_doit)(const struct genl_ops *ops, | 56 | void (*post_doit)(const struct genl_ops *ops, |
| 54 | struct sk_buff *skb, | 57 | struct sk_buff *skb, |
| 55 | struct genl_info *info); | 58 | struct genl_info *info); |
| 59 | int (*mcast_bind)(struct net *net, int group); | ||
| 60 | void (*mcast_unbind)(struct net *net, int group); | ||
| 56 | struct nlattr ** attrbuf; /* private */ | 61 | struct nlattr ** attrbuf; /* private */ |
| 57 | const struct genl_ops * ops; /* private */ | 62 | const struct genl_ops * ops; /* private */ |
| 58 | const struct genl_multicast_group *mcgrps; /* private */ | 63 | const struct genl_multicast_group *mcgrps; /* private */ |
| @@ -395,11 +400,11 @@ static inline int genl_set_err(struct genl_family *family, struct net *net, | |||
| 395 | } | 400 | } |
| 396 | 401 | ||
| 397 | static inline int genl_has_listeners(struct genl_family *family, | 402 | static inline int genl_has_listeners(struct genl_family *family, |
| 398 | struct sock *sk, unsigned int group) | 403 | struct net *net, unsigned int group) |
| 399 | { | 404 | { |
| 400 | if (WARN_ON_ONCE(group >= family->n_mcgrps)) | 405 | if (WARN_ON_ONCE(group >= family->n_mcgrps)) |
| 401 | return -EINVAL; | 406 | return -EINVAL; |
| 402 | group = family->mcgrp_offset + group; | 407 | group = family->mcgrp_offset + group; |
| 403 | return netlink_has_listeners(sk, group); | 408 | return netlink_has_listeners(net->genl_sock, group); |
| 404 | } | 409 | } |
| 405 | #endif /* __NET_GENERIC_NETLINK_H */ | 410 | #endif /* __NET_GENERIC_NETLINK_H */ |
diff --git a/include/net/neighbour.h b/include/net/neighbour.h index eb070b3674a1..76f708486aae 100644 --- a/include/net/neighbour.h +++ b/include/net/neighbour.h | |||
| @@ -190,7 +190,6 @@ struct neigh_hash_table { | |||
| 190 | 190 | ||
| 191 | 191 | ||
| 192 | struct neigh_table { | 192 | struct neigh_table { |
| 193 | struct neigh_table *next; | ||
| 194 | int family; | 193 | int family; |
| 195 | int entry_size; | 194 | int entry_size; |
| 196 | int key_len; | 195 | int key_len; |
diff --git a/include/net/vxlan.h b/include/net/vxlan.h index 57cccd0052e5..903461aa5644 100644 --- a/include/net/vxlan.h +++ b/include/net/vxlan.h | |||
| @@ -1,6 +1,9 @@ | |||
| 1 | #ifndef __NET_VXLAN_H | 1 | #ifndef __NET_VXLAN_H |
| 2 | #define __NET_VXLAN_H 1 | 2 | #define __NET_VXLAN_H 1 |
| 3 | 3 | ||
| 4 | #include <linux/ip.h> | ||
| 5 | #include <linux/ipv6.h> | ||
| 6 | #include <linux/if_vlan.h> | ||
| 4 | #include <linux/skbuff.h> | 7 | #include <linux/skbuff.h> |
| 5 | #include <linux/netdevice.h> | 8 | #include <linux/netdevice.h> |
| 6 | #include <linux/udp.h> | 9 | #include <linux/udp.h> |
| @@ -51,16 +54,33 @@ int vxlan_xmit_skb(struct vxlan_sock *vs, | |||
| 51 | __be32 src, __be32 dst, __u8 tos, __u8 ttl, __be16 df, | 54 | __be32 src, __be32 dst, __u8 tos, __u8 ttl, __be16 df, |
| 52 | __be16 src_port, __be16 dst_port, __be32 vni, bool xnet); | 55 | __be16 src_port, __be16 dst_port, __be32 vni, bool xnet); |
| 53 | 56 | ||
| 54 | static inline bool vxlan_gso_check(struct sk_buff *skb) | 57 | static inline netdev_features_t vxlan_features_check(struct sk_buff *skb, |
| 58 | netdev_features_t features) | ||
| 55 | { | 59 | { |
| 56 | if ((skb_shinfo(skb)->gso_type & SKB_GSO_UDP_TUNNEL) && | 60 | u8 l4_hdr = 0; |
| 61 | |||
| 62 | if (!skb->encapsulation) | ||
| 63 | return features; | ||
| 64 | |||
| 65 | switch (vlan_get_protocol(skb)) { | ||
| 66 | case htons(ETH_P_IP): | ||
| 67 | l4_hdr = ip_hdr(skb)->protocol; | ||
| 68 | break; | ||
| 69 | case htons(ETH_P_IPV6): | ||
| 70 | l4_hdr = ipv6_hdr(skb)->nexthdr; | ||
| 71 | break; | ||
| 72 | default: | ||
| 73 | return features;; | ||
| 74 | } | ||
| 75 | |||
| 76 | if ((l4_hdr == IPPROTO_UDP) && | ||
| 57 | (skb->inner_protocol_type != ENCAP_TYPE_ETHER || | 77 | (skb->inner_protocol_type != ENCAP_TYPE_ETHER || |
| 58 | skb->inner_protocol != htons(ETH_P_TEB) || | 78 | skb->inner_protocol != htons(ETH_P_TEB) || |
| 59 | (skb_inner_mac_header(skb) - skb_transport_header(skb) != | 79 | (skb_inner_mac_header(skb) - skb_transport_header(skb) != |
| 60 | sizeof(struct udphdr) + sizeof(struct vxlanhdr)))) | 80 | sizeof(struct udphdr) + sizeof(struct vxlanhdr)))) |
| 61 | return false; | 81 | return features & ~(NETIF_F_ALL_CSUM | NETIF_F_GSO_MASK); |
| 62 | 82 | ||
| 63 | return true; | 83 | return features; |
| 64 | } | 84 | } |
| 65 | 85 | ||
| 66 | /* IP header + UDP + VXLAN + Ethernet header */ | 86 | /* IP header + UDP + VXLAN + Ethernet header */ |
diff --git a/include/sound/pcm.h b/include/sound/pcm.h index 1e7f74acc2ec..b429b73e875e 100644 --- a/include/sound/pcm.h +++ b/include/sound/pcm.h | |||
| @@ -857,7 +857,7 @@ static inline unsigned int params_channels(const struct snd_pcm_hw_params *p) | |||
| 857 | } | 857 | } |
| 858 | 858 | ||
| 859 | /** | 859 | /** |
| 860 | * params_channels - Get the sample rate from the hw params | 860 | * params_rate - Get the sample rate from the hw params |
| 861 | * @p: hw params | 861 | * @p: hw params |
| 862 | */ | 862 | */ |
| 863 | static inline unsigned int params_rate(const struct snd_pcm_hw_params *p) | 863 | static inline unsigned int params_rate(const struct snd_pcm_hw_params *p) |
| @@ -866,7 +866,7 @@ static inline unsigned int params_rate(const struct snd_pcm_hw_params *p) | |||
| 866 | } | 866 | } |
| 867 | 867 | ||
| 868 | /** | 868 | /** |
| 869 | * params_channels - Get the period size (in frames) from the hw params | 869 | * params_period_size - Get the period size (in frames) from the hw params |
| 870 | * @p: hw params | 870 | * @p: hw params |
| 871 | */ | 871 | */ |
| 872 | static inline unsigned int params_period_size(const struct snd_pcm_hw_params *p) | 872 | static inline unsigned int params_period_size(const struct snd_pcm_hw_params *p) |
| @@ -875,7 +875,7 @@ static inline unsigned int params_period_size(const struct snd_pcm_hw_params *p) | |||
| 875 | } | 875 | } |
| 876 | 876 | ||
| 877 | /** | 877 | /** |
| 878 | * params_channels - Get the number of periods from the hw params | 878 | * params_periods - Get the number of periods from the hw params |
| 879 | * @p: hw params | 879 | * @p: hw params |
| 880 | */ | 880 | */ |
| 881 | static inline unsigned int params_periods(const struct snd_pcm_hw_params *p) | 881 | static inline unsigned int params_periods(const struct snd_pcm_hw_params *p) |
| @@ -884,7 +884,7 @@ static inline unsigned int params_periods(const struct snd_pcm_hw_params *p) | |||
| 884 | } | 884 | } |
| 885 | 885 | ||
| 886 | /** | 886 | /** |
| 887 | * params_channels - Get the buffer size (in frames) from the hw params | 887 | * params_buffer_size - Get the buffer size (in frames) from the hw params |
| 888 | * @p: hw params | 888 | * @p: hw params |
| 889 | */ | 889 | */ |
| 890 | static inline unsigned int params_buffer_size(const struct snd_pcm_hw_params *p) | 890 | static inline unsigned int params_buffer_size(const struct snd_pcm_hw_params *p) |
| @@ -893,7 +893,7 @@ static inline unsigned int params_buffer_size(const struct snd_pcm_hw_params *p) | |||
| 893 | } | 893 | } |
| 894 | 894 | ||
| 895 | /** | 895 | /** |
| 896 | * params_channels - Get the buffer size (in bytes) from the hw params | 896 | * params_buffer_bytes - Get the buffer size (in bytes) from the hw params |
| 897 | * @p: hw params | 897 | * @p: hw params |
| 898 | */ | 898 | */ |
| 899 | static inline unsigned int params_buffer_bytes(const struct snd_pcm_hw_params *p) | 899 | static inline unsigned int params_buffer_bytes(const struct snd_pcm_hw_params *p) |
diff --git a/include/uapi/linux/in6.h b/include/uapi/linux/in6.h index 74a2a1773494..79b12b004ade 100644 --- a/include/uapi/linux/in6.h +++ b/include/uapi/linux/in6.h | |||
| @@ -149,7 +149,7 @@ struct in6_flowlabel_req { | |||
| 149 | /* | 149 | /* |
| 150 | * IPV6 socket options | 150 | * IPV6 socket options |
| 151 | */ | 151 | */ |
| 152 | 152 | #if __UAPI_DEF_IPV6_OPTIONS | |
| 153 | #define IPV6_ADDRFORM 1 | 153 | #define IPV6_ADDRFORM 1 |
| 154 | #define IPV6_2292PKTINFO 2 | 154 | #define IPV6_2292PKTINFO 2 |
| 155 | #define IPV6_2292HOPOPTS 3 | 155 | #define IPV6_2292HOPOPTS 3 |
| @@ -196,6 +196,7 @@ struct in6_flowlabel_req { | |||
| 196 | 196 | ||
| 197 | #define IPV6_IPSEC_POLICY 34 | 197 | #define IPV6_IPSEC_POLICY 34 |
| 198 | #define IPV6_XFRM_POLICY 35 | 198 | #define IPV6_XFRM_POLICY 35 |
| 199 | #endif | ||
| 199 | 200 | ||
| 200 | /* | 201 | /* |
| 201 | * Multicast: | 202 | * Multicast: |
diff --git a/include/uapi/linux/libc-compat.h b/include/uapi/linux/libc-compat.h index c140620dad92..e28807ad17fa 100644 --- a/include/uapi/linux/libc-compat.h +++ b/include/uapi/linux/libc-compat.h | |||
| @@ -69,6 +69,7 @@ | |||
| 69 | #define __UAPI_DEF_SOCKADDR_IN6 0 | 69 | #define __UAPI_DEF_SOCKADDR_IN6 0 |
| 70 | #define __UAPI_DEF_IPV6_MREQ 0 | 70 | #define __UAPI_DEF_IPV6_MREQ 0 |
| 71 | #define __UAPI_DEF_IPPROTO_V6 0 | 71 | #define __UAPI_DEF_IPPROTO_V6 0 |
| 72 | #define __UAPI_DEF_IPV6_OPTIONS 0 | ||
| 72 | 73 | ||
| 73 | #else | 74 | #else |
| 74 | 75 | ||
| @@ -82,6 +83,7 @@ | |||
| 82 | #define __UAPI_DEF_SOCKADDR_IN6 1 | 83 | #define __UAPI_DEF_SOCKADDR_IN6 1 |
| 83 | #define __UAPI_DEF_IPV6_MREQ 1 | 84 | #define __UAPI_DEF_IPV6_MREQ 1 |
| 84 | #define __UAPI_DEF_IPPROTO_V6 1 | 85 | #define __UAPI_DEF_IPPROTO_V6 1 |
| 86 | #define __UAPI_DEF_IPV6_OPTIONS 1 | ||
| 85 | 87 | ||
| 86 | #endif /* _NETINET_IN_H */ | 88 | #endif /* _NETINET_IN_H */ |
| 87 | 89 | ||
| @@ -103,6 +105,7 @@ | |||
| 103 | #define __UAPI_DEF_SOCKADDR_IN6 1 | 105 | #define __UAPI_DEF_SOCKADDR_IN6 1 |
| 104 | #define __UAPI_DEF_IPV6_MREQ 1 | 106 | #define __UAPI_DEF_IPV6_MREQ 1 |
| 105 | #define __UAPI_DEF_IPPROTO_V6 1 | 107 | #define __UAPI_DEF_IPPROTO_V6 1 |
| 108 | #define __UAPI_DEF_IPV6_OPTIONS 1 | ||
| 106 | 109 | ||
| 107 | /* Definitions for xattr.h */ | 110 | /* Definitions for xattr.h */ |
| 108 | #define __UAPI_DEF_XATTR 1 | 111 | #define __UAPI_DEF_XATTR 1 |
diff --git a/include/uapi/linux/virtio_ring.h b/include/uapi/linux/virtio_ring.h index 61c818a7fe70..a3318f31e8e7 100644 --- a/include/uapi/linux/virtio_ring.h +++ b/include/uapi/linux/virtio_ring.h | |||
| @@ -101,6 +101,13 @@ struct vring { | |||
| 101 | struct vring_used *used; | 101 | struct vring_used *used; |
| 102 | }; | 102 | }; |
| 103 | 103 | ||
| 104 | /* Alignment requirements for vring elements. | ||
| 105 | * When using pre-virtio 1.0 layout, these fall out naturally. | ||
| 106 | */ | ||
| 107 | #define VRING_AVAIL_ALIGN_SIZE 2 | ||
| 108 | #define VRING_USED_ALIGN_SIZE 4 | ||
| 109 | #define VRING_DESC_ALIGN_SIZE 16 | ||
| 110 | |||
| 104 | /* The standard layout for the ring is a continuous chunk of memory which looks | 111 | /* The standard layout for the ring is a continuous chunk of memory which looks |
| 105 | * like this. We assume num is a power of 2. | 112 | * like this. We assume num is a power of 2. |
| 106 | * | 113 | * |
diff --git a/kernel/audit.c b/kernel/audit.c index f8f203e8018c..72ab759a0b43 100644 --- a/kernel/audit.c +++ b/kernel/audit.c | |||
| @@ -429,7 +429,7 @@ static void kauditd_send_skb(struct sk_buff *skb) | |||
| 429 | * This function doesn't consume an skb as might be expected since it has to | 429 | * This function doesn't consume an skb as might be expected since it has to |
| 430 | * copy it anyways. | 430 | * copy it anyways. |
| 431 | */ | 431 | */ |
| 432 | static void kauditd_send_multicast_skb(struct sk_buff *skb) | 432 | static void kauditd_send_multicast_skb(struct sk_buff *skb, gfp_t gfp_mask) |
| 433 | { | 433 | { |
| 434 | struct sk_buff *copy; | 434 | struct sk_buff *copy; |
| 435 | struct audit_net *aunet = net_generic(&init_net, audit_net_id); | 435 | struct audit_net *aunet = net_generic(&init_net, audit_net_id); |
| @@ -448,11 +448,11 @@ static void kauditd_send_multicast_skb(struct sk_buff *skb) | |||
| 448 | * no reason for new multicast clients to continue with this | 448 | * no reason for new multicast clients to continue with this |
| 449 | * non-compliance. | 449 | * non-compliance. |
| 450 | */ | 450 | */ |
| 451 | copy = skb_copy(skb, GFP_KERNEL); | 451 | copy = skb_copy(skb, gfp_mask); |
| 452 | if (!copy) | 452 | if (!copy) |
| 453 | return; | 453 | return; |
| 454 | 454 | ||
| 455 | nlmsg_multicast(sock, copy, 0, AUDIT_NLGRP_READLOG, GFP_KERNEL); | 455 | nlmsg_multicast(sock, copy, 0, AUDIT_NLGRP_READLOG, gfp_mask); |
| 456 | } | 456 | } |
| 457 | 457 | ||
| 458 | /* | 458 | /* |
| @@ -1100,7 +1100,7 @@ static void audit_receive(struct sk_buff *skb) | |||
| 1100 | } | 1100 | } |
| 1101 | 1101 | ||
| 1102 | /* Run custom bind function on netlink socket group connect or bind requests. */ | 1102 | /* Run custom bind function on netlink socket group connect or bind requests. */ |
| 1103 | static int audit_bind(int group) | 1103 | static int audit_bind(struct net *net, int group) |
| 1104 | { | 1104 | { |
| 1105 | if (!capable(CAP_AUDIT_READ)) | 1105 | if (!capable(CAP_AUDIT_READ)) |
| 1106 | return -EPERM; | 1106 | return -EPERM; |
| @@ -1940,7 +1940,7 @@ void audit_log_end(struct audit_buffer *ab) | |||
| 1940 | struct nlmsghdr *nlh = nlmsg_hdr(ab->skb); | 1940 | struct nlmsghdr *nlh = nlmsg_hdr(ab->skb); |
| 1941 | 1941 | ||
| 1942 | nlh->nlmsg_len = ab->skb->len; | 1942 | nlh->nlmsg_len = ab->skb->len; |
| 1943 | kauditd_send_multicast_skb(ab->skb); | 1943 | kauditd_send_multicast_skb(ab->skb, ab->gfp_mask); |
| 1944 | 1944 | ||
| 1945 | /* | 1945 | /* |
| 1946 | * The original kaudit unicast socket sends up messages with | 1946 | * The original kaudit unicast socket sends up messages with |
diff --git a/kernel/auditfilter.c b/kernel/auditfilter.c index 3598e13f2a65..4f68a326d92e 100644 --- a/kernel/auditfilter.c +++ b/kernel/auditfilter.c | |||
| @@ -442,19 +442,7 @@ static struct audit_entry *audit_data_to_entry(struct audit_rule_data *data, | |||
| 442 | if ((f->type == AUDIT_LOGINUID) && (f->val == AUDIT_UID_UNSET)) { | 442 | if ((f->type == AUDIT_LOGINUID) && (f->val == AUDIT_UID_UNSET)) { |
| 443 | f->type = AUDIT_LOGINUID_SET; | 443 | f->type = AUDIT_LOGINUID_SET; |
| 444 | f->val = 0; | 444 | f->val = 0; |
| 445 | } | 445 | entry->rule.pflags |= AUDIT_LOGINUID_LEGACY; |
| 446 | |||
| 447 | if ((f->type == AUDIT_PID) || (f->type == AUDIT_PPID)) { | ||
| 448 | struct pid *pid; | ||
| 449 | rcu_read_lock(); | ||
| 450 | pid = find_vpid(f->val); | ||
| 451 | if (!pid) { | ||
| 452 | rcu_read_unlock(); | ||
| 453 | err = -ESRCH; | ||
| 454 | goto exit_free; | ||
| 455 | } | ||
| 456 | f->val = pid_nr(pid); | ||
| 457 | rcu_read_unlock(); | ||
| 458 | } | 446 | } |
| 459 | 447 | ||
| 460 | err = audit_field_valid(entry, f); | 448 | err = audit_field_valid(entry, f); |
| @@ -630,6 +618,13 @@ static struct audit_rule_data *audit_krule_to_data(struct audit_krule *krule) | |||
| 630 | data->buflen += data->values[i] = | 618 | data->buflen += data->values[i] = |
| 631 | audit_pack_string(&bufp, krule->filterkey); | 619 | audit_pack_string(&bufp, krule->filterkey); |
| 632 | break; | 620 | break; |
| 621 | case AUDIT_LOGINUID_SET: | ||
| 622 | if (krule->pflags & AUDIT_LOGINUID_LEGACY && !f->val) { | ||
| 623 | data->fields[i] = AUDIT_LOGINUID; | ||
| 624 | data->values[i] = AUDIT_UID_UNSET; | ||
| 625 | break; | ||
| 626 | } | ||
| 627 | /* fallthrough if set */ | ||
| 633 | default: | 628 | default: |
| 634 | data->values[i] = f->val; | 629 | data->values[i] = f->val; |
| 635 | } | 630 | } |
| @@ -646,6 +641,7 @@ static int audit_compare_rule(struct audit_krule *a, struct audit_krule *b) | |||
| 646 | int i; | 641 | int i; |
| 647 | 642 | ||
| 648 | if (a->flags != b->flags || | 643 | if (a->flags != b->flags || |
| 644 | a->pflags != b->pflags || | ||
| 649 | a->listnr != b->listnr || | 645 | a->listnr != b->listnr || |
| 650 | a->action != b->action || | 646 | a->action != b->action || |
| 651 | a->field_count != b->field_count) | 647 | a->field_count != b->field_count) |
| @@ -764,6 +760,7 @@ struct audit_entry *audit_dupe_rule(struct audit_krule *old) | |||
| 764 | new = &entry->rule; | 760 | new = &entry->rule; |
| 765 | new->vers_ops = old->vers_ops; | 761 | new->vers_ops = old->vers_ops; |
| 766 | new->flags = old->flags; | 762 | new->flags = old->flags; |
| 763 | new->pflags = old->pflags; | ||
| 767 | new->listnr = old->listnr; | 764 | new->listnr = old->listnr; |
| 768 | new->action = old->action; | 765 | new->action = old->action; |
| 769 | for (i = 0; i < AUDIT_BITMASK_SIZE; i++) | 766 | for (i = 0; i < AUDIT_BITMASK_SIZE; i++) |
diff --git a/kernel/auditsc.c b/kernel/auditsc.c index c75522a83678..072566dd0caf 100644 --- a/kernel/auditsc.c +++ b/kernel/auditsc.c | |||
| @@ -72,6 +72,8 @@ | |||
| 72 | #include <linux/fs_struct.h> | 72 | #include <linux/fs_struct.h> |
| 73 | #include <linux/compat.h> | 73 | #include <linux/compat.h> |
| 74 | #include <linux/ctype.h> | 74 | #include <linux/ctype.h> |
| 75 | #include <linux/string.h> | ||
| 76 | #include <uapi/linux/limits.h> | ||
| 75 | 77 | ||
| 76 | #include "audit.h" | 78 | #include "audit.h" |
| 77 | 79 | ||
| @@ -1861,8 +1863,7 @@ void __audit_inode(struct filename *name, const struct dentry *dentry, | |||
| 1861 | } | 1863 | } |
| 1862 | 1864 | ||
| 1863 | list_for_each_entry_reverse(n, &context->names_list, list) { | 1865 | list_for_each_entry_reverse(n, &context->names_list, list) { |
| 1864 | /* does the name pointer match? */ | 1866 | if (!n->name || strcmp(n->name->name, name->name)) |
| 1865 | if (!n->name || n->name->name != name->name) | ||
| 1866 | continue; | 1867 | continue; |
| 1867 | 1868 | ||
| 1868 | /* match the correct record type */ | 1869 | /* match the correct record type */ |
| @@ -1877,12 +1878,48 @@ void __audit_inode(struct filename *name, const struct dentry *dentry, | |||
| 1877 | } | 1878 | } |
| 1878 | 1879 | ||
| 1879 | out_alloc: | 1880 | out_alloc: |
| 1880 | /* unable to find the name from a previous getname(). Allocate a new | 1881 | /* unable to find an entry with both a matching name and type */ |
| 1881 | * anonymous entry. | 1882 | n = audit_alloc_name(context, AUDIT_TYPE_UNKNOWN); |
| 1882 | */ | ||
| 1883 | n = audit_alloc_name(context, AUDIT_TYPE_NORMAL); | ||
| 1884 | if (!n) | 1883 | if (!n) |
| 1885 | return; | 1884 | return; |
| 1885 | /* unfortunately, while we may have a path name to record with the | ||
| 1886 | * inode, we can't always rely on the string lasting until the end of | ||
| 1887 | * the syscall so we need to create our own copy, it may fail due to | ||
| 1888 | * memory allocation issues, but we do our best */ | ||
| 1889 | if (name) { | ||
| 1890 | /* we can't use getname_kernel() due to size limits */ | ||
| 1891 | size_t len = strlen(name->name) + 1; | ||
| 1892 | struct filename *new = __getname(); | ||
| 1893 | |||
| 1894 | if (unlikely(!new)) | ||
| 1895 | goto out; | ||
| 1896 | |||
| 1897 | if (len <= (PATH_MAX - sizeof(*new))) { | ||
| 1898 | new->name = (char *)(new) + sizeof(*new); | ||
| 1899 | new->separate = false; | ||
| 1900 | } else if (len <= PATH_MAX) { | ||
| 1901 | /* this looks odd, but is due to final_putname() */ | ||
| 1902 | struct filename *new2; | ||
| 1903 | |||
| 1904 | new2 = kmalloc(sizeof(*new2), GFP_KERNEL); | ||
| 1905 | if (unlikely(!new2)) { | ||
| 1906 | __putname(new); | ||
| 1907 | goto out; | ||
| 1908 | } | ||
| 1909 | new2->name = (char *)new; | ||
| 1910 | new2->separate = true; | ||
| 1911 | new = new2; | ||
| 1912 | } else { | ||
| 1913 | /* we should never get here, but let's be safe */ | ||
| 1914 | __putname(new); | ||
| 1915 | goto out; | ||
| 1916 | } | ||
| 1917 | strlcpy((char *)new->name, name->name, len); | ||
| 1918 | new->uptr = NULL; | ||
| 1919 | new->aname = n; | ||
| 1920 | n->name = new; | ||
| 1921 | n->name_put = true; | ||
| 1922 | } | ||
| 1886 | out: | 1923 | out: |
| 1887 | if (parent) { | 1924 | if (parent) { |
| 1888 | n->name_len = n->name ? parent_len(n->name->name) : AUDIT_NAME_FULL; | 1925 | n->name_len = n->name ? parent_len(n->name->name) : AUDIT_NAME_FULL; |
diff --git a/kernel/kprobes.c b/kernel/kprobes.c index 06f58309fed2..bad4e959f2f7 100644 --- a/kernel/kprobes.c +++ b/kernel/kprobes.c | |||
| @@ -717,7 +717,7 @@ static void prepare_optimized_kprobe(struct kprobe *p) | |||
| 717 | struct optimized_kprobe *op; | 717 | struct optimized_kprobe *op; |
| 718 | 718 | ||
| 719 | op = container_of(p, struct optimized_kprobe, kp); | 719 | op = container_of(p, struct optimized_kprobe, kp); |
| 720 | arch_prepare_optimized_kprobe(op); | 720 | arch_prepare_optimized_kprobe(op, p); |
| 721 | } | 721 | } |
| 722 | 722 | ||
| 723 | /* Allocate new optimized_kprobe and try to prepare optimized instructions */ | 723 | /* Allocate new optimized_kprobe and try to prepare optimized instructions */ |
| @@ -731,7 +731,7 @@ static struct kprobe *alloc_aggr_kprobe(struct kprobe *p) | |||
| 731 | 731 | ||
| 732 | INIT_LIST_HEAD(&op->list); | 732 | INIT_LIST_HEAD(&op->list); |
| 733 | op->kp.addr = p->addr; | 733 | op->kp.addr = p->addr; |
| 734 | arch_prepare_optimized_kprobe(op); | 734 | arch_prepare_optimized_kprobe(op, p); |
| 735 | 735 | ||
| 736 | return &op->kp; | 736 | return &op->kp; |
| 737 | } | 737 | } |
diff --git a/mm/filemap.c b/mm/filemap.c index bd8543c6508f..673e4581a2e5 100644 --- a/mm/filemap.c +++ b/mm/filemap.c | |||
| @@ -1046,8 +1046,7 @@ EXPORT_SYMBOL(find_lock_entry); | |||
| 1046 | * @mapping: the address_space to search | 1046 | * @mapping: the address_space to search |
| 1047 | * @offset: the page index | 1047 | * @offset: the page index |
| 1048 | * @fgp_flags: PCG flags | 1048 | * @fgp_flags: PCG flags |
| 1049 | * @cache_gfp_mask: gfp mask to use for the page cache data page allocation | 1049 | * @gfp_mask: gfp mask to use for the page cache data page allocation |
| 1050 | * @radix_gfp_mask: gfp mask to use for radix tree node allocation | ||
| 1051 | * | 1050 | * |
| 1052 | * Looks up the page cache slot at @mapping & @offset. | 1051 | * Looks up the page cache slot at @mapping & @offset. |
| 1053 | * | 1052 | * |
| @@ -1056,11 +1055,9 @@ EXPORT_SYMBOL(find_lock_entry); | |||
| 1056 | * FGP_ACCESSED: the page will be marked accessed | 1055 | * FGP_ACCESSED: the page will be marked accessed |
| 1057 | * FGP_LOCK: Page is return locked | 1056 | * FGP_LOCK: Page is return locked |
| 1058 | * FGP_CREAT: If page is not present then a new page is allocated using | 1057 | * FGP_CREAT: If page is not present then a new page is allocated using |
| 1059 | * @cache_gfp_mask and added to the page cache and the VM's LRU | 1058 | * @gfp_mask and added to the page cache and the VM's LRU |
| 1060 | * list. If radix tree nodes are allocated during page cache | 1059 | * list. The page is returned locked and with an increased |
| 1061 | * insertion then @radix_gfp_mask is used. The page is returned | 1060 | * refcount. Otherwise, %NULL is returned. |
| 1062 | * locked and with an increased refcount. Otherwise, %NULL is | ||
| 1063 | * returned. | ||
| 1064 | * | 1061 | * |
| 1065 | * If FGP_LOCK or FGP_CREAT are specified then the function may sleep even | 1062 | * If FGP_LOCK or FGP_CREAT are specified then the function may sleep even |
| 1066 | * if the GFP flags specified for FGP_CREAT are atomic. | 1063 | * if the GFP flags specified for FGP_CREAT are atomic. |
| @@ -1068,7 +1065,7 @@ EXPORT_SYMBOL(find_lock_entry); | |||
| 1068 | * If there is a page cache page, it is returned with an increased refcount. | 1065 | * If there is a page cache page, it is returned with an increased refcount. |
| 1069 | */ | 1066 | */ |
| 1070 | struct page *pagecache_get_page(struct address_space *mapping, pgoff_t offset, | 1067 | struct page *pagecache_get_page(struct address_space *mapping, pgoff_t offset, |
| 1071 | int fgp_flags, gfp_t cache_gfp_mask, gfp_t radix_gfp_mask) | 1068 | int fgp_flags, gfp_t gfp_mask) |
| 1072 | { | 1069 | { |
| 1073 | struct page *page; | 1070 | struct page *page; |
| 1074 | 1071 | ||
| @@ -1105,13 +1102,11 @@ no_page: | |||
| 1105 | if (!page && (fgp_flags & FGP_CREAT)) { | 1102 | if (!page && (fgp_flags & FGP_CREAT)) { |
| 1106 | int err; | 1103 | int err; |
| 1107 | if ((fgp_flags & FGP_WRITE) && mapping_cap_account_dirty(mapping)) | 1104 | if ((fgp_flags & FGP_WRITE) && mapping_cap_account_dirty(mapping)) |
| 1108 | cache_gfp_mask |= __GFP_WRITE; | 1105 | gfp_mask |= __GFP_WRITE; |
| 1109 | if (fgp_flags & FGP_NOFS) { | 1106 | if (fgp_flags & FGP_NOFS) |
| 1110 | cache_gfp_mask &= ~__GFP_FS; | 1107 | gfp_mask &= ~__GFP_FS; |
| 1111 | radix_gfp_mask &= ~__GFP_FS; | ||
| 1112 | } | ||
| 1113 | 1108 | ||
| 1114 | page = __page_cache_alloc(cache_gfp_mask); | 1109 | page = __page_cache_alloc(gfp_mask); |
| 1115 | if (!page) | 1110 | if (!page) |
| 1116 | return NULL; | 1111 | return NULL; |
| 1117 | 1112 | ||
| @@ -1122,7 +1117,8 @@ no_page: | |||
| 1122 | if (fgp_flags & FGP_ACCESSED) | 1117 | if (fgp_flags & FGP_ACCESSED) |
| 1123 | __SetPageReferenced(page); | 1118 | __SetPageReferenced(page); |
| 1124 | 1119 | ||
| 1125 | err = add_to_page_cache_lru(page, mapping, offset, radix_gfp_mask); | 1120 | err = add_to_page_cache_lru(page, mapping, offset, |
| 1121 | gfp_mask & GFP_RECLAIM_MASK); | ||
| 1126 | if (unlikely(err)) { | 1122 | if (unlikely(err)) { |
| 1127 | page_cache_release(page); | 1123 | page_cache_release(page); |
| 1128 | page = NULL; | 1124 | page = NULL; |
| @@ -2443,8 +2439,7 @@ struct page *grab_cache_page_write_begin(struct address_space *mapping, | |||
| 2443 | fgp_flags |= FGP_NOFS; | 2439 | fgp_flags |= FGP_NOFS; |
| 2444 | 2440 | ||
| 2445 | page = pagecache_get_page(mapping, index, fgp_flags, | 2441 | page = pagecache_get_page(mapping, index, fgp_flags, |
| 2446 | mapping_gfp_mask(mapping), | 2442 | mapping_gfp_mask(mapping)); |
| 2447 | GFP_KERNEL); | ||
| 2448 | if (page) | 2443 | if (page) |
| 2449 | wait_for_stable_page(page); | 2444 | wait_for_stable_page(page); |
| 2450 | 2445 | ||
diff --git a/mm/memory.c b/mm/memory.c index 649e7d440bd7..ca920d1fd314 100644 --- a/mm/memory.c +++ b/mm/memory.c | |||
| @@ -2378,12 +2378,12 @@ void unmap_mapping_range(struct address_space *mapping, | |||
| 2378 | details.last_index = ULONG_MAX; | 2378 | details.last_index = ULONG_MAX; |
| 2379 | 2379 | ||
| 2380 | 2380 | ||
| 2381 | i_mmap_lock_read(mapping); | 2381 | i_mmap_lock_write(mapping); |
| 2382 | if (unlikely(!RB_EMPTY_ROOT(&mapping->i_mmap))) | 2382 | if (unlikely(!RB_EMPTY_ROOT(&mapping->i_mmap))) |
| 2383 | unmap_mapping_range_tree(&mapping->i_mmap, &details); | 2383 | unmap_mapping_range_tree(&mapping->i_mmap, &details); |
| 2384 | if (unlikely(!list_empty(&mapping->i_mmap_nonlinear))) | 2384 | if (unlikely(!list_empty(&mapping->i_mmap_nonlinear))) |
| 2385 | unmap_mapping_range_list(&mapping->i_mmap_nonlinear, &details); | 2385 | unmap_mapping_range_list(&mapping->i_mmap_nonlinear, &details); |
| 2386 | i_mmap_unlock_read(mapping); | 2386 | i_mmap_unlock_write(mapping); |
| 2387 | } | 2387 | } |
| 2388 | EXPORT_SYMBOL(unmap_mapping_range); | 2388 | EXPORT_SYMBOL(unmap_mapping_range); |
| 2389 | 2389 | ||
diff --git a/net/batman-adv/fragmentation.c b/net/batman-adv/fragmentation.c index fc1835c6bb40..00f9e144cc97 100644 --- a/net/batman-adv/fragmentation.c +++ b/net/batman-adv/fragmentation.c | |||
| @@ -251,7 +251,7 @@ batadv_frag_merge_packets(struct hlist_head *chain, struct sk_buff *skb) | |||
| 251 | kfree(entry); | 251 | kfree(entry); |
| 252 | 252 | ||
| 253 | /* Make room for the rest of the fragments. */ | 253 | /* Make room for the rest of the fragments. */ |
| 254 | if (pskb_expand_head(skb_out, 0, size - skb->len, GFP_ATOMIC) < 0) { | 254 | if (pskb_expand_head(skb_out, 0, size - skb_out->len, GFP_ATOMIC) < 0) { |
| 255 | kfree_skb(skb_out); | 255 | kfree_skb(skb_out); |
| 256 | skb_out = NULL; | 256 | skb_out = NULL; |
| 257 | goto free; | 257 | goto free; |
| @@ -434,7 +434,7 @@ bool batadv_frag_send_packet(struct sk_buff *skb, | |||
| 434 | * fragments larger than BATADV_FRAG_MAX_FRAG_SIZE | 434 | * fragments larger than BATADV_FRAG_MAX_FRAG_SIZE |
| 435 | */ | 435 | */ |
| 436 | mtu = min_t(unsigned, mtu, BATADV_FRAG_MAX_FRAG_SIZE); | 436 | mtu = min_t(unsigned, mtu, BATADV_FRAG_MAX_FRAG_SIZE); |
| 437 | max_fragment_size = (mtu - header_size - ETH_HLEN); | 437 | max_fragment_size = mtu - header_size; |
| 438 | max_packet_size = max_fragment_size * BATADV_FRAG_MAX_FRAGMENTS; | 438 | max_packet_size = max_fragment_size * BATADV_FRAG_MAX_FRAGMENTS; |
| 439 | 439 | ||
| 440 | /* Don't even try to fragment, if we need more than 16 fragments */ | 440 | /* Don't even try to fragment, if we need more than 16 fragments */ |
diff --git a/net/batman-adv/gateway_client.c b/net/batman-adv/gateway_client.c index 90cff585b37d..e0bcf9e84273 100644 --- a/net/batman-adv/gateway_client.c +++ b/net/batman-adv/gateway_client.c | |||
| @@ -810,7 +810,7 @@ bool batadv_gw_out_of_range(struct batadv_priv *bat_priv, | |||
| 810 | goto out; | 810 | goto out; |
| 811 | 811 | ||
| 812 | gw_node = batadv_gw_node_get(bat_priv, orig_dst_node); | 812 | gw_node = batadv_gw_node_get(bat_priv, orig_dst_node); |
| 813 | if (!gw_node->bandwidth_down == 0) | 813 | if (!gw_node) |
| 814 | goto out; | 814 | goto out; |
| 815 | 815 | ||
| 816 | switch (atomic_read(&bat_priv->gw_mode)) { | 816 | switch (atomic_read(&bat_priv->gw_mode)) { |
diff --git a/net/bluetooth/6lowpan.c b/net/bluetooth/6lowpan.c index 76617be1e797..c989253737f0 100644 --- a/net/bluetooth/6lowpan.c +++ b/net/bluetooth/6lowpan.c | |||
| @@ -390,7 +390,6 @@ static int recv_pkt(struct sk_buff *skb, struct net_device *dev, | |||
| 390 | 390 | ||
| 391 | drop: | 391 | drop: |
| 392 | dev->stats.rx_dropped++; | 392 | dev->stats.rx_dropped++; |
| 393 | kfree_skb(skb); | ||
| 394 | return NET_RX_DROP; | 393 | return NET_RX_DROP; |
| 395 | } | 394 | } |
| 396 | 395 | ||
diff --git a/net/bluetooth/bnep/core.c b/net/bluetooth/bnep/core.c index 85bcc21e84d2..ce82722d049b 100644 --- a/net/bluetooth/bnep/core.c +++ b/net/bluetooth/bnep/core.c | |||
| @@ -533,6 +533,9 @@ int bnep_add_connection(struct bnep_connadd_req *req, struct socket *sock) | |||
| 533 | 533 | ||
| 534 | BT_DBG(""); | 534 | BT_DBG(""); |
| 535 | 535 | ||
| 536 | if (!l2cap_is_socket(sock)) | ||
| 537 | return -EBADFD; | ||
| 538 | |||
| 536 | baswap((void *) dst, &l2cap_pi(sock->sk)->chan->dst); | 539 | baswap((void *) dst, &l2cap_pi(sock->sk)->chan->dst); |
| 537 | baswap((void *) src, &l2cap_pi(sock->sk)->chan->src); | 540 | baswap((void *) src, &l2cap_pi(sock->sk)->chan->src); |
| 538 | 541 | ||
diff --git a/net/bluetooth/cmtp/core.c b/net/bluetooth/cmtp/core.c index 67fe5e84e68f..278a194e6af4 100644 --- a/net/bluetooth/cmtp/core.c +++ b/net/bluetooth/cmtp/core.c | |||
| @@ -334,6 +334,9 @@ int cmtp_add_connection(struct cmtp_connadd_req *req, struct socket *sock) | |||
| 334 | 334 | ||
| 335 | BT_DBG(""); | 335 | BT_DBG(""); |
| 336 | 336 | ||
| 337 | if (!l2cap_is_socket(sock)) | ||
| 338 | return -EBADFD; | ||
| 339 | |||
| 337 | session = kzalloc(sizeof(struct cmtp_session), GFP_KERNEL); | 340 | session = kzalloc(sizeof(struct cmtp_session), GFP_KERNEL); |
| 338 | if (!session) | 341 | if (!session) |
| 339 | return -ENOMEM; | 342 | return -ENOMEM; |
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index 39a5c8a01726..3f2e8b830cbd 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c | |||
| @@ -242,7 +242,8 @@ static void hci_cc_read_local_name(struct hci_dev *hdev, struct sk_buff *skb) | |||
| 242 | if (rp->status) | 242 | if (rp->status) |
| 243 | return; | 243 | return; |
| 244 | 244 | ||
| 245 | if (test_bit(HCI_SETUP, &hdev->dev_flags)) | 245 | if (test_bit(HCI_SETUP, &hdev->dev_flags) || |
| 246 | test_bit(HCI_CONFIG, &hdev->dev_flags)) | ||
| 246 | memcpy(hdev->dev_name, rp->name, HCI_MAX_NAME_LENGTH); | 247 | memcpy(hdev->dev_name, rp->name, HCI_MAX_NAME_LENGTH); |
| 247 | } | 248 | } |
| 248 | 249 | ||
| @@ -509,7 +510,8 @@ static void hci_cc_read_local_version(struct hci_dev *hdev, struct sk_buff *skb) | |||
| 509 | if (rp->status) | 510 | if (rp->status) |
| 510 | return; | 511 | return; |
| 511 | 512 | ||
| 512 | if (test_bit(HCI_SETUP, &hdev->dev_flags)) { | 513 | if (test_bit(HCI_SETUP, &hdev->dev_flags) || |
| 514 | test_bit(HCI_CONFIG, &hdev->dev_flags)) { | ||
| 513 | hdev->hci_ver = rp->hci_ver; | 515 | hdev->hci_ver = rp->hci_ver; |
| 514 | hdev->hci_rev = __le16_to_cpu(rp->hci_rev); | 516 | hdev->hci_rev = __le16_to_cpu(rp->hci_rev); |
| 515 | hdev->lmp_ver = rp->lmp_ver; | 517 | hdev->lmp_ver = rp->lmp_ver; |
| @@ -528,7 +530,8 @@ static void hci_cc_read_local_commands(struct hci_dev *hdev, | |||
| 528 | if (rp->status) | 530 | if (rp->status) |
| 529 | return; | 531 | return; |
| 530 | 532 | ||
| 531 | if (test_bit(HCI_SETUP, &hdev->dev_flags)) | 533 | if (test_bit(HCI_SETUP, &hdev->dev_flags) || |
| 534 | test_bit(HCI_CONFIG, &hdev->dev_flags)) | ||
| 532 | memcpy(hdev->commands, rp->commands, sizeof(hdev->commands)); | 535 | memcpy(hdev->commands, rp->commands, sizeof(hdev->commands)); |
| 533 | } | 536 | } |
| 534 | 537 | ||
| @@ -2194,7 +2197,12 @@ static void hci_conn_request_evt(struct hci_dev *hdev, struct sk_buff *skb) | |||
| 2194 | return; | 2197 | return; |
| 2195 | } | 2198 | } |
| 2196 | 2199 | ||
| 2197 | if (!test_bit(HCI_CONNECTABLE, &hdev->dev_flags) && | 2200 | /* Require HCI_CONNECTABLE or a whitelist entry to accept the |
| 2201 | * connection. These features are only touched through mgmt so | ||
| 2202 | * only do the checks if HCI_MGMT is set. | ||
| 2203 | */ | ||
| 2204 | if (test_bit(HCI_MGMT, &hdev->dev_flags) && | ||
| 2205 | !test_bit(HCI_CONNECTABLE, &hdev->dev_flags) && | ||
| 2198 | !hci_bdaddr_list_lookup(&hdev->whitelist, &ev->bdaddr, | 2206 | !hci_bdaddr_list_lookup(&hdev->whitelist, &ev->bdaddr, |
| 2199 | BDADDR_BREDR)) { | 2207 | BDADDR_BREDR)) { |
| 2200 | hci_reject_conn(hdev, &ev->bdaddr); | 2208 | hci_reject_conn(hdev, &ev->bdaddr); |
diff --git a/net/bluetooth/hidp/core.c b/net/bluetooth/hidp/core.c index cc25d0b74b36..07348e142f16 100644 --- a/net/bluetooth/hidp/core.c +++ b/net/bluetooth/hidp/core.c | |||
| @@ -1314,13 +1314,14 @@ int hidp_connection_add(struct hidp_connadd_req *req, | |||
| 1314 | { | 1314 | { |
| 1315 | struct hidp_session *session; | 1315 | struct hidp_session *session; |
| 1316 | struct l2cap_conn *conn; | 1316 | struct l2cap_conn *conn; |
| 1317 | struct l2cap_chan *chan = l2cap_pi(ctrl_sock->sk)->chan; | 1317 | struct l2cap_chan *chan; |
| 1318 | int ret; | 1318 | int ret; |
| 1319 | 1319 | ||
| 1320 | ret = hidp_verify_sockets(ctrl_sock, intr_sock); | 1320 | ret = hidp_verify_sockets(ctrl_sock, intr_sock); |
| 1321 | if (ret) | 1321 | if (ret) |
| 1322 | return ret; | 1322 | return ret; |
| 1323 | 1323 | ||
| 1324 | chan = l2cap_pi(ctrl_sock->sk)->chan; | ||
| 1324 | conn = NULL; | 1325 | conn = NULL; |
| 1325 | l2cap_chan_lock(chan); | 1326 | l2cap_chan_lock(chan); |
| 1326 | if (chan->conn) | 1327 | if (chan->conn) |
diff --git a/net/core/dev.c b/net/core/dev.c index f411c28d0a66..683d493aa1bf 100644 --- a/net/core/dev.c +++ b/net/core/dev.c | |||
| @@ -1694,6 +1694,7 @@ int __dev_forward_skb(struct net_device *dev, struct sk_buff *skb) | |||
| 1694 | 1694 | ||
| 1695 | skb_scrub_packet(skb, true); | 1695 | skb_scrub_packet(skb, true); |
| 1696 | skb->protocol = eth_type_trans(skb, dev); | 1696 | skb->protocol = eth_type_trans(skb, dev); |
| 1697 | skb_postpull_rcsum(skb, eth_hdr(skb), ETH_HLEN); | ||
| 1697 | 1698 | ||
| 1698 | return 0; | 1699 | return 0; |
| 1699 | } | 1700 | } |
| @@ -2522,7 +2523,7 @@ static int illegal_highdma(struct net_device *dev, struct sk_buff *skb) | |||
| 2522 | /* If MPLS offload request, verify we are testing hardware MPLS features | 2523 | /* If MPLS offload request, verify we are testing hardware MPLS features |
| 2523 | * instead of standard features for the netdev. | 2524 | * instead of standard features for the netdev. |
| 2524 | */ | 2525 | */ |
| 2525 | #ifdef CONFIG_NET_MPLS_GSO | 2526 | #if IS_ENABLED(CONFIG_NET_MPLS_GSO) |
| 2526 | static netdev_features_t net_mpls_features(struct sk_buff *skb, | 2527 | static netdev_features_t net_mpls_features(struct sk_buff *skb, |
| 2527 | netdev_features_t features, | 2528 | netdev_features_t features, |
| 2528 | __be16 type) | 2529 | __be16 type) |
| @@ -2562,7 +2563,7 @@ static netdev_features_t harmonize_features(struct sk_buff *skb, | |||
| 2562 | 2563 | ||
| 2563 | netdev_features_t netif_skb_features(struct sk_buff *skb) | 2564 | netdev_features_t netif_skb_features(struct sk_buff *skb) |
| 2564 | { | 2565 | { |
| 2565 | const struct net_device *dev = skb->dev; | 2566 | struct net_device *dev = skb->dev; |
| 2566 | netdev_features_t features = dev->features; | 2567 | netdev_features_t features = dev->features; |
| 2567 | u16 gso_segs = skb_shinfo(skb)->gso_segs; | 2568 | u16 gso_segs = skb_shinfo(skb)->gso_segs; |
| 2568 | __be16 protocol = skb->protocol; | 2569 | __be16 protocol = skb->protocol; |
| @@ -2570,11 +2571,21 @@ netdev_features_t netif_skb_features(struct sk_buff *skb) | |||
| 2570 | if (gso_segs > dev->gso_max_segs || gso_segs < dev->gso_min_segs) | 2571 | if (gso_segs > dev->gso_max_segs || gso_segs < dev->gso_min_segs) |
| 2571 | features &= ~NETIF_F_GSO_MASK; | 2572 | features &= ~NETIF_F_GSO_MASK; |
| 2572 | 2573 | ||
| 2573 | if (protocol == htons(ETH_P_8021Q) || protocol == htons(ETH_P_8021AD)) { | 2574 | /* If encapsulation offload request, verify we are testing |
| 2574 | struct vlan_ethhdr *veh = (struct vlan_ethhdr *)skb->data; | 2575 | * hardware encapsulation features instead of standard |
| 2575 | protocol = veh->h_vlan_encapsulated_proto; | 2576 | * features for the netdev |
| 2576 | } else if (!vlan_tx_tag_present(skb)) { | 2577 | */ |
| 2577 | return harmonize_features(skb, features); | 2578 | if (skb->encapsulation) |
| 2579 | features &= dev->hw_enc_features; | ||
| 2580 | |||
| 2581 | if (!vlan_tx_tag_present(skb)) { | ||
| 2582 | if (unlikely(protocol == htons(ETH_P_8021Q) || | ||
| 2583 | protocol == htons(ETH_P_8021AD))) { | ||
| 2584 | struct vlan_ethhdr *veh = (struct vlan_ethhdr *)skb->data; | ||
| 2585 | protocol = veh->h_vlan_encapsulated_proto; | ||
| 2586 | } else { | ||
| 2587 | goto finalize; | ||
| 2588 | } | ||
| 2578 | } | 2589 | } |
| 2579 | 2590 | ||
| 2580 | features = netdev_intersect_features(features, | 2591 | features = netdev_intersect_features(features, |
| @@ -2591,6 +2602,11 @@ netdev_features_t netif_skb_features(struct sk_buff *skb) | |||
| 2591 | NETIF_F_HW_VLAN_CTAG_TX | | 2602 | NETIF_F_HW_VLAN_CTAG_TX | |
| 2592 | NETIF_F_HW_VLAN_STAG_TX); | 2603 | NETIF_F_HW_VLAN_STAG_TX); |
| 2593 | 2604 | ||
| 2605 | finalize: | ||
| 2606 | if (dev->netdev_ops->ndo_features_check) | ||
| 2607 | features &= dev->netdev_ops->ndo_features_check(skb, dev, | ||
| 2608 | features); | ||
| 2609 | |||
| 2594 | return harmonize_features(skb, features); | 2610 | return harmonize_features(skb, features); |
| 2595 | } | 2611 | } |
| 2596 | EXPORT_SYMBOL(netif_skb_features); | 2612 | EXPORT_SYMBOL(netif_skb_features); |
| @@ -2661,19 +2677,12 @@ static struct sk_buff *validate_xmit_skb(struct sk_buff *skb, struct net_device | |||
| 2661 | if (unlikely(!skb)) | 2677 | if (unlikely(!skb)) |
| 2662 | goto out_null; | 2678 | goto out_null; |
| 2663 | 2679 | ||
| 2664 | /* If encapsulation offload request, verify we are testing | ||
| 2665 | * hardware encapsulation features instead of standard | ||
| 2666 | * features for the netdev | ||
| 2667 | */ | ||
| 2668 | if (skb->encapsulation) | ||
| 2669 | features &= dev->hw_enc_features; | ||
| 2670 | |||
| 2671 | if (netif_needs_gso(dev, skb, features)) { | 2680 | if (netif_needs_gso(dev, skb, features)) { |
| 2672 | struct sk_buff *segs; | 2681 | struct sk_buff *segs; |
| 2673 | 2682 | ||
| 2674 | segs = skb_gso_segment(skb, features); | 2683 | segs = skb_gso_segment(skb, features); |
| 2675 | if (IS_ERR(segs)) { | 2684 | if (IS_ERR(segs)) { |
| 2676 | segs = NULL; | 2685 | goto out_kfree_skb; |
| 2677 | } else if (segs) { | 2686 | } else if (segs) { |
| 2678 | consume_skb(skb); | 2687 | consume_skb(skb); |
| 2679 | skb = segs; | 2688 | skb = segs; |
| @@ -4557,6 +4566,68 @@ void netif_napi_del(struct napi_struct *napi) | |||
| 4557 | } | 4566 | } |
| 4558 | EXPORT_SYMBOL(netif_napi_del); | 4567 | EXPORT_SYMBOL(netif_napi_del); |
| 4559 | 4568 | ||
| 4569 | static int napi_poll(struct napi_struct *n, struct list_head *repoll) | ||
| 4570 | { | ||
| 4571 | void *have; | ||
| 4572 | int work, weight; | ||
| 4573 | |||
| 4574 | list_del_init(&n->poll_list); | ||
| 4575 | |||
| 4576 | have = netpoll_poll_lock(n); | ||
| 4577 | |||
| 4578 | weight = n->weight; | ||
| 4579 | |||
| 4580 | /* This NAPI_STATE_SCHED test is for avoiding a race | ||
| 4581 | * with netpoll's poll_napi(). Only the entity which | ||
| 4582 | * obtains the lock and sees NAPI_STATE_SCHED set will | ||
| 4583 | * actually make the ->poll() call. Therefore we avoid | ||
| 4584 | * accidentally calling ->poll() when NAPI is not scheduled. | ||
| 4585 | */ | ||
| 4586 | work = 0; | ||
| 4587 | if (test_bit(NAPI_STATE_SCHED, &n->state)) { | ||
| 4588 | work = n->poll(n, weight); | ||
| 4589 | trace_napi_poll(n); | ||
| 4590 | } | ||
| 4591 | |||
| 4592 | WARN_ON_ONCE(work > weight); | ||
| 4593 | |||
| 4594 | if (likely(work < weight)) | ||
| 4595 | goto out_unlock; | ||
| 4596 | |||
| 4597 | /* Drivers must not modify the NAPI state if they | ||
| 4598 | * consume the entire weight. In such cases this code | ||
| 4599 | * still "owns" the NAPI instance and therefore can | ||
| 4600 | * move the instance around on the list at-will. | ||
| 4601 | */ | ||
| 4602 | if (unlikely(napi_disable_pending(n))) { | ||
| 4603 | napi_complete(n); | ||
| 4604 | goto out_unlock; | ||
| 4605 | } | ||
| 4606 | |||
| 4607 | if (n->gro_list) { | ||
| 4608 | /* flush too old packets | ||
| 4609 | * If HZ < 1000, flush all packets. | ||
| 4610 | */ | ||
| 4611 | napi_gro_flush(n, HZ >= 1000); | ||
| 4612 | } | ||
| 4613 | |||
| 4614 | /* Some drivers may have called napi_schedule | ||
| 4615 | * prior to exhausting their budget. | ||
| 4616 | */ | ||
| 4617 | if (unlikely(!list_empty(&n->poll_list))) { | ||
| 4618 | pr_warn_once("%s: Budget exhausted after napi rescheduled\n", | ||
| 4619 | n->dev ? n->dev->name : "backlog"); | ||
| 4620 | goto out_unlock; | ||
| 4621 | } | ||
| 4622 | |||
| 4623 | list_add_tail(&n->poll_list, repoll); | ||
| 4624 | |||
| 4625 | out_unlock: | ||
| 4626 | netpoll_poll_unlock(have); | ||
| 4627 | |||
| 4628 | return work; | ||
| 4629 | } | ||
| 4630 | |||
| 4560 | static void net_rx_action(struct softirq_action *h) | 4631 | static void net_rx_action(struct softirq_action *h) |
| 4561 | { | 4632 | { |
| 4562 | struct softnet_data *sd = this_cpu_ptr(&softnet_data); | 4633 | struct softnet_data *sd = this_cpu_ptr(&softnet_data); |
| @@ -4564,74 +4635,34 @@ static void net_rx_action(struct softirq_action *h) | |||
| 4564 | int budget = netdev_budget; | 4635 | int budget = netdev_budget; |
| 4565 | LIST_HEAD(list); | 4636 | LIST_HEAD(list); |
| 4566 | LIST_HEAD(repoll); | 4637 | LIST_HEAD(repoll); |
| 4567 | void *have; | ||
| 4568 | 4638 | ||
| 4569 | local_irq_disable(); | 4639 | local_irq_disable(); |
| 4570 | list_splice_init(&sd->poll_list, &list); | 4640 | list_splice_init(&sd->poll_list, &list); |
| 4571 | local_irq_enable(); | 4641 | local_irq_enable(); |
| 4572 | 4642 | ||
| 4573 | while (!list_empty(&list)) { | 4643 | for (;;) { |
| 4574 | struct napi_struct *n; | 4644 | struct napi_struct *n; |
| 4575 | int work, weight; | ||
| 4576 | |||
| 4577 | /* If softirq window is exhausted then punt. | ||
| 4578 | * Allow this to run for 2 jiffies since which will allow | ||
| 4579 | * an average latency of 1.5/HZ. | ||
| 4580 | */ | ||
| 4581 | if (unlikely(budget <= 0 || time_after_eq(jiffies, time_limit))) | ||
| 4582 | goto softnet_break; | ||
| 4583 | |||
| 4584 | |||
| 4585 | n = list_first_entry(&list, struct napi_struct, poll_list); | ||
| 4586 | list_del_init(&n->poll_list); | ||
| 4587 | 4645 | ||
| 4588 | have = netpoll_poll_lock(n); | 4646 | if (list_empty(&list)) { |
| 4589 | 4647 | if (!sd_has_rps_ipi_waiting(sd) && list_empty(&repoll)) | |
| 4590 | weight = n->weight; | 4648 | return; |
| 4591 | 4649 | break; | |
| 4592 | /* This NAPI_STATE_SCHED test is for avoiding a race | ||
| 4593 | * with netpoll's poll_napi(). Only the entity which | ||
| 4594 | * obtains the lock and sees NAPI_STATE_SCHED set will | ||
| 4595 | * actually make the ->poll() call. Therefore we avoid | ||
| 4596 | * accidentally calling ->poll() when NAPI is not scheduled. | ||
| 4597 | */ | ||
| 4598 | work = 0; | ||
| 4599 | if (test_bit(NAPI_STATE_SCHED, &n->state)) { | ||
| 4600 | work = n->poll(n, weight); | ||
| 4601 | trace_napi_poll(n); | ||
| 4602 | } | 4650 | } |
| 4603 | 4651 | ||
| 4604 | WARN_ON_ONCE(work > weight); | 4652 | n = list_first_entry(&list, struct napi_struct, poll_list); |
| 4605 | 4653 | budget -= napi_poll(n, &repoll); | |
| 4606 | budget -= work; | ||
| 4607 | 4654 | ||
| 4608 | /* Drivers must not modify the NAPI state if they | 4655 | /* If softirq window is exhausted then punt. |
| 4609 | * consume the entire weight. In such cases this code | 4656 | * Allow this to run for 2 jiffies since which will allow |
| 4610 | * still "owns" the NAPI instance and therefore can | 4657 | * an average latency of 1.5/HZ. |
| 4611 | * move the instance around on the list at-will. | ||
| 4612 | */ | 4658 | */ |
| 4613 | if (unlikely(work == weight)) { | 4659 | if (unlikely(budget <= 0 || |
| 4614 | if (unlikely(napi_disable_pending(n))) { | 4660 | time_after_eq(jiffies, time_limit))) { |
| 4615 | napi_complete(n); | 4661 | sd->time_squeeze++; |
| 4616 | } else { | 4662 | break; |
| 4617 | if (n->gro_list) { | ||
| 4618 | /* flush too old packets | ||
| 4619 | * If HZ < 1000, flush all packets. | ||
| 4620 | */ | ||
| 4621 | napi_gro_flush(n, HZ >= 1000); | ||
| 4622 | } | ||
| 4623 | list_add_tail(&n->poll_list, &repoll); | ||
| 4624 | } | ||
| 4625 | } | 4663 | } |
| 4626 | |||
| 4627 | netpoll_poll_unlock(have); | ||
| 4628 | } | 4664 | } |
| 4629 | 4665 | ||
| 4630 | if (!sd_has_rps_ipi_waiting(sd) && | ||
| 4631 | list_empty(&list) && | ||
| 4632 | list_empty(&repoll)) | ||
| 4633 | return; | ||
| 4634 | out: | ||
| 4635 | local_irq_disable(); | 4666 | local_irq_disable(); |
| 4636 | 4667 | ||
| 4637 | list_splice_tail_init(&sd->poll_list, &list); | 4668 | list_splice_tail_init(&sd->poll_list, &list); |
| @@ -4641,12 +4672,6 @@ out: | |||
| 4641 | __raise_softirq_irqoff(NET_RX_SOFTIRQ); | 4672 | __raise_softirq_irqoff(NET_RX_SOFTIRQ); |
| 4642 | 4673 | ||
| 4643 | net_rps_action_and_irq_enable(sd); | 4674 | net_rps_action_and_irq_enable(sd); |
| 4644 | |||
| 4645 | return; | ||
| 4646 | |||
| 4647 | softnet_break: | ||
| 4648 | sd->time_squeeze++; | ||
| 4649 | goto out; | ||
| 4650 | } | 4675 | } |
| 4651 | 4676 | ||
| 4652 | struct netdev_adjacent { | 4677 | struct netdev_adjacent { |
diff --git a/net/core/skbuff.c b/net/core/skbuff.c index ae13ef6b3ea7..395c15b82087 100644 --- a/net/core/skbuff.c +++ b/net/core/skbuff.c | |||
| @@ -4148,6 +4148,7 @@ void skb_scrub_packet(struct sk_buff *skb, bool xnet) | |||
| 4148 | skb->ignore_df = 0; | 4148 | skb->ignore_df = 0; |
| 4149 | skb_dst_drop(skb); | 4149 | skb_dst_drop(skb); |
| 4150 | skb->mark = 0; | 4150 | skb->mark = 0; |
| 4151 | skb_init_secmark(skb); | ||
| 4151 | secpath_reset(skb); | 4152 | secpath_reset(skb); |
| 4152 | nf_reset(skb); | 4153 | nf_reset(skb); |
| 4153 | nf_reset_trace(skb); | 4154 | nf_reset_trace(skb); |
diff --git a/net/ipv4/geneve.c b/net/ipv4/geneve.c index 95e47c97585e..394a200f93c1 100644 --- a/net/ipv4/geneve.c +++ b/net/ipv4/geneve.c | |||
| @@ -122,14 +122,18 @@ int geneve_xmit_skb(struct geneve_sock *gs, struct rtable *rt, | |||
| 122 | int err; | 122 | int err; |
| 123 | 123 | ||
| 124 | skb = udp_tunnel_handle_offloads(skb, !gs->sock->sk->sk_no_check_tx); | 124 | skb = udp_tunnel_handle_offloads(skb, !gs->sock->sk->sk_no_check_tx); |
| 125 | if (IS_ERR(skb)) | ||
| 126 | return PTR_ERR(skb); | ||
| 125 | 127 | ||
| 126 | min_headroom = LL_RESERVED_SPACE(rt->dst.dev) + rt->dst.header_len | 128 | min_headroom = LL_RESERVED_SPACE(rt->dst.dev) + rt->dst.header_len |
| 127 | + GENEVE_BASE_HLEN + opt_len + sizeof(struct iphdr) | 129 | + GENEVE_BASE_HLEN + opt_len + sizeof(struct iphdr) |
| 128 | + (vlan_tx_tag_present(skb) ? VLAN_HLEN : 0); | 130 | + (vlan_tx_tag_present(skb) ? VLAN_HLEN : 0); |
| 129 | 131 | ||
| 130 | err = skb_cow_head(skb, min_headroom); | 132 | err = skb_cow_head(skb, min_headroom); |
| 131 | if (unlikely(err)) | 133 | if (unlikely(err)) { |
| 134 | kfree_skb(skb); | ||
| 132 | return err; | 135 | return err; |
| 136 | } | ||
| 133 | 137 | ||
| 134 | skb = vlan_hwaccel_push_inside(skb); | 138 | skb = vlan_hwaccel_push_inside(skb); |
| 135 | if (unlikely(!skb)) | 139 | if (unlikely(!skb)) |
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index 5ff87805258e..9c0b54e87b47 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c | |||
| @@ -1387,6 +1387,28 @@ ipv6_pktoptions: | |||
| 1387 | return 0; | 1387 | return 0; |
| 1388 | } | 1388 | } |
| 1389 | 1389 | ||
| 1390 | static void tcp_v6_fill_cb(struct sk_buff *skb, const struct ipv6hdr *hdr, | ||
| 1391 | const struct tcphdr *th) | ||
| 1392 | { | ||
| 1393 | /* This is tricky: we move IP6CB at its correct location into | ||
| 1394 | * TCP_SKB_CB(). It must be done after xfrm6_policy_check(), because | ||
| 1395 | * _decode_session6() uses IP6CB(). | ||
| 1396 | * barrier() makes sure compiler won't play aliasing games. | ||
| 1397 | */ | ||
| 1398 | memmove(&TCP_SKB_CB(skb)->header.h6, IP6CB(skb), | ||
| 1399 | sizeof(struct inet6_skb_parm)); | ||
| 1400 | barrier(); | ||
| 1401 | |||
| 1402 | TCP_SKB_CB(skb)->seq = ntohl(th->seq); | ||
| 1403 | TCP_SKB_CB(skb)->end_seq = (TCP_SKB_CB(skb)->seq + th->syn + th->fin + | ||
| 1404 | skb->len - th->doff*4); | ||
| 1405 | TCP_SKB_CB(skb)->ack_seq = ntohl(th->ack_seq); | ||
| 1406 | TCP_SKB_CB(skb)->tcp_flags = tcp_flag_byte(th); | ||
| 1407 | TCP_SKB_CB(skb)->tcp_tw_isn = 0; | ||
| 1408 | TCP_SKB_CB(skb)->ip_dsfield = ipv6_get_dsfield(hdr); | ||
| 1409 | TCP_SKB_CB(skb)->sacked = 0; | ||
| 1410 | } | ||
| 1411 | |||
| 1390 | static int tcp_v6_rcv(struct sk_buff *skb) | 1412 | static int tcp_v6_rcv(struct sk_buff *skb) |
| 1391 | { | 1413 | { |
| 1392 | const struct tcphdr *th; | 1414 | const struct tcphdr *th; |
| @@ -1418,24 +1440,9 @@ static int tcp_v6_rcv(struct sk_buff *skb) | |||
| 1418 | 1440 | ||
| 1419 | th = tcp_hdr(skb); | 1441 | th = tcp_hdr(skb); |
| 1420 | hdr = ipv6_hdr(skb); | 1442 | hdr = ipv6_hdr(skb); |
| 1421 | /* This is tricky : We move IPCB at its correct location into TCP_SKB_CB() | ||
| 1422 | * barrier() makes sure compiler wont play fool^Waliasing games. | ||
| 1423 | */ | ||
| 1424 | memmove(&TCP_SKB_CB(skb)->header.h6, IP6CB(skb), | ||
| 1425 | sizeof(struct inet6_skb_parm)); | ||
| 1426 | barrier(); | ||
| 1427 | |||
| 1428 | TCP_SKB_CB(skb)->seq = ntohl(th->seq); | ||
| 1429 | TCP_SKB_CB(skb)->end_seq = (TCP_SKB_CB(skb)->seq + th->syn + th->fin + | ||
| 1430 | skb->len - th->doff*4); | ||
| 1431 | TCP_SKB_CB(skb)->ack_seq = ntohl(th->ack_seq); | ||
| 1432 | TCP_SKB_CB(skb)->tcp_flags = tcp_flag_byte(th); | ||
| 1433 | TCP_SKB_CB(skb)->tcp_tw_isn = 0; | ||
| 1434 | TCP_SKB_CB(skb)->ip_dsfield = ipv6_get_dsfield(hdr); | ||
| 1435 | TCP_SKB_CB(skb)->sacked = 0; | ||
| 1436 | 1443 | ||
| 1437 | sk = __inet6_lookup_skb(&tcp_hashinfo, skb, th->source, th->dest, | 1444 | sk = __inet6_lookup_skb(&tcp_hashinfo, skb, th->source, th->dest, |
| 1438 | tcp_v6_iif(skb)); | 1445 | inet6_iif(skb)); |
| 1439 | if (!sk) | 1446 | if (!sk) |
| 1440 | goto no_tcp_socket; | 1447 | goto no_tcp_socket; |
| 1441 | 1448 | ||
| @@ -1451,6 +1458,8 @@ process: | |||
| 1451 | if (!xfrm6_policy_check(sk, XFRM_POLICY_IN, skb)) | 1458 | if (!xfrm6_policy_check(sk, XFRM_POLICY_IN, skb)) |
| 1452 | goto discard_and_relse; | 1459 | goto discard_and_relse; |
| 1453 | 1460 | ||
| 1461 | tcp_v6_fill_cb(skb, hdr, th); | ||
| 1462 | |||
| 1454 | #ifdef CONFIG_TCP_MD5SIG | 1463 | #ifdef CONFIG_TCP_MD5SIG |
| 1455 | if (tcp_v6_inbound_md5_hash(sk, skb)) | 1464 | if (tcp_v6_inbound_md5_hash(sk, skb)) |
| 1456 | goto discard_and_relse; | 1465 | goto discard_and_relse; |
| @@ -1482,6 +1491,8 @@ no_tcp_socket: | |||
| 1482 | if (!xfrm6_policy_check(NULL, XFRM_POLICY_IN, skb)) | 1491 | if (!xfrm6_policy_check(NULL, XFRM_POLICY_IN, skb)) |
| 1483 | goto discard_it; | 1492 | goto discard_it; |
| 1484 | 1493 | ||
| 1494 | tcp_v6_fill_cb(skb, hdr, th); | ||
| 1495 | |||
| 1485 | if (skb->len < (th->doff<<2) || tcp_checksum_complete(skb)) { | 1496 | if (skb->len < (th->doff<<2) || tcp_checksum_complete(skb)) { |
| 1486 | csum_error: | 1497 | csum_error: |
| 1487 | TCP_INC_STATS_BH(net, TCP_MIB_CSUMERRORS); | 1498 | TCP_INC_STATS_BH(net, TCP_MIB_CSUMERRORS); |
| @@ -1505,6 +1516,8 @@ do_time_wait: | |||
| 1505 | goto discard_it; | 1516 | goto discard_it; |
| 1506 | } | 1517 | } |
| 1507 | 1518 | ||
| 1519 | tcp_v6_fill_cb(skb, hdr, th); | ||
| 1520 | |||
| 1508 | if (skb->len < (th->doff<<2)) { | 1521 | if (skb->len < (th->doff<<2)) { |
| 1509 | inet_twsk_put(inet_twsk(sk)); | 1522 | inet_twsk_put(inet_twsk(sk)); |
| 1510 | goto bad_packet; | 1523 | goto bad_packet; |
diff --git a/net/mpls/mpls_gso.c b/net/mpls/mpls_gso.c index ca27837974fe..349295d21946 100644 --- a/net/mpls/mpls_gso.c +++ b/net/mpls/mpls_gso.c | |||
| @@ -31,10 +31,7 @@ static struct sk_buff *mpls_gso_segment(struct sk_buff *skb, | |||
| 31 | SKB_GSO_TCPV6 | | 31 | SKB_GSO_TCPV6 | |
| 32 | SKB_GSO_UDP | | 32 | SKB_GSO_UDP | |
| 33 | SKB_GSO_DODGY | | 33 | SKB_GSO_DODGY | |
| 34 | SKB_GSO_TCP_ECN | | 34 | SKB_GSO_TCP_ECN))) |
| 35 | SKB_GSO_GRE | | ||
| 36 | SKB_GSO_GRE_CSUM | | ||
| 37 | SKB_GSO_IPIP))) | ||
| 38 | goto out; | 35 | goto out; |
| 39 | 36 | ||
| 40 | /* Setup inner SKB. */ | 37 | /* Setup inner SKB. */ |
diff --git a/net/netfilter/nfnetlink.c b/net/netfilter/nfnetlink.c index 13c2e17bbe27..cde4a6702fa3 100644 --- a/net/netfilter/nfnetlink.c +++ b/net/netfilter/nfnetlink.c | |||
| @@ -463,7 +463,7 @@ static void nfnetlink_rcv(struct sk_buff *skb) | |||
| 463 | } | 463 | } |
| 464 | 464 | ||
| 465 | #ifdef CONFIG_MODULES | 465 | #ifdef CONFIG_MODULES |
| 466 | static int nfnetlink_bind(int group) | 466 | static int nfnetlink_bind(struct net *net, int group) |
| 467 | { | 467 | { |
| 468 | const struct nfnetlink_subsystem *ss; | 468 | const struct nfnetlink_subsystem *ss; |
| 469 | int type; | 469 | int type; |
diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c index 074cf3e91c6f..84ea76ca3f1f 100644 --- a/net/netlink/af_netlink.c +++ b/net/netlink/af_netlink.c | |||
| @@ -1091,8 +1091,10 @@ static void netlink_remove(struct sock *sk) | |||
| 1091 | mutex_unlock(&nl_sk_hash_lock); | 1091 | mutex_unlock(&nl_sk_hash_lock); |
| 1092 | 1092 | ||
| 1093 | netlink_table_grab(); | 1093 | netlink_table_grab(); |
| 1094 | if (nlk_sk(sk)->subscriptions) | 1094 | if (nlk_sk(sk)->subscriptions) { |
| 1095 | __sk_del_bind_node(sk); | 1095 | __sk_del_bind_node(sk); |
| 1096 | netlink_update_listeners(sk); | ||
| 1097 | } | ||
| 1096 | netlink_table_ungrab(); | 1098 | netlink_table_ungrab(); |
| 1097 | } | 1099 | } |
| 1098 | 1100 | ||
| @@ -1139,8 +1141,8 @@ static int netlink_create(struct net *net, struct socket *sock, int protocol, | |||
| 1139 | struct module *module = NULL; | 1141 | struct module *module = NULL; |
| 1140 | struct mutex *cb_mutex; | 1142 | struct mutex *cb_mutex; |
| 1141 | struct netlink_sock *nlk; | 1143 | struct netlink_sock *nlk; |
| 1142 | int (*bind)(int group); | 1144 | int (*bind)(struct net *net, int group); |
| 1143 | void (*unbind)(int group); | 1145 | void (*unbind)(struct net *net, int group); |
| 1144 | int err = 0; | 1146 | int err = 0; |
| 1145 | 1147 | ||
| 1146 | sock->state = SS_UNCONNECTED; | 1148 | sock->state = SS_UNCONNECTED; |
| @@ -1226,8 +1228,8 @@ static int netlink_release(struct socket *sock) | |||
| 1226 | 1228 | ||
| 1227 | module_put(nlk->module); | 1229 | module_put(nlk->module); |
| 1228 | 1230 | ||
| 1229 | netlink_table_grab(); | ||
| 1230 | if (netlink_is_kernel(sk)) { | 1231 | if (netlink_is_kernel(sk)) { |
| 1232 | netlink_table_grab(); | ||
| 1231 | BUG_ON(nl_table[sk->sk_protocol].registered == 0); | 1233 | BUG_ON(nl_table[sk->sk_protocol].registered == 0); |
| 1232 | if (--nl_table[sk->sk_protocol].registered == 0) { | 1234 | if (--nl_table[sk->sk_protocol].registered == 0) { |
| 1233 | struct listeners *old; | 1235 | struct listeners *old; |
| @@ -1241,11 +1243,16 @@ static int netlink_release(struct socket *sock) | |||
| 1241 | nl_table[sk->sk_protocol].flags = 0; | 1243 | nl_table[sk->sk_protocol].flags = 0; |
| 1242 | nl_table[sk->sk_protocol].registered = 0; | 1244 | nl_table[sk->sk_protocol].registered = 0; |
| 1243 | } | 1245 | } |
| 1244 | } else if (nlk->subscriptions) { | 1246 | netlink_table_ungrab(); |
| 1245 | netlink_update_listeners(sk); | ||
| 1246 | } | 1247 | } |
| 1247 | netlink_table_ungrab(); | ||
| 1248 | 1248 | ||
| 1249 | if (nlk->netlink_unbind) { | ||
| 1250 | int i; | ||
| 1251 | |||
| 1252 | for (i = 0; i < nlk->ngroups; i++) | ||
| 1253 | if (test_bit(i, nlk->groups)) | ||
| 1254 | nlk->netlink_unbind(sock_net(sk), i + 1); | ||
| 1255 | } | ||
| 1249 | kfree(nlk->groups); | 1256 | kfree(nlk->groups); |
| 1250 | nlk->groups = NULL; | 1257 | nlk->groups = NULL; |
| 1251 | 1258 | ||
| @@ -1410,9 +1417,10 @@ static int netlink_realloc_groups(struct sock *sk) | |||
| 1410 | return err; | 1417 | return err; |
| 1411 | } | 1418 | } |
| 1412 | 1419 | ||
| 1413 | static void netlink_unbind(int group, long unsigned int groups, | 1420 | static void netlink_undo_bind(int group, long unsigned int groups, |
| 1414 | struct netlink_sock *nlk) | 1421 | struct sock *sk) |
| 1415 | { | 1422 | { |
| 1423 | struct netlink_sock *nlk = nlk_sk(sk); | ||
| 1416 | int undo; | 1424 | int undo; |
| 1417 | 1425 | ||
| 1418 | if (!nlk->netlink_unbind) | 1426 | if (!nlk->netlink_unbind) |
| @@ -1420,7 +1428,7 @@ static void netlink_unbind(int group, long unsigned int groups, | |||
| 1420 | 1428 | ||
| 1421 | for (undo = 0; undo < group; undo++) | 1429 | for (undo = 0; undo < group; undo++) |
| 1422 | if (test_bit(undo, &groups)) | 1430 | if (test_bit(undo, &groups)) |
| 1423 | nlk->netlink_unbind(undo); | 1431 | nlk->netlink_unbind(sock_net(sk), undo); |
| 1424 | } | 1432 | } |
| 1425 | 1433 | ||
| 1426 | static int netlink_bind(struct socket *sock, struct sockaddr *addr, | 1434 | static int netlink_bind(struct socket *sock, struct sockaddr *addr, |
| @@ -1458,10 +1466,10 @@ static int netlink_bind(struct socket *sock, struct sockaddr *addr, | |||
| 1458 | for (group = 0; group < nlk->ngroups; group++) { | 1466 | for (group = 0; group < nlk->ngroups; group++) { |
| 1459 | if (!test_bit(group, &groups)) | 1467 | if (!test_bit(group, &groups)) |
| 1460 | continue; | 1468 | continue; |
| 1461 | err = nlk->netlink_bind(group); | 1469 | err = nlk->netlink_bind(net, group); |
| 1462 | if (!err) | 1470 | if (!err) |
| 1463 | continue; | 1471 | continue; |
| 1464 | netlink_unbind(group, groups, nlk); | 1472 | netlink_undo_bind(group, groups, sk); |
| 1465 | return err; | 1473 | return err; |
| 1466 | } | 1474 | } |
| 1467 | } | 1475 | } |
| @@ -1471,7 +1479,7 @@ static int netlink_bind(struct socket *sock, struct sockaddr *addr, | |||
| 1471 | netlink_insert(sk, net, nladdr->nl_pid) : | 1479 | netlink_insert(sk, net, nladdr->nl_pid) : |
| 1472 | netlink_autobind(sock); | 1480 | netlink_autobind(sock); |
| 1473 | if (err) { | 1481 | if (err) { |
| 1474 | netlink_unbind(nlk->ngroups, groups, nlk); | 1482 | netlink_undo_bind(nlk->ngroups, groups, sk); |
| 1475 | return err; | 1483 | return err; |
| 1476 | } | 1484 | } |
| 1477 | } | 1485 | } |
| @@ -2122,7 +2130,7 @@ static int netlink_setsockopt(struct socket *sock, int level, int optname, | |||
| 2122 | if (!val || val - 1 >= nlk->ngroups) | 2130 | if (!val || val - 1 >= nlk->ngroups) |
| 2123 | return -EINVAL; | 2131 | return -EINVAL; |
| 2124 | if (optname == NETLINK_ADD_MEMBERSHIP && nlk->netlink_bind) { | 2132 | if (optname == NETLINK_ADD_MEMBERSHIP && nlk->netlink_bind) { |
| 2125 | err = nlk->netlink_bind(val); | 2133 | err = nlk->netlink_bind(sock_net(sk), val); |
| 2126 | if (err) | 2134 | if (err) |
| 2127 | return err; | 2135 | return err; |
| 2128 | } | 2136 | } |
| @@ -2131,7 +2139,7 @@ static int netlink_setsockopt(struct socket *sock, int level, int optname, | |||
| 2131 | optname == NETLINK_ADD_MEMBERSHIP); | 2139 | optname == NETLINK_ADD_MEMBERSHIP); |
| 2132 | netlink_table_ungrab(); | 2140 | netlink_table_ungrab(); |
| 2133 | if (optname == NETLINK_DROP_MEMBERSHIP && nlk->netlink_unbind) | 2141 | if (optname == NETLINK_DROP_MEMBERSHIP && nlk->netlink_unbind) |
| 2134 | nlk->netlink_unbind(val); | 2142 | nlk->netlink_unbind(sock_net(sk), val); |
| 2135 | 2143 | ||
| 2136 | err = 0; | 2144 | err = 0; |
| 2137 | break; | 2145 | break; |
diff --git a/net/netlink/af_netlink.h b/net/netlink/af_netlink.h index b20a1731759b..f123a88496f8 100644 --- a/net/netlink/af_netlink.h +++ b/net/netlink/af_netlink.h | |||
| @@ -39,8 +39,8 @@ struct netlink_sock { | |||
| 39 | struct mutex *cb_mutex; | 39 | struct mutex *cb_mutex; |
| 40 | struct mutex cb_def_mutex; | 40 | struct mutex cb_def_mutex; |
| 41 | void (*netlink_rcv)(struct sk_buff *skb); | 41 | void (*netlink_rcv)(struct sk_buff *skb); |
| 42 | int (*netlink_bind)(int group); | 42 | int (*netlink_bind)(struct net *net, int group); |
| 43 | void (*netlink_unbind)(int group); | 43 | void (*netlink_unbind)(struct net *net, int group); |
| 44 | struct module *module; | 44 | struct module *module; |
| 45 | #ifdef CONFIG_NETLINK_MMAP | 45 | #ifdef CONFIG_NETLINK_MMAP |
| 46 | struct mutex pg_vec_lock; | 46 | struct mutex pg_vec_lock; |
| @@ -65,8 +65,8 @@ struct netlink_table { | |||
| 65 | unsigned int groups; | 65 | unsigned int groups; |
| 66 | struct mutex *cb_mutex; | 66 | struct mutex *cb_mutex; |
| 67 | struct module *module; | 67 | struct module *module; |
| 68 | int (*bind)(int group); | 68 | int (*bind)(struct net *net, int group); |
| 69 | void (*unbind)(int group); | 69 | void (*unbind)(struct net *net, int group); |
| 70 | bool (*compare)(struct net *net, struct sock *sock); | 70 | bool (*compare)(struct net *net, struct sock *sock); |
| 71 | int registered; | 71 | int registered; |
| 72 | }; | 72 | }; |
diff --git a/net/netlink/genetlink.c b/net/netlink/genetlink.c index 76393f2f4b22..2e11061ef885 100644 --- a/net/netlink/genetlink.c +++ b/net/netlink/genetlink.c | |||
| @@ -983,11 +983,67 @@ static struct genl_multicast_group genl_ctrl_groups[] = { | |||
| 983 | { .name = "notify", }, | 983 | { .name = "notify", }, |
| 984 | }; | 984 | }; |
| 985 | 985 | ||
| 986 | static int genl_bind(struct net *net, int group) | ||
| 987 | { | ||
| 988 | int i, err = 0; | ||
| 989 | |||
| 990 | down_read(&cb_lock); | ||
| 991 | for (i = 0; i < GENL_FAM_TAB_SIZE; i++) { | ||
| 992 | struct genl_family *f; | ||
| 993 | |||
| 994 | list_for_each_entry(f, genl_family_chain(i), family_list) { | ||
| 995 | if (group >= f->mcgrp_offset && | ||
| 996 | group < f->mcgrp_offset + f->n_mcgrps) { | ||
| 997 | int fam_grp = group - f->mcgrp_offset; | ||
| 998 | |||
| 999 | if (!f->netnsok && net != &init_net) | ||
| 1000 | err = -ENOENT; | ||
| 1001 | else if (f->mcast_bind) | ||
| 1002 | err = f->mcast_bind(net, fam_grp); | ||
| 1003 | else | ||
| 1004 | err = 0; | ||
| 1005 | break; | ||
| 1006 | } | ||
| 1007 | } | ||
| 1008 | } | ||
| 1009 | up_read(&cb_lock); | ||
| 1010 | |||
| 1011 | return err; | ||
| 1012 | } | ||
| 1013 | |||
| 1014 | static void genl_unbind(struct net *net, int group) | ||
| 1015 | { | ||
| 1016 | int i; | ||
| 1017 | bool found = false; | ||
| 1018 | |||
| 1019 | down_read(&cb_lock); | ||
| 1020 | for (i = 0; i < GENL_FAM_TAB_SIZE; i++) { | ||
| 1021 | struct genl_family *f; | ||
| 1022 | |||
| 1023 | list_for_each_entry(f, genl_family_chain(i), family_list) { | ||
| 1024 | if (group >= f->mcgrp_offset && | ||
| 1025 | group < f->mcgrp_offset + f->n_mcgrps) { | ||
| 1026 | int fam_grp = group - f->mcgrp_offset; | ||
| 1027 | |||
| 1028 | if (f->mcast_unbind) | ||
| 1029 | f->mcast_unbind(net, fam_grp); | ||
| 1030 | found = true; | ||
| 1031 | break; | ||
| 1032 | } | ||
| 1033 | } | ||
| 1034 | } | ||
| 1035 | up_read(&cb_lock); | ||
| 1036 | |||
| 1037 | WARN_ON(!found); | ||
| 1038 | } | ||
| 1039 | |||
| 986 | static int __net_init genl_pernet_init(struct net *net) | 1040 | static int __net_init genl_pernet_init(struct net *net) |
| 987 | { | 1041 | { |
| 988 | struct netlink_kernel_cfg cfg = { | 1042 | struct netlink_kernel_cfg cfg = { |
| 989 | .input = genl_rcv, | 1043 | .input = genl_rcv, |
| 990 | .flags = NL_CFG_F_NONROOT_RECV, | 1044 | .flags = NL_CFG_F_NONROOT_RECV, |
| 1045 | .bind = genl_bind, | ||
| 1046 | .unbind = genl_unbind, | ||
| 991 | }; | 1047 | }; |
| 992 | 1048 | ||
| 993 | /* we'll bump the group number right afterwards */ | 1049 | /* we'll bump the group number right afterwards */ |
diff --git a/net/openvswitch/actions.c b/net/openvswitch/actions.c index 764fdc39c63b..770064c83711 100644 --- a/net/openvswitch/actions.c +++ b/net/openvswitch/actions.c | |||
| @@ -147,7 +147,8 @@ static int push_mpls(struct sk_buff *skb, struct sw_flow_key *key, | |||
| 147 | hdr = eth_hdr(skb); | 147 | hdr = eth_hdr(skb); |
| 148 | hdr->h_proto = mpls->mpls_ethertype; | 148 | hdr->h_proto = mpls->mpls_ethertype; |
| 149 | 149 | ||
| 150 | skb_set_inner_protocol(skb, skb->protocol); | 150 | if (!skb->inner_protocol) |
| 151 | skb_set_inner_protocol(skb, skb->protocol); | ||
| 151 | skb->protocol = mpls->mpls_ethertype; | 152 | skb->protocol = mpls->mpls_ethertype; |
| 152 | 153 | ||
| 153 | invalidate_flow_key(key); | 154 | invalidate_flow_key(key); |
diff --git a/net/openvswitch/datapath.c b/net/openvswitch/datapath.c index 332b5a031739..4e9a5f035cbc 100644 --- a/net/openvswitch/datapath.c +++ b/net/openvswitch/datapath.c | |||
| @@ -83,8 +83,7 @@ static bool ovs_must_notify(struct genl_family *family, struct genl_info *info, | |||
| 83 | unsigned int group) | 83 | unsigned int group) |
| 84 | { | 84 | { |
| 85 | return info->nlhdr->nlmsg_flags & NLM_F_ECHO || | 85 | return info->nlhdr->nlmsg_flags & NLM_F_ECHO || |
| 86 | genl_has_listeners(family, genl_info_net(info)->genl_sock, | 86 | genl_has_listeners(family, genl_info_net(info), group); |
| 87 | group); | ||
| 88 | } | 87 | } |
| 89 | 88 | ||
| 90 | static void ovs_notify(struct genl_family *family, | 89 | static void ovs_notify(struct genl_family *family, |
diff --git a/net/openvswitch/flow_netlink.c b/net/openvswitch/flow_netlink.c index 9645a21d9eaa..d1eecf707613 100644 --- a/net/openvswitch/flow_netlink.c +++ b/net/openvswitch/flow_netlink.c | |||
| @@ -1753,7 +1753,6 @@ static int __ovs_nla_copy_actions(const struct nlattr *attr, | |||
| 1753 | __be16 eth_type, __be16 vlan_tci, bool log) | 1753 | __be16 eth_type, __be16 vlan_tci, bool log) |
| 1754 | { | 1754 | { |
| 1755 | const struct nlattr *a; | 1755 | const struct nlattr *a; |
| 1756 | bool out_tnl_port = false; | ||
| 1757 | int rem, err; | 1756 | int rem, err; |
| 1758 | 1757 | ||
| 1759 | if (depth >= SAMPLE_ACTION_DEPTH) | 1758 | if (depth >= SAMPLE_ACTION_DEPTH) |
| @@ -1796,8 +1795,6 @@ static int __ovs_nla_copy_actions(const struct nlattr *attr, | |||
| 1796 | case OVS_ACTION_ATTR_OUTPUT: | 1795 | case OVS_ACTION_ATTR_OUTPUT: |
| 1797 | if (nla_get_u32(a) >= DP_MAX_PORTS) | 1796 | if (nla_get_u32(a) >= DP_MAX_PORTS) |
| 1798 | return -EINVAL; | 1797 | return -EINVAL; |
| 1799 | out_tnl_port = false; | ||
| 1800 | |||
| 1801 | break; | 1798 | break; |
| 1802 | 1799 | ||
| 1803 | case OVS_ACTION_ATTR_HASH: { | 1800 | case OVS_ACTION_ATTR_HASH: { |
| @@ -1832,12 +1829,6 @@ static int __ovs_nla_copy_actions(const struct nlattr *attr, | |||
| 1832 | case OVS_ACTION_ATTR_PUSH_MPLS: { | 1829 | case OVS_ACTION_ATTR_PUSH_MPLS: { |
| 1833 | const struct ovs_action_push_mpls *mpls = nla_data(a); | 1830 | const struct ovs_action_push_mpls *mpls = nla_data(a); |
| 1834 | 1831 | ||
| 1835 | /* Networking stack do not allow simultaneous Tunnel | ||
| 1836 | * and MPLS GSO. | ||
| 1837 | */ | ||
| 1838 | if (out_tnl_port) | ||
| 1839 | return -EINVAL; | ||
| 1840 | |||
| 1841 | if (!eth_p_mpls(mpls->mpls_ethertype)) | 1832 | if (!eth_p_mpls(mpls->mpls_ethertype)) |
| 1842 | return -EINVAL; | 1833 | return -EINVAL; |
| 1843 | /* Prohibit push MPLS other than to a white list | 1834 | /* Prohibit push MPLS other than to a white list |
| @@ -1873,11 +1864,9 @@ static int __ovs_nla_copy_actions(const struct nlattr *attr, | |||
| 1873 | 1864 | ||
| 1874 | case OVS_ACTION_ATTR_SET: | 1865 | case OVS_ACTION_ATTR_SET: |
| 1875 | err = validate_set(a, key, sfa, | 1866 | err = validate_set(a, key, sfa, |
| 1876 | &out_tnl_port, eth_type, log); | 1867 | &skip_copy, eth_type, log); |
| 1877 | if (err) | 1868 | if (err) |
| 1878 | return err; | 1869 | return err; |
| 1879 | |||
| 1880 | skip_copy = out_tnl_port; | ||
| 1881 | break; | 1870 | break; |
| 1882 | 1871 | ||
| 1883 | case OVS_ACTION_ATTR_SAMPLE: | 1872 | case OVS_ACTION_ATTR_SAMPLE: |
diff --git a/net/openvswitch/vport-geneve.c b/net/openvswitch/vport-geneve.c index 347fa2325b22..484864dd0e68 100644 --- a/net/openvswitch/vport-geneve.c +++ b/net/openvswitch/vport-geneve.c | |||
| @@ -219,7 +219,10 @@ static int geneve_tnl_send(struct vport *vport, struct sk_buff *skb) | |||
| 219 | false); | 219 | false); |
| 220 | if (err < 0) | 220 | if (err < 0) |
| 221 | ip_rt_put(rt); | 221 | ip_rt_put(rt); |
| 222 | return err; | ||
| 223 | |||
| 222 | error: | 224 | error: |
| 225 | kfree_skb(skb); | ||
| 223 | return err; | 226 | return err; |
| 224 | } | 227 | } |
| 225 | 228 | ||
diff --git a/net/openvswitch/vport-gre.c b/net/openvswitch/vport-gre.c index 6b69df545b1d..d4168c442db5 100644 --- a/net/openvswitch/vport-gre.c +++ b/net/openvswitch/vport-gre.c | |||
| @@ -73,7 +73,7 @@ static struct sk_buff *__build_header(struct sk_buff *skb, | |||
| 73 | 73 | ||
| 74 | skb = gre_handle_offloads(skb, !!(tun_key->tun_flags & TUNNEL_CSUM)); | 74 | skb = gre_handle_offloads(skb, !!(tun_key->tun_flags & TUNNEL_CSUM)); |
| 75 | if (IS_ERR(skb)) | 75 | if (IS_ERR(skb)) |
| 76 | return NULL; | 76 | return skb; |
| 77 | 77 | ||
| 78 | tpi.flags = filter_tnl_flags(tun_key->tun_flags); | 78 | tpi.flags = filter_tnl_flags(tun_key->tun_flags); |
| 79 | tpi.proto = htons(ETH_P_TEB); | 79 | tpi.proto = htons(ETH_P_TEB); |
| @@ -144,7 +144,7 @@ static int gre_tnl_send(struct vport *vport, struct sk_buff *skb) | |||
| 144 | 144 | ||
| 145 | if (unlikely(!OVS_CB(skb)->egress_tun_info)) { | 145 | if (unlikely(!OVS_CB(skb)->egress_tun_info)) { |
| 146 | err = -EINVAL; | 146 | err = -EINVAL; |
| 147 | goto error; | 147 | goto err_free_skb; |
| 148 | } | 148 | } |
| 149 | 149 | ||
| 150 | tun_key = &OVS_CB(skb)->egress_tun_info->tunnel; | 150 | tun_key = &OVS_CB(skb)->egress_tun_info->tunnel; |
| @@ -157,8 +157,10 @@ static int gre_tnl_send(struct vport *vport, struct sk_buff *skb) | |||
| 157 | fl.flowi4_proto = IPPROTO_GRE; | 157 | fl.flowi4_proto = IPPROTO_GRE; |
| 158 | 158 | ||
| 159 | rt = ip_route_output_key(net, &fl); | 159 | rt = ip_route_output_key(net, &fl); |
| 160 | if (IS_ERR(rt)) | 160 | if (IS_ERR(rt)) { |
| 161 | return PTR_ERR(rt); | 161 | err = PTR_ERR(rt); |
| 162 | goto err_free_skb; | ||
| 163 | } | ||
| 162 | 164 | ||
| 163 | tunnel_hlen = ip_gre_calc_hlen(tun_key->tun_flags); | 165 | tunnel_hlen = ip_gre_calc_hlen(tun_key->tun_flags); |
| 164 | 166 | ||
| @@ -183,8 +185,9 @@ static int gre_tnl_send(struct vport *vport, struct sk_buff *skb) | |||
| 183 | 185 | ||
| 184 | /* Push Tunnel header. */ | 186 | /* Push Tunnel header. */ |
| 185 | skb = __build_header(skb, tunnel_hlen); | 187 | skb = __build_header(skb, tunnel_hlen); |
| 186 | if (unlikely(!skb)) { | 188 | if (IS_ERR(skb)) { |
| 187 | err = 0; | 189 | err = PTR_ERR(skb); |
| 190 | skb = NULL; | ||
| 188 | goto err_free_rt; | 191 | goto err_free_rt; |
| 189 | } | 192 | } |
| 190 | 193 | ||
| @@ -198,7 +201,8 @@ static int gre_tnl_send(struct vport *vport, struct sk_buff *skb) | |||
| 198 | tun_key->ipv4_tos, tun_key->ipv4_ttl, df, false); | 201 | tun_key->ipv4_tos, tun_key->ipv4_ttl, df, false); |
| 199 | err_free_rt: | 202 | err_free_rt: |
| 200 | ip_rt_put(rt); | 203 | ip_rt_put(rt); |
| 201 | error: | 204 | err_free_skb: |
| 205 | kfree_skb(skb); | ||
| 202 | return err; | 206 | return err; |
| 203 | } | 207 | } |
| 204 | 208 | ||
diff --git a/net/openvswitch/vport-vxlan.c b/net/openvswitch/vport-vxlan.c index 38f95a52241b..d7c46b301024 100644 --- a/net/openvswitch/vport-vxlan.c +++ b/net/openvswitch/vport-vxlan.c | |||
| @@ -187,7 +187,9 @@ static int vxlan_tnl_send(struct vport *vport, struct sk_buff *skb) | |||
| 187 | false); | 187 | false); |
| 188 | if (err < 0) | 188 | if (err < 0) |
| 189 | ip_rt_put(rt); | 189 | ip_rt_put(rt); |
| 190 | return err; | ||
| 190 | error: | 191 | error: |
| 192 | kfree_skb(skb); | ||
| 191 | return err; | 193 | return err; |
| 192 | } | 194 | } |
| 193 | 195 | ||
diff --git a/net/openvswitch/vport.c b/net/openvswitch/vport.c index 9584526c0778..53f3ebbfceab 100644 --- a/net/openvswitch/vport.c +++ b/net/openvswitch/vport.c | |||
| @@ -519,10 +519,9 @@ int ovs_vport_send(struct vport *vport, struct sk_buff *skb) | |||
| 519 | u64_stats_update_end(&stats->syncp); | 519 | u64_stats_update_end(&stats->syncp); |
| 520 | } else if (sent < 0) { | 520 | } else if (sent < 0) { |
| 521 | ovs_vport_record_error(vport, VPORT_E_TX_ERROR); | 521 | ovs_vport_record_error(vport, VPORT_E_TX_ERROR); |
| 522 | kfree_skb(skb); | 522 | } else { |
| 523 | } else | ||
| 524 | ovs_vport_record_error(vport, VPORT_E_TX_DROPPED); | 523 | ovs_vport_record_error(vport, VPORT_E_TX_DROPPED); |
| 525 | 524 | } | |
| 526 | return sent; | 525 | return sent; |
| 527 | } | 526 | } |
| 528 | 527 | ||
diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c index e52a44785681..6880f34a529a 100644 --- a/net/packet/af_packet.c +++ b/net/packet/af_packet.c | |||
| @@ -785,6 +785,7 @@ static void prb_close_block(struct tpacket_kbdq_core *pkc1, | |||
| 785 | 785 | ||
| 786 | struct tpacket3_hdr *last_pkt; | 786 | struct tpacket3_hdr *last_pkt; |
| 787 | struct tpacket_hdr_v1 *h1 = &pbd1->hdr.bh1; | 787 | struct tpacket_hdr_v1 *h1 = &pbd1->hdr.bh1; |
| 788 | struct sock *sk = &po->sk; | ||
| 788 | 789 | ||
| 789 | if (po->stats.stats3.tp_drops) | 790 | if (po->stats.stats3.tp_drops) |
| 790 | status |= TP_STATUS_LOSING; | 791 | status |= TP_STATUS_LOSING; |
| @@ -809,6 +810,8 @@ static void prb_close_block(struct tpacket_kbdq_core *pkc1, | |||
| 809 | /* Flush the block */ | 810 | /* Flush the block */ |
| 810 | prb_flush_block(pkc1, pbd1, status); | 811 | prb_flush_block(pkc1, pbd1, status); |
| 811 | 812 | ||
| 813 | sk->sk_data_ready(sk); | ||
| 814 | |||
| 812 | pkc1->kactive_blk_num = GET_NEXT_PRB_BLK_NUM(pkc1); | 815 | pkc1->kactive_blk_num = GET_NEXT_PRB_BLK_NUM(pkc1); |
| 813 | } | 816 | } |
| 814 | 817 | ||
| @@ -2052,12 +2055,12 @@ static int tpacket_rcv(struct sk_buff *skb, struct net_device *dev, | |||
| 2052 | smp_wmb(); | 2055 | smp_wmb(); |
| 2053 | #endif | 2056 | #endif |
| 2054 | 2057 | ||
| 2055 | if (po->tp_version <= TPACKET_V2) | 2058 | if (po->tp_version <= TPACKET_V2) { |
| 2056 | __packet_set_status(po, h.raw, status); | 2059 | __packet_set_status(po, h.raw, status); |
| 2057 | else | 2060 | sk->sk_data_ready(sk); |
| 2061 | } else { | ||
| 2058 | prb_clear_blk_fill_status(&po->rx_ring); | 2062 | prb_clear_blk_fill_status(&po->rx_ring); |
| 2059 | 2063 | } | |
| 2060 | sk->sk_data_ready(sk); | ||
| 2061 | 2064 | ||
| 2062 | drop_n_restore: | 2065 | drop_n_restore: |
| 2063 | if (skb_head != skb->data && skb_shared(skb)) { | 2066 | if (skb_head != skb->data && skb_shared(skb)) { |
diff --git a/net/wireless/Kconfig b/net/wireless/Kconfig index 22ba971741e5..29c8675f9a11 100644 --- a/net/wireless/Kconfig +++ b/net/wireless/Kconfig | |||
| @@ -175,7 +175,7 @@ config CFG80211_INTERNAL_REGDB | |||
| 175 | Most distributions have a CRDA package. So if unsure, say N. | 175 | Most distributions have a CRDA package. So if unsure, say N. |
| 176 | 176 | ||
| 177 | config CFG80211_WEXT | 177 | config CFG80211_WEXT |
| 178 | bool | 178 | bool "cfg80211 wireless extensions compatibility" |
| 179 | depends on CFG80211 | 179 | depends on CFG80211 |
| 180 | select WEXT_CORE | 180 | select WEXT_CORE |
| 181 | help | 181 | help |
diff --git a/sound/pci/hda/hda_controller.c b/sound/pci/hda/hda_controller.c index 8276a743e22e..0cfc9c8c4b4e 100644 --- a/sound/pci/hda/hda_controller.c +++ b/sound/pci/hda/hda_controller.c | |||
| @@ -1922,10 +1922,18 @@ int azx_mixer_create(struct azx *chip) | |||
| 1922 | EXPORT_SYMBOL_GPL(azx_mixer_create); | 1922 | EXPORT_SYMBOL_GPL(azx_mixer_create); |
| 1923 | 1923 | ||
| 1924 | 1924 | ||
| 1925 | static bool is_input_stream(struct azx *chip, unsigned char index) | ||
| 1926 | { | ||
| 1927 | return (index >= chip->capture_index_offset && | ||
| 1928 | index < chip->capture_index_offset + chip->capture_streams); | ||
| 1929 | } | ||
| 1930 | |||
| 1925 | /* initialize SD streams */ | 1931 | /* initialize SD streams */ |
| 1926 | int azx_init_stream(struct azx *chip) | 1932 | int azx_init_stream(struct azx *chip) |
| 1927 | { | 1933 | { |
| 1928 | int i; | 1934 | int i; |
| 1935 | int in_stream_tag = 0; | ||
| 1936 | int out_stream_tag = 0; | ||
| 1929 | 1937 | ||
| 1930 | /* initialize each stream (aka device) | 1938 | /* initialize each stream (aka device) |
| 1931 | * assign the starting bdl address to each stream (device) | 1939 | * assign the starting bdl address to each stream (device) |
| @@ -1938,9 +1946,21 @@ int azx_init_stream(struct azx *chip) | |||
| 1938 | azx_dev->sd_addr = chip->remap_addr + (0x20 * i + 0x80); | 1946 | azx_dev->sd_addr = chip->remap_addr + (0x20 * i + 0x80); |
| 1939 | /* int mask: SDI0=0x01, SDI1=0x02, ... SDO3=0x80 */ | 1947 | /* int mask: SDI0=0x01, SDI1=0x02, ... SDO3=0x80 */ |
| 1940 | azx_dev->sd_int_sta_mask = 1 << i; | 1948 | azx_dev->sd_int_sta_mask = 1 << i; |
| 1941 | /* stream tag: must be non-zero and unique */ | ||
| 1942 | azx_dev->index = i; | 1949 | azx_dev->index = i; |
| 1943 | azx_dev->stream_tag = i + 1; | 1950 | |
| 1951 | /* stream tag must be unique throughout | ||
| 1952 | * the stream direction group, | ||
| 1953 | * valid values 1...15 | ||
| 1954 | * use separate stream tag if the flag | ||
| 1955 | * AZX_DCAPS_SEPARATE_STREAM_TAG is used | ||
| 1956 | */ | ||
| 1957 | if (chip->driver_caps & AZX_DCAPS_SEPARATE_STREAM_TAG) | ||
| 1958 | azx_dev->stream_tag = | ||
| 1959 | is_input_stream(chip, i) ? | ||
| 1960 | ++in_stream_tag : | ||
| 1961 | ++out_stream_tag; | ||
| 1962 | else | ||
| 1963 | azx_dev->stream_tag = i + 1; | ||
| 1944 | } | 1964 | } |
| 1945 | 1965 | ||
| 1946 | return 0; | 1966 | return 0; |
diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index 2bf0b568e3de..d426a0bd6a5f 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c | |||
| @@ -299,6 +299,9 @@ enum { | |||
| 299 | AZX_DCAPS_PM_RUNTIME | AZX_DCAPS_I915_POWERWELL |\ | 299 | AZX_DCAPS_PM_RUNTIME | AZX_DCAPS_I915_POWERWELL |\ |
| 300 | AZX_DCAPS_SNOOP_TYPE(SCH)) | 300 | AZX_DCAPS_SNOOP_TYPE(SCH)) |
| 301 | 301 | ||
| 302 | #define AZX_DCAPS_INTEL_SKYLAKE \ | ||
| 303 | (AZX_DCAPS_INTEL_PCH | AZX_DCAPS_SEPARATE_STREAM_TAG) | ||
| 304 | |||
| 302 | /* quirks for ATI SB / AMD Hudson */ | 305 | /* quirks for ATI SB / AMD Hudson */ |
| 303 | #define AZX_DCAPS_PRESET_ATI_SB \ | 306 | #define AZX_DCAPS_PRESET_ATI_SB \ |
| 304 | (AZX_DCAPS_NO_TCSEL | AZX_DCAPS_SYNC_WRITE | AZX_DCAPS_POSFIX_LPIB |\ | 307 | (AZX_DCAPS_NO_TCSEL | AZX_DCAPS_SYNC_WRITE | AZX_DCAPS_POSFIX_LPIB |\ |
| @@ -2027,7 +2030,7 @@ static const struct pci_device_id azx_ids[] = { | |||
| 2027 | .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_PCH }, | 2030 | .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_PCH }, |
| 2028 | /* Sunrise Point-LP */ | 2031 | /* Sunrise Point-LP */ |
| 2029 | { PCI_DEVICE(0x8086, 0x9d70), | 2032 | { PCI_DEVICE(0x8086, 0x9d70), |
| 2030 | .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_PCH }, | 2033 | .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_SKYLAKE }, |
| 2031 | /* Haswell */ | 2034 | /* Haswell */ |
| 2032 | { PCI_DEVICE(0x8086, 0x0a0c), | 2035 | { PCI_DEVICE(0x8086, 0x0a0c), |
| 2033 | .driver_data = AZX_DRIVER_HDMI | AZX_DCAPS_INTEL_HASWELL }, | 2036 | .driver_data = AZX_DRIVER_HDMI | AZX_DCAPS_INTEL_HASWELL }, |
diff --git a/sound/pci/hda/hda_priv.h b/sound/pci/hda/hda_priv.h index aa484fdf4338..166e3e84b963 100644 --- a/sound/pci/hda/hda_priv.h +++ b/sound/pci/hda/hda_priv.h | |||
| @@ -171,6 +171,7 @@ enum { SDI0, SDI1, SDI2, SDI3, SDO0, SDO1, SDO2, SDO3 }; | |||
| 171 | #define AZX_DCAPS_I915_POWERWELL (1 << 27) /* HSW i915 powerwell support */ | 171 | #define AZX_DCAPS_I915_POWERWELL (1 << 27) /* HSW i915 powerwell support */ |
| 172 | #define AZX_DCAPS_CORBRP_SELF_CLEAR (1 << 28) /* CORBRP clears itself after reset */ | 172 | #define AZX_DCAPS_CORBRP_SELF_CLEAR (1 << 28) /* CORBRP clears itself after reset */ |
| 173 | #define AZX_DCAPS_NO_MSI64 (1 << 29) /* Stick to 32-bit MSIs */ | 173 | #define AZX_DCAPS_NO_MSI64 (1 << 29) /* Stick to 32-bit MSIs */ |
| 174 | #define AZX_DCAPS_SEPARATE_STREAM_TAG (1 << 30) /* capture and playback use separate stream tag */ | ||
| 174 | 175 | ||
| 175 | enum { | 176 | enum { |
| 176 | AZX_SNOOP_TYPE_NONE , | 177 | AZX_SNOOP_TYPE_NONE , |
diff --git a/sound/soc/codecs/rt5677.c b/sound/soc/codecs/rt5677.c index 81fe1464d268..c0fbe1881439 100644 --- a/sound/soc/codecs/rt5677.c +++ b/sound/soc/codecs/rt5677.c | |||
| @@ -784,8 +784,8 @@ static unsigned int bst_tlv[] = { | |||
| 784 | static int rt5677_dsp_vad_get(struct snd_kcontrol *kcontrol, | 784 | static int rt5677_dsp_vad_get(struct snd_kcontrol *kcontrol, |
| 785 | struct snd_ctl_elem_value *ucontrol) | 785 | struct snd_ctl_elem_value *ucontrol) |
| 786 | { | 786 | { |
| 787 | struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); | 787 | struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); |
| 788 | struct rt5677_priv *rt5677 = snd_soc_codec_get_drvdata(codec); | 788 | struct rt5677_priv *rt5677 = snd_soc_component_get_drvdata(component); |
| 789 | 789 | ||
| 790 | ucontrol->value.integer.value[0] = rt5677->dsp_vad_en; | 790 | ucontrol->value.integer.value[0] = rt5677->dsp_vad_en; |
| 791 | 791 | ||
| @@ -795,8 +795,9 @@ static int rt5677_dsp_vad_get(struct snd_kcontrol *kcontrol, | |||
| 795 | static int rt5677_dsp_vad_put(struct snd_kcontrol *kcontrol, | 795 | static int rt5677_dsp_vad_put(struct snd_kcontrol *kcontrol, |
| 796 | struct snd_ctl_elem_value *ucontrol) | 796 | struct snd_ctl_elem_value *ucontrol) |
| 797 | { | 797 | { |
| 798 | struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); | 798 | struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); |
| 799 | struct rt5677_priv *rt5677 = snd_soc_codec_get_drvdata(codec); | 799 | struct rt5677_priv *rt5677 = snd_soc_component_get_drvdata(component); |
| 800 | struct snd_soc_codec *codec = snd_soc_component_to_codec(component); | ||
| 800 | 801 | ||
| 801 | rt5677->dsp_vad_en = !!ucontrol->value.integer.value[0]; | 802 | rt5677->dsp_vad_en = !!ucontrol->value.integer.value[0]; |
| 802 | 803 | ||
diff --git a/sound/soc/dwc/designware_i2s.c b/sound/soc/dwc/designware_i2s.c index b93168d4f648..8d18bbda661b 100644 --- a/sound/soc/dwc/designware_i2s.c +++ b/sound/soc/dwc/designware_i2s.c | |||
| @@ -209,16 +209,9 @@ static int dw_i2s_hw_params(struct snd_pcm_substream *substream, | |||
| 209 | 209 | ||
| 210 | switch (config->chan_nr) { | 210 | switch (config->chan_nr) { |
| 211 | case EIGHT_CHANNEL_SUPPORT: | 211 | case EIGHT_CHANNEL_SUPPORT: |
| 212 | ch_reg = 3; | ||
| 213 | break; | ||
| 214 | case SIX_CHANNEL_SUPPORT: | 212 | case SIX_CHANNEL_SUPPORT: |
| 215 | ch_reg = 2; | ||
| 216 | break; | ||
| 217 | case FOUR_CHANNEL_SUPPORT: | 213 | case FOUR_CHANNEL_SUPPORT: |
| 218 | ch_reg = 1; | ||
| 219 | break; | ||
| 220 | case TWO_CHANNEL_SUPPORT: | 214 | case TWO_CHANNEL_SUPPORT: |
| 221 | ch_reg = 0; | ||
| 222 | break; | 215 | break; |
| 223 | default: | 216 | default: |
| 224 | dev_err(dev->dev, "channel not supported\n"); | 217 | dev_err(dev->dev, "channel not supported\n"); |
| @@ -227,18 +220,22 @@ static int dw_i2s_hw_params(struct snd_pcm_substream *substream, | |||
| 227 | 220 | ||
| 228 | i2s_disable_channels(dev, substream->stream); | 221 | i2s_disable_channels(dev, substream->stream); |
| 229 | 222 | ||
| 230 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { | 223 | for (ch_reg = 0; ch_reg < (config->chan_nr / 2); ch_reg++) { |
| 231 | i2s_write_reg(dev->i2s_base, TCR(ch_reg), xfer_resolution); | 224 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { |
| 232 | i2s_write_reg(dev->i2s_base, TFCR(ch_reg), 0x02); | 225 | i2s_write_reg(dev->i2s_base, TCR(ch_reg), |
| 233 | irq = i2s_read_reg(dev->i2s_base, IMR(ch_reg)); | 226 | xfer_resolution); |
| 234 | i2s_write_reg(dev->i2s_base, IMR(ch_reg), irq & ~0x30); | 227 | i2s_write_reg(dev->i2s_base, TFCR(ch_reg), 0x02); |
| 235 | i2s_write_reg(dev->i2s_base, TER(ch_reg), 1); | 228 | irq = i2s_read_reg(dev->i2s_base, IMR(ch_reg)); |
| 236 | } else { | 229 | i2s_write_reg(dev->i2s_base, IMR(ch_reg), irq & ~0x30); |
| 237 | i2s_write_reg(dev->i2s_base, RCR(ch_reg), xfer_resolution); | 230 | i2s_write_reg(dev->i2s_base, TER(ch_reg), 1); |
| 238 | i2s_write_reg(dev->i2s_base, RFCR(ch_reg), 0x07); | 231 | } else { |
| 239 | irq = i2s_read_reg(dev->i2s_base, IMR(ch_reg)); | 232 | i2s_write_reg(dev->i2s_base, RCR(ch_reg), |
| 240 | i2s_write_reg(dev->i2s_base, IMR(ch_reg), irq & ~0x03); | 233 | xfer_resolution); |
| 241 | i2s_write_reg(dev->i2s_base, RER(ch_reg), 1); | 234 | i2s_write_reg(dev->i2s_base, RFCR(ch_reg), 0x07); |
| 235 | irq = i2s_read_reg(dev->i2s_base, IMR(ch_reg)); | ||
| 236 | i2s_write_reg(dev->i2s_base, IMR(ch_reg), irq & ~0x03); | ||
| 237 | i2s_write_reg(dev->i2s_base, RER(ch_reg), 1); | ||
| 238 | } | ||
| 242 | } | 239 | } |
| 243 | 240 | ||
| 244 | i2s_write_reg(dev->i2s_base, CCR, ccr); | 241 | i2s_write_reg(dev->i2s_base, CCR, ccr); |
| @@ -263,6 +260,19 @@ static void dw_i2s_shutdown(struct snd_pcm_substream *substream, | |||
| 263 | snd_soc_dai_set_dma_data(dai, substream, NULL); | 260 | snd_soc_dai_set_dma_data(dai, substream, NULL); |
| 264 | } | 261 | } |
| 265 | 262 | ||
| 263 | static int dw_i2s_prepare(struct snd_pcm_substream *substream, | ||
| 264 | struct snd_soc_dai *dai) | ||
| 265 | { | ||
| 266 | struct dw_i2s_dev *dev = snd_soc_dai_get_drvdata(dai); | ||
| 267 | |||
| 268 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) | ||
| 269 | i2s_write_reg(dev->i2s_base, TXFFR, 1); | ||
| 270 | else | ||
| 271 | i2s_write_reg(dev->i2s_base, RXFFR, 1); | ||
| 272 | |||
| 273 | return 0; | ||
| 274 | } | ||
| 275 | |||
| 266 | static int dw_i2s_trigger(struct snd_pcm_substream *substream, | 276 | static int dw_i2s_trigger(struct snd_pcm_substream *substream, |
| 267 | int cmd, struct snd_soc_dai *dai) | 277 | int cmd, struct snd_soc_dai *dai) |
| 268 | { | 278 | { |
| @@ -294,6 +304,7 @@ static struct snd_soc_dai_ops dw_i2s_dai_ops = { | |||
| 294 | .startup = dw_i2s_startup, | 304 | .startup = dw_i2s_startup, |
| 295 | .shutdown = dw_i2s_shutdown, | 305 | .shutdown = dw_i2s_shutdown, |
| 296 | .hw_params = dw_i2s_hw_params, | 306 | .hw_params = dw_i2s_hw_params, |
| 307 | .prepare = dw_i2s_prepare, | ||
| 297 | .trigger = dw_i2s_trigger, | 308 | .trigger = dw_i2s_trigger, |
| 298 | }; | 309 | }; |
| 299 | 310 | ||
diff --git a/sound/soc/intel/Kconfig b/sound/soc/intel/Kconfig index e989ecf046c9..f86de1211b96 100644 --- a/sound/soc/intel/Kconfig +++ b/sound/soc/intel/Kconfig | |||
| @@ -89,7 +89,7 @@ config SND_SOC_INTEL_BROADWELL_MACH | |||
| 89 | 89 | ||
| 90 | config SND_SOC_INTEL_BYTCR_RT5640_MACH | 90 | config SND_SOC_INTEL_BYTCR_RT5640_MACH |
| 91 | tristate "ASoC Audio DSP Support for MID BYT Platform" | 91 | tristate "ASoC Audio DSP Support for MID BYT Platform" |
| 92 | depends on X86 | 92 | depends on X86 && I2C |
| 93 | select SND_SOC_RT5640 | 93 | select SND_SOC_RT5640 |
| 94 | select SND_SST_MFLD_PLATFORM | 94 | select SND_SST_MFLD_PLATFORM |
| 95 | select SND_SST_IPC_ACPI | 95 | select SND_SST_IPC_ACPI |
| @@ -101,7 +101,7 @@ config SND_SOC_INTEL_BYTCR_RT5640_MACH | |||
| 101 | 101 | ||
| 102 | config SND_SOC_INTEL_CHT_BSW_RT5672_MACH | 102 | config SND_SOC_INTEL_CHT_BSW_RT5672_MACH |
| 103 | tristate "ASoC Audio driver for Intel Cherrytrail & Braswell with RT5672 codec" | 103 | tristate "ASoC Audio driver for Intel Cherrytrail & Braswell with RT5672 codec" |
| 104 | depends on X86_INTEL_LPSS | 104 | depends on X86_INTEL_LPSS && I2C |
| 105 | select SND_SOC_RT5670 | 105 | select SND_SOC_RT5670 |
| 106 | select SND_SST_MFLD_PLATFORM | 106 | select SND_SST_MFLD_PLATFORM |
| 107 | select SND_SST_IPC_ACPI | 107 | select SND_SST_IPC_ACPI |
diff --git a/sound/soc/intel/bytcr_dpcm_rt5640.c b/sound/soc/intel/bytcr_dpcm_rt5640.c index f5d0fc1ab10c..eef0c56ec32e 100644 --- a/sound/soc/intel/bytcr_dpcm_rt5640.c +++ b/sound/soc/intel/bytcr_dpcm_rt5640.c | |||
| @@ -227,4 +227,4 @@ module_platform_driver(snd_byt_mc_driver); | |||
| 227 | MODULE_DESCRIPTION("ASoC Intel(R) Baytrail CR Machine driver"); | 227 | MODULE_DESCRIPTION("ASoC Intel(R) Baytrail CR Machine driver"); |
| 228 | MODULE_AUTHOR("Subhransu S. Prusty <subhransu.s.prusty@intel.com>"); | 228 | MODULE_AUTHOR("Subhransu S. Prusty <subhransu.s.prusty@intel.com>"); |
| 229 | MODULE_LICENSE("GPL v2"); | 229 | MODULE_LICENSE("GPL v2"); |
| 230 | MODULE_ALIAS("platform:bytrt5640-audio"); | 230 | MODULE_ALIAS("platform:bytt100_rt5640"); |
diff --git a/sound/soc/intel/sst-firmware.c b/sound/soc/intel/sst-firmware.c index 4a5bde9c686b..ef2e8b5766a1 100644 --- a/sound/soc/intel/sst-firmware.c +++ b/sound/soc/intel/sst-firmware.c | |||
| @@ -763,8 +763,12 @@ static int block_alloc_fixed(struct sst_dsp *dsp, struct sst_block_allocator *ba | |||
| 763 | /* does block span more than 1 section */ | 763 | /* does block span more than 1 section */ |
| 764 | if (ba->offset >= block->offset && ba->offset < block_end) { | 764 | if (ba->offset >= block->offset && ba->offset < block_end) { |
| 765 | 765 | ||
| 766 | /* add block */ | ||
| 767 | list_move(&block->list, &dsp->used_block_list); | ||
| 768 | list_add(&block->module_list, block_list); | ||
| 766 | /* align ba to block boundary */ | 769 | /* align ba to block boundary */ |
| 767 | ba->offset = block->offset; | 770 | ba->size -= block_end - ba->offset; |
| 771 | ba->offset = block_end; | ||
| 768 | 772 | ||
| 769 | err = block_alloc_contiguous(dsp, ba, block_list); | 773 | err = block_alloc_contiguous(dsp, ba, block_list); |
| 770 | if (err < 0) | 774 | if (err < 0) |
diff --git a/sound/soc/intel/sst/sst_acpi.c b/sound/soc/intel/sst/sst_acpi.c index 3abc29e8a928..2ac72eb5e75d 100644 --- a/sound/soc/intel/sst/sst_acpi.c +++ b/sound/soc/intel/sst/sst_acpi.c | |||
| @@ -343,7 +343,7 @@ int sst_acpi_remove(struct platform_device *pdev) | |||
| 343 | } | 343 | } |
| 344 | 344 | ||
| 345 | static struct sst_machines sst_acpi_bytcr[] = { | 345 | static struct sst_machines sst_acpi_bytcr[] = { |
| 346 | {"10EC5640", "T100", "bytt100_rt5640", NULL, "fw_sst_0f28.bin", | 346 | {"10EC5640", "T100", "bytt100_rt5640", NULL, "intel/fw_sst_0f28.bin", |
| 347 | &byt_rvp_platform_data }, | 347 | &byt_rvp_platform_data }, |
| 348 | {}, | 348 | {}, |
| 349 | }; | 349 | }; |
diff --git a/sound/soc/rockchip/rockchip_i2s.c b/sound/soc/rockchip/rockchip_i2s.c index 26ec5117b35c..13d8507333b8 100644 --- a/sound/soc/rockchip/rockchip_i2s.c +++ b/sound/soc/rockchip/rockchip_i2s.c | |||
| @@ -454,11 +454,11 @@ static int rockchip_i2s_probe(struct platform_device *pdev) | |||
| 454 | 454 | ||
| 455 | i2s->playback_dma_data.addr = res->start + I2S_TXDR; | 455 | i2s->playback_dma_data.addr = res->start + I2S_TXDR; |
| 456 | i2s->playback_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; | 456 | i2s->playback_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; |
| 457 | i2s->playback_dma_data.maxburst = 16; | 457 | i2s->playback_dma_data.maxburst = 4; |
| 458 | 458 | ||
| 459 | i2s->capture_dma_data.addr = res->start + I2S_RXDR; | 459 | i2s->capture_dma_data.addr = res->start + I2S_RXDR; |
| 460 | i2s->capture_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; | 460 | i2s->capture_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; |
| 461 | i2s->capture_dma_data.maxburst = 16; | 461 | i2s->capture_dma_data.maxburst = 4; |
| 462 | 462 | ||
| 463 | i2s->dev = &pdev->dev; | 463 | i2s->dev = &pdev->dev; |
| 464 | dev_set_drvdata(&pdev->dev, i2s); | 464 | dev_set_drvdata(&pdev->dev, i2s); |
diff --git a/sound/soc/rockchip/rockchip_i2s.h b/sound/soc/rockchip/rockchip_i2s.h index 89a5d8bc6ee7..93f456f518a9 100644 --- a/sound/soc/rockchip/rockchip_i2s.h +++ b/sound/soc/rockchip/rockchip_i2s.h | |||
| @@ -127,7 +127,7 @@ | |||
| 127 | #define I2S_DMACR_TDE_DISABLE (0 << I2S_DMACR_TDE_SHIFT) | 127 | #define I2S_DMACR_TDE_DISABLE (0 << I2S_DMACR_TDE_SHIFT) |
| 128 | #define I2S_DMACR_TDE_ENABLE (1 << I2S_DMACR_TDE_SHIFT) | 128 | #define I2S_DMACR_TDE_ENABLE (1 << I2S_DMACR_TDE_SHIFT) |
| 129 | #define I2S_DMACR_TDL_SHIFT 0 | 129 | #define I2S_DMACR_TDL_SHIFT 0 |
| 130 | #define I2S_DMACR_TDL(x) ((x - 1) << I2S_DMACR_TDL_SHIFT) | 130 | #define I2S_DMACR_TDL(x) ((x) << I2S_DMACR_TDL_SHIFT) |
| 131 | #define I2S_DMACR_TDL_MASK (0x1f << I2S_DMACR_TDL_SHIFT) | 131 | #define I2S_DMACR_TDL_MASK (0x1f << I2S_DMACR_TDL_SHIFT) |
| 132 | 132 | ||
| 133 | /* | 133 | /* |
diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index 985052b3fbed..2c62620abca6 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c | |||
| @@ -3230,7 +3230,7 @@ int snd_soc_of_parse_audio_routing(struct snd_soc_card *card, | |||
| 3230 | const char *propname) | 3230 | const char *propname) |
| 3231 | { | 3231 | { |
| 3232 | struct device_node *np = card->dev->of_node; | 3232 | struct device_node *np = card->dev->of_node; |
| 3233 | int num_routes, old_routes; | 3233 | int num_routes; |
| 3234 | struct snd_soc_dapm_route *routes; | 3234 | struct snd_soc_dapm_route *routes; |
| 3235 | int i, ret; | 3235 | int i, ret; |
| 3236 | 3236 | ||
| @@ -3248,9 +3248,7 @@ int snd_soc_of_parse_audio_routing(struct snd_soc_card *card, | |||
| 3248 | return -EINVAL; | 3248 | return -EINVAL; |
| 3249 | } | 3249 | } |
| 3250 | 3250 | ||
| 3251 | old_routes = card->num_dapm_routes; | 3251 | routes = devm_kzalloc(card->dev, num_routes * sizeof(*routes), |
| 3252 | routes = devm_kzalloc(card->dev, | ||
| 3253 | (old_routes + num_routes) * sizeof(*routes), | ||
| 3254 | GFP_KERNEL); | 3252 | GFP_KERNEL); |
| 3255 | if (!routes) { | 3253 | if (!routes) { |
| 3256 | dev_err(card->dev, | 3254 | dev_err(card->dev, |
| @@ -3258,11 +3256,9 @@ int snd_soc_of_parse_audio_routing(struct snd_soc_card *card, | |||
| 3258 | return -EINVAL; | 3256 | return -EINVAL; |
| 3259 | } | 3257 | } |
| 3260 | 3258 | ||
| 3261 | memcpy(routes, card->dapm_routes, old_routes * sizeof(*routes)); | ||
| 3262 | |||
| 3263 | for (i = 0; i < num_routes; i++) { | 3259 | for (i = 0; i < num_routes; i++) { |
| 3264 | ret = of_property_read_string_index(np, propname, | 3260 | ret = of_property_read_string_index(np, propname, |
| 3265 | 2 * i, &routes[old_routes + i].sink); | 3261 | 2 * i, &routes[i].sink); |
| 3266 | if (ret) { | 3262 | if (ret) { |
| 3267 | dev_err(card->dev, | 3263 | dev_err(card->dev, |
| 3268 | "ASoC: Property '%s' index %d could not be read: %d\n", | 3264 | "ASoC: Property '%s' index %d could not be read: %d\n", |
| @@ -3270,7 +3266,7 @@ int snd_soc_of_parse_audio_routing(struct snd_soc_card *card, | |||
| 3270 | return -EINVAL; | 3266 | return -EINVAL; |
| 3271 | } | 3267 | } |
| 3272 | ret = of_property_read_string_index(np, propname, | 3268 | ret = of_property_read_string_index(np, propname, |
| 3273 | (2 * i) + 1, &routes[old_routes + i].source); | 3269 | (2 * i) + 1, &routes[i].source); |
| 3274 | if (ret) { | 3270 | if (ret) { |
| 3275 | dev_err(card->dev, | 3271 | dev_err(card->dev, |
| 3276 | "ASoC: Property '%s' index %d could not be read: %d\n", | 3272 | "ASoC: Property '%s' index %d could not be read: %d\n", |
| @@ -3279,7 +3275,7 @@ int snd_soc_of_parse_audio_routing(struct snd_soc_card *card, | |||
| 3279 | } | 3275 | } |
| 3280 | } | 3276 | } |
| 3281 | 3277 | ||
| 3282 | card->num_dapm_routes += num_routes; | 3278 | card->num_dapm_routes = num_routes; |
| 3283 | card->dapm_routes = routes; | 3279 | card->dapm_routes = routes; |
| 3284 | 3280 | ||
| 3285 | return 0; | 3281 | return 0; |
diff --git a/tools/power/cpupower/utils/cpupower.c b/tools/power/cpupower/utils/cpupower.c index 7cdcf88659c7..9ea914378985 100644 --- a/tools/power/cpupower/utils/cpupower.c +++ b/tools/power/cpupower/utils/cpupower.c | |||
| @@ -199,7 +199,7 @@ int main(int argc, const char *argv[]) | |||
| 199 | } | 199 | } |
| 200 | 200 | ||
| 201 | get_cpu_info(0, &cpupower_cpu_info); | 201 | get_cpu_info(0, &cpupower_cpu_info); |
| 202 | run_as_root = !getuid(); | 202 | run_as_root = !geteuid(); |
| 203 | if (run_as_root) { | 203 | if (run_as_root) { |
| 204 | ret = uname(&uts); | 204 | ret = uname(&uts); |
| 205 | if (!ret && !strcmp(uts.machine, "x86_64") && | 205 | if (!ret && !strcmp(uts.machine, "x86_64") && |
diff --git a/tools/power/cpupower/utils/helpers/sysfs.c b/tools/power/cpupower/utils/helpers/sysfs.c index 09afe5d87f2b..4e8fe2c7b054 100644 --- a/tools/power/cpupower/utils/helpers/sysfs.c +++ b/tools/power/cpupower/utils/helpers/sysfs.c | |||
| @@ -361,7 +361,7 @@ unsigned int sysfs_get_idlestate_count(unsigned int cpu) | |||
| 361 | 361 | ||
| 362 | snprintf(file, SYSFS_PATH_MAX, PATH_TO_CPU "cpuidle"); | 362 | snprintf(file, SYSFS_PATH_MAX, PATH_TO_CPU "cpuidle"); |
| 363 | if (stat(file, &statbuf) != 0 || !S_ISDIR(statbuf.st_mode)) | 363 | if (stat(file, &statbuf) != 0 || !S_ISDIR(statbuf.st_mode)) |
| 364 | return -ENODEV; | 364 | return 0; |
| 365 | 365 | ||
| 366 | snprintf(file, SYSFS_PATH_MAX, PATH_TO_CPU "cpu%u/cpuidle/state0", cpu); | 366 | snprintf(file, SYSFS_PATH_MAX, PATH_TO_CPU "cpu%u/cpuidle/state0", cpu); |
| 367 | if (stat(file, &statbuf) != 0 || !S_ISDIR(statbuf.st_mode)) | 367 | if (stat(file, &statbuf) != 0 || !S_ISDIR(statbuf.st_mode)) |
diff --git a/tools/testing/selftests/exec/execveat.c b/tools/testing/selftests/exec/execveat.c index 33a5c06d95ca..d273624c93a6 100644 --- a/tools/testing/selftests/exec/execveat.c +++ b/tools/testing/selftests/exec/execveat.c | |||
| @@ -179,11 +179,11 @@ static int check_execveat_pathmax(int dot_dfd, const char *src, int is_script) | |||
| 179 | */ | 179 | */ |
| 180 | fd = open(longpath, O_RDONLY); | 180 | fd = open(longpath, O_RDONLY); |
| 181 | if (fd > 0) { | 181 | if (fd > 0) { |
| 182 | printf("Invoke copy of '%s' via filename of length %lu:\n", | 182 | printf("Invoke copy of '%s' via filename of length %zu:\n", |
| 183 | src, strlen(longpath)); | 183 | src, strlen(longpath)); |
| 184 | fail += check_execveat(fd, "", AT_EMPTY_PATH); | 184 | fail += check_execveat(fd, "", AT_EMPTY_PATH); |
| 185 | } else { | 185 | } else { |
| 186 | printf("Failed to open length %lu filename, errno=%d (%s)\n", | 186 | printf("Failed to open length %zu filename, errno=%d (%s)\n", |
| 187 | strlen(longpath), errno, strerror(errno)); | 187 | strlen(longpath), errno, strerror(errno)); |
| 188 | fail++; | 188 | fail++; |
| 189 | } | 189 | } |
diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c index f5283438ee05..1cc6e2e19982 100644 --- a/virt/kvm/kvm_main.c +++ b/virt/kvm/kvm_main.c | |||
| @@ -671,6 +671,7 @@ static void update_memslots(struct kvm_memslots *slots, | |||
| 671 | 671 | ||
| 672 | WARN_ON(mslots[i].id != id); | 672 | WARN_ON(mslots[i].id != id); |
| 673 | if (!new->npages) { | 673 | if (!new->npages) { |
| 674 | WARN_ON(!mslots[i].npages); | ||
| 674 | new->base_gfn = 0; | 675 | new->base_gfn = 0; |
| 675 | if (mslots[i].npages) | 676 | if (mslots[i].npages) |
| 676 | slots->used_slots--; | 677 | slots->used_slots--; |
| @@ -687,12 +688,25 @@ static void update_memslots(struct kvm_memslots *slots, | |||
| 687 | slots->id_to_index[mslots[i].id] = i; | 688 | slots->id_to_index[mslots[i].id] = i; |
| 688 | i++; | 689 | i++; |
| 689 | } | 690 | } |
| 690 | while (i > 0 && | 691 | |
| 691 | new->base_gfn > mslots[i - 1].base_gfn) { | 692 | /* |
| 692 | mslots[i] = mslots[i - 1]; | 693 | * The ">=" is needed when creating a slot with base_gfn == 0, |
| 693 | slots->id_to_index[mslots[i].id] = i; | 694 | * so that it moves before all those with base_gfn == npages == 0. |
| 694 | i--; | 695 | * |
| 695 | } | 696 | * On the other hand, if new->npages is zero, the above loop has |
| 697 | * already left i pointing to the beginning of the empty part of | ||
| 698 | * mslots, and the ">=" would move the hole backwards in this | ||
| 699 | * case---which is wrong. So skip the loop when deleting a slot. | ||
| 700 | */ | ||
| 701 | if (new->npages) { | ||
| 702 | while (i > 0 && | ||
| 703 | new->base_gfn >= mslots[i - 1].base_gfn) { | ||
| 704 | mslots[i] = mslots[i - 1]; | ||
| 705 | slots->id_to_index[mslots[i].id] = i; | ||
| 706 | i--; | ||
| 707 | } | ||
| 708 | } else | ||
| 709 | WARN_ON_ONCE(i != slots->used_slots); | ||
| 696 | 710 | ||
| 697 | mslots[i] = *new; | 711 | mslots[i] = *new; |
| 698 | slots->id_to_index[mslots[i].id] = i; | 712 | slots->id_to_index[mslots[i].id] = i; |
