mirror of
https://github.com/Fishwaldo/build.git
synced 2025-03-27 01:02:19 +00:00
6489 lines
205 KiB
Diff
6489 lines
205 KiB
Diff
diff --git a/Makefile b/Makefile
|
|
index 9be88c9d9fc9..787cf6605209 100644
|
|
--- a/Makefile
|
|
+++ b/Makefile
|
|
@@ -1,7 +1,7 @@
|
|
# SPDX-License-Identifier: GPL-2.0
|
|
VERSION = 4
|
|
PATCHLEVEL = 14
|
|
-SUBLEVEL = 43
|
|
+SUBLEVEL = 44
|
|
EXTRAVERSION =
|
|
NAME = Petit Gorille
|
|
|
|
diff --git a/arch/arm/boot/dts/imx7d-sdb.dts b/arch/arm/boot/dts/imx7d-sdb.dts
|
|
index 44637cabcc56..255e64ba32e2 100644
|
|
--- a/arch/arm/boot/dts/imx7d-sdb.dts
|
|
+++ b/arch/arm/boot/dts/imx7d-sdb.dts
|
|
@@ -82,7 +82,7 @@
|
|
enable-active-high;
|
|
};
|
|
|
|
- reg_usb_otg2_vbus: regulator-usb-otg1-vbus {
|
|
+ reg_usb_otg2_vbus: regulator-usb-otg2-vbus {
|
|
compatible = "regulator-fixed";
|
|
regulator-name = "usb_otg2_vbus";
|
|
regulator-min-microvolt = <5000000>;
|
|
diff --git a/arch/s390/crypto/crc32be-vx.S b/arch/s390/crypto/crc32be-vx.S
|
|
index e8077f0971f8..2bf01ba44107 100644
|
|
--- a/arch/s390/crypto/crc32be-vx.S
|
|
+++ b/arch/s390/crypto/crc32be-vx.S
|
|
@@ -13,6 +13,7 @@
|
|
*/
|
|
|
|
#include <linux/linkage.h>
|
|
+#include <asm/nospec-insn.h>
|
|
#include <asm/vx-insn.h>
|
|
|
|
/* Vector register range containing CRC-32 constants */
|
|
@@ -67,6 +68,8 @@
|
|
|
|
.previous
|
|
|
|
+ GEN_BR_THUNK %r14
|
|
+
|
|
.text
|
|
/*
|
|
* The CRC-32 function(s) use these calling conventions:
|
|
@@ -203,6 +206,6 @@ ENTRY(crc32_be_vgfm_16)
|
|
|
|
.Ldone:
|
|
VLGVF %r2,%v2,3
|
|
- br %r14
|
|
+ BR_EX %r14
|
|
|
|
.previous
|
|
diff --git a/arch/s390/crypto/crc32le-vx.S b/arch/s390/crypto/crc32le-vx.S
|
|
index d8c67a58c0c5..7d6f568bd3ad 100644
|
|
--- a/arch/s390/crypto/crc32le-vx.S
|
|
+++ b/arch/s390/crypto/crc32le-vx.S
|
|
@@ -14,6 +14,7 @@
|
|
*/
|
|
|
|
#include <linux/linkage.h>
|
|
+#include <asm/nospec-insn.h>
|
|
#include <asm/vx-insn.h>
|
|
|
|
/* Vector register range containing CRC-32 constants */
|
|
@@ -76,6 +77,7 @@
|
|
|
|
.previous
|
|
|
|
+ GEN_BR_THUNK %r14
|
|
|
|
.text
|
|
|
|
@@ -264,6 +266,6 @@ crc32_le_vgfm_generic:
|
|
|
|
.Ldone:
|
|
VLGVF %r2,%v2,2
|
|
- br %r14
|
|
+ BR_EX %r14
|
|
|
|
.previous
|
|
diff --git a/arch/s390/include/asm/alternative-asm.h b/arch/s390/include/asm/alternative-asm.h
|
|
new file mode 100644
|
|
index 000000000000..955d620db23e
|
|
--- /dev/null
|
|
+++ b/arch/s390/include/asm/alternative-asm.h
|
|
@@ -0,0 +1,108 @@
|
|
+/* SPDX-License-Identifier: GPL-2.0 */
|
|
+#ifndef _ASM_S390_ALTERNATIVE_ASM_H
|
|
+#define _ASM_S390_ALTERNATIVE_ASM_H
|
|
+
|
|
+#ifdef __ASSEMBLY__
|
|
+
|
|
+/*
|
|
+ * Check the length of an instruction sequence. The length may not be larger
|
|
+ * than 254 bytes and it has to be divisible by 2.
|
|
+ */
|
|
+.macro alt_len_check start,end
|
|
+ .if ( \end - \start ) > 254
|
|
+ .error "cpu alternatives does not support instructions blocks > 254 bytes\n"
|
|
+ .endif
|
|
+ .if ( \end - \start ) % 2
|
|
+ .error "cpu alternatives instructions length is odd\n"
|
|
+ .endif
|
|
+.endm
|
|
+
|
|
+/*
|
|
+ * Issue one struct alt_instr descriptor entry (need to put it into
|
|
+ * the section .altinstructions, see below). This entry contains
|
|
+ * enough information for the alternatives patching code to patch an
|
|
+ * instruction. See apply_alternatives().
|
|
+ */
|
|
+.macro alt_entry orig_start, orig_end, alt_start, alt_end, feature
|
|
+ .long \orig_start - .
|
|
+ .long \alt_start - .
|
|
+ .word \feature
|
|
+ .byte \orig_end - \orig_start
|
|
+ .byte \alt_end - \alt_start
|
|
+.endm
|
|
+
|
|
+/*
|
|
+ * Fill up @bytes with nops. The macro emits 6-byte nop instructions
|
|
+ * for the bulk of the area, possibly followed by a 4-byte and/or
|
|
+ * a 2-byte nop if the size of the area is not divisible by 6.
|
|
+ */
|
|
+.macro alt_pad_fill bytes
|
|
+ .fill ( \bytes ) / 6, 6, 0xc0040000
|
|
+ .fill ( \bytes ) % 6 / 4, 4, 0x47000000
|
|
+ .fill ( \bytes ) % 6 % 4 / 2, 2, 0x0700
|
|
+.endm
|
|
+
|
|
+/*
|
|
+ * Fill up @bytes with nops. If the number of bytes is larger
|
|
+ * than 6, emit a jg instruction to branch over all nops, then
|
|
+ * fill an area of size (@bytes - 6) with nop instructions.
|
|
+ */
|
|
+.macro alt_pad bytes
|
|
+ .if ( \bytes > 0 )
|
|
+ .if ( \bytes > 6 )
|
|
+ jg . + \bytes
|
|
+ alt_pad_fill \bytes - 6
|
|
+ .else
|
|
+ alt_pad_fill \bytes
|
|
+ .endif
|
|
+ .endif
|
|
+.endm
|
|
+
|
|
+/*
|
|
+ * Define an alternative between two instructions. If @feature is
|
|
+ * present, early code in apply_alternatives() replaces @oldinstr with
|
|
+ * @newinstr. ".skip" directive takes care of proper instruction padding
|
|
+ * in case @newinstr is longer than @oldinstr.
|
|
+ */
|
|
+.macro ALTERNATIVE oldinstr, newinstr, feature
|
|
+ .pushsection .altinstr_replacement,"ax"
|
|
+770: \newinstr
|
|
+771: .popsection
|
|
+772: \oldinstr
|
|
+773: alt_len_check 770b, 771b
|
|
+ alt_len_check 772b, 773b
|
|
+ alt_pad ( ( 771b - 770b ) - ( 773b - 772b ) )
|
|
+774: .pushsection .altinstructions,"a"
|
|
+ alt_entry 772b, 774b, 770b, 771b, \feature
|
|
+ .popsection
|
|
+.endm
|
|
+
|
|
+/*
|
|
+ * Define an alternative between two instructions. If @feature is
|
|
+ * present, early code in apply_alternatives() replaces @oldinstr with
|
|
+ * @newinstr. ".skip" directive takes care of proper instruction padding
|
|
+ * in case @newinstr is longer than @oldinstr.
|
|
+ */
|
|
+.macro ALTERNATIVE_2 oldinstr, newinstr1, feature1, newinstr2, feature2
|
|
+ .pushsection .altinstr_replacement,"ax"
|
|
+770: \newinstr1
|
|
+771: \newinstr2
|
|
+772: .popsection
|
|
+773: \oldinstr
|
|
+774: alt_len_check 770b, 771b
|
|
+ alt_len_check 771b, 772b
|
|
+ alt_len_check 773b, 774b
|
|
+ .if ( 771b - 770b > 772b - 771b )
|
|
+ alt_pad ( ( 771b - 770b ) - ( 774b - 773b ) )
|
|
+ .else
|
|
+ alt_pad ( ( 772b - 771b ) - ( 774b - 773b ) )
|
|
+ .endif
|
|
+775: .pushsection .altinstructions,"a"
|
|
+ alt_entry 773b, 775b, 770b, 771b,\feature1
|
|
+ alt_entry 773b, 775b, 771b, 772b,\feature2
|
|
+ .popsection
|
|
+.endm
|
|
+
|
|
+#endif /* __ASSEMBLY__ */
|
|
+
|
|
+#endif /* _ASM_S390_ALTERNATIVE_ASM_H */
|
|
diff --git a/arch/s390/include/asm/nospec-insn.h b/arch/s390/include/asm/nospec-insn.h
|
|
new file mode 100644
|
|
index 000000000000..9a56e738d645
|
|
--- /dev/null
|
|
+++ b/arch/s390/include/asm/nospec-insn.h
|
|
@@ -0,0 +1,195 @@
|
|
+/* SPDX-License-Identifier: GPL-2.0 */
|
|
+#ifndef _ASM_S390_NOSPEC_ASM_H
|
|
+#define _ASM_S390_NOSPEC_ASM_H
|
|
+
|
|
+#include <asm/alternative-asm.h>
|
|
+#include <asm/asm-offsets.h>
|
|
+
|
|
+#ifdef __ASSEMBLY__
|
|
+
|
|
+#ifdef CONFIG_EXPOLINE
|
|
+
|
|
+_LC_BR_R1 = __LC_BR_R1
|
|
+
|
|
+/*
|
|
+ * The expoline macros are used to create thunks in the same format
|
|
+ * as gcc generates them. The 'comdat' section flag makes sure that
|
|
+ * the various thunks are merged into a single copy.
|
|
+ */
|
|
+ .macro __THUNK_PROLOG_NAME name
|
|
+ .pushsection .text.\name,"axG",@progbits,\name,comdat
|
|
+ .globl \name
|
|
+ .hidden \name
|
|
+ .type \name,@function
|
|
+\name:
|
|
+ .cfi_startproc
|
|
+ .endm
|
|
+
|
|
+ .macro __THUNK_EPILOG
|
|
+ .cfi_endproc
|
|
+ .popsection
|
|
+ .endm
|
|
+
|
|
+ .macro __THUNK_PROLOG_BR r1,r2
|
|
+ __THUNK_PROLOG_NAME __s390x_indirect_jump_r\r2\()use_r\r1
|
|
+ .endm
|
|
+
|
|
+ .macro __THUNK_PROLOG_BC d0,r1,r2
|
|
+ __THUNK_PROLOG_NAME __s390x_indirect_branch_\d0\()_\r2\()use_\r1
|
|
+ .endm
|
|
+
|
|
+ .macro __THUNK_BR r1,r2
|
|
+ jg __s390x_indirect_jump_r\r2\()use_r\r1
|
|
+ .endm
|
|
+
|
|
+ .macro __THUNK_BC d0,r1,r2
|
|
+ jg __s390x_indirect_branch_\d0\()_\r2\()use_\r1
|
|
+ .endm
|
|
+
|
|
+ .macro __THUNK_BRASL r1,r2,r3
|
|
+ brasl \r1,__s390x_indirect_jump_r\r3\()use_r\r2
|
|
+ .endm
|
|
+
|
|
+ .macro __DECODE_RR expand,reg,ruse
|
|
+ .set __decode_fail,1
|
|
+ .irp r1,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15
|
|
+ .ifc \reg,%r\r1
|
|
+ .irp r2,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15
|
|
+ .ifc \ruse,%r\r2
|
|
+ \expand \r1,\r2
|
|
+ .set __decode_fail,0
|
|
+ .endif
|
|
+ .endr
|
|
+ .endif
|
|
+ .endr
|
|
+ .if __decode_fail == 1
|
|
+ .error "__DECODE_RR failed"
|
|
+ .endif
|
|
+ .endm
|
|
+
|
|
+ .macro __DECODE_RRR expand,rsave,rtarget,ruse
|
|
+ .set __decode_fail,1
|
|
+ .irp r1,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15
|
|
+ .ifc \rsave,%r\r1
|
|
+ .irp r2,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15
|
|
+ .ifc \rtarget,%r\r2
|
|
+ .irp r3,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15
|
|
+ .ifc \ruse,%r\r3
|
|
+ \expand \r1,\r2,\r3
|
|
+ .set __decode_fail,0
|
|
+ .endif
|
|
+ .endr
|
|
+ .endif
|
|
+ .endr
|
|
+ .endif
|
|
+ .endr
|
|
+ .if __decode_fail == 1
|
|
+ .error "__DECODE_RRR failed"
|
|
+ .endif
|
|
+ .endm
|
|
+
|
|
+ .macro __DECODE_DRR expand,disp,reg,ruse
|
|
+ .set __decode_fail,1
|
|
+ .irp r1,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15
|
|
+ .ifc \reg,%r\r1
|
|
+ .irp r2,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15
|
|
+ .ifc \ruse,%r\r2
|
|
+ \expand \disp,\r1,\r2
|
|
+ .set __decode_fail,0
|
|
+ .endif
|
|
+ .endr
|
|
+ .endif
|
|
+ .endr
|
|
+ .if __decode_fail == 1
|
|
+ .error "__DECODE_DRR failed"
|
|
+ .endif
|
|
+ .endm
|
|
+
|
|
+ .macro __THUNK_EX_BR reg,ruse
|
|
+ # Be very careful when adding instructions to this macro!
|
|
+ # The ALTERNATIVE replacement code has a .+10 which targets
|
|
+ # the "br \reg" after the code has been patched.
|
|
+#ifdef CONFIG_HAVE_MARCH_Z10_FEATURES
|
|
+ exrl 0,555f
|
|
+ j .
|
|
+#else
|
|
+ .ifc \reg,%r1
|
|
+ ALTERNATIVE "ex %r0,_LC_BR_R1", ".insn ril,0xc60000000000,0,.+10", 35
|
|
+ j .
|
|
+ .else
|
|
+ larl \ruse,555f
|
|
+ ex 0,0(\ruse)
|
|
+ j .
|
|
+ .endif
|
|
+#endif
|
|
+555: br \reg
|
|
+ .endm
|
|
+
|
|
+ .macro __THUNK_EX_BC disp,reg,ruse
|
|
+#ifdef CONFIG_HAVE_MARCH_Z10_FEATURES
|
|
+ exrl 0,556f
|
|
+ j .
|
|
+#else
|
|
+ larl \ruse,556f
|
|
+ ex 0,0(\ruse)
|
|
+ j .
|
|
+#endif
|
|
+556: b \disp(\reg)
|
|
+ .endm
|
|
+
|
|
+ .macro GEN_BR_THUNK reg,ruse=%r1
|
|
+ __DECODE_RR __THUNK_PROLOG_BR,\reg,\ruse
|
|
+ __THUNK_EX_BR \reg,\ruse
|
|
+ __THUNK_EPILOG
|
|
+ .endm
|
|
+
|
|
+ .macro GEN_B_THUNK disp,reg,ruse=%r1
|
|
+ __DECODE_DRR __THUNK_PROLOG_BC,\disp,\reg,\ruse
|
|
+ __THUNK_EX_BC \disp,\reg,\ruse
|
|
+ __THUNK_EPILOG
|
|
+ .endm
|
|
+
|
|
+ .macro BR_EX reg,ruse=%r1
|
|
+557: __DECODE_RR __THUNK_BR,\reg,\ruse
|
|
+ .pushsection .s390_indirect_branches,"a",@progbits
|
|
+ .long 557b-.
|
|
+ .popsection
|
|
+ .endm
|
|
+
|
|
+ .macro B_EX disp,reg,ruse=%r1
|
|
+558: __DECODE_DRR __THUNK_BC,\disp,\reg,\ruse
|
|
+ .pushsection .s390_indirect_branches,"a",@progbits
|
|
+ .long 558b-.
|
|
+ .popsection
|
|
+ .endm
|
|
+
|
|
+ .macro BASR_EX rsave,rtarget,ruse=%r1
|
|
+559: __DECODE_RRR __THUNK_BRASL,\rsave,\rtarget,\ruse
|
|
+ .pushsection .s390_indirect_branches,"a",@progbits
|
|
+ .long 559b-.
|
|
+ .popsection
|
|
+ .endm
|
|
+
|
|
+#else
|
|
+ .macro GEN_BR_THUNK reg,ruse=%r1
|
|
+ .endm
|
|
+
|
|
+ .macro GEN_B_THUNK disp,reg,ruse=%r1
|
|
+ .endm
|
|
+
|
|
+ .macro BR_EX reg,ruse=%r1
|
|
+ br \reg
|
|
+ .endm
|
|
+
|
|
+ .macro B_EX disp,reg,ruse=%r1
|
|
+ b \disp(\reg)
|
|
+ .endm
|
|
+
|
|
+ .macro BASR_EX rsave,rtarget,ruse=%r1
|
|
+ basr \rsave,\rtarget
|
|
+ .endm
|
|
+#endif
|
|
+
|
|
+#endif /* __ASSEMBLY__ */
|
|
+
|
|
+#endif /* _ASM_S390_NOSPEC_ASM_H */
|
|
diff --git a/arch/s390/kernel/Makefile b/arch/s390/kernel/Makefile
|
|
index a3a4cafb6080..e0784fff07f5 100644
|
|
--- a/arch/s390/kernel/Makefile
|
|
+++ b/arch/s390/kernel/Makefile
|
|
@@ -63,6 +63,7 @@ obj-y += nospec-branch.o
|
|
|
|
extra-y += head.o head64.o vmlinux.lds
|
|
|
|
+obj-$(CONFIG_SYSFS) += nospec-sysfs.o
|
|
CFLAGS_REMOVE_nospec-branch.o += $(CC_FLAGS_EXPOLINE)
|
|
|
|
obj-$(CONFIG_MODULES) += module.o
|
|
diff --git a/arch/s390/kernel/asm-offsets.c b/arch/s390/kernel/asm-offsets.c
|
|
index 0e6d2b032484..4e69bf909e87 100644
|
|
--- a/arch/s390/kernel/asm-offsets.c
|
|
+++ b/arch/s390/kernel/asm-offsets.c
|
|
@@ -177,6 +177,7 @@ int main(void)
|
|
OFFSET(__LC_PREEMPT_COUNT, lowcore, preempt_count);
|
|
OFFSET(__LC_GMAP, lowcore, gmap);
|
|
OFFSET(__LC_PASTE, lowcore, paste);
|
|
+ OFFSET(__LC_BR_R1, lowcore, br_r1_trampoline);
|
|
/* software defined ABI-relevant lowcore locations 0xe00 - 0xe20 */
|
|
OFFSET(__LC_DUMP_REIPL, lowcore, ipib);
|
|
/* hardware defined lowcore locations 0x1000 - 0x18ff */
|
|
diff --git a/arch/s390/kernel/base.S b/arch/s390/kernel/base.S
|
|
index f6c56009e822..b65874b0b412 100644
|
|
--- a/arch/s390/kernel/base.S
|
|
+++ b/arch/s390/kernel/base.S
|
|
@@ -9,18 +9,22 @@
|
|
|
|
#include <linux/linkage.h>
|
|
#include <asm/asm-offsets.h>
|
|
+#include <asm/nospec-insn.h>
|
|
#include <asm/ptrace.h>
|
|
#include <asm/sigp.h>
|
|
|
|
+ GEN_BR_THUNK %r9
|
|
+ GEN_BR_THUNK %r14
|
|
+
|
|
ENTRY(s390_base_mcck_handler)
|
|
basr %r13,0
|
|
0: lg %r15,__LC_PANIC_STACK # load panic stack
|
|
aghi %r15,-STACK_FRAME_OVERHEAD
|
|
larl %r1,s390_base_mcck_handler_fn
|
|
- lg %r1,0(%r1)
|
|
- ltgr %r1,%r1
|
|
+ lg %r9,0(%r1)
|
|
+ ltgr %r9,%r9
|
|
jz 1f
|
|
- basr %r14,%r1
|
|
+ BASR_EX %r14,%r9
|
|
1: la %r1,4095
|
|
lmg %r0,%r15,__LC_GPREGS_SAVE_AREA-4095(%r1)
|
|
lpswe __LC_MCK_OLD_PSW
|
|
@@ -37,10 +41,10 @@ ENTRY(s390_base_ext_handler)
|
|
basr %r13,0
|
|
0: aghi %r15,-STACK_FRAME_OVERHEAD
|
|
larl %r1,s390_base_ext_handler_fn
|
|
- lg %r1,0(%r1)
|
|
- ltgr %r1,%r1
|
|
+ lg %r9,0(%r1)
|
|
+ ltgr %r9,%r9
|
|
jz 1f
|
|
- basr %r14,%r1
|
|
+ BASR_EX %r14,%r9
|
|
1: lmg %r0,%r15,__LC_SAVE_AREA_ASYNC
|
|
ni __LC_EXT_OLD_PSW+1,0xfd # clear wait state bit
|
|
lpswe __LC_EXT_OLD_PSW
|
|
@@ -57,10 +61,10 @@ ENTRY(s390_base_pgm_handler)
|
|
basr %r13,0
|
|
0: aghi %r15,-STACK_FRAME_OVERHEAD
|
|
larl %r1,s390_base_pgm_handler_fn
|
|
- lg %r1,0(%r1)
|
|
- ltgr %r1,%r1
|
|
+ lg %r9,0(%r1)
|
|
+ ltgr %r9,%r9
|
|
jz 1f
|
|
- basr %r14,%r1
|
|
+ BASR_EX %r14,%r9
|
|
lmg %r0,%r15,__LC_SAVE_AREA_SYNC
|
|
lpswe __LC_PGM_OLD_PSW
|
|
1: lpswe disabled_wait_psw-0b(%r13)
|
|
@@ -117,7 +121,7 @@ ENTRY(diag308_reset)
|
|
larl %r4,.Lcontinue_psw # Restore PSW flags
|
|
lpswe 0(%r4)
|
|
.Lcontinue:
|
|
- br %r14
|
|
+ BR_EX %r14
|
|
.align 16
|
|
.Lrestart_psw:
|
|
.long 0x00080000,0x80000000 + .Lrestart_part2
|
|
diff --git a/arch/s390/kernel/entry.S b/arch/s390/kernel/entry.S
|
|
index ed9aaa212d4a..be20b1f73384 100644
|
|
--- a/arch/s390/kernel/entry.S
|
|
+++ b/arch/s390/kernel/entry.S
|
|
@@ -25,6 +25,7 @@
|
|
#include <asm/setup.h>
|
|
#include <asm/nmi.h>
|
|
#include <asm/export.h>
|
|
+#include <asm/nospec-insn.h>
|
|
|
|
__PT_R0 = __PT_GPRS
|
|
__PT_R1 = __PT_GPRS + 8
|
|
@@ -221,67 +222,9 @@ _PIF_WORK = (_PIF_PER_TRAP | _PIF_SYSCALL_RESTART)
|
|
.popsection
|
|
.endm
|
|
|
|
-#ifdef CONFIG_EXPOLINE
|
|
-
|
|
- .macro GEN_BR_THUNK name,reg,tmp
|
|
- .section .text.\name,"axG",@progbits,\name,comdat
|
|
- .globl \name
|
|
- .hidden \name
|
|
- .type \name,@function
|
|
-\name:
|
|
- .cfi_startproc
|
|
-#ifdef CONFIG_HAVE_MARCH_Z10_FEATURES
|
|
- exrl 0,0f
|
|
-#else
|
|
- larl \tmp,0f
|
|
- ex 0,0(\tmp)
|
|
-#endif
|
|
- j .
|
|
-0: br \reg
|
|
- .cfi_endproc
|
|
- .endm
|
|
-
|
|
- GEN_BR_THUNK __s390x_indirect_jump_r1use_r9,%r9,%r1
|
|
- GEN_BR_THUNK __s390x_indirect_jump_r1use_r14,%r14,%r1
|
|
- GEN_BR_THUNK __s390x_indirect_jump_r11use_r14,%r14,%r11
|
|
-
|
|
- .macro BASR_R14_R9
|
|
-0: brasl %r14,__s390x_indirect_jump_r1use_r9
|
|
- .pushsection .s390_indirect_branches,"a",@progbits
|
|
- .long 0b-.
|
|
- .popsection
|
|
- .endm
|
|
-
|
|
- .macro BR_R1USE_R14
|
|
-0: jg __s390x_indirect_jump_r1use_r14
|
|
- .pushsection .s390_indirect_branches,"a",@progbits
|
|
- .long 0b-.
|
|
- .popsection
|
|
- .endm
|
|
-
|
|
- .macro BR_R11USE_R14
|
|
-0: jg __s390x_indirect_jump_r11use_r14
|
|
- .pushsection .s390_indirect_branches,"a",@progbits
|
|
- .long 0b-.
|
|
- .popsection
|
|
- .endm
|
|
-
|
|
-#else /* CONFIG_EXPOLINE */
|
|
-
|
|
- .macro BASR_R14_R9
|
|
- basr %r14,%r9
|
|
- .endm
|
|
-
|
|
- .macro BR_R1USE_R14
|
|
- br %r14
|
|
- .endm
|
|
-
|
|
- .macro BR_R11USE_R14
|
|
- br %r14
|
|
- .endm
|
|
-
|
|
-#endif /* CONFIG_EXPOLINE */
|
|
-
|
|
+ GEN_BR_THUNK %r9
|
|
+ GEN_BR_THUNK %r14
|
|
+ GEN_BR_THUNK %r14,%r11
|
|
|
|
.section .kprobes.text, "ax"
|
|
.Ldummy:
|
|
@@ -298,7 +241,7 @@ _PIF_WORK = (_PIF_PER_TRAP | _PIF_SYSCALL_RESTART)
|
|
ENTRY(__bpon)
|
|
.globl __bpon
|
|
BPON
|
|
- BR_R1USE_R14
|
|
+ BR_EX %r14
|
|
|
|
/*
|
|
* Scheduler resume function, called by switch_to
|
|
@@ -325,7 +268,7 @@ ENTRY(__switch_to)
|
|
TSTMSK __LC_MACHINE_FLAGS,MACHINE_FLAG_LPP
|
|
jz 0f
|
|
.insn s,0xb2800000,__LC_LPP # set program parameter
|
|
-0: BR_R1USE_R14
|
|
+0: BR_EX %r14
|
|
|
|
.L__critical_start:
|
|
|
|
@@ -392,7 +335,7 @@ sie_exit:
|
|
xgr %r5,%r5
|
|
lmg %r6,%r14,__SF_GPRS(%r15) # restore kernel registers
|
|
lg %r2,__SF_EMPTY+16(%r15) # return exit reason code
|
|
- BR_R1USE_R14
|
|
+ BR_EX %r14
|
|
.Lsie_fault:
|
|
lghi %r14,-EFAULT
|
|
stg %r14,__SF_EMPTY+16(%r15) # set exit reason code
|
|
@@ -451,7 +394,7 @@ ENTRY(system_call)
|
|
lgf %r9,0(%r8,%r10) # get system call add.
|
|
TSTMSK __TI_flags(%r12),_TIF_TRACE
|
|
jnz .Lsysc_tracesys
|
|
- BASR_R14_R9 # call sys_xxxx
|
|
+ BASR_EX %r14,%r9 # call sys_xxxx
|
|
stg %r2,__PT_R2(%r11) # store return value
|
|
|
|
.Lsysc_return:
|
|
@@ -628,7 +571,7 @@ ENTRY(system_call)
|
|
lmg %r3,%r7,__PT_R3(%r11)
|
|
stg %r7,STACK_FRAME_OVERHEAD(%r15)
|
|
lg %r2,__PT_ORIG_GPR2(%r11)
|
|
- BASR_R14_R9 # call sys_xxx
|
|
+ BASR_EX %r14,%r9 # call sys_xxx
|
|
stg %r2,__PT_R2(%r11) # store return value
|
|
.Lsysc_tracenogo:
|
|
TSTMSK __TI_flags(%r12),_TIF_TRACE
|
|
@@ -652,7 +595,7 @@ ENTRY(ret_from_fork)
|
|
lmg %r9,%r10,__PT_R9(%r11) # load gprs
|
|
ENTRY(kernel_thread_starter)
|
|
la %r2,0(%r10)
|
|
- BASR_R14_R9
|
|
+ BASR_EX %r14,%r9
|
|
j .Lsysc_tracenogo
|
|
|
|
/*
|
|
@@ -731,7 +674,7 @@ ENTRY(pgm_check_handler)
|
|
je .Lpgm_return
|
|
lgf %r9,0(%r10,%r1) # load address of handler routine
|
|
lgr %r2,%r11 # pass pointer to pt_regs
|
|
- BASR_R14_R9 # branch to interrupt-handler
|
|
+ BASR_EX %r14,%r9 # branch to interrupt-handler
|
|
.Lpgm_return:
|
|
LOCKDEP_SYS_EXIT
|
|
tm __PT_PSW+1(%r11),0x01 # returning to user ?
|
|
@@ -1041,7 +984,7 @@ ENTRY(psw_idle)
|
|
stpt __TIMER_IDLE_ENTER(%r2)
|
|
.Lpsw_idle_lpsw:
|
|
lpswe __SF_EMPTY(%r15)
|
|
- BR_R1USE_R14
|
|
+ BR_EX %r14
|
|
.Lpsw_idle_end:
|
|
|
|
/*
|
|
@@ -1083,7 +1026,7 @@ ENTRY(save_fpu_regs)
|
|
.Lsave_fpu_regs_done:
|
|
oi __LC_CPU_FLAGS+7,_CIF_FPU
|
|
.Lsave_fpu_regs_exit:
|
|
- BR_R1USE_R14
|
|
+ BR_EX %r14
|
|
.Lsave_fpu_regs_end:
|
|
EXPORT_SYMBOL(save_fpu_regs)
|
|
|
|
@@ -1129,7 +1072,7 @@ load_fpu_regs:
|
|
.Lload_fpu_regs_done:
|
|
ni __LC_CPU_FLAGS+7,255-_CIF_FPU
|
|
.Lload_fpu_regs_exit:
|
|
- BR_R1USE_R14
|
|
+ BR_EX %r14
|
|
.Lload_fpu_regs_end:
|
|
|
|
.L__critical_end:
|
|
@@ -1301,7 +1244,7 @@ cleanup_critical:
|
|
jl 0f
|
|
clg %r9,BASED(.Lcleanup_table+104) # .Lload_fpu_regs_end
|
|
jl .Lcleanup_load_fpu_regs
|
|
-0: BR_R11USE_R14
|
|
+0: BR_EX %r14
|
|
|
|
.align 8
|
|
.Lcleanup_table:
|
|
@@ -1337,7 +1280,7 @@ cleanup_critical:
|
|
ni __SIE_PROG0C+3(%r9),0xfe # no longer in SIE
|
|
lctlg %c1,%c1,__LC_USER_ASCE # load primary asce
|
|
larl %r9,sie_exit # skip forward to sie_exit
|
|
- BR_R11USE_R14
|
|
+ BR_EX %r14
|
|
#endif
|
|
|
|
.Lcleanup_system_call:
|
|
@@ -1391,7 +1334,7 @@ cleanup_critical:
|
|
stg %r15,56(%r11) # r15 stack pointer
|
|
# set new psw address and exit
|
|
larl %r9,.Lsysc_do_svc
|
|
- BR_R11USE_R14
|
|
+ BR_EX %r14,%r11
|
|
.Lcleanup_system_call_insn:
|
|
.quad system_call
|
|
.quad .Lsysc_stmg
|
|
@@ -1403,7 +1346,7 @@ cleanup_critical:
|
|
|
|
.Lcleanup_sysc_tif:
|
|
larl %r9,.Lsysc_tif
|
|
- BR_R11USE_R14
|
|
+ BR_EX %r14,%r11
|
|
|
|
.Lcleanup_sysc_restore:
|
|
# check if stpt has been executed
|
|
@@ -1420,14 +1363,14 @@ cleanup_critical:
|
|
mvc 0(64,%r11),__PT_R8(%r9)
|
|
lmg %r0,%r7,__PT_R0(%r9)
|
|
1: lmg %r8,%r9,__LC_RETURN_PSW
|
|
- BR_R11USE_R14
|
|
+ BR_EX %r14,%r11
|
|
.Lcleanup_sysc_restore_insn:
|
|
.quad .Lsysc_exit_timer
|
|
.quad .Lsysc_done - 4
|
|
|
|
.Lcleanup_io_tif:
|
|
larl %r9,.Lio_tif
|
|
- BR_R11USE_R14
|
|
+ BR_EX %r14,%r11
|
|
|
|
.Lcleanup_io_restore:
|
|
# check if stpt has been executed
|
|
@@ -1441,7 +1384,7 @@ cleanup_critical:
|
|
mvc 0(64,%r11),__PT_R8(%r9)
|
|
lmg %r0,%r7,__PT_R0(%r9)
|
|
1: lmg %r8,%r9,__LC_RETURN_PSW
|
|
- BR_R11USE_R14
|
|
+ BR_EX %r14,%r11
|
|
.Lcleanup_io_restore_insn:
|
|
.quad .Lio_exit_timer
|
|
.quad .Lio_done - 4
|
|
@@ -1494,17 +1437,17 @@ cleanup_critical:
|
|
# prepare return psw
|
|
nihh %r8,0xfcfd # clear irq & wait state bits
|
|
lg %r9,48(%r11) # return from psw_idle
|
|
- BR_R11USE_R14
|
|
+ BR_EX %r14,%r11
|
|
.Lcleanup_idle_insn:
|
|
.quad .Lpsw_idle_lpsw
|
|
|
|
.Lcleanup_save_fpu_regs:
|
|
larl %r9,save_fpu_regs
|
|
- BR_R11USE_R14
|
|
+ BR_EX %r14,%r11
|
|
|
|
.Lcleanup_load_fpu_regs:
|
|
larl %r9,load_fpu_regs
|
|
- BR_R11USE_R14
|
|
+ BR_EX %r14,%r11
|
|
|
|
/*
|
|
* Integer constants
|
|
diff --git a/arch/s390/kernel/mcount.S b/arch/s390/kernel/mcount.S
|
|
index 82df7d80fab2..27110f3294ed 100644
|
|
--- a/arch/s390/kernel/mcount.S
|
|
+++ b/arch/s390/kernel/mcount.S
|
|
@@ -9,13 +9,17 @@
|
|
#include <linux/linkage.h>
|
|
#include <asm/asm-offsets.h>
|
|
#include <asm/ftrace.h>
|
|
+#include <asm/nospec-insn.h>
|
|
#include <asm/ptrace.h>
|
|
#include <asm/export.h>
|
|
|
|
+ GEN_BR_THUNK %r1
|
|
+ GEN_BR_THUNK %r14
|
|
+
|
|
.section .kprobes.text, "ax"
|
|
|
|
ENTRY(ftrace_stub)
|
|
- br %r14
|
|
+ BR_EX %r14
|
|
|
|
#define STACK_FRAME_SIZE (STACK_FRAME_OVERHEAD + __PT_SIZE)
|
|
#define STACK_PTREGS (STACK_FRAME_OVERHEAD)
|
|
@@ -23,7 +27,7 @@ ENTRY(ftrace_stub)
|
|
#define STACK_PTREGS_PSW (STACK_PTREGS + __PT_PSW)
|
|
|
|
ENTRY(_mcount)
|
|
- br %r14
|
|
+ BR_EX %r14
|
|
|
|
EXPORT_SYMBOL(_mcount)
|
|
|
|
@@ -53,7 +57,7 @@ ENTRY(ftrace_caller)
|
|
#endif
|
|
lgr %r3,%r14
|
|
la %r5,STACK_PTREGS(%r15)
|
|
- basr %r14,%r1
|
|
+ BASR_EX %r14,%r1
|
|
#ifdef CONFIG_FUNCTION_GRAPH_TRACER
|
|
# The j instruction gets runtime patched to a nop instruction.
|
|
# See ftrace_enable_ftrace_graph_caller.
|
|
@@ -68,7 +72,7 @@ ftrace_graph_caller_end:
|
|
#endif
|
|
lg %r1,(STACK_PTREGS_PSW+8)(%r15)
|
|
lmg %r2,%r15,(STACK_PTREGS_GPRS+2*8)(%r15)
|
|
- br %r1
|
|
+ BR_EX %r1
|
|
|
|
#ifdef CONFIG_FUNCTION_GRAPH_TRACER
|
|
|
|
@@ -81,6 +85,6 @@ ENTRY(return_to_handler)
|
|
aghi %r15,STACK_FRAME_OVERHEAD
|
|
lgr %r14,%r2
|
|
lmg %r2,%r5,32(%r15)
|
|
- br %r14
|
|
+ BR_EX %r14
|
|
|
|
#endif
|
|
diff --git a/arch/s390/kernel/nospec-branch.c b/arch/s390/kernel/nospec-branch.c
|
|
index 9f3b5b382743..d5eed651b5ab 100644
|
|
--- a/arch/s390/kernel/nospec-branch.c
|
|
+++ b/arch/s390/kernel/nospec-branch.c
|
|
@@ -44,24 +44,6 @@ static int __init nospec_report(void)
|
|
}
|
|
arch_initcall(nospec_report);
|
|
|
|
-#ifdef CONFIG_SYSFS
|
|
-ssize_t cpu_show_spectre_v1(struct device *dev,
|
|
- struct device_attribute *attr, char *buf)
|
|
-{
|
|
- return sprintf(buf, "Mitigation: __user pointer sanitization\n");
|
|
-}
|
|
-
|
|
-ssize_t cpu_show_spectre_v2(struct device *dev,
|
|
- struct device_attribute *attr, char *buf)
|
|
-{
|
|
- if (IS_ENABLED(CC_USING_EXPOLINE) && !nospec_disable)
|
|
- return sprintf(buf, "Mitigation: execute trampolines\n");
|
|
- if (__test_facility(82, S390_lowcore.alt_stfle_fac_list))
|
|
- return sprintf(buf, "Mitigation: limited branch prediction.\n");
|
|
- return sprintf(buf, "Vulnerable\n");
|
|
-}
|
|
-#endif
|
|
-
|
|
#ifdef CONFIG_EXPOLINE
|
|
|
|
int nospec_disable = IS_ENABLED(CONFIG_EXPOLINE_OFF);
|
|
@@ -112,7 +94,6 @@ static void __init_or_module __nospec_revert(s32 *start, s32 *end)
|
|
s32 *epo;
|
|
|
|
/* Second part of the instruction replace is always a nop */
|
|
- memcpy(insnbuf + 2, (char[]) { 0x47, 0x00, 0x00, 0x00 }, 4);
|
|
for (epo = start; epo < end; epo++) {
|
|
instr = (u8 *) epo + *epo;
|
|
if (instr[0] == 0xc0 && (instr[1] & 0x0f) == 0x04)
|
|
@@ -133,18 +114,34 @@ static void __init_or_module __nospec_revert(s32 *start, s32 *end)
|
|
br = thunk + (*(int *)(thunk + 2)) * 2;
|
|
else
|
|
continue;
|
|
- if (br[0] != 0x07 || (br[1] & 0xf0) != 0xf0)
|
|
+ /* Check for unconditional branch 0x07f? or 0x47f???? */
|
|
+ if ((br[0] & 0xbf) != 0x07 || (br[1] & 0xf0) != 0xf0)
|
|
continue;
|
|
+
|
|
+ memcpy(insnbuf + 2, (char[]) { 0x47, 0x00, 0x07, 0x00 }, 4);
|
|
switch (type) {
|
|
case BRCL_EXPOLINE:
|
|
- /* brcl to thunk, replace with br + nop */
|
|
insnbuf[0] = br[0];
|
|
insnbuf[1] = (instr[1] & 0xf0) | (br[1] & 0x0f);
|
|
+ if (br[0] == 0x47) {
|
|
+ /* brcl to b, replace with bc + nopr */
|
|
+ insnbuf[2] = br[2];
|
|
+ insnbuf[3] = br[3];
|
|
+ } else {
|
|
+ /* brcl to br, replace with bcr + nop */
|
|
+ }
|
|
break;
|
|
case BRASL_EXPOLINE:
|
|
- /* brasl to thunk, replace with basr + nop */
|
|
- insnbuf[0] = 0x0d;
|
|
insnbuf[1] = (instr[1] & 0xf0) | (br[1] & 0x0f);
|
|
+ if (br[0] == 0x47) {
|
|
+ /* brasl to b, replace with bas + nopr */
|
|
+ insnbuf[0] = 0x4d;
|
|
+ insnbuf[2] = br[2];
|
|
+ insnbuf[3] = br[3];
|
|
+ } else {
|
|
+ /* brasl to br, replace with basr + nop */
|
|
+ insnbuf[0] = 0x0d;
|
|
+ }
|
|
break;
|
|
}
|
|
|
|
diff --git a/arch/s390/kernel/nospec-sysfs.c b/arch/s390/kernel/nospec-sysfs.c
|
|
new file mode 100644
|
|
index 000000000000..8affad5f18cb
|
|
--- /dev/null
|
|
+++ b/arch/s390/kernel/nospec-sysfs.c
|
|
@@ -0,0 +1,21 @@
|
|
+// SPDX-License-Identifier: GPL-2.0
|
|
+#include <linux/device.h>
|
|
+#include <linux/cpu.h>
|
|
+#include <asm/facility.h>
|
|
+#include <asm/nospec-branch.h>
|
|
+
|
|
+ssize_t cpu_show_spectre_v1(struct device *dev,
|
|
+ struct device_attribute *attr, char *buf)
|
|
+{
|
|
+ return sprintf(buf, "Mitigation: __user pointer sanitization\n");
|
|
+}
|
|
+
|
|
+ssize_t cpu_show_spectre_v2(struct device *dev,
|
|
+ struct device_attribute *attr, char *buf)
|
|
+{
|
|
+ if (IS_ENABLED(CC_USING_EXPOLINE) && !nospec_disable)
|
|
+ return sprintf(buf, "Mitigation: execute trampolines\n");
|
|
+ if (__test_facility(82, S390_lowcore.alt_stfle_fac_list))
|
|
+ return sprintf(buf, "Mitigation: limited branch prediction\n");
|
|
+ return sprintf(buf, "Vulnerable\n");
|
|
+}
|
|
diff --git a/arch/s390/kernel/reipl.S b/arch/s390/kernel/reipl.S
|
|
index a40ebd1d29d0..8e954c102639 100644
|
|
--- a/arch/s390/kernel/reipl.S
|
|
+++ b/arch/s390/kernel/reipl.S
|
|
@@ -7,8 +7,11 @@
|
|
|
|
#include <linux/linkage.h>
|
|
#include <asm/asm-offsets.h>
|
|
+#include <asm/nospec-insn.h>
|
|
#include <asm/sigp.h>
|
|
|
|
+ GEN_BR_THUNK %r9
|
|
+
|
|
#
|
|
# Issue "store status" for the current CPU to its prefix page
|
|
# and call passed function afterwards
|
|
@@ -67,9 +70,9 @@ ENTRY(store_status)
|
|
st %r4,0(%r1)
|
|
st %r5,4(%r1)
|
|
stg %r2,8(%r1)
|
|
- lgr %r1,%r2
|
|
+ lgr %r9,%r2
|
|
lgr %r2,%r3
|
|
- br %r1
|
|
+ BR_EX %r9
|
|
|
|
.section .bss
|
|
.align 8
|
|
diff --git a/arch/s390/kernel/swsusp.S b/arch/s390/kernel/swsusp.S
|
|
index e99187149f17..a049a7b9d6e8 100644
|
|
--- a/arch/s390/kernel/swsusp.S
|
|
+++ b/arch/s390/kernel/swsusp.S
|
|
@@ -13,6 +13,7 @@
|
|
#include <asm/ptrace.h>
|
|
#include <asm/thread_info.h>
|
|
#include <asm/asm-offsets.h>
|
|
+#include <asm/nospec-insn.h>
|
|
#include <asm/sigp.h>
|
|
|
|
/*
|
|
@@ -24,6 +25,8 @@
|
|
* (see below) in the resume process.
|
|
* This function runs with disabled interrupts.
|
|
*/
|
|
+ GEN_BR_THUNK %r14
|
|
+
|
|
.section .text
|
|
ENTRY(swsusp_arch_suspend)
|
|
stmg %r6,%r15,__SF_GPRS(%r15)
|
|
@@ -103,7 +106,7 @@ ENTRY(swsusp_arch_suspend)
|
|
spx 0x318(%r1)
|
|
lmg %r6,%r15,STACK_FRAME_OVERHEAD + __SF_GPRS(%r15)
|
|
lghi %r2,0
|
|
- br %r14
|
|
+ BR_EX %r14
|
|
|
|
/*
|
|
* Restore saved memory image to correct place and restore register context.
|
|
@@ -197,11 +200,10 @@ pgm_check_entry:
|
|
larl %r15,init_thread_union
|
|
ahi %r15,1<<(PAGE_SHIFT+THREAD_SIZE_ORDER)
|
|
larl %r2,.Lpanic_string
|
|
- larl %r3,sclp_early_printk
|
|
lghi %r1,0
|
|
sam31
|
|
sigp %r1,%r0,SIGP_SET_ARCHITECTURE
|
|
- basr %r14,%r3
|
|
+ brasl %r14,sclp_early_printk
|
|
larl %r3,.Ldisabled_wait_31
|
|
lpsw 0(%r3)
|
|
4:
|
|
@@ -267,7 +269,7 @@ restore_registers:
|
|
/* Return 0 */
|
|
lmg %r6,%r15,STACK_FRAME_OVERHEAD + __SF_GPRS(%r15)
|
|
lghi %r2,0
|
|
- br %r14
|
|
+ BR_EX %r14
|
|
|
|
.section .data..nosave,"aw",@progbits
|
|
.align 8
|
|
diff --git a/arch/s390/lib/mem.S b/arch/s390/lib/mem.S
|
|
index d66751397e72..e1fa974ac500 100644
|
|
--- a/arch/s390/lib/mem.S
|
|
+++ b/arch/s390/lib/mem.S
|
|
@@ -7,6 +7,9 @@
|
|
|
|
#include <linux/linkage.h>
|
|
#include <asm/export.h>
|
|
+#include <asm/nospec-insn.h>
|
|
+
|
|
+ GEN_BR_THUNK %r14
|
|
|
|
/*
|
|
* void *memmove(void *dest, const void *src, size_t n)
|
|
@@ -33,14 +36,14 @@ ENTRY(memmove)
|
|
.Lmemmove_forward_remainder:
|
|
larl %r5,.Lmemmove_mvc
|
|
ex %r4,0(%r5)
|
|
- br %r14
|
|
+ BR_EX %r14
|
|
.Lmemmove_reverse:
|
|
ic %r0,0(%r4,%r3)
|
|
stc %r0,0(%r4,%r1)
|
|
brctg %r4,.Lmemmove_reverse
|
|
ic %r0,0(%r4,%r3)
|
|
stc %r0,0(%r4,%r1)
|
|
- br %r14
|
|
+ BR_EX %r14
|
|
.Lmemmove_mvc:
|
|
mvc 0(1,%r1),0(%r3)
|
|
EXPORT_SYMBOL(memmove)
|
|
@@ -77,7 +80,7 @@ ENTRY(memset)
|
|
.Lmemset_clear_remainder:
|
|
larl %r3,.Lmemset_xc
|
|
ex %r4,0(%r3)
|
|
- br %r14
|
|
+ BR_EX %r14
|
|
.Lmemset_fill:
|
|
stc %r3,0(%r2)
|
|
cghi %r4,1
|
|
@@ -94,7 +97,7 @@ ENTRY(memset)
|
|
.Lmemset_fill_remainder:
|
|
larl %r3,.Lmemset_mvc
|
|
ex %r4,0(%r3)
|
|
- br %r14
|
|
+ BR_EX %r14
|
|
.Lmemset_xc:
|
|
xc 0(1,%r1),0(%r1)
|
|
.Lmemset_mvc:
|
|
@@ -117,7 +120,7 @@ ENTRY(memcpy)
|
|
.Lmemcpy_remainder:
|
|
larl %r5,.Lmemcpy_mvc
|
|
ex %r4,0(%r5)
|
|
- br %r14
|
|
+ BR_EX %r14
|
|
.Lmemcpy_loop:
|
|
mvc 0(256,%r1),0(%r3)
|
|
la %r1,256(%r1)
|
|
diff --git a/arch/s390/net/bpf_jit.S b/arch/s390/net/bpf_jit.S
|
|
index 25bb4643c4f4..9f794869c1b0 100644
|
|
--- a/arch/s390/net/bpf_jit.S
|
|
+++ b/arch/s390/net/bpf_jit.S
|
|
@@ -9,6 +9,7 @@
|
|
*/
|
|
|
|
#include <linux/linkage.h>
|
|
+#include <asm/nospec-insn.h>
|
|
#include "bpf_jit.h"
|
|
|
|
/*
|
|
@@ -54,7 +55,7 @@ ENTRY(sk_load_##NAME##_pos); \
|
|
clg %r3,STK_OFF_HLEN(%r15); /* Offset + SIZE > hlen? */ \
|
|
jh sk_load_##NAME##_slow; \
|
|
LOAD %r14,-SIZE(%r3,%r12); /* Get data from skb */ \
|
|
- b OFF_OK(%r6); /* Return */ \
|
|
+ B_EX OFF_OK,%r6; /* Return */ \
|
|
\
|
|
sk_load_##NAME##_slow:; \
|
|
lgr %r2,%r7; /* Arg1 = skb pointer */ \
|
|
@@ -64,11 +65,14 @@ sk_load_##NAME##_slow:; \
|
|
brasl %r14,skb_copy_bits; /* Get data from skb */ \
|
|
LOAD %r14,STK_OFF_TMP(%r15); /* Load from temp bufffer */ \
|
|
ltgr %r2,%r2; /* Set cc to (%r2 != 0) */ \
|
|
- br %r6; /* Return */
|
|
+ BR_EX %r6; /* Return */
|
|
|
|
sk_load_common(word, 4, llgf) /* r14 = *(u32 *) (skb->data+offset) */
|
|
sk_load_common(half, 2, llgh) /* r14 = *(u16 *) (skb->data+offset) */
|
|
|
|
+ GEN_BR_THUNK %r6
|
|
+ GEN_B_THUNK OFF_OK,%r6
|
|
+
|
|
/*
|
|
* Load 1 byte from SKB (optimized version)
|
|
*/
|
|
@@ -80,7 +84,7 @@ ENTRY(sk_load_byte_pos)
|
|
clg %r3,STK_OFF_HLEN(%r15) # Offset >= hlen?
|
|
jnl sk_load_byte_slow
|
|
llgc %r14,0(%r3,%r12) # Get byte from skb
|
|
- b OFF_OK(%r6) # Return OK
|
|
+ B_EX OFF_OK,%r6 # Return OK
|
|
|
|
sk_load_byte_slow:
|
|
lgr %r2,%r7 # Arg1 = skb pointer
|
|
@@ -90,7 +94,7 @@ sk_load_byte_slow:
|
|
brasl %r14,skb_copy_bits # Get data from skb
|
|
llgc %r14,STK_OFF_TMP(%r15) # Load result from temp buffer
|
|
ltgr %r2,%r2 # Set cc to (%r2 != 0)
|
|
- br %r6 # Return cc
|
|
+ BR_EX %r6 # Return cc
|
|
|
|
#define sk_negative_common(NAME, SIZE, LOAD) \
|
|
sk_load_##NAME##_slow_neg:; \
|
|
@@ -104,7 +108,7 @@ sk_load_##NAME##_slow_neg:; \
|
|
jz bpf_error; \
|
|
LOAD %r14,0(%r2); /* Get data from pointer */ \
|
|
xr %r3,%r3; /* Set cc to zero */ \
|
|
- br %r6; /* Return cc */
|
|
+ BR_EX %r6; /* Return cc */
|
|
|
|
sk_negative_common(word, 4, llgf)
|
|
sk_negative_common(half, 2, llgh)
|
|
@@ -113,4 +117,4 @@ sk_negative_common(byte, 1, llgc)
|
|
bpf_error:
|
|
# force a return 0 from jit handler
|
|
ltgr %r15,%r15 # Set condition code
|
|
- br %r6
|
|
+ BR_EX %r6
|
|
diff --git a/arch/s390/net/bpf_jit_comp.c b/arch/s390/net/bpf_jit_comp.c
|
|
index 33e2785f6842..11cd151733d4 100644
|
|
--- a/arch/s390/net/bpf_jit_comp.c
|
|
+++ b/arch/s390/net/bpf_jit_comp.c
|
|
@@ -25,6 +25,8 @@
|
|
#include <linux/bpf.h>
|
|
#include <asm/cacheflush.h>
|
|
#include <asm/dis.h>
|
|
+#include <asm/facility.h>
|
|
+#include <asm/nospec-branch.h>
|
|
#include <asm/set_memory.h>
|
|
#include "bpf_jit.h"
|
|
|
|
@@ -43,6 +45,8 @@ struct bpf_jit {
|
|
int base_ip; /* Base address for literal pool */
|
|
int ret0_ip; /* Address of return 0 */
|
|
int exit_ip; /* Address of exit */
|
|
+ int r1_thunk_ip; /* Address of expoline thunk for 'br %r1' */
|
|
+ int r14_thunk_ip; /* Address of expoline thunk for 'br %r14' */
|
|
int tail_call_start; /* Tail call start offset */
|
|
int labels[1]; /* Labels for local jumps */
|
|
};
|
|
@@ -252,6 +256,19 @@ static inline void reg_set_seen(struct bpf_jit *jit, u32 b1)
|
|
REG_SET_SEEN(b2); \
|
|
})
|
|
|
|
+#define EMIT6_PCREL_RILB(op, b, target) \
|
|
+({ \
|
|
+ int rel = (target - jit->prg) / 2; \
|
|
+ _EMIT6(op | reg_high(b) << 16 | rel >> 16, rel & 0xffff); \
|
|
+ REG_SET_SEEN(b); \
|
|
+})
|
|
+
|
|
+#define EMIT6_PCREL_RIL(op, target) \
|
|
+({ \
|
|
+ int rel = (target - jit->prg) / 2; \
|
|
+ _EMIT6(op | rel >> 16, rel & 0xffff); \
|
|
+})
|
|
+
|
|
#define _EMIT6_IMM(op, imm) \
|
|
({ \
|
|
unsigned int __imm = (imm); \
|
|
@@ -471,8 +488,45 @@ static void bpf_jit_epilogue(struct bpf_jit *jit)
|
|
EMIT4(0xb9040000, REG_2, BPF_REG_0);
|
|
/* Restore registers */
|
|
save_restore_regs(jit, REGS_RESTORE);
|
|
+ if (IS_ENABLED(CC_USING_EXPOLINE) && !nospec_disable) {
|
|
+ jit->r14_thunk_ip = jit->prg;
|
|
+ /* Generate __s390_indirect_jump_r14 thunk */
|
|
+ if (test_facility(35)) {
|
|
+ /* exrl %r0,.+10 */
|
|
+ EMIT6_PCREL_RIL(0xc6000000, jit->prg + 10);
|
|
+ } else {
|
|
+ /* larl %r1,.+14 */
|
|
+ EMIT6_PCREL_RILB(0xc0000000, REG_1, jit->prg + 14);
|
|
+ /* ex 0,0(%r1) */
|
|
+ EMIT4_DISP(0x44000000, REG_0, REG_1, 0);
|
|
+ }
|
|
+ /* j . */
|
|
+ EMIT4_PCREL(0xa7f40000, 0);
|
|
+ }
|
|
/* br %r14 */
|
|
_EMIT2(0x07fe);
|
|
+
|
|
+ if (IS_ENABLED(CC_USING_EXPOLINE) && !nospec_disable &&
|
|
+ (jit->seen & SEEN_FUNC)) {
|
|
+ jit->r1_thunk_ip = jit->prg;
|
|
+ /* Generate __s390_indirect_jump_r1 thunk */
|
|
+ if (test_facility(35)) {
|
|
+ /* exrl %r0,.+10 */
|
|
+ EMIT6_PCREL_RIL(0xc6000000, jit->prg + 10);
|
|
+ /* j . */
|
|
+ EMIT4_PCREL(0xa7f40000, 0);
|
|
+ /* br %r1 */
|
|
+ _EMIT2(0x07f1);
|
|
+ } else {
|
|
+ /* larl %r1,.+14 */
|
|
+ EMIT6_PCREL_RILB(0xc0000000, REG_1, jit->prg + 14);
|
|
+ /* ex 0,S390_lowcore.br_r1_tampoline */
|
|
+ EMIT4_DISP(0x44000000, REG_0, REG_0,
|
|
+ offsetof(struct lowcore, br_r1_trampoline));
|
|
+ /* j . */
|
|
+ EMIT4_PCREL(0xa7f40000, 0);
|
|
+ }
|
|
+ }
|
|
}
|
|
|
|
/*
|
|
@@ -978,8 +1032,13 @@ static noinline int bpf_jit_insn(struct bpf_jit *jit, struct bpf_prog *fp, int i
|
|
/* lg %w1,<d(imm)>(%l) */
|
|
EMIT6_DISP_LH(0xe3000000, 0x0004, REG_W1, REG_0, REG_L,
|
|
EMIT_CONST_U64(func));
|
|
- /* basr %r14,%w1 */
|
|
- EMIT2(0x0d00, REG_14, REG_W1);
|
|
+ if (IS_ENABLED(CC_USING_EXPOLINE) && !nospec_disable) {
|
|
+ /* brasl %r14,__s390_indirect_jump_r1 */
|
|
+ EMIT6_PCREL_RILB(0xc0050000, REG_14, jit->r1_thunk_ip);
|
|
+ } else {
|
|
+ /* basr %r14,%w1 */
|
|
+ EMIT2(0x0d00, REG_14, REG_W1);
|
|
+ }
|
|
/* lgr %b0,%r2: load return value into %b0 */
|
|
EMIT4(0xb9040000, BPF_REG_0, REG_2);
|
|
if ((jit->seen & SEEN_SKB) &&
|
|
diff --git a/arch/sparc/kernel/vio.c b/arch/sparc/kernel/vio.c
|
|
index 1a0fa10cb6b7..32bae68e34c1 100644
|
|
--- a/arch/sparc/kernel/vio.c
|
|
+++ b/arch/sparc/kernel/vio.c
|
|
@@ -403,7 +403,7 @@ static struct vio_dev *vio_create_one(struct mdesc_handle *hp, u64 mp,
|
|
if (err) {
|
|
printk(KERN_ERR "VIO: Could not register device %s, err=%d\n",
|
|
dev_name(&vdev->dev), err);
|
|
- kfree(vdev);
|
|
+ put_device(&vdev->dev);
|
|
return NULL;
|
|
}
|
|
if (vdev->dp)
|
|
diff --git a/arch/x86/kernel/machine_kexec_32.c b/arch/x86/kernel/machine_kexec_32.c
|
|
index edfede768688..5167f3f74136 100644
|
|
--- a/arch/x86/kernel/machine_kexec_32.c
|
|
+++ b/arch/x86/kernel/machine_kexec_32.c
|
|
@@ -57,12 +57,17 @@ static void load_segments(void)
|
|
static void machine_kexec_free_page_tables(struct kimage *image)
|
|
{
|
|
free_page((unsigned long)image->arch.pgd);
|
|
+ image->arch.pgd = NULL;
|
|
#ifdef CONFIG_X86_PAE
|
|
free_page((unsigned long)image->arch.pmd0);
|
|
+ image->arch.pmd0 = NULL;
|
|
free_page((unsigned long)image->arch.pmd1);
|
|
+ image->arch.pmd1 = NULL;
|
|
#endif
|
|
free_page((unsigned long)image->arch.pte0);
|
|
+ image->arch.pte0 = NULL;
|
|
free_page((unsigned long)image->arch.pte1);
|
|
+ image->arch.pte1 = NULL;
|
|
}
|
|
|
|
static int machine_kexec_alloc_page_tables(struct kimage *image)
|
|
@@ -79,7 +84,6 @@ static int machine_kexec_alloc_page_tables(struct kimage *image)
|
|
!image->arch.pmd0 || !image->arch.pmd1 ||
|
|
#endif
|
|
!image->arch.pte0 || !image->arch.pte1) {
|
|
- machine_kexec_free_page_tables(image);
|
|
return -ENOMEM;
|
|
}
|
|
return 0;
|
|
diff --git a/arch/x86/kernel/machine_kexec_64.c b/arch/x86/kernel/machine_kexec_64.c
|
|
index 3b7427aa7d85..5bce2a88e8a3 100644
|
|
--- a/arch/x86/kernel/machine_kexec_64.c
|
|
+++ b/arch/x86/kernel/machine_kexec_64.c
|
|
@@ -38,9 +38,13 @@ static struct kexec_file_ops *kexec_file_loaders[] = {
|
|
static void free_transition_pgtable(struct kimage *image)
|
|
{
|
|
free_page((unsigned long)image->arch.p4d);
|
|
+ image->arch.p4d = NULL;
|
|
free_page((unsigned long)image->arch.pud);
|
|
+ image->arch.pud = NULL;
|
|
free_page((unsigned long)image->arch.pmd);
|
|
+ image->arch.pmd = NULL;
|
|
free_page((unsigned long)image->arch.pte);
|
|
+ image->arch.pte = NULL;
|
|
}
|
|
|
|
static int init_transition_pgtable(struct kimage *image, pgd_t *pgd)
|
|
@@ -90,7 +94,6 @@ static int init_transition_pgtable(struct kimage *image, pgd_t *pgd)
|
|
set_pte(pte, pfn_pte(paddr >> PAGE_SHIFT, PAGE_KERNEL_EXEC_NOENC));
|
|
return 0;
|
|
err:
|
|
- free_transition_pgtable(image);
|
|
return result;
|
|
}
|
|
|
|
diff --git a/drivers/block/loop.c b/drivers/block/loop.c
|
|
index 754852156622..1a87f87c88d0 100644
|
|
--- a/drivers/block/loop.c
|
|
+++ b/drivers/block/loop.c
|
|
@@ -1166,21 +1166,17 @@ loop_set_status(struct loop_device *lo, const struct loop_info64 *info)
|
|
static int
|
|
loop_get_status(struct loop_device *lo, struct loop_info64 *info)
|
|
{
|
|
- struct file *file = lo->lo_backing_file;
|
|
+ struct file *file;
|
|
struct kstat stat;
|
|
- int error;
|
|
+ int ret;
|
|
|
|
- if (lo->lo_state != Lo_bound)
|
|
+ if (lo->lo_state != Lo_bound) {
|
|
+ mutex_unlock(&lo->lo_ctl_mutex);
|
|
return -ENXIO;
|
|
- error = vfs_getattr(&file->f_path, &stat,
|
|
- STATX_INO, AT_STATX_SYNC_AS_STAT);
|
|
- if (error)
|
|
- return error;
|
|
+ }
|
|
+
|
|
memset(info, 0, sizeof(*info));
|
|
info->lo_number = lo->lo_number;
|
|
- info->lo_device = huge_encode_dev(stat.dev);
|
|
- info->lo_inode = stat.ino;
|
|
- info->lo_rdevice = huge_encode_dev(lo->lo_device ? stat.rdev : stat.dev);
|
|
info->lo_offset = lo->lo_offset;
|
|
info->lo_sizelimit = lo->lo_sizelimit;
|
|
info->lo_flags = lo->lo_flags;
|
|
@@ -1193,7 +1189,19 @@ loop_get_status(struct loop_device *lo, struct loop_info64 *info)
|
|
memcpy(info->lo_encrypt_key, lo->lo_encrypt_key,
|
|
lo->lo_encrypt_key_size);
|
|
}
|
|
- return 0;
|
|
+
|
|
+ /* Drop lo_ctl_mutex while we call into the filesystem. */
|
|
+ file = get_file(lo->lo_backing_file);
|
|
+ mutex_unlock(&lo->lo_ctl_mutex);
|
|
+ ret = vfs_getattr(&file->f_path, &stat, STATX_INO,
|
|
+ AT_STATX_SYNC_AS_STAT);
|
|
+ if (!ret) {
|
|
+ info->lo_device = huge_encode_dev(stat.dev);
|
|
+ info->lo_inode = stat.ino;
|
|
+ info->lo_rdevice = huge_encode_dev(stat.rdev);
|
|
+ }
|
|
+ fput(file);
|
|
+ return ret;
|
|
}
|
|
|
|
static void
|
|
@@ -1274,12 +1282,13 @@ static int
|
|
loop_get_status_old(struct loop_device *lo, struct loop_info __user *arg) {
|
|
struct loop_info info;
|
|
struct loop_info64 info64;
|
|
- int err = 0;
|
|
+ int err;
|
|
|
|
- if (!arg)
|
|
- err = -EINVAL;
|
|
- if (!err)
|
|
- err = loop_get_status(lo, &info64);
|
|
+ if (!arg) {
|
|
+ mutex_unlock(&lo->lo_ctl_mutex);
|
|
+ return -EINVAL;
|
|
+ }
|
|
+ err = loop_get_status(lo, &info64);
|
|
if (!err)
|
|
err = loop_info64_to_old(&info64, &info);
|
|
if (!err && copy_to_user(arg, &info, sizeof(info)))
|
|
@@ -1291,12 +1300,13 @@ loop_get_status_old(struct loop_device *lo, struct loop_info __user *arg) {
|
|
static int
|
|
loop_get_status64(struct loop_device *lo, struct loop_info64 __user *arg) {
|
|
struct loop_info64 info64;
|
|
- int err = 0;
|
|
+ int err;
|
|
|
|
- if (!arg)
|
|
- err = -EINVAL;
|
|
- if (!err)
|
|
- err = loop_get_status(lo, &info64);
|
|
+ if (!arg) {
|
|
+ mutex_unlock(&lo->lo_ctl_mutex);
|
|
+ return -EINVAL;
|
|
+ }
|
|
+ err = loop_get_status(lo, &info64);
|
|
if (!err && copy_to_user(arg, &info64, sizeof(info64)))
|
|
err = -EFAULT;
|
|
|
|
@@ -1373,7 +1383,8 @@ static int lo_ioctl(struct block_device *bdev, fmode_t mode,
|
|
break;
|
|
case LOOP_GET_STATUS:
|
|
err = loop_get_status_old(lo, (struct loop_info __user *) arg);
|
|
- break;
|
|
+ /* loop_get_status() unlocks lo_ctl_mutex */
|
|
+ goto out_unlocked;
|
|
case LOOP_SET_STATUS64:
|
|
err = -EPERM;
|
|
if ((mode & FMODE_WRITE) || capable(CAP_SYS_ADMIN))
|
|
@@ -1382,7 +1393,8 @@ static int lo_ioctl(struct block_device *bdev, fmode_t mode,
|
|
break;
|
|
case LOOP_GET_STATUS64:
|
|
err = loop_get_status64(lo, (struct loop_info64 __user *) arg);
|
|
- break;
|
|
+ /* loop_get_status() unlocks lo_ctl_mutex */
|
|
+ goto out_unlocked;
|
|
case LOOP_SET_CAPACITY:
|
|
err = -EPERM;
|
|
if ((mode & FMODE_WRITE) || capable(CAP_SYS_ADMIN))
|
|
@@ -1515,12 +1527,13 @@ loop_get_status_compat(struct loop_device *lo,
|
|
struct compat_loop_info __user *arg)
|
|
{
|
|
struct loop_info64 info64;
|
|
- int err = 0;
|
|
+ int err;
|
|
|
|
- if (!arg)
|
|
- err = -EINVAL;
|
|
- if (!err)
|
|
- err = loop_get_status(lo, &info64);
|
|
+ if (!arg) {
|
|
+ mutex_unlock(&lo->lo_ctl_mutex);
|
|
+ return -EINVAL;
|
|
+ }
|
|
+ err = loop_get_status(lo, &info64);
|
|
if (!err)
|
|
err = loop_info64_to_compat(&info64, arg);
|
|
return err;
|
|
@@ -1543,7 +1556,7 @@ static int lo_compat_ioctl(struct block_device *bdev, fmode_t mode,
|
|
mutex_lock(&lo->lo_ctl_mutex);
|
|
err = loop_get_status_compat(
|
|
lo, (struct compat_loop_info __user *) arg);
|
|
- mutex_unlock(&lo->lo_ctl_mutex);
|
|
+ /* loop_get_status() unlocks lo_ctl_mutex */
|
|
break;
|
|
case LOOP_SET_CAPACITY:
|
|
case LOOP_CLR_FD:
|
|
diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c
|
|
index 7fcc4d7f4909..86d7975afaeb 100644
|
|
--- a/drivers/bluetooth/btusb.c
|
|
+++ b/drivers/bluetooth/btusb.c
|
|
@@ -370,6 +370,9 @@ static const struct usb_device_id blacklist_table[] = {
|
|
{ USB_DEVICE(0x13d3, 0x3459), .driver_info = BTUSB_REALTEK },
|
|
{ USB_DEVICE(0x13d3, 0x3494), .driver_info = BTUSB_REALTEK },
|
|
|
|
+ /* Additional Realtek 8723BU Bluetooth devices */
|
|
+ { USB_DEVICE(0x7392, 0xa611), .driver_info = BTUSB_REALTEK },
|
|
+
|
|
/* Additional Realtek 8821AE Bluetooth devices */
|
|
{ USB_DEVICE(0x0b05, 0x17dc), .driver_info = BTUSB_REALTEK },
|
|
{ USB_DEVICE(0x13d3, 0x3414), .driver_info = BTUSB_REALTEK },
|
|
@@ -377,6 +380,9 @@ static const struct usb_device_id blacklist_table[] = {
|
|
{ USB_DEVICE(0x13d3, 0x3461), .driver_info = BTUSB_REALTEK },
|
|
{ USB_DEVICE(0x13d3, 0x3462), .driver_info = BTUSB_REALTEK },
|
|
|
|
+ /* Additional Realtek 8822BE Bluetooth devices */
|
|
+ { USB_DEVICE(0x0b05, 0x185c), .driver_info = BTUSB_REALTEK },
|
|
+
|
|
/* Silicon Wave based devices */
|
|
{ USB_DEVICE(0x0c10, 0x0000), .driver_info = BTUSB_SWAVE },
|
|
|
|
diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
|
|
index 60c7fde37d23..4e21f5bcd954 100644
|
|
--- a/drivers/clk/clk.c
|
|
+++ b/drivers/clk/clk.c
|
|
@@ -1931,6 +1931,9 @@ static int clk_core_get_phase(struct clk_core *core)
|
|
int ret;
|
|
|
|
clk_prepare_lock();
|
|
+ /* Always try to update cached phase if possible */
|
|
+ if (core->ops->get_phase)
|
|
+ core->phase = core->ops->get_phase(core->hw);
|
|
ret = core->phase;
|
|
clk_prepare_unlock();
|
|
|
|
diff --git a/drivers/clk/hisilicon/crg-hi3516cv300.c b/drivers/clk/hisilicon/crg-hi3516cv300.c
|
|
index 2007123832bb..53450b651e4c 100644
|
|
--- a/drivers/clk/hisilicon/crg-hi3516cv300.c
|
|
+++ b/drivers/clk/hisilicon/crg-hi3516cv300.c
|
|
@@ -204,7 +204,7 @@ static const struct hisi_crg_funcs hi3516cv300_crg_funcs = {
|
|
/* hi3516CV300 sysctrl CRG */
|
|
#define HI3516CV300_SYSCTRL_NR_CLKS 16
|
|
|
|
-static const char *wdt_mux_p[] __initconst = { "3m", "apb" };
|
|
+static const char *const wdt_mux_p[] __initconst = { "3m", "apb" };
|
|
static u32 wdt_mux_table[] = {0, 1};
|
|
|
|
static const struct hisi_mux_clock hi3516cv300_sysctrl_mux_clks[] = {
|
|
diff --git a/drivers/clk/rockchip/clk-mmc-phase.c b/drivers/clk/rockchip/clk-mmc-phase.c
|
|
index 077fcdc7908b..fe7d9ed1d436 100644
|
|
--- a/drivers/clk/rockchip/clk-mmc-phase.c
|
|
+++ b/drivers/clk/rockchip/clk-mmc-phase.c
|
|
@@ -58,6 +58,12 @@ static int rockchip_mmc_get_phase(struct clk_hw *hw)
|
|
u16 degrees;
|
|
u32 delay_num = 0;
|
|
|
|
+ /* See the comment for rockchip_mmc_set_phase below */
|
|
+ if (!rate) {
|
|
+ pr_err("%s: invalid clk rate\n", __func__);
|
|
+ return -EINVAL;
|
|
+ }
|
|
+
|
|
raw_value = readl(mmc_clock->reg) >> (mmc_clock->shift);
|
|
|
|
degrees = (raw_value & ROCKCHIP_MMC_DEGREE_MASK) * 90;
|
|
@@ -84,6 +90,23 @@ static int rockchip_mmc_set_phase(struct clk_hw *hw, int degrees)
|
|
u32 raw_value;
|
|
u32 delay;
|
|
|
|
+ /*
|
|
+ * The below calculation is based on the output clock from
|
|
+ * MMC host to the card, which expects the phase clock inherits
|
|
+ * the clock rate from its parent, namely the output clock
|
|
+ * provider of MMC host. However, things may go wrong if
|
|
+ * (1) It is orphan.
|
|
+ * (2) It is assigned to the wrong parent.
|
|
+ *
|
|
+ * This check help debug the case (1), which seems to be the
|
|
+ * most likely problem we often face and which makes it difficult
|
|
+ * for people to debug unstable mmc tuning results.
|
|
+ */
|
|
+ if (!rate) {
|
|
+ pr_err("%s: invalid clk rate\n", __func__);
|
|
+ return -EINVAL;
|
|
+ }
|
|
+
|
|
nineties = degrees / 90;
|
|
remainder = (degrees % 90);
|
|
|
|
diff --git a/drivers/clk/rockchip/clk-rk3228.c b/drivers/clk/rockchip/clk-rk3228.c
|
|
index 11e7f2d1c054..7af48184b022 100644
|
|
--- a/drivers/clk/rockchip/clk-rk3228.c
|
|
+++ b/drivers/clk/rockchip/clk-rk3228.c
|
|
@@ -387,7 +387,7 @@ static struct rockchip_clk_branch rk3228_clk_branches[] __initdata = {
|
|
RK2928_CLKSEL_CON(23), 5, 2, MFLAGS, 0, 6, DFLAGS,
|
|
RK2928_CLKGATE_CON(2), 15, GFLAGS),
|
|
|
|
- COMPOSITE(SCLK_SDMMC, "sclk_sdmmc0", mux_mmc_src_p, 0,
|
|
+ COMPOSITE(SCLK_SDMMC, "sclk_sdmmc", mux_mmc_src_p, 0,
|
|
RK2928_CLKSEL_CON(11), 8, 2, MFLAGS, 0, 8, DFLAGS,
|
|
RK2928_CLKGATE_CON(2), 11, GFLAGS),
|
|
|
|
diff --git a/drivers/clk/samsung/clk-exynos3250.c b/drivers/clk/samsung/clk-exynos3250.c
|
|
index 1b81e283f605..ed36728424a2 100644
|
|
--- a/drivers/clk/samsung/clk-exynos3250.c
|
|
+++ b/drivers/clk/samsung/clk-exynos3250.c
|
|
@@ -698,7 +698,7 @@ static const struct samsung_pll_rate_table exynos3250_epll_rates[] __initconst =
|
|
PLL_36XX_RATE(144000000, 96, 2, 3, 0),
|
|
PLL_36XX_RATE( 96000000, 128, 2, 4, 0),
|
|
PLL_36XX_RATE( 84000000, 112, 2, 4, 0),
|
|
- PLL_36XX_RATE( 80000004, 106, 2, 4, 43691),
|
|
+ PLL_36XX_RATE( 80000003, 106, 2, 4, 43691),
|
|
PLL_36XX_RATE( 73728000, 98, 2, 4, 19923),
|
|
PLL_36XX_RATE( 67737598, 270, 3, 5, 62285),
|
|
PLL_36XX_RATE( 65535999, 174, 2, 5, 49982),
|
|
@@ -734,7 +734,7 @@ static const struct samsung_pll_rate_table exynos3250_vpll_rates[] __initconst =
|
|
PLL_36XX_RATE(148352005, 98, 2, 3, 59070),
|
|
PLL_36XX_RATE(108000000, 144, 2, 4, 0),
|
|
PLL_36XX_RATE( 74250000, 99, 2, 4, 0),
|
|
- PLL_36XX_RATE( 74176002, 98, 3, 4, 59070),
|
|
+ PLL_36XX_RATE( 74176002, 98, 2, 4, 59070),
|
|
PLL_36XX_RATE( 54054000, 216, 3, 5, 14156),
|
|
PLL_36XX_RATE( 54000000, 144, 2, 5, 0),
|
|
{ /* sentinel */ }
|
|
diff --git a/drivers/clk/samsung/clk-exynos5250.c b/drivers/clk/samsung/clk-exynos5250.c
|
|
index 27a227d6620c..6a0cb8a515e8 100644
|
|
--- a/drivers/clk/samsung/clk-exynos5250.c
|
|
+++ b/drivers/clk/samsung/clk-exynos5250.c
|
|
@@ -711,13 +711,13 @@ static const struct samsung_pll_rate_table epll_24mhz_tbl[] __initconst = {
|
|
/* sorted in descending order */
|
|
/* PLL_36XX_RATE(rate, m, p, s, k) */
|
|
PLL_36XX_RATE(192000000, 64, 2, 2, 0),
|
|
- PLL_36XX_RATE(180633600, 90, 3, 2, 20762),
|
|
+ PLL_36XX_RATE(180633605, 90, 3, 2, 20762),
|
|
PLL_36XX_RATE(180000000, 90, 3, 2, 0),
|
|
PLL_36XX_RATE(73728000, 98, 2, 4, 19923),
|
|
- PLL_36XX_RATE(67737600, 90, 2, 4, 20762),
|
|
+ PLL_36XX_RATE(67737602, 90, 2, 4, 20762),
|
|
PLL_36XX_RATE(49152000, 98, 3, 4, 19923),
|
|
- PLL_36XX_RATE(45158400, 90, 3, 4, 20762),
|
|
- PLL_36XX_RATE(32768000, 131, 3, 5, 4719),
|
|
+ PLL_36XX_RATE(45158401, 90, 3, 4, 20762),
|
|
+ PLL_36XX_RATE(32768001, 131, 3, 5, 4719),
|
|
{ },
|
|
};
|
|
|
|
diff --git a/drivers/clk/samsung/clk-exynos5260.c b/drivers/clk/samsung/clk-exynos5260.c
|
|
index fd1d9bfc151b..8eae1752d700 100644
|
|
--- a/drivers/clk/samsung/clk-exynos5260.c
|
|
+++ b/drivers/clk/samsung/clk-exynos5260.c
|
|
@@ -65,7 +65,7 @@ static const struct samsung_pll_rate_table pll2650_24mhz_tbl[] __initconst = {
|
|
PLL_36XX_RATE(480000000, 160, 2, 2, 0),
|
|
PLL_36XX_RATE(432000000, 144, 2, 2, 0),
|
|
PLL_36XX_RATE(400000000, 200, 3, 2, 0),
|
|
- PLL_36XX_RATE(394073130, 459, 7, 2, 49282),
|
|
+ PLL_36XX_RATE(394073128, 459, 7, 2, 49282),
|
|
PLL_36XX_RATE(333000000, 111, 2, 2, 0),
|
|
PLL_36XX_RATE(300000000, 100, 2, 2, 0),
|
|
PLL_36XX_RATE(266000000, 266, 3, 3, 0),
|
|
diff --git a/drivers/clk/samsung/clk-exynos5433.c b/drivers/clk/samsung/clk-exynos5433.c
|
|
index 11343a597093..1d2265f9ee97 100644
|
|
--- a/drivers/clk/samsung/clk-exynos5433.c
|
|
+++ b/drivers/clk/samsung/clk-exynos5433.c
|
|
@@ -725,7 +725,7 @@ static const struct samsung_pll_rate_table exynos5433_pll_rates[] __initconst =
|
|
PLL_35XX_RATE(800000000U, 400, 6, 1),
|
|
PLL_35XX_RATE(733000000U, 733, 12, 1),
|
|
PLL_35XX_RATE(700000000U, 175, 3, 1),
|
|
- PLL_35XX_RATE(667000000U, 222, 4, 1),
|
|
+ PLL_35XX_RATE(666000000U, 222, 4, 1),
|
|
PLL_35XX_RATE(633000000U, 211, 4, 1),
|
|
PLL_35XX_RATE(600000000U, 500, 5, 2),
|
|
PLL_35XX_RATE(552000000U, 460, 5, 2),
|
|
@@ -753,12 +753,12 @@ static const struct samsung_pll_rate_table exynos5433_pll_rates[] __initconst =
|
|
/* AUD_PLL */
|
|
static const struct samsung_pll_rate_table exynos5433_aud_pll_rates[] __initconst = {
|
|
PLL_36XX_RATE(400000000U, 200, 3, 2, 0),
|
|
- PLL_36XX_RATE(393216000U, 197, 3, 2, -25690),
|
|
+ PLL_36XX_RATE(393216003U, 197, 3, 2, -25690),
|
|
PLL_36XX_RATE(384000000U, 128, 2, 2, 0),
|
|
- PLL_36XX_RATE(368640000U, 246, 4, 2, -15729),
|
|
- PLL_36XX_RATE(361507200U, 181, 3, 2, -16148),
|
|
- PLL_36XX_RATE(338688000U, 113, 2, 2, -6816),
|
|
- PLL_36XX_RATE(294912000U, 98, 1, 3, 19923),
|
|
+ PLL_36XX_RATE(368639991U, 246, 4, 2, -15729),
|
|
+ PLL_36XX_RATE(361507202U, 181, 3, 2, -16148),
|
|
+ PLL_36XX_RATE(338687988U, 113, 2, 2, -6816),
|
|
+ PLL_36XX_RATE(294912002U, 98, 1, 3, 19923),
|
|
PLL_36XX_RATE(288000000U, 96, 1, 3, 0),
|
|
PLL_36XX_RATE(252000000U, 84, 1, 3, 0),
|
|
{ /* sentinel */ }
|
|
diff --git a/drivers/clk/samsung/clk-exynos7.c b/drivers/clk/samsung/clk-exynos7.c
|
|
index 5931a4140c3d..bbfa57b4e017 100644
|
|
--- a/drivers/clk/samsung/clk-exynos7.c
|
|
+++ b/drivers/clk/samsung/clk-exynos7.c
|
|
@@ -140,7 +140,7 @@ static const struct samsung_div_clock topc_div_clks[] __initconst = {
|
|
};
|
|
|
|
static const struct samsung_pll_rate_table pll1460x_24mhz_tbl[] __initconst = {
|
|
- PLL_36XX_RATE(491520000, 20, 1, 0, 31457),
|
|
+ PLL_36XX_RATE(491519897, 20, 1, 0, 31457),
|
|
{},
|
|
};
|
|
|
|
diff --git a/drivers/clk/samsung/clk-s3c2410.c b/drivers/clk/samsung/clk-s3c2410.c
|
|
index e0650c33863b..d8e58a659467 100644
|
|
--- a/drivers/clk/samsung/clk-s3c2410.c
|
|
+++ b/drivers/clk/samsung/clk-s3c2410.c
|
|
@@ -168,7 +168,7 @@ static struct samsung_pll_rate_table pll_s3c2410_12mhz_tbl[] __initdata = {
|
|
PLL_35XX_RATE(226000000, 105, 1, 1),
|
|
PLL_35XX_RATE(210000000, 132, 2, 1),
|
|
/* 2410 common */
|
|
- PLL_35XX_RATE(203000000, 161, 3, 1),
|
|
+ PLL_35XX_RATE(202800000, 161, 3, 1),
|
|
PLL_35XX_RATE(192000000, 88, 1, 1),
|
|
PLL_35XX_RATE(186000000, 85, 1, 1),
|
|
PLL_35XX_RATE(180000000, 82, 1, 1),
|
|
@@ -178,18 +178,18 @@ static struct samsung_pll_rate_table pll_s3c2410_12mhz_tbl[] __initdata = {
|
|
PLL_35XX_RATE(147000000, 90, 2, 1),
|
|
PLL_35XX_RATE(135000000, 82, 2, 1),
|
|
PLL_35XX_RATE(124000000, 116, 1, 2),
|
|
- PLL_35XX_RATE(118000000, 150, 2, 2),
|
|
+ PLL_35XX_RATE(118500000, 150, 2, 2),
|
|
PLL_35XX_RATE(113000000, 105, 1, 2),
|
|
- PLL_35XX_RATE(101000000, 127, 2, 2),
|
|
+ PLL_35XX_RATE(101250000, 127, 2, 2),
|
|
PLL_35XX_RATE(90000000, 112, 2, 2),
|
|
- PLL_35XX_RATE(85000000, 105, 2, 2),
|
|
+ PLL_35XX_RATE(84750000, 105, 2, 2),
|
|
PLL_35XX_RATE(79000000, 71, 1, 2),
|
|
- PLL_35XX_RATE(68000000, 82, 2, 2),
|
|
- PLL_35XX_RATE(56000000, 142, 2, 3),
|
|
+ PLL_35XX_RATE(67500000, 82, 2, 2),
|
|
+ PLL_35XX_RATE(56250000, 142, 2, 3),
|
|
PLL_35XX_RATE(48000000, 120, 2, 3),
|
|
- PLL_35XX_RATE(51000000, 161, 3, 3),
|
|
+ PLL_35XX_RATE(50700000, 161, 3, 3),
|
|
PLL_35XX_RATE(45000000, 82, 1, 3),
|
|
- PLL_35XX_RATE(34000000, 82, 2, 3),
|
|
+ PLL_35XX_RATE(33750000, 82, 2, 3),
|
|
{ /* sentinel */ },
|
|
};
|
|
|
|
diff --git a/drivers/clk/tegra/clk-pll.c b/drivers/clk/tegra/clk-pll.c
|
|
index 7c369e21c91c..830d1c87fa7c 100644
|
|
--- a/drivers/clk/tegra/clk-pll.c
|
|
+++ b/drivers/clk/tegra/clk-pll.c
|
|
@@ -1151,6 +1151,8 @@ static const struct clk_ops tegra_clk_pllu_ops = {
|
|
.enable = clk_pllu_enable,
|
|
.disable = clk_pll_disable,
|
|
.recalc_rate = clk_pll_recalc_rate,
|
|
+ .round_rate = clk_pll_round_rate,
|
|
+ .set_rate = clk_pll_set_rate,
|
|
};
|
|
|
|
static int _pll_fixed_mdiv(struct tegra_clk_pll_params *pll_params,
|
|
diff --git a/drivers/crypto/atmel-aes.c b/drivers/crypto/atmel-aes.c
|
|
index 29e20c37f3a6..11129b796dda 100644
|
|
--- a/drivers/crypto/atmel-aes.c
|
|
+++ b/drivers/crypto/atmel-aes.c
|
|
@@ -2145,7 +2145,7 @@ static int atmel_aes_authenc_setkey(struct crypto_aead *tfm, const u8 *key,
|
|
|
|
badkey:
|
|
crypto_aead_set_flags(tfm, CRYPTO_TFM_RES_BAD_KEY_LEN);
|
|
- memzero_explicit(&key, sizeof(keys));
|
|
+ memzero_explicit(&keys, sizeof(keys));
|
|
return -EINVAL;
|
|
}
|
|
|
|
diff --git a/drivers/crypto/ccp/ccp-debugfs.c b/drivers/crypto/ccp/ccp-debugfs.c
|
|
index 59d4ca4e72d8..1a734bd2070a 100644
|
|
--- a/drivers/crypto/ccp/ccp-debugfs.c
|
|
+++ b/drivers/crypto/ccp/ccp-debugfs.c
|
|
@@ -278,7 +278,7 @@ static const struct file_operations ccp_debugfs_stats_ops = {
|
|
};
|
|
|
|
static struct dentry *ccp_debugfs_dir;
|
|
-static DEFINE_RWLOCK(ccp_debugfs_lock);
|
|
+static DEFINE_MUTEX(ccp_debugfs_lock);
|
|
|
|
#define MAX_NAME_LEN 20
|
|
|
|
@@ -290,16 +290,15 @@ void ccp5_debugfs_setup(struct ccp_device *ccp)
|
|
struct dentry *debugfs_stats;
|
|
struct dentry *debugfs_q_instance;
|
|
struct dentry *debugfs_q_stats;
|
|
- unsigned long flags;
|
|
int i;
|
|
|
|
if (!debugfs_initialized())
|
|
return;
|
|
|
|
- write_lock_irqsave(&ccp_debugfs_lock, flags);
|
|
+ mutex_lock(&ccp_debugfs_lock);
|
|
if (!ccp_debugfs_dir)
|
|
ccp_debugfs_dir = debugfs_create_dir(KBUILD_MODNAME, NULL);
|
|
- write_unlock_irqrestore(&ccp_debugfs_lock, flags);
|
|
+ mutex_unlock(&ccp_debugfs_lock);
|
|
if (!ccp_debugfs_dir)
|
|
return;
|
|
|
|
diff --git a/drivers/crypto/inside-secure/safexcel.c b/drivers/crypto/inside-secure/safexcel.c
|
|
index d4c81cb73bee..3ee68ecde9ec 100644
|
|
--- a/drivers/crypto/inside-secure/safexcel.c
|
|
+++ b/drivers/crypto/inside-secure/safexcel.c
|
|
@@ -462,6 +462,15 @@ void safexcel_dequeue(struct safexcel_crypto_priv *priv, int ring)
|
|
if (backlog)
|
|
backlog->complete(backlog, -EINPROGRESS);
|
|
|
|
+ /* In case the send() helper did not issue any command to push
|
|
+ * to the engine because the input data was cached, continue to
|
|
+ * dequeue other requests as this is valid and not an error.
|
|
+ */
|
|
+ if (!commands && !results) {
|
|
+ kfree(request);
|
|
+ continue;
|
|
+ }
|
|
+
|
|
spin_lock_bh(&priv->ring[ring].egress_lock);
|
|
list_add_tail(&request->list, &priv->ring[ring].list);
|
|
spin_unlock_bh(&priv->ring[ring].egress_lock);
|
|
diff --git a/drivers/crypto/inside-secure/safexcel_cipher.c b/drivers/crypto/inside-secure/safexcel_cipher.c
|
|
index fcc0a606d748..29cf7e00b574 100644
|
|
--- a/drivers/crypto/inside-secure/safexcel_cipher.c
|
|
+++ b/drivers/crypto/inside-secure/safexcel_cipher.c
|
|
@@ -446,7 +446,7 @@ static int safexcel_cipher_exit_inv(struct crypto_tfm *tfm)
|
|
if (!priv->ring[ring].need_dequeue)
|
|
safexcel_dequeue(priv, ring);
|
|
|
|
- wait_for_completion_interruptible(&result.completion);
|
|
+ wait_for_completion(&result.completion);
|
|
|
|
if (result.error) {
|
|
dev_warn(priv->dev,
|
|
diff --git a/drivers/crypto/inside-secure/safexcel_hash.c b/drivers/crypto/inside-secure/safexcel_hash.c
|
|
index d626aa485a76..69f29776591a 100644
|
|
--- a/drivers/crypto/inside-secure/safexcel_hash.c
|
|
+++ b/drivers/crypto/inside-secure/safexcel_hash.c
|
|
@@ -185,7 +185,7 @@ static int safexcel_ahash_send_req(struct crypto_async_request *async, int ring,
|
|
int i, queued, len, cache_len, extra, n_cdesc = 0, ret = 0;
|
|
|
|
queued = len = req->len - req->processed;
|
|
- if (queued < crypto_ahash_blocksize(ahash))
|
|
+ if (queued <= crypto_ahash_blocksize(ahash))
|
|
cache_len = queued;
|
|
else
|
|
cache_len = queued - areq->nbytes;
|
|
@@ -199,7 +199,7 @@ static int safexcel_ahash_send_req(struct crypto_async_request *async, int ring,
|
|
/* If this is not the last request and the queued data
|
|
* is a multiple of a block, cache the last one for now.
|
|
*/
|
|
- extra = queued - crypto_ahash_blocksize(ahash);
|
|
+ extra = crypto_ahash_blocksize(ahash);
|
|
|
|
if (extra) {
|
|
sg_pcopy_to_buffer(areq->src, sg_nents(areq->src),
|
|
@@ -494,7 +494,7 @@ static int safexcel_ahash_exit_inv(struct crypto_tfm *tfm)
|
|
if (!priv->ring[ring].need_dequeue)
|
|
safexcel_dequeue(priv, ring);
|
|
|
|
- wait_for_completion_interruptible(&result.completion);
|
|
+ wait_for_completion(&result.completion);
|
|
|
|
if (result.error) {
|
|
dev_warn(priv->dev, "hash: completion error (%d)\n",
|
|
@@ -819,7 +819,7 @@ static int safexcel_hmac_init_pad(struct ahash_request *areq,
|
|
init_completion(&result.completion);
|
|
|
|
ret = crypto_ahash_digest(areq);
|
|
- if (ret == -EINPROGRESS) {
|
|
+ if (ret == -EINPROGRESS || ret == -EBUSY) {
|
|
wait_for_completion_interruptible(&result.completion);
|
|
ret = result.error;
|
|
}
|
|
diff --git a/drivers/crypto/sunxi-ss/sun4i-ss-core.c b/drivers/crypto/sunxi-ss/sun4i-ss-core.c
|
|
index 1547cbe13dc2..a81d89b3b7d8 100644
|
|
--- a/drivers/crypto/sunxi-ss/sun4i-ss-core.c
|
|
+++ b/drivers/crypto/sunxi-ss/sun4i-ss-core.c
|
|
@@ -451,6 +451,7 @@ static struct platform_driver sun4i_ss_driver = {
|
|
|
|
module_platform_driver(sun4i_ss_driver);
|
|
|
|
+MODULE_ALIAS("platform:sun4i-ss");
|
|
MODULE_DESCRIPTION("Allwinner Security System cryptographic accelerator");
|
|
MODULE_LICENSE("GPL");
|
|
MODULE_AUTHOR("Corentin LABBE <clabbe.montjoie@gmail.com>");
|
|
diff --git a/drivers/media/dvb-core/dmxdev.c b/drivers/media/dvb-core/dmxdev.c
|
|
index 18e4230865be..51009b2718a3 100644
|
|
--- a/drivers/media/dvb-core/dmxdev.c
|
|
+++ b/drivers/media/dvb-core/dmxdev.c
|
|
@@ -1055,7 +1055,7 @@ static int dvb_demux_do_ioctl(struct file *file,
|
|
break;
|
|
|
|
default:
|
|
- ret = -EINVAL;
|
|
+ ret = -ENOTTY;
|
|
break;
|
|
}
|
|
mutex_unlock(&dmxdev->mutex);
|
|
diff --git a/drivers/media/dvb-frontends/lgdt3306a.c b/drivers/media/dvb-frontends/lgdt3306a.c
|
|
index c9b1eb38444e..fbb3b2f49d2d 100644
|
|
--- a/drivers/media/dvb-frontends/lgdt3306a.c
|
|
+++ b/drivers/media/dvb-frontends/lgdt3306a.c
|
|
@@ -1767,7 +1767,13 @@ static void lgdt3306a_release(struct dvb_frontend *fe)
|
|
struct lgdt3306a_state *state = fe->demodulator_priv;
|
|
|
|
dbg_info("\n");
|
|
- kfree(state);
|
|
+
|
|
+ /*
|
|
+ * If state->muxc is not NULL, then we are an i2c device
|
|
+ * and lgdt3306a_remove will clean up state
|
|
+ */
|
|
+ if (!state->muxc)
|
|
+ kfree(state);
|
|
}
|
|
|
|
static const struct dvb_frontend_ops lgdt3306a_ops;
|
|
@@ -2168,7 +2174,7 @@ static int lgdt3306a_probe(struct i2c_client *client,
|
|
sizeof(struct lgdt3306a_config));
|
|
|
|
config->i2c_addr = client->addr;
|
|
- fe = lgdt3306a_attach(config, client->adapter);
|
|
+ fe = dvb_attach(lgdt3306a_attach, config, client->adapter);
|
|
if (fe == NULL) {
|
|
ret = -ENODEV;
|
|
goto err_fe;
|
|
diff --git a/drivers/media/i2c/adv748x/adv748x-hdmi.c b/drivers/media/i2c/adv748x/adv748x-hdmi.c
|
|
index 4da4253553fc..10d229a4f088 100644
|
|
--- a/drivers/media/i2c/adv748x/adv748x-hdmi.c
|
|
+++ b/drivers/media/i2c/adv748x/adv748x-hdmi.c
|
|
@@ -105,6 +105,9 @@ static void adv748x_hdmi_fill_format(struct adv748x_hdmi *hdmi,
|
|
|
|
fmt->width = hdmi->timings.bt.width;
|
|
fmt->height = hdmi->timings.bt.height;
|
|
+
|
|
+ if (fmt->field == V4L2_FIELD_ALTERNATE)
|
|
+ fmt->height /= 2;
|
|
}
|
|
|
|
static void adv748x_fill_optional_dv_timings(struct v4l2_dv_timings *timings)
|
|
diff --git a/drivers/media/i2c/ov5645.c b/drivers/media/i2c/ov5645.c
|
|
index d28845f7356f..a31fe18c71d6 100644
|
|
--- a/drivers/media/i2c/ov5645.c
|
|
+++ b/drivers/media/i2c/ov5645.c
|
|
@@ -1131,13 +1131,14 @@ static int ov5645_probe(struct i2c_client *client,
|
|
|
|
ret = v4l2_fwnode_endpoint_parse(of_fwnode_handle(endpoint),
|
|
&ov5645->ep);
|
|
+
|
|
+ of_node_put(endpoint);
|
|
+
|
|
if (ret < 0) {
|
|
dev_err(dev, "parsing endpoint node failed\n");
|
|
return ret;
|
|
}
|
|
|
|
- of_node_put(endpoint);
|
|
-
|
|
if (ov5645->ep.bus_type != V4L2_MBUS_CSI2) {
|
|
dev_err(dev, "invalid bus type, must be CSI2\n");
|
|
return -EINVAL;
|
|
diff --git a/drivers/media/i2c/tvp5150.c b/drivers/media/i2c/tvp5150.c
|
|
index 7b79a7498751..698fa764999c 100644
|
|
--- a/drivers/media/i2c/tvp5150.c
|
|
+++ b/drivers/media/i2c/tvp5150.c
|
|
@@ -506,80 +506,77 @@ static struct i2c_vbi_ram_value vbi_ram_default[] =
|
|
/* FIXME: Current api doesn't handle all VBI types, those not
|
|
yet supported are placed under #if 0 */
|
|
#if 0
|
|
- {0x010, /* Teletext, SECAM, WST System A */
|
|
+ [0] = {0x010, /* Teletext, SECAM, WST System A */
|
|
{V4L2_SLICED_TELETEXT_SECAM,6,23,1},
|
|
{ 0xaa, 0xaa, 0xff, 0xff, 0xe7, 0x2e, 0x20, 0x26,
|
|
0xe6, 0xb4, 0x0e, 0x00, 0x00, 0x00, 0x10, 0x00 }
|
|
},
|
|
#endif
|
|
- {0x030, /* Teletext, PAL, WST System B */
|
|
+ [1] = {0x030, /* Teletext, PAL, WST System B */
|
|
{V4L2_SLICED_TELETEXT_B,6,22,1},
|
|
{ 0xaa, 0xaa, 0xff, 0xff, 0x27, 0x2e, 0x20, 0x2b,
|
|
0xa6, 0x72, 0x10, 0x00, 0x00, 0x00, 0x10, 0x00 }
|
|
},
|
|
#if 0
|
|
- {0x050, /* Teletext, PAL, WST System C */
|
|
+ [2] = {0x050, /* Teletext, PAL, WST System C */
|
|
{V4L2_SLICED_TELETEXT_PAL_C,6,22,1},
|
|
{ 0xaa, 0xaa, 0xff, 0xff, 0xe7, 0x2e, 0x20, 0x22,
|
|
0xa6, 0x98, 0x0d, 0x00, 0x00, 0x00, 0x10, 0x00 }
|
|
},
|
|
- {0x070, /* Teletext, NTSC, WST System B */
|
|
+ [3] = {0x070, /* Teletext, NTSC, WST System B */
|
|
{V4L2_SLICED_TELETEXT_NTSC_B,10,21,1},
|
|
{ 0xaa, 0xaa, 0xff, 0xff, 0x27, 0x2e, 0x20, 0x23,
|
|
0x69, 0x93, 0x0d, 0x00, 0x00, 0x00, 0x10, 0x00 }
|
|
},
|
|
- {0x090, /* Tetetext, NTSC NABTS System C */
|
|
+ [4] = {0x090, /* Tetetext, NTSC NABTS System C */
|
|
{V4L2_SLICED_TELETEXT_NTSC_C,10,21,1},
|
|
{ 0xaa, 0xaa, 0xff, 0xff, 0xe7, 0x2e, 0x20, 0x22,
|
|
0x69, 0x93, 0x0d, 0x00, 0x00, 0x00, 0x15, 0x00 }
|
|
},
|
|
- {0x0b0, /* Teletext, NTSC-J, NABTS System D */
|
|
+ [5] = {0x0b0, /* Teletext, NTSC-J, NABTS System D */
|
|
{V4L2_SLICED_TELETEXT_NTSC_D,10,21,1},
|
|
{ 0xaa, 0xaa, 0xff, 0xff, 0xa7, 0x2e, 0x20, 0x23,
|
|
0x69, 0x93, 0x0d, 0x00, 0x00, 0x00, 0x10, 0x00 }
|
|
},
|
|
- {0x0d0, /* Closed Caption, PAL/SECAM */
|
|
+ [6] = {0x0d0, /* Closed Caption, PAL/SECAM */
|
|
{V4L2_SLICED_CAPTION_625,22,22,1},
|
|
{ 0xaa, 0x2a, 0xff, 0x3f, 0x04, 0x51, 0x6e, 0x02,
|
|
0xa6, 0x7b, 0x09, 0x00, 0x00, 0x00, 0x27, 0x00 }
|
|
},
|
|
#endif
|
|
- {0x0f0, /* Closed Caption, NTSC */
|
|
+ [7] = {0x0f0, /* Closed Caption, NTSC */
|
|
{V4L2_SLICED_CAPTION_525,21,21,1},
|
|
{ 0xaa, 0x2a, 0xff, 0x3f, 0x04, 0x51, 0x6e, 0x02,
|
|
0x69, 0x8c, 0x09, 0x00, 0x00, 0x00, 0x27, 0x00 }
|
|
},
|
|
- {0x110, /* Wide Screen Signal, PAL/SECAM */
|
|
+ [8] = {0x110, /* Wide Screen Signal, PAL/SECAM */
|
|
{V4L2_SLICED_WSS_625,23,23,1},
|
|
{ 0x5b, 0x55, 0xc5, 0xff, 0x00, 0x71, 0x6e, 0x42,
|
|
0xa6, 0xcd, 0x0f, 0x00, 0x00, 0x00, 0x3a, 0x00 }
|
|
},
|
|
#if 0
|
|
- {0x130, /* Wide Screen Signal, NTSC C */
|
|
+ [9] = {0x130, /* Wide Screen Signal, NTSC C */
|
|
{V4L2_SLICED_WSS_525,20,20,1},
|
|
{ 0x38, 0x00, 0x3f, 0x00, 0x00, 0x71, 0x6e, 0x43,
|
|
0x69, 0x7c, 0x08, 0x00, 0x00, 0x00, 0x39, 0x00 }
|
|
},
|
|
- {0x150, /* Vertical Interval Timecode (VITC), PAL/SECAM */
|
|
+ [10] = {0x150, /* Vertical Interval Timecode (VITC), PAL/SECAM */
|
|
{V4l2_SLICED_VITC_625,6,22,0},
|
|
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x8f, 0x6d, 0x49,
|
|
0xa6, 0x85, 0x08, 0x00, 0x00, 0x00, 0x4c, 0x00 }
|
|
},
|
|
- {0x170, /* Vertical Interval Timecode (VITC), NTSC */
|
|
+ [11] = {0x170, /* Vertical Interval Timecode (VITC), NTSC */
|
|
{V4l2_SLICED_VITC_525,10,20,0},
|
|
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x8f, 0x6d, 0x49,
|
|
0x69, 0x94, 0x08, 0x00, 0x00, 0x00, 0x4c, 0x00 }
|
|
},
|
|
#endif
|
|
- {0x190, /* Video Program System (VPS), PAL */
|
|
+ [12] = {0x190, /* Video Program System (VPS), PAL */
|
|
{V4L2_SLICED_VPS,16,16,0},
|
|
{ 0xaa, 0xaa, 0xff, 0xff, 0xba, 0xce, 0x2b, 0x0d,
|
|
0xa6, 0xda, 0x0b, 0x00, 0x00, 0x00, 0x60, 0x00 }
|
|
},
|
|
/* 0x1d0 User programmable */
|
|
-
|
|
- /* End of struct */
|
|
- { (u16)-1 }
|
|
};
|
|
|
|
static int tvp5150_write_inittab(struct v4l2_subdev *sd,
|
|
@@ -592,10 +589,10 @@ static int tvp5150_write_inittab(struct v4l2_subdev *sd,
|
|
return 0;
|
|
}
|
|
|
|
-static int tvp5150_vdp_init(struct v4l2_subdev *sd,
|
|
- const struct i2c_vbi_ram_value *regs)
|
|
+static int tvp5150_vdp_init(struct v4l2_subdev *sd)
|
|
{
|
|
unsigned int i;
|
|
+ int j;
|
|
|
|
/* Disable Full Field */
|
|
tvp5150_write(sd, TVP5150_FULL_FIELD_ENA, 0);
|
|
@@ -605,14 +602,17 @@ static int tvp5150_vdp_init(struct v4l2_subdev *sd,
|
|
tvp5150_write(sd, i, 0xff);
|
|
|
|
/* Load Ram Table */
|
|
- while (regs->reg != (u16)-1) {
|
|
+ for (j = 0; j < ARRAY_SIZE(vbi_ram_default); j++) {
|
|
+ const struct i2c_vbi_ram_value *regs = &vbi_ram_default[j];
|
|
+
|
|
+ if (!regs->type.vbi_type)
|
|
+ continue;
|
|
+
|
|
tvp5150_write(sd, TVP5150_CONF_RAM_ADDR_HIGH, regs->reg >> 8);
|
|
tvp5150_write(sd, TVP5150_CONF_RAM_ADDR_LOW, regs->reg);
|
|
|
|
for (i = 0; i < 16; i++)
|
|
tvp5150_write(sd, TVP5150_VDP_CONF_RAM_DATA, regs->values[i]);
|
|
-
|
|
- regs++;
|
|
}
|
|
return 0;
|
|
}
|
|
@@ -621,19 +621,23 @@ static int tvp5150_vdp_init(struct v4l2_subdev *sd,
|
|
static int tvp5150_g_sliced_vbi_cap(struct v4l2_subdev *sd,
|
|
struct v4l2_sliced_vbi_cap *cap)
|
|
{
|
|
- const struct i2c_vbi_ram_value *regs = vbi_ram_default;
|
|
- int line;
|
|
+ int line, i;
|
|
|
|
dev_dbg_lvl(sd->dev, 1, debug, "g_sliced_vbi_cap\n");
|
|
memset(cap, 0, sizeof *cap);
|
|
|
|
- while (regs->reg != (u16)-1 ) {
|
|
- for (line=regs->type.ini_line;line<=regs->type.end_line;line++) {
|
|
+ for (i = 0; i < ARRAY_SIZE(vbi_ram_default); i++) {
|
|
+ const struct i2c_vbi_ram_value *regs = &vbi_ram_default[i];
|
|
+
|
|
+ if (!regs->type.vbi_type)
|
|
+ continue;
|
|
+
|
|
+ for (line = regs->type.ini_line;
|
|
+ line <= regs->type.end_line;
|
|
+ line++) {
|
|
cap->service_lines[0][line] |= regs->type.vbi_type;
|
|
}
|
|
cap->service_set |= regs->type.vbi_type;
|
|
-
|
|
- regs++;
|
|
}
|
|
return 0;
|
|
}
|
|
@@ -652,14 +656,13 @@ static int tvp5150_g_sliced_vbi_cap(struct v4l2_subdev *sd,
|
|
* MSB = field2
|
|
*/
|
|
static int tvp5150_set_vbi(struct v4l2_subdev *sd,
|
|
- const struct i2c_vbi_ram_value *regs,
|
|
unsigned int type,u8 flags, int line,
|
|
const int fields)
|
|
{
|
|
struct tvp5150 *decoder = to_tvp5150(sd);
|
|
v4l2_std_id std = decoder->norm;
|
|
u8 reg;
|
|
- int pos = 0;
|
|
+ int i, pos = 0;
|
|
|
|
if (std == V4L2_STD_ALL) {
|
|
dev_err(sd->dev, "VBI can't be configured without knowing number of lines\n");
|
|
@@ -672,19 +675,19 @@ static int tvp5150_set_vbi(struct v4l2_subdev *sd,
|
|
if (line < 6 || line > 27)
|
|
return 0;
|
|
|
|
- while (regs->reg != (u16)-1) {
|
|
+ for (i = 0; i < ARRAY_SIZE(vbi_ram_default); i++) {
|
|
+ const struct i2c_vbi_ram_value *regs = &vbi_ram_default[i];
|
|
+
|
|
+ if (!regs->type.vbi_type)
|
|
+ continue;
|
|
+
|
|
if ((type & regs->type.vbi_type) &&
|
|
(line >= regs->type.ini_line) &&
|
|
(line <= regs->type.end_line))
|
|
break;
|
|
-
|
|
- regs++;
|
|
pos++;
|
|
}
|
|
|
|
- if (regs->reg == (u16)-1)
|
|
- return 0;
|
|
-
|
|
type = pos | (flags & 0xf0);
|
|
reg = ((line - 6) << 1) + TVP5150_LINE_MODE_INI;
|
|
|
|
@@ -697,8 +700,7 @@ static int tvp5150_set_vbi(struct v4l2_subdev *sd,
|
|
return type;
|
|
}
|
|
|
|
-static int tvp5150_get_vbi(struct v4l2_subdev *sd,
|
|
- const struct i2c_vbi_ram_value *regs, int line)
|
|
+static int tvp5150_get_vbi(struct v4l2_subdev *sd, int line)
|
|
{
|
|
struct tvp5150 *decoder = to_tvp5150(sd);
|
|
v4l2_std_id std = decoder->norm;
|
|
@@ -727,8 +729,8 @@ static int tvp5150_get_vbi(struct v4l2_subdev *sd,
|
|
return 0;
|
|
}
|
|
pos = ret & 0x0f;
|
|
- if (pos < 0x0f)
|
|
- type |= regs[pos].type.vbi_type;
|
|
+ if (pos < ARRAY_SIZE(vbi_ram_default))
|
|
+ type |= vbi_ram_default[pos].type.vbi_type;
|
|
}
|
|
|
|
return type;
|
|
@@ -789,7 +791,7 @@ static int tvp5150_reset(struct v4l2_subdev *sd, u32 val)
|
|
tvp5150_write_inittab(sd, tvp5150_init_default);
|
|
|
|
/* Initializes VDP registers */
|
|
- tvp5150_vdp_init(sd, vbi_ram_default);
|
|
+ tvp5150_vdp_init(sd);
|
|
|
|
/* Selects decoder input */
|
|
tvp5150_selmux(sd);
|
|
@@ -1122,8 +1124,8 @@ static int tvp5150_s_sliced_fmt(struct v4l2_subdev *sd, struct v4l2_sliced_vbi_f
|
|
for (i = 0; i <= 23; i++) {
|
|
svbi->service_lines[1][i] = 0;
|
|
svbi->service_lines[0][i] =
|
|
- tvp5150_set_vbi(sd, vbi_ram_default,
|
|
- svbi->service_lines[0][i], 0xf0, i, 3);
|
|
+ tvp5150_set_vbi(sd, svbi->service_lines[0][i],
|
|
+ 0xf0, i, 3);
|
|
}
|
|
/* Enables FIFO */
|
|
tvp5150_write(sd, TVP5150_FIFO_OUT_CTRL, 1);
|
|
@@ -1149,7 +1151,7 @@ static int tvp5150_g_sliced_fmt(struct v4l2_subdev *sd, struct v4l2_sliced_vbi_f
|
|
|
|
for (i = 0; i <= 23; i++) {
|
|
svbi->service_lines[0][i] =
|
|
- tvp5150_get_vbi(sd, vbi_ram_default, i);
|
|
+ tvp5150_get_vbi(sd, i);
|
|
mask |= svbi->service_lines[0][i];
|
|
}
|
|
svbi->service_set = mask;
|
|
diff --git a/drivers/media/pci/cx23885/cx23885-cards.c b/drivers/media/pci/cx23885/cx23885-cards.c
|
|
index 78a8836d03e4..6c0fd9438dd9 100644
|
|
--- a/drivers/media/pci/cx23885/cx23885-cards.c
|
|
+++ b/drivers/media/pci/cx23885/cx23885-cards.c
|
|
@@ -2286,6 +2286,10 @@ void cx23885_card_setup(struct cx23885_dev *dev)
|
|
&dev->i2c_bus[2].i2c_adap,
|
|
"cx25840", 0x88 >> 1, NULL);
|
|
if (dev->sd_cx25840) {
|
|
+ /* set host data for clk_freq configuration */
|
|
+ v4l2_set_subdev_hostdata(dev->sd_cx25840,
|
|
+ &dev->clk_freq);
|
|
+
|
|
dev->sd_cx25840->grp_id = CX23885_HW_AV_CORE;
|
|
v4l2_subdev_call(dev->sd_cx25840, core, load_fw);
|
|
}
|
|
diff --git a/drivers/media/pci/cx23885/cx23885-core.c b/drivers/media/pci/cx23885/cx23885-core.c
|
|
index 8f63df1cb418..4612f26fcd6d 100644
|
|
--- a/drivers/media/pci/cx23885/cx23885-core.c
|
|
+++ b/drivers/media/pci/cx23885/cx23885-core.c
|
|
@@ -873,6 +873,16 @@ static int cx23885_dev_setup(struct cx23885_dev *dev)
|
|
if (cx23885_boards[dev->board].clk_freq > 0)
|
|
dev->clk_freq = cx23885_boards[dev->board].clk_freq;
|
|
|
|
+ if (dev->board == CX23885_BOARD_HAUPPAUGE_IMPACTVCBE &&
|
|
+ dev->pci->subsystem_device == 0x7137) {
|
|
+ /* Hauppauge ImpactVCBe device ID 0x7137 is populated
|
|
+ * with an 888, and a 25Mhz crystal, instead of the
|
|
+ * usual third overtone 50Mhz. The default clock rate must
|
|
+ * be overridden so the cx25840 is properly configured
|
|
+ */
|
|
+ dev->clk_freq = 25000000;
|
|
+ }
|
|
+
|
|
dev->pci_bus = dev->pci->bus->number;
|
|
dev->pci_slot = PCI_SLOT(dev->pci->devfn);
|
|
cx23885_irq_add(dev, 0x001f00);
|
|
diff --git a/drivers/media/pci/cx25821/cx25821-core.c b/drivers/media/pci/cx25821/cx25821-core.c
|
|
index 04aa4a68a0ae..040c6c251d3a 100644
|
|
--- a/drivers/media/pci/cx25821/cx25821-core.c
|
|
+++ b/drivers/media/pci/cx25821/cx25821-core.c
|
|
@@ -867,6 +867,10 @@ static int cx25821_dev_setup(struct cx25821_dev *dev)
|
|
dev->nr = ++cx25821_devcount;
|
|
sprintf(dev->name, "cx25821[%d]", dev->nr);
|
|
|
|
+ if (dev->nr >= ARRAY_SIZE(card)) {
|
|
+ CX25821_INFO("dev->nr >= %zd", ARRAY_SIZE(card));
|
|
+ return -ENODEV;
|
|
+ }
|
|
if (dev->pci->device != 0x8210) {
|
|
pr_info("%s(): Exiting. Incorrect Hardware device = 0x%02x\n",
|
|
__func__, dev->pci->device);
|
|
@@ -882,9 +886,6 @@ static int cx25821_dev_setup(struct cx25821_dev *dev)
|
|
dev->channels[i].sram_channels = &cx25821_sram_channels[i];
|
|
}
|
|
|
|
- if (dev->nr > 1)
|
|
- CX25821_INFO("dev->nr > 1!");
|
|
-
|
|
/* board config */
|
|
dev->board = 1; /* card[dev->nr]; */
|
|
dev->_max_num_decoders = MAX_DECODERS;
|
|
diff --git a/drivers/media/platform/s3c-camif/camif-capture.c b/drivers/media/platform/s3c-camif/camif-capture.c
|
|
index 25c7a7d42292..0f0324a14d51 100644
|
|
--- a/drivers/media/platform/s3c-camif/camif-capture.c
|
|
+++ b/drivers/media/platform/s3c-camif/camif-capture.c
|
|
@@ -1256,16 +1256,17 @@ static void __camif_subdev_try_format(struct camif_dev *camif,
|
|
{
|
|
const struct s3c_camif_variant *variant = camif->variant;
|
|
const struct vp_pix_limits *pix_lim;
|
|
- int i = ARRAY_SIZE(camif_mbus_formats);
|
|
+ unsigned int i;
|
|
|
|
/* FIXME: constraints against codec or preview path ? */
|
|
pix_lim = &variant->vp_pix_limits[VP_CODEC];
|
|
|
|
- while (i-- >= 0)
|
|
+ for (i = 0; i < ARRAY_SIZE(camif_mbus_formats); i++)
|
|
if (camif_mbus_formats[i] == mf->code)
|
|
break;
|
|
|
|
- mf->code = camif_mbus_formats[i];
|
|
+ if (i == ARRAY_SIZE(camif_mbus_formats))
|
|
+ mf->code = camif_mbus_formats[0];
|
|
|
|
if (pad == CAMIF_SD_PAD_SINK) {
|
|
v4l_bound_align_image(&mf->width, 8, CAMIF_MAX_PIX_WIDTH,
|
|
diff --git a/drivers/media/platform/vivid/vivid-ctrls.c b/drivers/media/platform/vivid/vivid-ctrls.c
|
|
index 34731f71cc00..8ca9343b6730 100644
|
|
--- a/drivers/media/platform/vivid/vivid-ctrls.c
|
|
+++ b/drivers/media/platform/vivid/vivid-ctrls.c
|
|
@@ -1191,6 +1191,7 @@ static int vivid_radio_rx_s_ctrl(struct v4l2_ctrl *ctrl)
|
|
v4l2_ctrl_activate(dev->radio_rx_rds_ta, dev->radio_rx_rds_controls);
|
|
v4l2_ctrl_activate(dev->radio_rx_rds_tp, dev->radio_rx_rds_controls);
|
|
v4l2_ctrl_activate(dev->radio_rx_rds_ms, dev->radio_rx_rds_controls);
|
|
+ dev->radio_rx_dev.device_caps = dev->radio_rx_caps;
|
|
break;
|
|
case V4L2_CID_RDS_RECEPTION:
|
|
dev->radio_rx_rds_enabled = ctrl->val;
|
|
@@ -1265,6 +1266,7 @@ static int vivid_radio_tx_s_ctrl(struct v4l2_ctrl *ctrl)
|
|
dev->radio_tx_caps &= ~V4L2_CAP_READWRITE;
|
|
if (!dev->radio_tx_rds_controls)
|
|
dev->radio_tx_caps |= V4L2_CAP_READWRITE;
|
|
+ dev->radio_tx_dev.device_caps = dev->radio_tx_caps;
|
|
break;
|
|
case V4L2_CID_RDS_TX_PTY:
|
|
if (dev->radio_rx_rds_controls)
|
|
diff --git a/drivers/media/platform/vsp1/vsp1_drm.c b/drivers/media/platform/vsp1/vsp1_drm.c
|
|
index 4dfbeac8f42c..d3cd57f6ba52 100644
|
|
--- a/drivers/media/platform/vsp1/vsp1_drm.c
|
|
+++ b/drivers/media/platform/vsp1/vsp1_drm.c
|
|
@@ -504,6 +504,15 @@ void vsp1_du_atomic_flush(struct device *dev, unsigned int pipe_index)
|
|
struct vsp1_rwpf *rpf = vsp1->rpf[i];
|
|
unsigned int j;
|
|
|
|
+ /*
|
|
+ * Make sure we don't accept more inputs than the hardware can
|
|
+ * handle. This is a temporary fix to avoid display stall, we
|
|
+ * need to instead allocate the BRU or BRS to display pipelines
|
|
+ * dynamically based on the number of planes they each use.
|
|
+ */
|
|
+ if (pipe->num_inputs >= pipe->bru->source_pad)
|
|
+ pipe->inputs[i] = NULL;
|
|
+
|
|
if (!pipe->inputs[i])
|
|
continue;
|
|
|
|
diff --git a/drivers/media/usb/em28xx/em28xx-cards.c b/drivers/media/usb/em28xx/em28xx-cards.c
|
|
index 4c57fd7929cb..11a59854a0a6 100644
|
|
--- a/drivers/media/usb/em28xx/em28xx-cards.c
|
|
+++ b/drivers/media/usb/em28xx/em28xx-cards.c
|
|
@@ -508,8 +508,10 @@ static struct em28xx_reg_seq plex_px_bcud[] = {
|
|
};
|
|
|
|
/*
|
|
- * 2040:0265 Hauppauge WinTV-dualHD DVB
|
|
- * 2040:026d Hauppauge WinTV-dualHD ATSC/QAM
|
|
+ * 2040:0265 Hauppauge WinTV-dualHD DVB Isoc
|
|
+ * 2040:8265 Hauppauge WinTV-dualHD DVB Bulk
|
|
+ * 2040:026d Hauppauge WinTV-dualHD ATSC/QAM Isoc
|
|
+ * 2040:826d Hauppauge WinTV-dualHD ATSC/QAM Bulk
|
|
* reg 0x80/0x84:
|
|
* GPIO_0: Yellow LED tuner 1, 0=on, 1=off
|
|
* GPIO_1: Green LED tuner 1, 0=on, 1=off
|
|
@@ -2392,7 +2394,8 @@ struct em28xx_board em28xx_boards[] = {
|
|
.has_dvb = 1,
|
|
},
|
|
/*
|
|
- * 2040:0265 Hauppauge WinTV-dualHD (DVB version).
|
|
+ * 2040:0265 Hauppauge WinTV-dualHD (DVB version) Isoc.
|
|
+ * 2040:8265 Hauppauge WinTV-dualHD (DVB version) Bulk.
|
|
* Empia EM28274, 2x Silicon Labs Si2168, 2x Silicon Labs Si2157
|
|
*/
|
|
[EM28174_BOARD_HAUPPAUGE_WINTV_DUALHD_DVB] = {
|
|
@@ -2407,7 +2410,8 @@ struct em28xx_board em28xx_boards[] = {
|
|
.leds = hauppauge_dualhd_leds,
|
|
},
|
|
/*
|
|
- * 2040:026d Hauppauge WinTV-dualHD (model 01595 - ATSC/QAM).
|
|
+ * 2040:026d Hauppauge WinTV-dualHD (model 01595 - ATSC/QAM) Isoc.
|
|
+ * 2040:826d Hauppauge WinTV-dualHD (model 01595 - ATSC/QAM) Bulk.
|
|
* Empia EM28274, 2x LG LGDT3306A, 2x Silicon Labs Si2157
|
|
*/
|
|
[EM28174_BOARD_HAUPPAUGE_WINTV_DUALHD_01595] = {
|
|
@@ -2548,8 +2552,12 @@ struct usb_device_id em28xx_id_table[] = {
|
|
.driver_info = EM2883_BOARD_HAUPPAUGE_WINTV_HVR_850 },
|
|
{ USB_DEVICE(0x2040, 0x0265),
|
|
.driver_info = EM28174_BOARD_HAUPPAUGE_WINTV_DUALHD_DVB },
|
|
+ { USB_DEVICE(0x2040, 0x8265),
|
|
+ .driver_info = EM28174_BOARD_HAUPPAUGE_WINTV_DUALHD_DVB },
|
|
{ USB_DEVICE(0x2040, 0x026d),
|
|
.driver_info = EM28174_BOARD_HAUPPAUGE_WINTV_DUALHD_01595 },
|
|
+ { USB_DEVICE(0x2040, 0x826d),
|
|
+ .driver_info = EM28174_BOARD_HAUPPAUGE_WINTV_DUALHD_01595 },
|
|
{ USB_DEVICE(0x0438, 0xb002),
|
|
.driver_info = EM2880_BOARD_AMD_ATI_TV_WONDER_HD_600 },
|
|
{ USB_DEVICE(0x2001, 0xf112),
|
|
@@ -2610,7 +2618,11 @@ struct usb_device_id em28xx_id_table[] = {
|
|
.driver_info = EM28178_BOARD_PCTV_461E },
|
|
{ USB_DEVICE(0x2013, 0x025f),
|
|
.driver_info = EM28178_BOARD_PCTV_292E },
|
|
- { USB_DEVICE(0x2040, 0x0264), /* Hauppauge WinTV-soloHD */
|
|
+ { USB_DEVICE(0x2040, 0x0264), /* Hauppauge WinTV-soloHD Isoc */
|
|
+ .driver_info = EM28178_BOARD_PCTV_292E },
|
|
+ { USB_DEVICE(0x2040, 0x8264), /* Hauppauge OEM Generic WinTV-soloHD Bulk */
|
|
+ .driver_info = EM28178_BOARD_PCTV_292E },
|
|
+ { USB_DEVICE(0x2040, 0x8268), /* Hauppauge Retail WinTV-soloHD Bulk */
|
|
.driver_info = EM28178_BOARD_PCTV_292E },
|
|
{ USB_DEVICE(0x0413, 0x6f07),
|
|
.driver_info = EM2861_BOARD_LEADTEK_VC100 },
|
|
diff --git a/drivers/media/usb/em28xx/em28xx.h b/drivers/media/usb/em28xx/em28xx.h
|
|
index 88084f24f033..094e83b6908d 100644
|
|
--- a/drivers/media/usb/em28xx/em28xx.h
|
|
+++ b/drivers/media/usb/em28xx/em28xx.h
|
|
@@ -191,7 +191,7 @@
|
|
USB 2.0 spec says bulk packet size is always 512 bytes
|
|
*/
|
|
#define EM28XX_BULK_PACKET_MULTIPLIER 384
|
|
-#define EM28XX_DVB_BULK_PACKET_MULTIPLIER 384
|
|
+#define EM28XX_DVB_BULK_PACKET_MULTIPLIER 94
|
|
|
|
#define EM28XX_INTERLACED_DEFAULT 1
|
|
|
|
diff --git a/drivers/media/v4l2-core/videobuf2-vmalloc.c b/drivers/media/v4l2-core/videobuf2-vmalloc.c
|
|
index 3a7c80cd1a17..359fb9804d16 100644
|
|
--- a/drivers/media/v4l2-core/videobuf2-vmalloc.c
|
|
+++ b/drivers/media/v4l2-core/videobuf2-vmalloc.c
|
|
@@ -106,7 +106,7 @@ static void *vb2_vmalloc_get_userptr(struct device *dev, unsigned long vaddr,
|
|
if (nums[i-1] + 1 != nums[i])
|
|
goto fail_map;
|
|
buf->vaddr = (__force void *)
|
|
- ioremap_nocache(nums[0] << PAGE_SHIFT, size);
|
|
+ ioremap_nocache(__pfn_to_phys(nums[0]), size + offset);
|
|
} else {
|
|
buf->vaddr = vm_map_ram(frame_vector_pages(vec), n_pages, -1,
|
|
PAGE_KERNEL);
|
|
diff --git a/drivers/message/fusion/mptctl.c b/drivers/message/fusion/mptctl.c
|
|
index 7b3b41368931..cf6ce9f600ca 100644
|
|
--- a/drivers/message/fusion/mptctl.c
|
|
+++ b/drivers/message/fusion/mptctl.c
|
|
@@ -2698,6 +2698,8 @@ mptctl_hp_targetinfo(unsigned long arg)
|
|
__FILE__, __LINE__, iocnum);
|
|
return -ENODEV;
|
|
}
|
|
+ if (karg.hdr.id >= MPT_MAX_FC_DEVICES)
|
|
+ return -EINVAL;
|
|
dctlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "mptctl_hp_targetinfo called.\n",
|
|
ioc->name));
|
|
|
|
diff --git a/drivers/net/ethernet/mellanox/mlx4/main.c b/drivers/net/ethernet/mellanox/mlx4/main.c
|
|
index e61c99ef741d..c273a3ebb8e8 100644
|
|
--- a/drivers/net/ethernet/mellanox/mlx4/main.c
|
|
+++ b/drivers/net/ethernet/mellanox/mlx4/main.c
|
|
@@ -3007,6 +3007,7 @@ static int mlx4_init_port_info(struct mlx4_dev *dev, int port)
|
|
mlx4_err(dev, "Failed to create file for port %d\n", port);
|
|
devlink_port_unregister(&info->devlink_port);
|
|
info->port = -1;
|
|
+ return err;
|
|
}
|
|
|
|
sprintf(info->dev_mtu_name, "mlx4_port%d_mtu", port);
|
|
@@ -3028,9 +3029,10 @@ static int mlx4_init_port_info(struct mlx4_dev *dev, int port)
|
|
&info->port_attr);
|
|
devlink_port_unregister(&info->devlink_port);
|
|
info->port = -1;
|
|
+ return err;
|
|
}
|
|
|
|
- return err;
|
|
+ return 0;
|
|
}
|
|
|
|
static void mlx4_cleanup_port_info(struct mlx4_port_info *info)
|
|
diff --git a/drivers/net/hyperv/hyperv_net.h b/drivers/net/hyperv/hyperv_net.h
|
|
index 4f3afcf92a7c..01017dd88802 100644
|
|
--- a/drivers/net/hyperv/hyperv_net.h
|
|
+++ b/drivers/net/hyperv/hyperv_net.h
|
|
@@ -179,7 +179,7 @@ struct rndis_device {
|
|
|
|
u8 hw_mac_adr[ETH_ALEN];
|
|
u8 rss_key[NETVSC_HASH_KEYLEN];
|
|
- u16 ind_table[ITAB_NUM];
|
|
+ u16 rx_table[ITAB_NUM];
|
|
};
|
|
|
|
|
|
@@ -192,7 +192,7 @@ struct netvsc_device *netvsc_device_add(struct hv_device *device,
|
|
const struct netvsc_device_info *info);
|
|
int netvsc_alloc_recv_comp_ring(struct netvsc_device *net_device, u32 q_idx);
|
|
void netvsc_device_remove(struct hv_device *device);
|
|
-int netvsc_send(struct net_device_context *ndc,
|
|
+int netvsc_send(struct net_device *net,
|
|
struct hv_netvsc_packet *packet,
|
|
struct rndis_message *rndis_msg,
|
|
struct hv_page_buffer *page_buffer,
|
|
@@ -208,7 +208,6 @@ void netvsc_channel_cb(void *context);
|
|
int netvsc_poll(struct napi_struct *napi, int budget);
|
|
|
|
void rndis_set_subchannel(struct work_struct *w);
|
|
-bool rndis_filter_opened(const struct netvsc_device *nvdev);
|
|
int rndis_filter_open(struct netvsc_device *nvdev);
|
|
int rndis_filter_close(struct netvsc_device *nvdev);
|
|
struct netvsc_device *rndis_filter_device_add(struct hv_device *dev,
|
|
@@ -659,6 +658,10 @@ struct nvsp_message {
|
|
#define NETVSC_RECEIVE_BUFFER_ID 0xcafe
|
|
#define NETVSC_SEND_BUFFER_ID 0
|
|
|
|
+#define NETVSC_SUPPORTED_HW_FEATURES (NETIF_F_RXCSUM | NETIF_F_IP_CSUM | \
|
|
+ NETIF_F_TSO | NETIF_F_IPV6_CSUM | \
|
|
+ NETIF_F_TSO6)
|
|
+
|
|
#define VRSS_SEND_TAB_SIZE 16 /* must be power of 2 */
|
|
#define VRSS_CHANNEL_MAX 64
|
|
#define VRSS_CHANNEL_DEFAULT 8
|
|
@@ -734,7 +737,7 @@ struct net_device_context {
|
|
|
|
u32 tx_checksum_mask;
|
|
|
|
- u32 tx_send_table[VRSS_SEND_TAB_SIZE];
|
|
+ u32 tx_table[VRSS_SEND_TAB_SIZE];
|
|
|
|
/* Ethtool settings */
|
|
bool udp4_l4_hash;
|
|
diff --git a/drivers/net/hyperv/netvsc.c b/drivers/net/hyperv/netvsc.c
|
|
index a6bafcf55776..99be63eacaeb 100644
|
|
--- a/drivers/net/hyperv/netvsc.c
|
|
+++ b/drivers/net/hyperv/netvsc.c
|
|
@@ -89,6 +89,11 @@ static void free_netvsc_device(struct rcu_head *head)
|
|
= container_of(head, struct netvsc_device, rcu);
|
|
int i;
|
|
|
|
+ kfree(nvdev->extension);
|
|
+ vfree(nvdev->recv_buf);
|
|
+ vfree(nvdev->send_buf);
|
|
+ kfree(nvdev->send_section_map);
|
|
+
|
|
for (i = 0; i < VRSS_CHANNEL_MAX; i++)
|
|
vfree(nvdev->chan_table[i].mrc.slots);
|
|
|
|
@@ -100,12 +105,11 @@ static void free_netvsc_device_rcu(struct netvsc_device *nvdev)
|
|
call_rcu(&nvdev->rcu, free_netvsc_device);
|
|
}
|
|
|
|
-static void netvsc_destroy_buf(struct hv_device *device)
|
|
+static void netvsc_revoke_recv_buf(struct hv_device *device,
|
|
+ struct netvsc_device *net_device)
|
|
{
|
|
- struct nvsp_message *revoke_packet;
|
|
struct net_device *ndev = hv_get_drvdata(device);
|
|
- struct net_device_context *ndc = netdev_priv(ndev);
|
|
- struct netvsc_device *net_device = rtnl_dereference(ndc->nvdev);
|
|
+ struct nvsp_message *revoke_packet;
|
|
int ret;
|
|
|
|
/*
|
|
@@ -147,28 +151,14 @@ static void netvsc_destroy_buf(struct hv_device *device)
|
|
}
|
|
net_device->recv_section_cnt = 0;
|
|
}
|
|
+}
|
|
|
|
- /* Teardown the gpadl on the vsp end */
|
|
- if (net_device->recv_buf_gpadl_handle) {
|
|
- ret = vmbus_teardown_gpadl(device->channel,
|
|
- net_device->recv_buf_gpadl_handle);
|
|
-
|
|
- /* If we failed here, we might as well return and have a leak
|
|
- * rather than continue and a bugchk
|
|
- */
|
|
- if (ret != 0) {
|
|
- netdev_err(ndev,
|
|
- "unable to teardown receive buffer's gpadl\n");
|
|
- return;
|
|
- }
|
|
- net_device->recv_buf_gpadl_handle = 0;
|
|
- }
|
|
-
|
|
- if (net_device->recv_buf) {
|
|
- /* Free up the receive buffer */
|
|
- vfree(net_device->recv_buf);
|
|
- net_device->recv_buf = NULL;
|
|
- }
|
|
+static void netvsc_revoke_send_buf(struct hv_device *device,
|
|
+ struct netvsc_device *net_device)
|
|
+{
|
|
+ struct net_device *ndev = hv_get_drvdata(device);
|
|
+ struct nvsp_message *revoke_packet;
|
|
+ int ret;
|
|
|
|
/* Deal with the send buffer we may have setup.
|
|
* If we got a send section size, it means we received a
|
|
@@ -210,7 +200,36 @@ static void netvsc_destroy_buf(struct hv_device *device)
|
|
}
|
|
net_device->send_section_cnt = 0;
|
|
}
|
|
- /* Teardown the gpadl on the vsp end */
|
|
+}
|
|
+
|
|
+static void netvsc_teardown_recv_gpadl(struct hv_device *device,
|
|
+ struct netvsc_device *net_device)
|
|
+{
|
|
+ struct net_device *ndev = hv_get_drvdata(device);
|
|
+ int ret;
|
|
+
|
|
+ if (net_device->recv_buf_gpadl_handle) {
|
|
+ ret = vmbus_teardown_gpadl(device->channel,
|
|
+ net_device->recv_buf_gpadl_handle);
|
|
+
|
|
+ /* If we failed here, we might as well return and have a leak
|
|
+ * rather than continue and a bugchk
|
|
+ */
|
|
+ if (ret != 0) {
|
|
+ netdev_err(ndev,
|
|
+ "unable to teardown receive buffer's gpadl\n");
|
|
+ return;
|
|
+ }
|
|
+ net_device->recv_buf_gpadl_handle = 0;
|
|
+ }
|
|
+}
|
|
+
|
|
+static void netvsc_teardown_send_gpadl(struct hv_device *device,
|
|
+ struct netvsc_device *net_device)
|
|
+{
|
|
+ struct net_device *ndev = hv_get_drvdata(device);
|
|
+ int ret;
|
|
+
|
|
if (net_device->send_buf_gpadl_handle) {
|
|
ret = vmbus_teardown_gpadl(device->channel,
|
|
net_device->send_buf_gpadl_handle);
|
|
@@ -225,12 +244,6 @@ static void netvsc_destroy_buf(struct hv_device *device)
|
|
}
|
|
net_device->send_buf_gpadl_handle = 0;
|
|
}
|
|
- if (net_device->send_buf) {
|
|
- /* Free up the send buffer */
|
|
- vfree(net_device->send_buf);
|
|
- net_device->send_buf = NULL;
|
|
- }
|
|
- kfree(net_device->send_section_map);
|
|
}
|
|
|
|
int netvsc_alloc_recv_comp_ring(struct netvsc_device *net_device, u32 q_idx)
|
|
@@ -425,7 +438,10 @@ static int netvsc_init_buf(struct hv_device *device,
|
|
goto exit;
|
|
|
|
cleanup:
|
|
- netvsc_destroy_buf(device);
|
|
+ netvsc_revoke_recv_buf(device, net_device);
|
|
+ netvsc_revoke_send_buf(device, net_device);
|
|
+ netvsc_teardown_recv_gpadl(device, net_device);
|
|
+ netvsc_teardown_send_gpadl(device, net_device);
|
|
|
|
exit:
|
|
return ret;
|
|
@@ -544,11 +560,6 @@ static int netvsc_connect_vsp(struct hv_device *device,
|
|
return ret;
|
|
}
|
|
|
|
-static void netvsc_disconnect_vsp(struct hv_device *device)
|
|
-{
|
|
- netvsc_destroy_buf(device);
|
|
-}
|
|
-
|
|
/*
|
|
* netvsc_device_remove - Callback when the root bus device is removed
|
|
*/
|
|
@@ -560,12 +571,24 @@ void netvsc_device_remove(struct hv_device *device)
|
|
= rtnl_dereference(net_device_ctx->nvdev);
|
|
int i;
|
|
|
|
- cancel_work_sync(&net_device->subchan_work);
|
|
+ /*
|
|
+ * Revoke receive buffer. If host is pre-Win2016 then tear down
|
|
+ * receive buffer GPADL. Do the same for send buffer.
|
|
+ */
|
|
+ netvsc_revoke_recv_buf(device, net_device);
|
|
+ if (vmbus_proto_version < VERSION_WIN10)
|
|
+ netvsc_teardown_recv_gpadl(device, net_device);
|
|
|
|
- netvsc_disconnect_vsp(device);
|
|
+ netvsc_revoke_send_buf(device, net_device);
|
|
+ if (vmbus_proto_version < VERSION_WIN10)
|
|
+ netvsc_teardown_send_gpadl(device, net_device);
|
|
|
|
RCU_INIT_POINTER(net_device_ctx->nvdev, NULL);
|
|
|
|
+ /* And disassociate NAPI context from device */
|
|
+ for (i = 0; i < net_device->num_chn; i++)
|
|
+ netif_napi_del(&net_device->chan_table[i].napi);
|
|
+
|
|
/*
|
|
* At this point, no one should be accessing net_device
|
|
* except in here
|
|
@@ -575,9 +598,14 @@ void netvsc_device_remove(struct hv_device *device)
|
|
/* Now, we can close the channel safely */
|
|
vmbus_close(device->channel);
|
|
|
|
- /* And dissassociate NAPI context from device */
|
|
- for (i = 0; i < net_device->num_chn; i++)
|
|
- netif_napi_del(&net_device->chan_table[i].napi);
|
|
+ /*
|
|
+ * If host is Win2016 or higher then we do the GPADL tear down
|
|
+ * here after VMBus is closed.
|
|
+ */
|
|
+ if (vmbus_proto_version >= VERSION_WIN10) {
|
|
+ netvsc_teardown_recv_gpadl(device, net_device);
|
|
+ netvsc_teardown_send_gpadl(device, net_device);
|
|
+ }
|
|
|
|
/* Release all resources */
|
|
free_netvsc_device_rcu(net_device);
|
|
@@ -643,13 +671,18 @@ static void netvsc_send_tx_complete(struct netvsc_device *net_device,
|
|
queue_sends =
|
|
atomic_dec_return(&net_device->chan_table[q_idx].queue_sends);
|
|
|
|
- if (net_device->destroy && queue_sends == 0)
|
|
- wake_up(&net_device->wait_drain);
|
|
+ if (unlikely(net_device->destroy)) {
|
|
+ if (queue_sends == 0)
|
|
+ wake_up(&net_device->wait_drain);
|
|
+ } else {
|
|
+ struct netdev_queue *txq = netdev_get_tx_queue(ndev, q_idx);
|
|
|
|
- if (netif_tx_queue_stopped(netdev_get_tx_queue(ndev, q_idx)) &&
|
|
- (hv_ringbuf_avail_percent(&channel->outbound) > RING_AVAIL_PERCENT_HIWATER ||
|
|
- queue_sends < 1))
|
|
- netif_tx_wake_queue(netdev_get_tx_queue(ndev, q_idx));
|
|
+ if (netif_tx_queue_stopped(txq) &&
|
|
+ (hv_ringbuf_avail_percent(&channel->outbound) > RING_AVAIL_PERCENT_HIWATER ||
|
|
+ queue_sends < 1)) {
|
|
+ netif_tx_wake_queue(txq);
|
|
+ }
|
|
+ }
|
|
}
|
|
|
|
static void netvsc_send_completion(struct netvsc_device *net_device,
|
|
@@ -697,13 +730,13 @@ static u32 netvsc_get_next_send_section(struct netvsc_device *net_device)
|
|
return NETVSC_INVALID_INDEX;
|
|
}
|
|
|
|
-static u32 netvsc_copy_to_send_buf(struct netvsc_device *net_device,
|
|
- unsigned int section_index,
|
|
- u32 pend_size,
|
|
- struct hv_netvsc_packet *packet,
|
|
- struct rndis_message *rndis_msg,
|
|
- struct hv_page_buffer *pb,
|
|
- struct sk_buff *skb)
|
|
+static void netvsc_copy_to_send_buf(struct netvsc_device *net_device,
|
|
+ unsigned int section_index,
|
|
+ u32 pend_size,
|
|
+ struct hv_netvsc_packet *packet,
|
|
+ struct rndis_message *rndis_msg,
|
|
+ struct hv_page_buffer *pb,
|
|
+ bool xmit_more)
|
|
{
|
|
char *start = net_device->send_buf;
|
|
char *dest = start + (section_index * net_device->send_section_size)
|
|
@@ -716,7 +749,8 @@ static u32 netvsc_copy_to_send_buf(struct netvsc_device *net_device,
|
|
packet->page_buf_cnt;
|
|
|
|
/* Add padding */
|
|
- if (skb->xmit_more && remain && !packet->cp_partial) {
|
|
+ remain = packet->total_data_buflen & (net_device->pkt_align - 1);
|
|
+ if (xmit_more && remain) {
|
|
padding = net_device->pkt_align - remain;
|
|
rndis_msg->msg_len += padding;
|
|
packet->total_data_buflen += padding;
|
|
@@ -736,8 +770,6 @@ static u32 netvsc_copy_to_send_buf(struct netvsc_device *net_device,
|
|
memset(dest, 0, padding);
|
|
msg_size += padding;
|
|
}
|
|
-
|
|
- return msg_size;
|
|
}
|
|
|
|
static inline int netvsc_send_pkt(
|
|
@@ -825,12 +857,13 @@ static inline void move_pkt_msd(struct hv_netvsc_packet **msd_send,
|
|
}
|
|
|
|
/* RCU already held by caller */
|
|
-int netvsc_send(struct net_device_context *ndev_ctx,
|
|
+int netvsc_send(struct net_device *ndev,
|
|
struct hv_netvsc_packet *packet,
|
|
struct rndis_message *rndis_msg,
|
|
struct hv_page_buffer *pb,
|
|
struct sk_buff *skb)
|
|
{
|
|
+ struct net_device_context *ndev_ctx = netdev_priv(ndev);
|
|
struct netvsc_device *net_device
|
|
= rcu_dereference_bh(ndev_ctx->nvdev);
|
|
struct hv_device *device = ndev_ctx->device_ctx;
|
|
@@ -841,20 +874,12 @@ int netvsc_send(struct net_device_context *ndev_ctx,
|
|
struct multi_send_data *msdp;
|
|
struct hv_netvsc_packet *msd_send = NULL, *cur_send = NULL;
|
|
struct sk_buff *msd_skb = NULL;
|
|
- bool try_batch;
|
|
- bool xmit_more = (skb != NULL) ? skb->xmit_more : false;
|
|
+ bool try_batch, xmit_more;
|
|
|
|
/* If device is rescinded, return error and packet will get dropped. */
|
|
if (unlikely(!net_device || net_device->destroy))
|
|
return -ENODEV;
|
|
|
|
- /* We may race with netvsc_connect_vsp()/netvsc_init_buf() and get
|
|
- * here before the negotiation with the host is finished and
|
|
- * send_section_map may not be allocated yet.
|
|
- */
|
|
- if (unlikely(!net_device->send_section_map))
|
|
- return -EAGAIN;
|
|
-
|
|
nvchan = &net_device->chan_table[packet->q_idx];
|
|
packet->send_buf_index = NETVSC_INVALID_INDEX;
|
|
packet->cp_partial = false;
|
|
@@ -862,10 +887,8 @@ int netvsc_send(struct net_device_context *ndev_ctx,
|
|
/* Send control message directly without accessing msd (Multi-Send
|
|
* Data) field which may be changed during data packet processing.
|
|
*/
|
|
- if (!skb) {
|
|
- cur_send = packet;
|
|
- goto send_now;
|
|
- }
|
|
+ if (!skb)
|
|
+ return netvsc_send_pkt(device, packet, net_device, pb, skb);
|
|
|
|
/* batch packets in send buffer if possible */
|
|
msdp = &nvchan->msd;
|
|
@@ -893,10 +916,17 @@ int netvsc_send(struct net_device_context *ndev_ctx,
|
|
}
|
|
}
|
|
|
|
+ /* Keep aggregating only if stack says more data is coming
|
|
+ * and not doing mixed modes send and not flow blocked
|
|
+ */
|
|
+ xmit_more = skb->xmit_more &&
|
|
+ !packet->cp_partial &&
|
|
+ !netif_xmit_stopped(netdev_get_tx_queue(ndev, packet->q_idx));
|
|
+
|
|
if (section_index != NETVSC_INVALID_INDEX) {
|
|
netvsc_copy_to_send_buf(net_device,
|
|
section_index, msd_len,
|
|
- packet, rndis_msg, pb, skb);
|
|
+ packet, rndis_msg, pb, xmit_more);
|
|
|
|
packet->send_buf_index = section_index;
|
|
|
|
@@ -916,7 +946,7 @@ int netvsc_send(struct net_device_context *ndev_ctx,
|
|
if (msdp->skb)
|
|
dev_consume_skb_any(msdp->skb);
|
|
|
|
- if (xmit_more && !packet->cp_partial) {
|
|
+ if (xmit_more) {
|
|
msdp->skb = skb;
|
|
msdp->pkt = packet;
|
|
msdp->count++;
|
|
@@ -942,7 +972,6 @@ int netvsc_send(struct net_device_context *ndev_ctx,
|
|
}
|
|
}
|
|
|
|
-send_now:
|
|
if (cur_send)
|
|
ret = netvsc_send_pkt(device, cur_send, net_device, pb, skb);
|
|
|
|
@@ -1107,7 +1136,7 @@ static void netvsc_send_table(struct hv_device *hdev,
|
|
nvmsg->msg.v5_msg.send_table.offset);
|
|
|
|
for (i = 0; i < count; i++)
|
|
- net_device_ctx->tx_send_table[i] = tab[i];
|
|
+ net_device_ctx->tx_table[i] = tab[i];
|
|
}
|
|
|
|
static void netvsc_send_vf(struct net_device_context *net_device_ctx,
|
|
@@ -1206,9 +1235,10 @@ int netvsc_poll(struct napi_struct *napi, int budget)
|
|
if (send_recv_completions(ndev, net_device, nvchan) == 0 &&
|
|
work_done < budget &&
|
|
napi_complete_done(napi, work_done) &&
|
|
- hv_end_read(&channel->inbound)) {
|
|
+ hv_end_read(&channel->inbound) &&
|
|
+ napi_schedule_prep(napi)) {
|
|
hv_begin_read(&channel->inbound);
|
|
- napi_reschedule(napi);
|
|
+ __napi_schedule(napi);
|
|
}
|
|
|
|
/* Driver may overshoot since multiple packets per descriptor */
|
|
@@ -1252,6 +1282,9 @@ struct netvsc_device *netvsc_device_add(struct hv_device *device,
|
|
if (!net_device)
|
|
return ERR_PTR(-ENOMEM);
|
|
|
|
+ for (i = 0; i < VRSS_SEND_TAB_SIZE; i++)
|
|
+ net_device_ctx->tx_table[i] = 0;
|
|
+
|
|
net_device->ring_size = ring_size;
|
|
|
|
/* Because the device uses NAPI, all the interrupt batching and
|
|
@@ -1286,7 +1319,6 @@ struct netvsc_device *netvsc_device_add(struct hv_device *device,
|
|
net_device->chan_table);
|
|
|
|
if (ret != 0) {
|
|
- netif_napi_del(&net_device->chan_table[0].napi);
|
|
netdev_err(ndev, "unable to open channel: %d\n", ret);
|
|
goto cleanup;
|
|
}
|
|
@@ -1296,11 +1328,6 @@ struct netvsc_device *netvsc_device_add(struct hv_device *device,
|
|
|
|
napi_enable(&net_device->chan_table[0].napi);
|
|
|
|
- /* Writing nvdev pointer unlocks netvsc_send(), make sure chn_table is
|
|
- * populated.
|
|
- */
|
|
- rcu_assign_pointer(net_device_ctx->nvdev, net_device);
|
|
-
|
|
/* Connect with the NetVsp */
|
|
ret = netvsc_connect_vsp(device, net_device, device_info);
|
|
if (ret != 0) {
|
|
@@ -1309,6 +1336,11 @@ struct netvsc_device *netvsc_device_add(struct hv_device *device,
|
|
goto close;
|
|
}
|
|
|
|
+ /* Writing nvdev pointer unlocks netvsc_send(), make sure chn_table is
|
|
+ * populated.
|
|
+ */
|
|
+ rcu_assign_pointer(net_device_ctx->nvdev, net_device);
|
|
+
|
|
return net_device;
|
|
|
|
close:
|
|
@@ -1319,6 +1351,7 @@ struct netvsc_device *netvsc_device_add(struct hv_device *device,
|
|
vmbus_close(device->channel);
|
|
|
|
cleanup:
|
|
+ netif_napi_del(&net_device->chan_table[0].napi);
|
|
free_netvsc_device(&net_device->rcu);
|
|
|
|
return ERR_PTR(ret);
|
|
diff --git a/drivers/net/hyperv/netvsc_drv.c b/drivers/net/hyperv/netvsc_drv.c
|
|
index 444e560d928b..11b46c8d2d67 100644
|
|
--- a/drivers/net/hyperv/netvsc_drv.c
|
|
+++ b/drivers/net/hyperv/netvsc_drv.c
|
|
@@ -45,7 +45,10 @@
|
|
|
|
#include "hyperv_net.h"
|
|
|
|
-#define RING_SIZE_MIN 64
|
|
+#define RING_SIZE_MIN 64
|
|
+#define RETRY_US_LO 5000
|
|
+#define RETRY_US_HI 10000
|
|
+#define RETRY_MAX 2000 /* >10 sec */
|
|
|
|
#define LINKCHANGE_INT (2 * HZ)
|
|
#define VF_TAKEOVER_INT (HZ / 10)
|
|
@@ -88,10 +91,7 @@ static int netvsc_open(struct net_device *net)
|
|
return ret;
|
|
}
|
|
|
|
- netif_tx_wake_all_queues(net);
|
|
-
|
|
rdev = nvdev->extension;
|
|
-
|
|
if (!rdev->link_state)
|
|
netif_carrier_on(net);
|
|
|
|
@@ -109,36 +109,25 @@ static int netvsc_open(struct net_device *net)
|
|
return 0;
|
|
}
|
|
|
|
-static int netvsc_close(struct net_device *net)
|
|
+static int netvsc_wait_until_empty(struct netvsc_device *nvdev)
|
|
{
|
|
- struct net_device_context *net_device_ctx = netdev_priv(net);
|
|
- struct net_device *vf_netdev
|
|
- = rtnl_dereference(net_device_ctx->vf_netdev);
|
|
- struct netvsc_device *nvdev = rtnl_dereference(net_device_ctx->nvdev);
|
|
- int ret = 0;
|
|
- u32 aread, i, msec = 10, retry = 0, retry_max = 20;
|
|
- struct vmbus_channel *chn;
|
|
-
|
|
- netif_tx_disable(net);
|
|
-
|
|
- /* No need to close rndis filter if it is removed already */
|
|
- if (!nvdev)
|
|
- goto out;
|
|
-
|
|
- ret = rndis_filter_close(nvdev);
|
|
- if (ret != 0) {
|
|
- netdev_err(net, "unable to close device (ret %d).\n", ret);
|
|
- return ret;
|
|
- }
|
|
+ unsigned int retry = 0;
|
|
+ int i;
|
|
|
|
/* Ensure pending bytes in ring are read */
|
|
- while (true) {
|
|
- aread = 0;
|
|
+ for (;;) {
|
|
+ u32 aread = 0;
|
|
+
|
|
for (i = 0; i < nvdev->num_chn; i++) {
|
|
- chn = nvdev->chan_table[i].channel;
|
|
+ struct vmbus_channel *chn
|
|
+ = nvdev->chan_table[i].channel;
|
|
+
|
|
if (!chn)
|
|
continue;
|
|
|
|
+ /* make sure receive not running now */
|
|
+ napi_synchronize(&nvdev->chan_table[i].napi);
|
|
+
|
|
aread = hv_get_bytes_to_read(&chn->inbound);
|
|
if (aread)
|
|
break;
|
|
@@ -148,22 +137,40 @@ static int netvsc_close(struct net_device *net)
|
|
break;
|
|
}
|
|
|
|
- retry++;
|
|
- if (retry > retry_max || aread == 0)
|
|
- break;
|
|
+ if (aread == 0)
|
|
+ return 0;
|
|
|
|
- msleep(msec);
|
|
+ if (++retry > RETRY_MAX)
|
|
+ return -ETIMEDOUT;
|
|
|
|
- if (msec < 1000)
|
|
- msec *= 2;
|
|
+ usleep_range(RETRY_US_LO, RETRY_US_HI);
|
|
}
|
|
+}
|
|
|
|
- if (aread) {
|
|
- netdev_err(net, "Ring buffer not empty after closing rndis\n");
|
|
- ret = -ETIMEDOUT;
|
|
+static int netvsc_close(struct net_device *net)
|
|
+{
|
|
+ struct net_device_context *net_device_ctx = netdev_priv(net);
|
|
+ struct net_device *vf_netdev
|
|
+ = rtnl_dereference(net_device_ctx->vf_netdev);
|
|
+ struct netvsc_device *nvdev = rtnl_dereference(net_device_ctx->nvdev);
|
|
+ int ret;
|
|
+
|
|
+ netif_tx_disable(net);
|
|
+
|
|
+ /* No need to close rndis filter if it is removed already */
|
|
+ if (!nvdev)
|
|
+ return 0;
|
|
+
|
|
+ ret = rndis_filter_close(nvdev);
|
|
+ if (ret != 0) {
|
|
+ netdev_err(net, "unable to close device (ret %d).\n", ret);
|
|
+ return ret;
|
|
}
|
|
|
|
-out:
|
|
+ ret = netvsc_wait_until_empty(nvdev);
|
|
+ if (ret)
|
|
+ netdev_err(net, "Ring buffer not empty after closing rndis\n");
|
|
+
|
|
if (vf_netdev)
|
|
dev_close(vf_netdev);
|
|
|
|
@@ -234,8 +241,8 @@ static inline int netvsc_get_tx_queue(struct net_device *ndev,
|
|
struct sock *sk = skb->sk;
|
|
int q_idx;
|
|
|
|
- q_idx = ndc->tx_send_table[netvsc_get_hash(skb, ndc) &
|
|
- (VRSS_SEND_TAB_SIZE - 1)];
|
|
+ q_idx = ndc->tx_table[netvsc_get_hash(skb, ndc) &
|
|
+ (VRSS_SEND_TAB_SIZE - 1)];
|
|
|
|
/* If queue index changed record the new value */
|
|
if (q_idx != old_idx &&
|
|
@@ -284,8 +291,19 @@ static u16 netvsc_select_queue(struct net_device *ndev, struct sk_buff *skb,
|
|
rcu_read_lock();
|
|
vf_netdev = rcu_dereference(ndc->vf_netdev);
|
|
if (vf_netdev) {
|
|
- txq = skb_rx_queue_recorded(skb) ? skb_get_rx_queue(skb) : 0;
|
|
- qdisc_skb_cb(skb)->slave_dev_queue_mapping = skb->queue_mapping;
|
|
+ const struct net_device_ops *vf_ops = vf_netdev->netdev_ops;
|
|
+
|
|
+ if (vf_ops->ndo_select_queue)
|
|
+ txq = vf_ops->ndo_select_queue(vf_netdev, skb,
|
|
+ accel_priv, fallback);
|
|
+ else
|
|
+ txq = fallback(vf_netdev, skb);
|
|
+
|
|
+ /* Record the queue selected by VF so that it can be
|
|
+ * used for common case where VF has more queues than
|
|
+ * the synthetic device.
|
|
+ */
|
|
+ qdisc_skb_cb(skb)->slave_dev_queue_mapping = txq;
|
|
} else {
|
|
txq = netvsc_pick_tx(ndev, skb);
|
|
}
|
|
@@ -614,7 +632,7 @@ static int netvsc_start_xmit(struct sk_buff *skb, struct net_device *net)
|
|
/* timestamp packet in software */
|
|
skb_tx_timestamp(skb);
|
|
|
|
- ret = netvsc_send(net_device_ctx, packet, rndis_msg, pb, skb);
|
|
+ ret = netvsc_send(net, packet, rndis_msg, pb, skb);
|
|
if (likely(ret == 0))
|
|
return NETDEV_TX_OK;
|
|
|
|
@@ -810,16 +828,81 @@ static void netvsc_get_channels(struct net_device *net,
|
|
}
|
|
}
|
|
|
|
+static int netvsc_detach(struct net_device *ndev,
|
|
+ struct netvsc_device *nvdev)
|
|
+{
|
|
+ struct net_device_context *ndev_ctx = netdev_priv(ndev);
|
|
+ struct hv_device *hdev = ndev_ctx->device_ctx;
|
|
+ int ret;
|
|
+
|
|
+ /* Don't try continuing to try and setup sub channels */
|
|
+ if (cancel_work_sync(&nvdev->subchan_work))
|
|
+ nvdev->num_chn = 1;
|
|
+
|
|
+ /* If device was up (receiving) then shutdown */
|
|
+ if (netif_running(ndev)) {
|
|
+ netif_tx_disable(ndev);
|
|
+
|
|
+ ret = rndis_filter_close(nvdev);
|
|
+ if (ret) {
|
|
+ netdev_err(ndev,
|
|
+ "unable to close device (ret %d).\n", ret);
|
|
+ return ret;
|
|
+ }
|
|
+
|
|
+ ret = netvsc_wait_until_empty(nvdev);
|
|
+ if (ret) {
|
|
+ netdev_err(ndev,
|
|
+ "Ring buffer not empty after closing rndis\n");
|
|
+ return ret;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ netif_device_detach(ndev);
|
|
+
|
|
+ rndis_filter_device_remove(hdev, nvdev);
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static int netvsc_attach(struct net_device *ndev,
|
|
+ struct netvsc_device_info *dev_info)
|
|
+{
|
|
+ struct net_device_context *ndev_ctx = netdev_priv(ndev);
|
|
+ struct hv_device *hdev = ndev_ctx->device_ctx;
|
|
+ struct netvsc_device *nvdev;
|
|
+ struct rndis_device *rdev;
|
|
+ int ret;
|
|
+
|
|
+ nvdev = rndis_filter_device_add(hdev, dev_info);
|
|
+ if (IS_ERR(nvdev))
|
|
+ return PTR_ERR(nvdev);
|
|
+
|
|
+ /* Note: enable and attach happen when sub-channels setup */
|
|
+
|
|
+ netif_carrier_off(ndev);
|
|
+
|
|
+ if (netif_running(ndev)) {
|
|
+ ret = rndis_filter_open(nvdev);
|
|
+ if (ret)
|
|
+ return ret;
|
|
+
|
|
+ rdev = nvdev->extension;
|
|
+ if (!rdev->link_state)
|
|
+ netif_carrier_on(ndev);
|
|
+ }
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
static int netvsc_set_channels(struct net_device *net,
|
|
struct ethtool_channels *channels)
|
|
{
|
|
struct net_device_context *net_device_ctx = netdev_priv(net);
|
|
- struct hv_device *dev = net_device_ctx->device_ctx;
|
|
struct netvsc_device *nvdev = rtnl_dereference(net_device_ctx->nvdev);
|
|
unsigned int orig, count = channels->combined_count;
|
|
struct netvsc_device_info device_info;
|
|
- bool was_opened;
|
|
- int ret = 0;
|
|
+ int ret;
|
|
|
|
/* We do not support separate count for rx, tx, or other */
|
|
if (count == 0 ||
|
|
@@ -836,9 +919,6 @@ static int netvsc_set_channels(struct net_device *net,
|
|
return -EINVAL;
|
|
|
|
orig = nvdev->num_chn;
|
|
- was_opened = rndis_filter_opened(nvdev);
|
|
- if (was_opened)
|
|
- rndis_filter_close(nvdev);
|
|
|
|
memset(&device_info, 0, sizeof(device_info));
|
|
device_info.num_chn = count;
|
|
@@ -848,28 +928,17 @@ static int netvsc_set_channels(struct net_device *net,
|
|
device_info.recv_sections = nvdev->recv_section_cnt;
|
|
device_info.recv_section_size = nvdev->recv_section_size;
|
|
|
|
- rndis_filter_device_remove(dev, nvdev);
|
|
+ ret = netvsc_detach(net, nvdev);
|
|
+ if (ret)
|
|
+ return ret;
|
|
|
|
- nvdev = rndis_filter_device_add(dev, &device_info);
|
|
- if (IS_ERR(nvdev)) {
|
|
- ret = PTR_ERR(nvdev);
|
|
+ ret = netvsc_attach(net, &device_info);
|
|
+ if (ret) {
|
|
device_info.num_chn = orig;
|
|
- nvdev = rndis_filter_device_add(dev, &device_info);
|
|
-
|
|
- if (IS_ERR(nvdev)) {
|
|
- netdev_err(net, "restoring channel setting failed: %ld\n",
|
|
- PTR_ERR(nvdev));
|
|
- return ret;
|
|
- }
|
|
+ if (netvsc_attach(net, &device_info))
|
|
+ netdev_err(net, "restoring channel setting failed\n");
|
|
}
|
|
|
|
- if (was_opened)
|
|
- rndis_filter_open(nvdev);
|
|
-
|
|
- /* We may have missed link change notifications */
|
|
- net_device_ctx->last_reconfig = 0;
|
|
- schedule_delayed_work(&net_device_ctx->dwork, 0);
|
|
-
|
|
return ret;
|
|
}
|
|
|
|
@@ -936,10 +1005,8 @@ static int netvsc_change_mtu(struct net_device *ndev, int mtu)
|
|
struct net_device_context *ndevctx = netdev_priv(ndev);
|
|
struct net_device *vf_netdev = rtnl_dereference(ndevctx->vf_netdev);
|
|
struct netvsc_device *nvdev = rtnl_dereference(ndevctx->nvdev);
|
|
- struct hv_device *hdev = ndevctx->device_ctx;
|
|
int orig_mtu = ndev->mtu;
|
|
struct netvsc_device_info device_info;
|
|
- bool was_opened;
|
|
int ret = 0;
|
|
|
|
if (!nvdev || nvdev->destroy)
|
|
@@ -952,11 +1019,6 @@ static int netvsc_change_mtu(struct net_device *ndev, int mtu)
|
|
return ret;
|
|
}
|
|
|
|
- netif_device_detach(ndev);
|
|
- was_opened = rndis_filter_opened(nvdev);
|
|
- if (was_opened)
|
|
- rndis_filter_close(nvdev);
|
|
-
|
|
memset(&device_info, 0, sizeof(device_info));
|
|
device_info.ring_size = ring_size;
|
|
device_info.num_chn = nvdev->num_chn;
|
|
@@ -965,35 +1027,27 @@ static int netvsc_change_mtu(struct net_device *ndev, int mtu)
|
|
device_info.recv_sections = nvdev->recv_section_cnt;
|
|
device_info.recv_section_size = nvdev->recv_section_size;
|
|
|
|
- rndis_filter_device_remove(hdev, nvdev);
|
|
+ ret = netvsc_detach(ndev, nvdev);
|
|
+ if (ret)
|
|
+ goto rollback_vf;
|
|
|
|
ndev->mtu = mtu;
|
|
|
|
- nvdev = rndis_filter_device_add(hdev, &device_info);
|
|
- if (IS_ERR(nvdev)) {
|
|
- ret = PTR_ERR(nvdev);
|
|
-
|
|
- /* Attempt rollback to original MTU */
|
|
- ndev->mtu = orig_mtu;
|
|
- nvdev = rndis_filter_device_add(hdev, &device_info);
|
|
-
|
|
- if (vf_netdev)
|
|
- dev_set_mtu(vf_netdev, orig_mtu);
|
|
-
|
|
- if (IS_ERR(nvdev)) {
|
|
- netdev_err(ndev, "restoring mtu failed: %ld\n",
|
|
- PTR_ERR(nvdev));
|
|
- return ret;
|
|
- }
|
|
- }
|
|
+ ret = netvsc_attach(ndev, &device_info);
|
|
+ if (ret)
|
|
+ goto rollback;
|
|
|
|
- if (was_opened)
|
|
- rndis_filter_open(nvdev);
|
|
+ return 0;
|
|
|
|
- netif_device_attach(ndev);
|
|
+rollback:
|
|
+ /* Attempt rollback to original MTU */
|
|
+ ndev->mtu = orig_mtu;
|
|
|
|
- /* We may have missed link change notifications */
|
|
- schedule_delayed_work(&ndevctx->dwork, 0);
|
|
+ if (netvsc_attach(ndev, &device_info))
|
|
+ netdev_err(ndev, "restoring mtu failed\n");
|
|
+rollback_vf:
|
|
+ if (vf_netdev)
|
|
+ dev_set_mtu(vf_netdev, orig_mtu);
|
|
|
|
return ret;
|
|
}
|
|
@@ -1378,7 +1432,7 @@ static int netvsc_get_rxfh(struct net_device *dev, u32 *indir, u8 *key,
|
|
rndis_dev = ndev->extension;
|
|
if (indir) {
|
|
for (i = 0; i < ITAB_NUM; i++)
|
|
- indir[i] = rndis_dev->ind_table[i];
|
|
+ indir[i] = rndis_dev->rx_table[i];
|
|
}
|
|
|
|
if (key)
|
|
@@ -1408,7 +1462,7 @@ static int netvsc_set_rxfh(struct net_device *dev, const u32 *indir,
|
|
return -EINVAL;
|
|
|
|
for (i = 0; i < ITAB_NUM; i++)
|
|
- rndis_dev->ind_table[i] = indir[i];
|
|
+ rndis_dev->rx_table[i] = indir[i];
|
|
}
|
|
|
|
if (!key) {
|
|
@@ -1459,11 +1513,9 @@ static int netvsc_set_ringparam(struct net_device *ndev,
|
|
{
|
|
struct net_device_context *ndevctx = netdev_priv(ndev);
|
|
struct netvsc_device *nvdev = rtnl_dereference(ndevctx->nvdev);
|
|
- struct hv_device *hdev = ndevctx->device_ctx;
|
|
struct netvsc_device_info device_info;
|
|
struct ethtool_ringparam orig;
|
|
u32 new_tx, new_rx;
|
|
- bool was_opened;
|
|
int ret = 0;
|
|
|
|
if (!nvdev || nvdev->destroy)
|
|
@@ -1489,34 +1541,18 @@ static int netvsc_set_ringparam(struct net_device *ndev,
|
|
device_info.recv_sections = new_rx;
|
|
device_info.recv_section_size = nvdev->recv_section_size;
|
|
|
|
- netif_device_detach(ndev);
|
|
- was_opened = rndis_filter_opened(nvdev);
|
|
- if (was_opened)
|
|
- rndis_filter_close(nvdev);
|
|
-
|
|
- rndis_filter_device_remove(hdev, nvdev);
|
|
-
|
|
- nvdev = rndis_filter_device_add(hdev, &device_info);
|
|
- if (IS_ERR(nvdev)) {
|
|
- ret = PTR_ERR(nvdev);
|
|
+ ret = netvsc_detach(ndev, nvdev);
|
|
+ if (ret)
|
|
+ return ret;
|
|
|
|
+ ret = netvsc_attach(ndev, &device_info);
|
|
+ if (ret) {
|
|
device_info.send_sections = orig.tx_pending;
|
|
device_info.recv_sections = orig.rx_pending;
|
|
- nvdev = rndis_filter_device_add(hdev, &device_info);
|
|
- if (IS_ERR(nvdev)) {
|
|
- netdev_err(ndev, "restoring ringparam failed: %ld\n",
|
|
- PTR_ERR(nvdev));
|
|
- return ret;
|
|
- }
|
|
- }
|
|
-
|
|
- if (was_opened)
|
|
- rndis_filter_open(nvdev);
|
|
- netif_device_attach(ndev);
|
|
|
|
- /* We may have missed link change notifications */
|
|
- ndevctx->last_reconfig = 0;
|
|
- schedule_delayed_work(&ndevctx->dwork, 0);
|
|
+ if (netvsc_attach(ndev, &device_info))
|
|
+ netdev_err(ndev, "restoring ringparam failed");
|
|
+ }
|
|
|
|
return ret;
|
|
}
|
|
@@ -1932,6 +1968,12 @@ static int netvsc_probe(struct hv_device *dev,
|
|
/* We always need headroom for rndis header */
|
|
net->needed_headroom = RNDIS_AND_PPI_SIZE;
|
|
|
|
+ /* Initialize the number of queues to be 1, we may change it if more
|
|
+ * channels are offered later.
|
|
+ */
|
|
+ netif_set_real_num_tx_queues(net, 1);
|
|
+ netif_set_real_num_rx_queues(net, 1);
|
|
+
|
|
/* Notify the netvsc driver of the new device */
|
|
memset(&device_info, 0, sizeof(device_info));
|
|
device_info.ring_size = ring_size;
|
|
@@ -1950,7 +1992,7 @@ static int netvsc_probe(struct hv_device *dev,
|
|
|
|
memcpy(net->dev_addr, device_info.mac_adr, ETH_ALEN);
|
|
|
|
- /* hw_features computed in rndis_filter_device_add */
|
|
+ /* hw_features computed in rndis_netdev_set_hwcaps() */
|
|
net->features = net->hw_features |
|
|
NETIF_F_HIGHDMA | NETIF_F_SG |
|
|
NETIF_F_HW_VLAN_CTAG_TX | NETIF_F_HW_VLAN_CTAG_RX;
|
|
@@ -1987,8 +2029,8 @@ static int netvsc_probe(struct hv_device *dev,
|
|
static int netvsc_remove(struct hv_device *dev)
|
|
{
|
|
struct net_device_context *ndev_ctx;
|
|
- struct net_device *vf_netdev;
|
|
- struct net_device *net;
|
|
+ struct net_device *vf_netdev, *net;
|
|
+ struct netvsc_device *nvdev;
|
|
|
|
net = hv_get_drvdata(dev);
|
|
if (net == NULL) {
|
|
@@ -1998,10 +2040,14 @@ static int netvsc_remove(struct hv_device *dev)
|
|
|
|
ndev_ctx = netdev_priv(net);
|
|
|
|
- netif_device_detach(net);
|
|
-
|
|
cancel_delayed_work_sync(&ndev_ctx->dwork);
|
|
|
|
+ rcu_read_lock();
|
|
+ nvdev = rcu_dereference(ndev_ctx->nvdev);
|
|
+
|
|
+ if (nvdev)
|
|
+ cancel_work_sync(&nvdev->subchan_work);
|
|
+
|
|
/*
|
|
* Call to the vsc driver to let it know that the device is being
|
|
* removed. Also blocks mtu and channel changes.
|
|
@@ -2011,11 +2057,13 @@ static int netvsc_remove(struct hv_device *dev)
|
|
if (vf_netdev)
|
|
netvsc_unregister_vf(vf_netdev);
|
|
|
|
+ if (nvdev)
|
|
+ rndis_filter_device_remove(dev, nvdev);
|
|
+
|
|
unregister_netdevice(net);
|
|
|
|
- rndis_filter_device_remove(dev,
|
|
- rtnl_dereference(ndev_ctx->nvdev));
|
|
rtnl_unlock();
|
|
+ rcu_read_unlock();
|
|
|
|
hv_set_drvdata(dev, NULL);
|
|
|
|
diff --git a/drivers/net/hyperv/rndis_filter.c b/drivers/net/hyperv/rndis_filter.c
|
|
index 065b204d8e17..6dde92c1c113 100644
|
|
--- a/drivers/net/hyperv/rndis_filter.c
|
|
+++ b/drivers/net/hyperv/rndis_filter.c
|
|
@@ -217,7 +217,6 @@ static int rndis_filter_send_request(struct rndis_device *dev,
|
|
struct hv_netvsc_packet *packet;
|
|
struct hv_page_buffer page_buf[2];
|
|
struct hv_page_buffer *pb = page_buf;
|
|
- struct net_device_context *net_device_ctx = netdev_priv(dev->ndev);
|
|
int ret;
|
|
|
|
/* Setup the packet to send it */
|
|
@@ -245,7 +244,7 @@ static int rndis_filter_send_request(struct rndis_device *dev,
|
|
}
|
|
|
|
rcu_read_lock_bh();
|
|
- ret = netvsc_send(net_device_ctx, packet, NULL, pb, NULL);
|
|
+ ret = netvsc_send(dev->ndev, packet, NULL, pb, NULL);
|
|
rcu_read_unlock_bh();
|
|
|
|
return ret;
|
|
@@ -267,13 +266,23 @@ static void rndis_set_link_state(struct rndis_device *rdev,
|
|
}
|
|
}
|
|
|
|
-static void rndis_filter_receive_response(struct rndis_device *dev,
|
|
- struct rndis_message *resp)
|
|
+static void rndis_filter_receive_response(struct net_device *ndev,
|
|
+ struct netvsc_device *nvdev,
|
|
+ const struct rndis_message *resp)
|
|
{
|
|
+ struct rndis_device *dev = nvdev->extension;
|
|
struct rndis_request *request = NULL;
|
|
bool found = false;
|
|
unsigned long flags;
|
|
- struct net_device *ndev = dev->ndev;
|
|
+
|
|
+ /* This should never happen, it means control message
|
|
+ * response received after device removed.
|
|
+ */
|
|
+ if (dev->state == RNDIS_DEV_UNINITIALIZED) {
|
|
+ netdev_err(ndev,
|
|
+ "got rndis message uninitialized\n");
|
|
+ return;
|
|
+ }
|
|
|
|
spin_lock_irqsave(&dev->request_lock, flags);
|
|
list_for_each_entry(request, &dev->req_list, list_ent) {
|
|
@@ -354,7 +363,7 @@ static inline void *rndis_get_ppi(struct rndis_packet *rpkt, u32 type)
|
|
}
|
|
|
|
static int rndis_filter_receive_data(struct net_device *ndev,
|
|
- struct rndis_device *dev,
|
|
+ struct netvsc_device *nvdev,
|
|
struct rndis_message *msg,
|
|
struct vmbus_channel *channel,
|
|
void *data, u32 data_buflen)
|
|
@@ -374,7 +383,7 @@ static int rndis_filter_receive_data(struct net_device *ndev,
|
|
* should be the data packet size plus the trailer padding size
|
|
*/
|
|
if (unlikely(data_buflen < rndis_pkt->data_len)) {
|
|
- netdev_err(dev->ndev, "rndis message buffer "
|
|
+ netdev_err(ndev, "rndis message buffer "
|
|
"overflow detected (got %u, min %u)"
|
|
"...dropping this message!\n",
|
|
data_buflen, rndis_pkt->data_len);
|
|
@@ -402,34 +411,20 @@ int rndis_filter_receive(struct net_device *ndev,
|
|
void *data, u32 buflen)
|
|
{
|
|
struct net_device_context *net_device_ctx = netdev_priv(ndev);
|
|
- struct rndis_device *rndis_dev = net_dev->extension;
|
|
struct rndis_message *rndis_msg = data;
|
|
|
|
- /* Make sure the rndis device state is initialized */
|
|
- if (unlikely(!rndis_dev)) {
|
|
- netif_err(net_device_ctx, rx_err, ndev,
|
|
- "got rndis message but no rndis device!\n");
|
|
- return NVSP_STAT_FAIL;
|
|
- }
|
|
-
|
|
- if (unlikely(rndis_dev->state == RNDIS_DEV_UNINITIALIZED)) {
|
|
- netif_err(net_device_ctx, rx_err, ndev,
|
|
- "got rndis message uninitialized\n");
|
|
- return NVSP_STAT_FAIL;
|
|
- }
|
|
-
|
|
if (netif_msg_rx_status(net_device_ctx))
|
|
dump_rndis_message(dev, rndis_msg);
|
|
|
|
switch (rndis_msg->ndis_msg_type) {
|
|
case RNDIS_MSG_PACKET:
|
|
- return rndis_filter_receive_data(ndev, rndis_dev, rndis_msg,
|
|
+ return rndis_filter_receive_data(ndev, net_dev, rndis_msg,
|
|
channel, data, buflen);
|
|
case RNDIS_MSG_INIT_C:
|
|
case RNDIS_MSG_QUERY_C:
|
|
case RNDIS_MSG_SET_C:
|
|
/* completion msgs */
|
|
- rndis_filter_receive_response(rndis_dev, rndis_msg);
|
|
+ rndis_filter_receive_response(ndev, net_dev, rndis_msg);
|
|
break;
|
|
|
|
case RNDIS_MSG_INDICATE:
|
|
@@ -759,7 +754,7 @@ int rndis_filter_set_rss_param(struct rndis_device *rdev,
|
|
/* Set indirection table entries */
|
|
itab = (u32 *)(rssp + 1);
|
|
for (i = 0; i < ITAB_NUM; i++)
|
|
- itab[i] = rdev->ind_table[i];
|
|
+ itab[i] = rdev->rx_table[i];
|
|
|
|
/* Set hask key values */
|
|
keyp = (u8 *)((unsigned long)rssp + rssp->kashkey_offset);
|
|
@@ -1114,6 +1109,10 @@ void rndis_set_subchannel(struct work_struct *w)
|
|
netif_set_real_num_tx_queues(ndev, nvdev->num_chn);
|
|
netif_set_real_num_rx_queues(ndev, nvdev->num_chn);
|
|
|
|
+ for (i = 0; i < VRSS_SEND_TAB_SIZE; i++)
|
|
+ ndev_ctx->tx_table[i] = i % nvdev->num_chn;
|
|
+
|
|
+ netif_device_attach(ndev);
|
|
rtnl_unlock();
|
|
return;
|
|
|
|
@@ -1124,73 +1123,26 @@ void rndis_set_subchannel(struct work_struct *w)
|
|
|
|
nvdev->max_chn = 1;
|
|
nvdev->num_chn = 1;
|
|
+
|
|
+ netif_device_attach(ndev);
|
|
unlock:
|
|
rtnl_unlock();
|
|
}
|
|
|
|
-struct netvsc_device *rndis_filter_device_add(struct hv_device *dev,
|
|
- struct netvsc_device_info *device_info)
|
|
+static int rndis_netdev_set_hwcaps(struct rndis_device *rndis_device,
|
|
+ struct netvsc_device *nvdev)
|
|
{
|
|
- struct net_device *net = hv_get_drvdata(dev);
|
|
+ struct net_device *net = rndis_device->ndev;
|
|
struct net_device_context *net_device_ctx = netdev_priv(net);
|
|
- struct netvsc_device *net_device;
|
|
- struct rndis_device *rndis_device;
|
|
struct ndis_offload hwcaps;
|
|
struct ndis_offload_params offloads;
|
|
- struct ndis_recv_scale_cap rsscap;
|
|
- u32 rsscap_size = sizeof(struct ndis_recv_scale_cap);
|
|
unsigned int gso_max_size = GSO_MAX_SIZE;
|
|
- u32 mtu, size;
|
|
- const struct cpumask *node_cpu_mask;
|
|
- u32 num_possible_rss_qs;
|
|
- int i, ret;
|
|
-
|
|
- rndis_device = get_rndis_device();
|
|
- if (!rndis_device)
|
|
- return ERR_PTR(-ENODEV);
|
|
-
|
|
- /*
|
|
- * Let the inner driver handle this first to create the netvsc channel
|
|
- * NOTE! Once the channel is created, we may get a receive callback
|
|
- * (RndisFilterOnReceive()) before this call is completed
|
|
- */
|
|
- net_device = netvsc_device_add(dev, device_info);
|
|
- if (IS_ERR(net_device)) {
|
|
- kfree(rndis_device);
|
|
- return net_device;
|
|
- }
|
|
-
|
|
- /* Initialize the rndis device */
|
|
- net_device->max_chn = 1;
|
|
- net_device->num_chn = 1;
|
|
-
|
|
- net_device->extension = rndis_device;
|
|
- rndis_device->ndev = net;
|
|
-
|
|
- /* Send the rndis initialization message */
|
|
- ret = rndis_filter_init_device(rndis_device, net_device);
|
|
- if (ret != 0)
|
|
- goto err_dev_remv;
|
|
-
|
|
- /* Get the MTU from the host */
|
|
- size = sizeof(u32);
|
|
- ret = rndis_filter_query_device(rndis_device, net_device,
|
|
- RNDIS_OID_GEN_MAXIMUM_FRAME_SIZE,
|
|
- &mtu, &size);
|
|
- if (ret == 0 && size == sizeof(u32) && mtu < net->mtu)
|
|
- net->mtu = mtu;
|
|
-
|
|
- /* Get the mac address */
|
|
- ret = rndis_filter_query_device_mac(rndis_device, net_device);
|
|
- if (ret != 0)
|
|
- goto err_dev_remv;
|
|
-
|
|
- memcpy(device_info->mac_adr, rndis_device->hw_mac_adr, ETH_ALEN);
|
|
+ int ret;
|
|
|
|
/* Find HW offload capabilities */
|
|
- ret = rndis_query_hwcaps(rndis_device, net_device, &hwcaps);
|
|
+ ret = rndis_query_hwcaps(rndis_device, nvdev, &hwcaps);
|
|
if (ret != 0)
|
|
- goto err_dev_remv;
|
|
+ return ret;
|
|
|
|
/* A value of zero means "no change"; now turn on what we want. */
|
|
memset(&offloads, 0, sizeof(struct ndis_offload_params));
|
|
@@ -1198,8 +1150,12 @@ struct netvsc_device *rndis_filter_device_add(struct hv_device *dev,
|
|
/* Linux does not care about IP checksum, always does in kernel */
|
|
offloads.ip_v4_csum = NDIS_OFFLOAD_PARAMETERS_TX_RX_DISABLED;
|
|
|
|
+ /* Reset previously set hw_features flags */
|
|
+ net->hw_features &= ~NETVSC_SUPPORTED_HW_FEATURES;
|
|
+ net_device_ctx->tx_checksum_mask = 0;
|
|
+
|
|
/* Compute tx offload settings based on hw capabilities */
|
|
- net->hw_features = NETIF_F_RXCSUM;
|
|
+ net->hw_features |= NETIF_F_RXCSUM;
|
|
|
|
if ((hwcaps.csum.ip4_txcsum & NDIS_TXCSUM_ALL_TCP4) == NDIS_TXCSUM_ALL_TCP4) {
|
|
/* Can checksum TCP */
|
|
@@ -1243,10 +1199,74 @@ struct netvsc_device *rndis_filter_device_add(struct hv_device *dev,
|
|
}
|
|
}
|
|
|
|
+ /* In case some hw_features disappeared we need to remove them from
|
|
+ * net->features list as they're no longer supported.
|
|
+ */
|
|
+ net->features &= ~NETVSC_SUPPORTED_HW_FEATURES | net->hw_features;
|
|
+
|
|
netif_set_gso_max_size(net, gso_max_size);
|
|
|
|
- ret = rndis_filter_set_offload_params(net, net_device, &offloads);
|
|
- if (ret)
|
|
+ ret = rndis_filter_set_offload_params(net, nvdev, &offloads);
|
|
+
|
|
+ return ret;
|
|
+}
|
|
+
|
|
+struct netvsc_device *rndis_filter_device_add(struct hv_device *dev,
|
|
+ struct netvsc_device_info *device_info)
|
|
+{
|
|
+ struct net_device *net = hv_get_drvdata(dev);
|
|
+ struct netvsc_device *net_device;
|
|
+ struct rndis_device *rndis_device;
|
|
+ struct ndis_recv_scale_cap rsscap;
|
|
+ u32 rsscap_size = sizeof(struct ndis_recv_scale_cap);
|
|
+ u32 mtu, size;
|
|
+ u32 num_possible_rss_qs;
|
|
+ int i, ret;
|
|
+
|
|
+ rndis_device = get_rndis_device();
|
|
+ if (!rndis_device)
|
|
+ return ERR_PTR(-ENODEV);
|
|
+
|
|
+ /* Let the inner driver handle this first to create the netvsc channel
|
|
+ * NOTE! Once the channel is created, we may get a receive callback
|
|
+ * (RndisFilterOnReceive()) before this call is completed
|
|
+ */
|
|
+ net_device = netvsc_device_add(dev, device_info);
|
|
+ if (IS_ERR(net_device)) {
|
|
+ kfree(rndis_device);
|
|
+ return net_device;
|
|
+ }
|
|
+
|
|
+ /* Initialize the rndis device */
|
|
+ net_device->max_chn = 1;
|
|
+ net_device->num_chn = 1;
|
|
+
|
|
+ net_device->extension = rndis_device;
|
|
+ rndis_device->ndev = net;
|
|
+
|
|
+ /* Send the rndis initialization message */
|
|
+ ret = rndis_filter_init_device(rndis_device, net_device);
|
|
+ if (ret != 0)
|
|
+ goto err_dev_remv;
|
|
+
|
|
+ /* Get the MTU from the host */
|
|
+ size = sizeof(u32);
|
|
+ ret = rndis_filter_query_device(rndis_device, net_device,
|
|
+ RNDIS_OID_GEN_MAXIMUM_FRAME_SIZE,
|
|
+ &mtu, &size);
|
|
+ if (ret == 0 && size == sizeof(u32) && mtu < net->mtu)
|
|
+ net->mtu = mtu;
|
|
+
|
|
+ /* Get the mac address */
|
|
+ ret = rndis_filter_query_device_mac(rndis_device, net_device);
|
|
+ if (ret != 0)
|
|
+ goto err_dev_remv;
|
|
+
|
|
+ memcpy(device_info->mac_adr, rndis_device->hw_mac_adr, ETH_ALEN);
|
|
+
|
|
+ /* Query and set hardware capabilities */
|
|
+ ret = rndis_netdev_set_hwcaps(rndis_device, net_device);
|
|
+ if (ret != 0)
|
|
goto err_dev_remv;
|
|
|
|
rndis_filter_query_device_link_status(rndis_device, net_device);
|
|
@@ -1256,7 +1276,7 @@ struct netvsc_device *rndis_filter_device_add(struct hv_device *dev,
|
|
rndis_device->link_state ? "down" : "up");
|
|
|
|
if (net_device->nvsp_version < NVSP_PROTOCOL_VERSION_5)
|
|
- return net_device;
|
|
+ goto out;
|
|
|
|
rndis_filter_query_link_speed(rndis_device, net_device);
|
|
|
|
@@ -1268,14 +1288,8 @@ struct netvsc_device *rndis_filter_device_add(struct hv_device *dev,
|
|
if (ret || rsscap.num_recv_que < 2)
|
|
goto out;
|
|
|
|
- /*
|
|
- * We will limit the VRSS channels to the number CPUs in the NUMA node
|
|
- * the primary channel is currently bound to.
|
|
- *
|
|
- * This also guarantees that num_possible_rss_qs <= num_online_cpus
|
|
- */
|
|
- node_cpu_mask = cpumask_of_node(cpu_to_node(dev->channel->target_cpu));
|
|
- num_possible_rss_qs = min_t(u32, cpumask_weight(node_cpu_mask),
|
|
+ /* This guarantees that num_possible_rss_qs <= num_online_cpus */
|
|
+ num_possible_rss_qs = min_t(u32, num_online_cpus(),
|
|
rsscap.num_recv_que);
|
|
|
|
net_device->max_chn = min_t(u32, VRSS_CHANNEL_MAX, num_possible_rss_qs);
|
|
@@ -1284,8 +1298,8 @@ struct netvsc_device *rndis_filter_device_add(struct hv_device *dev,
|
|
net_device->num_chn = min(net_device->max_chn, device_info->num_chn);
|
|
|
|
for (i = 0; i < ITAB_NUM; i++)
|
|
- rndis_device->ind_table[i] = ethtool_rxfh_indir_default(i,
|
|
- net_device->num_chn);
|
|
+ rndis_device->rx_table[i] = ethtool_rxfh_indir_default(
|
|
+ i, net_device->num_chn);
|
|
|
|
atomic_set(&net_device->open_chn, 1);
|
|
vmbus_set_sc_create_callback(dev->channel, netvsc_sc_open);
|
|
@@ -1313,6 +1327,10 @@ struct netvsc_device *rndis_filter_device_add(struct hv_device *dev,
|
|
net_device->num_chn = 1;
|
|
}
|
|
|
|
+ /* No sub channels, device is ready */
|
|
+ if (net_device->num_chn == 1)
|
|
+ netif_device_attach(net);
|
|
+
|
|
return net_device;
|
|
|
|
err_dev_remv:
|
|
@@ -1331,7 +1349,6 @@ void rndis_filter_device_remove(struct hv_device *dev,
|
|
net_dev->extension = NULL;
|
|
|
|
netvsc_device_remove(dev);
|
|
- kfree(rndis_dev);
|
|
}
|
|
|
|
int rndis_filter_open(struct netvsc_device *nvdev)
|
|
@@ -1355,8 +1372,3 @@ int rndis_filter_close(struct netvsc_device *nvdev)
|
|
|
|
return rndis_filter_close_device(nvdev->extension);
|
|
}
|
|
-
|
|
-bool rndis_filter_opened(const struct netvsc_device *nvdev)
|
|
-{
|
|
- return atomic_read(&nvdev->open_cnt) > 0;
|
|
-}
|
|
diff --git a/drivers/net/usb/qmi_wwan.c b/drivers/net/usb/qmi_wwan.c
|
|
index 2f828eb9ace6..e522085ecbf7 100644
|
|
--- a/drivers/net/usb/qmi_wwan.c
|
|
+++ b/drivers/net/usb/qmi_wwan.c
|
|
@@ -1105,6 +1105,9 @@ static const struct usb_device_id products[] = {
|
|
{QMI_FIXED_INTF(0x0846, 0x68a2, 8)},
|
|
{QMI_FIXED_INTF(0x12d1, 0x140c, 1)}, /* Huawei E173 */
|
|
{QMI_FIXED_INTF(0x12d1, 0x14ac, 1)}, /* Huawei E1820 */
|
|
+ {QMI_FIXED_INTF(0x1435, 0xd181, 3)}, /* Wistron NeWeb D18Q1 */
|
|
+ {QMI_FIXED_INTF(0x1435, 0xd181, 4)}, /* Wistron NeWeb D18Q1 */
|
|
+ {QMI_FIXED_INTF(0x1435, 0xd181, 5)}, /* Wistron NeWeb D18Q1 */
|
|
{QMI_FIXED_INTF(0x16d8, 0x6003, 0)}, /* CMOTech 6003 */
|
|
{QMI_FIXED_INTF(0x16d8, 0x6007, 0)}, /* CMOTech CHE-628S */
|
|
{QMI_FIXED_INTF(0x16d8, 0x6008, 0)}, /* CMOTech CMU-301 */
|
|
@@ -1241,6 +1244,7 @@ static const struct usb_device_id products[] = {
|
|
{QMI_FIXED_INTF(0x413c, 0x81b6, 8)}, /* Dell Wireless 5811e */
|
|
{QMI_FIXED_INTF(0x413c, 0x81b6, 10)}, /* Dell Wireless 5811e */
|
|
{QMI_FIXED_INTF(0x03f0, 0x4e1d, 8)}, /* HP lt4111 LTE/EV-DO/HSPA+ Gobi 4G Module */
|
|
+ {QMI_FIXED_INTF(0x03f0, 0x9d1d, 1)}, /* HP lt4120 Snapdragon X5 LTE */
|
|
{QMI_FIXED_INTF(0x22de, 0x9061, 3)}, /* WeTelecom WPD-600N */
|
|
{QMI_FIXED_INTF(0x1e0e, 0x9001, 5)}, /* SIMCom 7230E */
|
|
{QMI_QUIRK_SET_DTR(0x2c7c, 0x0125, 4)}, /* Quectel EC25, EC20 R2.0 Mini PCIe */
|
|
diff --git a/drivers/net/usb/usbnet.c b/drivers/net/usb/usbnet.c
|
|
index 42baad125a7d..32fc69539126 100644
|
|
--- a/drivers/net/usb/usbnet.c
|
|
+++ b/drivers/net/usb/usbnet.c
|
|
@@ -315,6 +315,7 @@ static void __usbnet_status_stop_force(struct usbnet *dev)
|
|
void usbnet_skb_return (struct usbnet *dev, struct sk_buff *skb)
|
|
{
|
|
struct pcpu_sw_netstats *stats64 = this_cpu_ptr(dev->stats64);
|
|
+ unsigned long flags;
|
|
int status;
|
|
|
|
if (test_bit(EVENT_RX_PAUSED, &dev->flags)) {
|
|
@@ -326,10 +327,10 @@ void usbnet_skb_return (struct usbnet *dev, struct sk_buff *skb)
|
|
if (skb->protocol == 0)
|
|
skb->protocol = eth_type_trans (skb, dev->net);
|
|
|
|
- u64_stats_update_begin(&stats64->syncp);
|
|
+ flags = u64_stats_update_begin_irqsave(&stats64->syncp);
|
|
stats64->rx_packets++;
|
|
stats64->rx_bytes += skb->len;
|
|
- u64_stats_update_end(&stats64->syncp);
|
|
+ u64_stats_update_end_irqrestore(&stats64->syncp, flags);
|
|
|
|
netif_dbg(dev, rx_status, dev->net, "< rx, len %zu, type 0x%x\n",
|
|
skb->len + sizeof (struct ethhdr), skb->protocol);
|
|
@@ -1250,11 +1251,12 @@ static void tx_complete (struct urb *urb)
|
|
|
|
if (urb->status == 0) {
|
|
struct pcpu_sw_netstats *stats64 = this_cpu_ptr(dev->stats64);
|
|
+ unsigned long flags;
|
|
|
|
- u64_stats_update_begin(&stats64->syncp);
|
|
+ flags = u64_stats_update_begin_irqsave(&stats64->syncp);
|
|
stats64->tx_packets += entry->packets;
|
|
stats64->tx_bytes += entry->length;
|
|
- u64_stats_update_end(&stats64->syncp);
|
|
+ u64_stats_update_end_irqrestore(&stats64->syncp, flags);
|
|
} else {
|
|
dev->net->stats.tx_errors++;
|
|
|
|
diff --git a/drivers/net/vmxnet3/vmxnet3_drv.c b/drivers/net/vmxnet3/vmxnet3_drv.c
|
|
index cf95290b160c..3628fd7e606f 100644
|
|
--- a/drivers/net/vmxnet3/vmxnet3_drv.c
|
|
+++ b/drivers/net/vmxnet3/vmxnet3_drv.c
|
|
@@ -369,6 +369,11 @@ vmxnet3_tq_tx_complete(struct vmxnet3_tx_queue *tq,
|
|
|
|
gdesc = tq->comp_ring.base + tq->comp_ring.next2proc;
|
|
while (VMXNET3_TCD_GET_GEN(&gdesc->tcd) == tq->comp_ring.gen) {
|
|
+ /* Prevent any &gdesc->tcd field from being (speculatively)
|
|
+ * read before (&gdesc->tcd)->gen is read.
|
|
+ */
|
|
+ dma_rmb();
|
|
+
|
|
completed += vmxnet3_unmap_pkt(VMXNET3_TCD_GET_TXIDX(
|
|
&gdesc->tcd), tq, adapter->pdev,
|
|
adapter);
|
|
@@ -1099,6 +1104,11 @@ vmxnet3_tq_xmit(struct sk_buff *skb, struct vmxnet3_tx_queue *tq,
|
|
gdesc->txd.tci = skb_vlan_tag_get(skb);
|
|
}
|
|
|
|
+ /* Ensure that the write to (&gdesc->txd)->gen will be observed after
|
|
+ * all other writes to &gdesc->txd.
|
|
+ */
|
|
+ dma_wmb();
|
|
+
|
|
/* finally flips the GEN bit of the SOP desc. */
|
|
gdesc->dword[2] = cpu_to_le32(le32_to_cpu(gdesc->dword[2]) ^
|
|
VMXNET3_TXD_GEN);
|
|
@@ -1286,6 +1296,12 @@ vmxnet3_rq_rx_complete(struct vmxnet3_rx_queue *rq,
|
|
*/
|
|
break;
|
|
}
|
|
+
|
|
+ /* Prevent any rcd field from being (speculatively) read before
|
|
+ * rcd->gen is read.
|
|
+ */
|
|
+ dma_rmb();
|
|
+
|
|
BUG_ON(rcd->rqID != rq->qid && rcd->rqID != rq->qid2 &&
|
|
rcd->rqID != rq->dataRingQid);
|
|
idx = rcd->rxdIdx;
|
|
@@ -1515,6 +1531,12 @@ vmxnet3_rq_rx_complete(struct vmxnet3_rx_queue *rq,
|
|
ring->next2comp = idx;
|
|
num_to_alloc = vmxnet3_cmd_ring_desc_avail(ring);
|
|
ring = rq->rx_ring + ring_idx;
|
|
+
|
|
+ /* Ensure that the writes to rxd->gen bits will be observed
|
|
+ * after all other writes to rxd objects.
|
|
+ */
|
|
+ dma_wmb();
|
|
+
|
|
while (num_to_alloc) {
|
|
vmxnet3_getRxDesc(rxd, &ring->base[ring->next2fill].rxd,
|
|
&rxCmdDesc);
|
|
@@ -2675,7 +2697,7 @@ vmxnet3_set_mac_addr(struct net_device *netdev, void *p)
|
|
/* ==================== initialization and cleanup routines ============ */
|
|
|
|
static int
|
|
-vmxnet3_alloc_pci_resources(struct vmxnet3_adapter *adapter, bool *dma64)
|
|
+vmxnet3_alloc_pci_resources(struct vmxnet3_adapter *adapter)
|
|
{
|
|
int err;
|
|
unsigned long mmio_start, mmio_len;
|
|
@@ -2687,30 +2709,12 @@ vmxnet3_alloc_pci_resources(struct vmxnet3_adapter *adapter, bool *dma64)
|
|
return err;
|
|
}
|
|
|
|
- if (pci_set_dma_mask(pdev, DMA_BIT_MASK(64)) == 0) {
|
|
- if (pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64)) != 0) {
|
|
- dev_err(&pdev->dev,
|
|
- "pci_set_consistent_dma_mask failed\n");
|
|
- err = -EIO;
|
|
- goto err_set_mask;
|
|
- }
|
|
- *dma64 = true;
|
|
- } else {
|
|
- if (pci_set_dma_mask(pdev, DMA_BIT_MASK(32)) != 0) {
|
|
- dev_err(&pdev->dev,
|
|
- "pci_set_dma_mask failed\n");
|
|
- err = -EIO;
|
|
- goto err_set_mask;
|
|
- }
|
|
- *dma64 = false;
|
|
- }
|
|
-
|
|
err = pci_request_selected_regions(pdev, (1 << 2) - 1,
|
|
vmxnet3_driver_name);
|
|
if (err) {
|
|
dev_err(&pdev->dev,
|
|
"Failed to request region for adapter: error %d\n", err);
|
|
- goto err_set_mask;
|
|
+ goto err_enable_device;
|
|
}
|
|
|
|
pci_set_master(pdev);
|
|
@@ -2738,7 +2742,7 @@ vmxnet3_alloc_pci_resources(struct vmxnet3_adapter *adapter, bool *dma64)
|
|
iounmap(adapter->hw_addr0);
|
|
err_ioremap:
|
|
pci_release_selected_regions(pdev, (1 << 2) - 1);
|
|
-err_set_mask:
|
|
+err_enable_device:
|
|
pci_disable_device(pdev);
|
|
return err;
|
|
}
|
|
@@ -3243,7 +3247,7 @@ vmxnet3_probe_device(struct pci_dev *pdev,
|
|
#endif
|
|
};
|
|
int err;
|
|
- bool dma64 = false; /* stupid gcc */
|
|
+ bool dma64;
|
|
u32 ver;
|
|
struct net_device *netdev;
|
|
struct vmxnet3_adapter *adapter;
|
|
@@ -3289,6 +3293,24 @@ vmxnet3_probe_device(struct pci_dev *pdev,
|
|
adapter->rx_ring_size = VMXNET3_DEF_RX_RING_SIZE;
|
|
adapter->rx_ring2_size = VMXNET3_DEF_RX_RING2_SIZE;
|
|
|
|
+ if (pci_set_dma_mask(pdev, DMA_BIT_MASK(64)) == 0) {
|
|
+ if (pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64)) != 0) {
|
|
+ dev_err(&pdev->dev,
|
|
+ "pci_set_consistent_dma_mask failed\n");
|
|
+ err = -EIO;
|
|
+ goto err_set_mask;
|
|
+ }
|
|
+ dma64 = true;
|
|
+ } else {
|
|
+ if (pci_set_dma_mask(pdev, DMA_BIT_MASK(32)) != 0) {
|
|
+ dev_err(&pdev->dev,
|
|
+ "pci_set_dma_mask failed\n");
|
|
+ err = -EIO;
|
|
+ goto err_set_mask;
|
|
+ }
|
|
+ dma64 = false;
|
|
+ }
|
|
+
|
|
spin_lock_init(&adapter->cmd_lock);
|
|
adapter->adapter_pa = dma_map_single(&adapter->pdev->dev, adapter,
|
|
sizeof(struct vmxnet3_adapter),
|
|
@@ -3296,7 +3318,7 @@ vmxnet3_probe_device(struct pci_dev *pdev,
|
|
if (dma_mapping_error(&adapter->pdev->dev, adapter->adapter_pa)) {
|
|
dev_err(&pdev->dev, "Failed to map dma\n");
|
|
err = -EFAULT;
|
|
- goto err_dma_map;
|
|
+ goto err_set_mask;
|
|
}
|
|
adapter->shared = dma_alloc_coherent(
|
|
&adapter->pdev->dev,
|
|
@@ -3347,7 +3369,7 @@ vmxnet3_probe_device(struct pci_dev *pdev,
|
|
}
|
|
#endif /* VMXNET3_RSS */
|
|
|
|
- err = vmxnet3_alloc_pci_resources(adapter, &dma64);
|
|
+ err = vmxnet3_alloc_pci_resources(adapter);
|
|
if (err < 0)
|
|
goto err_alloc_pci;
|
|
|
|
@@ -3493,7 +3515,7 @@ vmxnet3_probe_device(struct pci_dev *pdev,
|
|
err_alloc_shared:
|
|
dma_unmap_single(&adapter->pdev->dev, adapter->adapter_pa,
|
|
sizeof(struct vmxnet3_adapter), PCI_DMA_TODEVICE);
|
|
-err_dma_map:
|
|
+err_set_mask:
|
|
free_netdev(netdev);
|
|
return err;
|
|
}
|
|
diff --git a/drivers/rtc/hctosys.c b/drivers/rtc/hctosys.c
|
|
index e1cfa06810ef..e79f2a181ad2 100644
|
|
--- a/drivers/rtc/hctosys.c
|
|
+++ b/drivers/rtc/hctosys.c
|
|
@@ -49,6 +49,11 @@ static int __init rtc_hctosys(void)
|
|
|
|
tv64.tv_sec = rtc_tm_to_time64(&tm);
|
|
|
|
+#if BITS_PER_LONG == 32
|
|
+ if (tv64.tv_sec > INT_MAX)
|
|
+ goto err_read;
|
|
+#endif
|
|
+
|
|
err = do_settimeofday64(&tv64);
|
|
|
|
dev_info(rtc->dev.parent,
|
|
diff --git a/drivers/rtc/rtc-goldfish.c b/drivers/rtc/rtc-goldfish.c
|
|
index d67769265185..a1c44d0c8557 100644
|
|
--- a/drivers/rtc/rtc-goldfish.c
|
|
+++ b/drivers/rtc/rtc-goldfish.c
|
|
@@ -235,3 +235,5 @@ static struct platform_driver goldfish_rtc = {
|
|
};
|
|
|
|
module_platform_driver(goldfish_rtc);
|
|
+
|
|
+MODULE_LICENSE("GPL v2");
|
|
diff --git a/drivers/rtc/rtc-m41t80.c b/drivers/rtc/rtc-m41t80.c
|
|
index c90fba3ed861..6620016869cf 100644
|
|
--- a/drivers/rtc/rtc-m41t80.c
|
|
+++ b/drivers/rtc/rtc-m41t80.c
|
|
@@ -885,7 +885,6 @@ static int m41t80_probe(struct i2c_client *client,
|
|
{
|
|
struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);
|
|
int rc = 0;
|
|
- struct rtc_device *rtc = NULL;
|
|
struct rtc_time tm;
|
|
struct m41t80_data *m41t80_data = NULL;
|
|
bool wakeup_source = false;
|
|
@@ -909,6 +908,10 @@ static int m41t80_probe(struct i2c_client *client,
|
|
m41t80_data->features = id->driver_data;
|
|
i2c_set_clientdata(client, m41t80_data);
|
|
|
|
+ m41t80_data->rtc = devm_rtc_allocate_device(&client->dev);
|
|
+ if (IS_ERR(m41t80_data->rtc))
|
|
+ return PTR_ERR(m41t80_data->rtc);
|
|
+
|
|
#ifdef CONFIG_OF
|
|
wakeup_source = of_property_read_bool(client->dev.of_node,
|
|
"wakeup-source");
|
|
@@ -932,15 +935,11 @@ static int m41t80_probe(struct i2c_client *client,
|
|
device_init_wakeup(&client->dev, true);
|
|
}
|
|
|
|
- rtc = devm_rtc_device_register(&client->dev, client->name,
|
|
- &m41t80_rtc_ops, THIS_MODULE);
|
|
- if (IS_ERR(rtc))
|
|
- return PTR_ERR(rtc);
|
|
+ m41t80_data->rtc->ops = &m41t80_rtc_ops;
|
|
|
|
- m41t80_data->rtc = rtc;
|
|
if (client->irq <= 0) {
|
|
/* We cannot support UIE mode if we do not have an IRQ line */
|
|
- rtc->uie_unsupported = 1;
|
|
+ m41t80_data->rtc->uie_unsupported = 1;
|
|
}
|
|
|
|
/* Make sure HT (Halt Update) bit is cleared */
|
|
@@ -993,6 +992,11 @@ static int m41t80_probe(struct i2c_client *client,
|
|
if (m41t80_data->features & M41T80_FEATURE_SQ)
|
|
m41t80_sqw_register_clk(m41t80_data);
|
|
#endif
|
|
+
|
|
+ rc = rtc_register_device(m41t80_data->rtc);
|
|
+ if (rc)
|
|
+ return rc;
|
|
+
|
|
return 0;
|
|
}
|
|
|
|
diff --git a/drivers/rtc/rtc-rk808.c b/drivers/rtc/rtc-rk808.c
|
|
index 35c9aada07c8..79c8da54e922 100644
|
|
--- a/drivers/rtc/rtc-rk808.c
|
|
+++ b/drivers/rtc/rtc-rk808.c
|
|
@@ -416,12 +416,11 @@ static int rk808_rtc_probe(struct platform_device *pdev)
|
|
|
|
device_init_wakeup(&pdev->dev, 1);
|
|
|
|
- rk808_rtc->rtc = devm_rtc_device_register(&pdev->dev, "rk808-rtc",
|
|
- &rk808_rtc_ops, THIS_MODULE);
|
|
- if (IS_ERR(rk808_rtc->rtc)) {
|
|
- ret = PTR_ERR(rk808_rtc->rtc);
|
|
- return ret;
|
|
- }
|
|
+ rk808_rtc->rtc = devm_rtc_allocate_device(&pdev->dev);
|
|
+ if (IS_ERR(rk808_rtc->rtc))
|
|
+ return PTR_ERR(rk808_rtc->rtc);
|
|
+
|
|
+ rk808_rtc->rtc->ops = &rk808_rtc_ops;
|
|
|
|
rk808_rtc->irq = platform_get_irq(pdev, 0);
|
|
if (rk808_rtc->irq < 0) {
|
|
@@ -438,9 +437,10 @@ static int rk808_rtc_probe(struct platform_device *pdev)
|
|
if (ret) {
|
|
dev_err(&pdev->dev, "Failed to request alarm IRQ %d: %d\n",
|
|
rk808_rtc->irq, ret);
|
|
+ return ret;
|
|
}
|
|
|
|
- return ret;
|
|
+ return rtc_register_device(rk808_rtc->rtc);
|
|
}
|
|
|
|
static struct platform_driver rk808_rtc_driver = {
|
|
diff --git a/drivers/rtc/rtc-rp5c01.c b/drivers/rtc/rtc-rp5c01.c
|
|
index 026035373ae6..38a12435b5a0 100644
|
|
--- a/drivers/rtc/rtc-rp5c01.c
|
|
+++ b/drivers/rtc/rtc-rp5c01.c
|
|
@@ -249,16 +249,24 @@ static int __init rp5c01_rtc_probe(struct platform_device *dev)
|
|
|
|
platform_set_drvdata(dev, priv);
|
|
|
|
- rtc = devm_rtc_device_register(&dev->dev, "rtc-rp5c01", &rp5c01_rtc_ops,
|
|
- THIS_MODULE);
|
|
+ rtc = devm_rtc_allocate_device(&dev->dev);
|
|
if (IS_ERR(rtc))
|
|
return PTR_ERR(rtc);
|
|
+
|
|
+ rtc->ops = &rp5c01_rtc_ops;
|
|
+
|
|
priv->rtc = rtc;
|
|
|
|
error = sysfs_create_bin_file(&dev->dev.kobj, &priv->nvram_attr);
|
|
if (error)
|
|
return error;
|
|
|
|
+ error = rtc_register_device(rtc);
|
|
+ if (error) {
|
|
+ sysfs_remove_bin_file(&dev->dev.kobj, &priv->nvram_attr);
|
|
+ return error;
|
|
+ }
|
|
+
|
|
return 0;
|
|
}
|
|
|
|
diff --git a/drivers/rtc/rtc-snvs.c b/drivers/rtc/rtc-snvs.c
|
|
index d8ef9e052c4f..9af591d5223c 100644
|
|
--- a/drivers/rtc/rtc-snvs.c
|
|
+++ b/drivers/rtc/rtc-snvs.c
|
|
@@ -132,20 +132,23 @@ static int snvs_rtc_set_time(struct device *dev, struct rtc_time *tm)
|
|
{
|
|
struct snvs_rtc_data *data = dev_get_drvdata(dev);
|
|
unsigned long time;
|
|
+ int ret;
|
|
|
|
rtc_tm_to_time(tm, &time);
|
|
|
|
/* Disable RTC first */
|
|
- snvs_rtc_enable(data, false);
|
|
+ ret = snvs_rtc_enable(data, false);
|
|
+ if (ret)
|
|
+ return ret;
|
|
|
|
/* Write 32-bit time to 47-bit timer, leaving 15 LSBs blank */
|
|
regmap_write(data->regmap, data->offset + SNVS_LPSRTCLR, time << CNTR_TO_SECS_SH);
|
|
regmap_write(data->regmap, data->offset + SNVS_LPSRTCMR, time >> (32 - CNTR_TO_SECS_SH));
|
|
|
|
/* Enable RTC again */
|
|
- snvs_rtc_enable(data, true);
|
|
+ ret = snvs_rtc_enable(data, true);
|
|
|
|
- return 0;
|
|
+ return ret;
|
|
}
|
|
|
|
static int snvs_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
|
|
@@ -288,7 +291,11 @@ static int snvs_rtc_probe(struct platform_device *pdev)
|
|
regmap_write(data->regmap, data->offset + SNVS_LPSR, 0xffffffff);
|
|
|
|
/* Enable RTC */
|
|
- snvs_rtc_enable(data, true);
|
|
+ ret = snvs_rtc_enable(data, true);
|
|
+ if (ret) {
|
|
+ dev_err(&pdev->dev, "failed to enable rtc %d\n", ret);
|
|
+ goto error_rtc_device_register;
|
|
+ }
|
|
|
|
device_init_wakeup(&pdev->dev, true);
|
|
|
|
diff --git a/drivers/rtc/rtc-tx4939.c b/drivers/rtc/rtc-tx4939.c
|
|
index 560d9a5e0225..a9528083061d 100644
|
|
--- a/drivers/rtc/rtc-tx4939.c
|
|
+++ b/drivers/rtc/rtc-tx4939.c
|
|
@@ -86,7 +86,8 @@ static int tx4939_rtc_read_time(struct device *dev, struct rtc_time *tm)
|
|
for (i = 2; i < 6; i++)
|
|
buf[i] = __raw_readl(&rtcreg->dat);
|
|
spin_unlock_irq(&pdata->lock);
|
|
- sec = (buf[5] << 24) | (buf[4] << 16) | (buf[3] << 8) | buf[2];
|
|
+ sec = ((unsigned long)buf[5] << 24) | (buf[4] << 16) |
|
|
+ (buf[3] << 8) | buf[2];
|
|
rtc_time_to_tm(sec, tm);
|
|
return rtc_valid_tm(tm);
|
|
}
|
|
@@ -147,7 +148,8 @@ static int tx4939_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
|
|
alrm->enabled = (ctl & TX4939_RTCCTL_ALME) ? 1 : 0;
|
|
alrm->pending = (ctl & TX4939_RTCCTL_ALMD) ? 1 : 0;
|
|
spin_unlock_irq(&pdata->lock);
|
|
- sec = (buf[5] << 24) | (buf[4] << 16) | (buf[3] << 8) | buf[2];
|
|
+ sec = ((unsigned long)buf[5] << 24) | (buf[4] << 16) |
|
|
+ (buf[3] << 8) | buf[2];
|
|
rtc_time_to_tm(sec, &alrm->time);
|
|
return rtc_valid_tm(&alrm->time);
|
|
}
|
|
diff --git a/drivers/s390/scsi/zfcp_dbf.c b/drivers/s390/scsi/zfcp_dbf.c
|
|
index a8b831000b2d..18c4f933e8b9 100644
|
|
--- a/drivers/s390/scsi/zfcp_dbf.c
|
|
+++ b/drivers/s390/scsi/zfcp_dbf.c
|
|
@@ -4,7 +4,7 @@
|
|
*
|
|
* Debug traces for zfcp.
|
|
*
|
|
- * Copyright IBM Corp. 2002, 2017
|
|
+ * Copyright IBM Corp. 2002, 2018
|
|
*/
|
|
|
|
#define KMSG_COMPONENT "zfcp"
|
|
@@ -308,6 +308,27 @@ void zfcp_dbf_rec_trig(char *tag, struct zfcp_adapter *adapter,
|
|
spin_unlock_irqrestore(&dbf->rec_lock, flags);
|
|
}
|
|
|
|
+/**
|
|
+ * zfcp_dbf_rec_trig_lock - trace event related to triggered recovery with lock
|
|
+ * @tag: identifier for event
|
|
+ * @adapter: adapter on which the erp_action should run
|
|
+ * @port: remote port involved in the erp_action
|
|
+ * @sdev: scsi device involved in the erp_action
|
|
+ * @want: wanted erp_action
|
|
+ * @need: required erp_action
|
|
+ *
|
|
+ * The adapter->erp_lock must not be held.
|
|
+ */
|
|
+void zfcp_dbf_rec_trig_lock(char *tag, struct zfcp_adapter *adapter,
|
|
+ struct zfcp_port *port, struct scsi_device *sdev,
|
|
+ u8 want, u8 need)
|
|
+{
|
|
+ unsigned long flags;
|
|
+
|
|
+ read_lock_irqsave(&adapter->erp_lock, flags);
|
|
+ zfcp_dbf_rec_trig(tag, adapter, port, sdev, want, need);
|
|
+ read_unlock_irqrestore(&adapter->erp_lock, flags);
|
|
+}
|
|
|
|
/**
|
|
* zfcp_dbf_rec_run_lvl - trace event related to running recovery
|
|
diff --git a/drivers/s390/scsi/zfcp_ext.h b/drivers/s390/scsi/zfcp_ext.h
|
|
index 8ca2ab7deaa9..b1cbb14fb2ae 100644
|
|
--- a/drivers/s390/scsi/zfcp_ext.h
|
|
+++ b/drivers/s390/scsi/zfcp_ext.h
|
|
@@ -4,7 +4,7 @@
|
|
*
|
|
* External function declarations.
|
|
*
|
|
- * Copyright IBM Corp. 2002, 2016
|
|
+ * Copyright IBM Corp. 2002, 2018
|
|
*/
|
|
|
|
#ifndef ZFCP_EXT_H
|
|
@@ -35,6 +35,9 @@ extern int zfcp_dbf_adapter_register(struct zfcp_adapter *);
|
|
extern void zfcp_dbf_adapter_unregister(struct zfcp_adapter *);
|
|
extern void zfcp_dbf_rec_trig(char *, struct zfcp_adapter *,
|
|
struct zfcp_port *, struct scsi_device *, u8, u8);
|
|
+extern void zfcp_dbf_rec_trig_lock(char *tag, struct zfcp_adapter *adapter,
|
|
+ struct zfcp_port *port,
|
|
+ struct scsi_device *sdev, u8 want, u8 need);
|
|
extern void zfcp_dbf_rec_run(char *, struct zfcp_erp_action *);
|
|
extern void zfcp_dbf_rec_run_lvl(int level, char *tag,
|
|
struct zfcp_erp_action *erp);
|
|
diff --git a/drivers/s390/scsi/zfcp_scsi.c b/drivers/s390/scsi/zfcp_scsi.c
|
|
index 4d2ba5682493..22f9562f415c 100644
|
|
--- a/drivers/s390/scsi/zfcp_scsi.c
|
|
+++ b/drivers/s390/scsi/zfcp_scsi.c
|
|
@@ -4,7 +4,7 @@
|
|
*
|
|
* Interface to Linux SCSI midlayer.
|
|
*
|
|
- * Copyright IBM Corp. 2002, 2017
|
|
+ * Copyright IBM Corp. 2002, 2018
|
|
*/
|
|
|
|
#define KMSG_COMPONENT "zfcp"
|
|
@@ -618,9 +618,9 @@ static void zfcp_scsi_rport_register(struct zfcp_port *port)
|
|
ids.port_id = port->d_id;
|
|
ids.roles = FC_RPORT_ROLE_FCP_TARGET;
|
|
|
|
- zfcp_dbf_rec_trig("scpaddy", port->adapter, port, NULL,
|
|
- ZFCP_PSEUDO_ERP_ACTION_RPORT_ADD,
|
|
- ZFCP_PSEUDO_ERP_ACTION_RPORT_ADD);
|
|
+ zfcp_dbf_rec_trig_lock("scpaddy", port->adapter, port, NULL,
|
|
+ ZFCP_PSEUDO_ERP_ACTION_RPORT_ADD,
|
|
+ ZFCP_PSEUDO_ERP_ACTION_RPORT_ADD);
|
|
rport = fc_remote_port_add(port->adapter->scsi_host, 0, &ids);
|
|
if (!rport) {
|
|
dev_err(&port->adapter->ccw_device->dev,
|
|
@@ -642,9 +642,9 @@ static void zfcp_scsi_rport_block(struct zfcp_port *port)
|
|
struct fc_rport *rport = port->rport;
|
|
|
|
if (rport) {
|
|
- zfcp_dbf_rec_trig("scpdely", port->adapter, port, NULL,
|
|
- ZFCP_PSEUDO_ERP_ACTION_RPORT_DEL,
|
|
- ZFCP_PSEUDO_ERP_ACTION_RPORT_DEL);
|
|
+ zfcp_dbf_rec_trig_lock("scpdely", port->adapter, port, NULL,
|
|
+ ZFCP_PSEUDO_ERP_ACTION_RPORT_DEL,
|
|
+ ZFCP_PSEUDO_ERP_ACTION_RPORT_DEL);
|
|
fc_remote_port_delete(rport);
|
|
port->rport = NULL;
|
|
}
|
|
diff --git a/drivers/scsi/aacraid/commsup.c b/drivers/scsi/aacraid/commsup.c
|
|
index 3696f9ded252..998788a967be 100644
|
|
--- a/drivers/scsi/aacraid/commsup.c
|
|
+++ b/drivers/scsi/aacraid/commsup.c
|
|
@@ -1530,9 +1530,10 @@ static int _aac_reset_adapter(struct aac_dev *aac, int forced, u8 reset_type)
|
|
host = aac->scsi_host_ptr;
|
|
scsi_block_requests(host);
|
|
aac_adapter_disable_int(aac);
|
|
- if (aac->thread->pid != current->pid) {
|
|
+ if (aac->thread && aac->thread->pid != current->pid) {
|
|
spin_unlock_irq(host->host_lock);
|
|
kthread_stop(aac->thread);
|
|
+ aac->thread = NULL;
|
|
jafo = 1;
|
|
}
|
|
|
|
@@ -1619,6 +1620,7 @@ static int _aac_reset_adapter(struct aac_dev *aac, int forced, u8 reset_type)
|
|
aac->name);
|
|
if (IS_ERR(aac->thread)) {
|
|
retval = PTR_ERR(aac->thread);
|
|
+ aac->thread = NULL;
|
|
goto out;
|
|
}
|
|
}
|
|
diff --git a/drivers/scsi/aacraid/linit.c b/drivers/scsi/aacraid/linit.c
|
|
index 509fe23fafe1..4917649cacd5 100644
|
|
--- a/drivers/scsi/aacraid/linit.c
|
|
+++ b/drivers/scsi/aacraid/linit.c
|
|
@@ -1565,6 +1565,7 @@ static void __aac_shutdown(struct aac_dev * aac)
|
|
up(&fib->event_wait);
|
|
}
|
|
kthread_stop(aac->thread);
|
|
+ aac->thread = NULL;
|
|
}
|
|
|
|
aac_send_shutdown(aac);
|
|
@@ -1690,8 +1691,10 @@ static int aac_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
|
|
* Map in the registers from the adapter.
|
|
*/
|
|
aac->base_size = AAC_MIN_FOOTPRINT_SIZE;
|
|
- if ((*aac_drivers[index].init)(aac))
|
|
+ if ((*aac_drivers[index].init)(aac)) {
|
|
+ error = -ENODEV;
|
|
goto out_unmap;
|
|
+ }
|
|
|
|
if (aac->sync_mode) {
|
|
if (aac_sync_mode)
|
|
diff --git a/drivers/scsi/bnx2fc/bnx2fc_io.c b/drivers/scsi/bnx2fc/bnx2fc_io.c
|
|
index 5b6153f23f01..6626b28ba8fe 100644
|
|
--- a/drivers/scsi/bnx2fc/bnx2fc_io.c
|
|
+++ b/drivers/scsi/bnx2fc/bnx2fc_io.c
|
|
@@ -1865,6 +1865,7 @@ void bnx2fc_process_scsi_cmd_compl(struct bnx2fc_cmd *io_req,
|
|
/* we will not receive ABTS response for this IO */
|
|
BNX2FC_IO_DBG(io_req, "Timer context finished processing "
|
|
"this scsi cmd\n");
|
|
+ return;
|
|
}
|
|
|
|
/* Cancel the timeout_work, as we received IO completion */
|
|
diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c
|
|
index 4d934d6c3e13..e11eff6b0e97 100644
|
|
--- a/drivers/scsi/iscsi_tcp.c
|
|
+++ b/drivers/scsi/iscsi_tcp.c
|
|
@@ -37,6 +37,7 @@
|
|
#include <linux/kfifo.h>
|
|
#include <linux/scatterlist.h>
|
|
#include <linux/module.h>
|
|
+#include <linux/backing-dev.h>
|
|
#include <net/tcp.h>
|
|
#include <scsi/scsi_cmnd.h>
|
|
#include <scsi/scsi_device.h>
|
|
@@ -952,6 +953,13 @@ static int iscsi_sw_tcp_slave_alloc(struct scsi_device *sdev)
|
|
|
|
static int iscsi_sw_tcp_slave_configure(struct scsi_device *sdev)
|
|
{
|
|
+ struct iscsi_sw_tcp_host *tcp_sw_host = iscsi_host_priv(sdev->host);
|
|
+ struct iscsi_session *session = tcp_sw_host->session;
|
|
+ struct iscsi_conn *conn = session->leadconn;
|
|
+
|
|
+ if (conn->datadgst_en)
|
|
+ sdev->request_queue->backing_dev_info->capabilities
|
|
+ |= BDI_CAP_STABLE_WRITES;
|
|
blk_queue_bounce_limit(sdev->request_queue, BLK_BOUNCE_ANY);
|
|
blk_queue_dma_alignment(sdev->request_queue, 0);
|
|
return 0;
|
|
diff --git a/drivers/scsi/libsas/sas_scsi_host.c b/drivers/scsi/libsas/sas_scsi_host.c
|
|
index 10b17da20176..0c4b186c852a 100644
|
|
--- a/drivers/scsi/libsas/sas_scsi_host.c
|
|
+++ b/drivers/scsi/libsas/sas_scsi_host.c
|
|
@@ -222,6 +222,7 @@ int sas_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *cmd)
|
|
static void sas_eh_finish_cmd(struct scsi_cmnd *cmd)
|
|
{
|
|
struct sas_ha_struct *sas_ha = SHOST_TO_SAS_HA(cmd->device->host);
|
|
+ struct domain_device *dev = cmd_to_domain_dev(cmd);
|
|
struct sas_task *task = TO_SAS_TASK(cmd);
|
|
|
|
/* At this point, we only get called following an actual abort
|
|
@@ -230,6 +231,14 @@ static void sas_eh_finish_cmd(struct scsi_cmnd *cmd)
|
|
*/
|
|
sas_end_task(cmd, task);
|
|
|
|
+ if (dev_is_sata(dev)) {
|
|
+ /* defer commands to libata so that libata EH can
|
|
+ * handle ata qcs correctly
|
|
+ */
|
|
+ list_move_tail(&cmd->eh_entry, &sas_ha->eh_ata_q);
|
|
+ return;
|
|
+ }
|
|
+
|
|
/* now finish the command and move it on to the error
|
|
* handler done list, this also takes it off the
|
|
* error handler pending list.
|
|
@@ -237,22 +246,6 @@ static void sas_eh_finish_cmd(struct scsi_cmnd *cmd)
|
|
scsi_eh_finish_cmd(cmd, &sas_ha->eh_done_q);
|
|
}
|
|
|
|
-static void sas_eh_defer_cmd(struct scsi_cmnd *cmd)
|
|
-{
|
|
- struct domain_device *dev = cmd_to_domain_dev(cmd);
|
|
- struct sas_ha_struct *ha = dev->port->ha;
|
|
- struct sas_task *task = TO_SAS_TASK(cmd);
|
|
-
|
|
- if (!dev_is_sata(dev)) {
|
|
- sas_eh_finish_cmd(cmd);
|
|
- return;
|
|
- }
|
|
-
|
|
- /* report the timeout to libata */
|
|
- sas_end_task(cmd, task);
|
|
- list_move_tail(&cmd->eh_entry, &ha->eh_ata_q);
|
|
-}
|
|
-
|
|
static void sas_scsi_clear_queue_lu(struct list_head *error_q, struct scsi_cmnd *my_cmd)
|
|
{
|
|
struct scsi_cmnd *cmd, *n;
|
|
@@ -260,7 +253,7 @@ static void sas_scsi_clear_queue_lu(struct list_head *error_q, struct scsi_cmnd
|
|
list_for_each_entry_safe(cmd, n, error_q, eh_entry) {
|
|
if (cmd->device->sdev_target == my_cmd->device->sdev_target &&
|
|
cmd->device->lun == my_cmd->device->lun)
|
|
- sas_eh_defer_cmd(cmd);
|
|
+ sas_eh_finish_cmd(cmd);
|
|
}
|
|
}
|
|
|
|
@@ -630,12 +623,12 @@ static void sas_eh_handle_sas_errors(struct Scsi_Host *shost, struct list_head *
|
|
case TASK_IS_DONE:
|
|
SAS_DPRINTK("%s: task 0x%p is done\n", __func__,
|
|
task);
|
|
- sas_eh_defer_cmd(cmd);
|
|
+ sas_eh_finish_cmd(cmd);
|
|
continue;
|
|
case TASK_IS_ABORTED:
|
|
SAS_DPRINTK("%s: task 0x%p is aborted\n",
|
|
__func__, task);
|
|
- sas_eh_defer_cmd(cmd);
|
|
+ sas_eh_finish_cmd(cmd);
|
|
continue;
|
|
case TASK_IS_AT_LU:
|
|
SAS_DPRINTK("task 0x%p is at LU: lu recover\n", task);
|
|
@@ -646,7 +639,7 @@ static void sas_eh_handle_sas_errors(struct Scsi_Host *shost, struct list_head *
|
|
"recovered\n",
|
|
SAS_ADDR(task->dev),
|
|
cmd->device->lun);
|
|
- sas_eh_defer_cmd(cmd);
|
|
+ sas_eh_finish_cmd(cmd);
|
|
sas_scsi_clear_queue_lu(work_q, cmd);
|
|
goto Again;
|
|
}
|
|
diff --git a/drivers/scsi/lpfc/lpfc_attr.c b/drivers/scsi/lpfc/lpfc_attr.c
|
|
index dc6519b2c53a..3da242201cb4 100644
|
|
--- a/drivers/scsi/lpfc/lpfc_attr.c
|
|
+++ b/drivers/scsi/lpfc/lpfc_attr.c
|
|
@@ -871,7 +871,12 @@ lpfc_issue_lip(struct Scsi_Host *shost)
|
|
LPFC_MBOXQ_t *pmboxq;
|
|
int mbxstatus = MBXERR_ERROR;
|
|
|
|
+ /*
|
|
+ * If the link is offline, disabled or BLOCK_MGMT_IO
|
|
+ * it doesn't make any sense to allow issue_lip
|
|
+ */
|
|
if ((vport->fc_flag & FC_OFFLINE_MODE) ||
|
|
+ (phba->hba_flag & LINK_DISABLED) ||
|
|
(phba->sli.sli_flag & LPFC_BLOCK_MGMT_IO))
|
|
return -EPERM;
|
|
|
|
diff --git a/drivers/scsi/lpfc/lpfc_hbadisc.c b/drivers/scsi/lpfc/lpfc_hbadisc.c
|
|
index d9a03beb76a4..4962d665b4d2 100644
|
|
--- a/drivers/scsi/lpfc/lpfc_hbadisc.c
|
|
+++ b/drivers/scsi/lpfc/lpfc_hbadisc.c
|
|
@@ -698,8 +698,9 @@ lpfc_work_done(struct lpfc_hba *phba)
|
|
phba->hba_flag & HBA_SP_QUEUE_EVT)) {
|
|
if (pring->flag & LPFC_STOP_IOCB_EVENT) {
|
|
pring->flag |= LPFC_DEFERRED_RING_EVENT;
|
|
- /* Set the lpfc data pending flag */
|
|
- set_bit(LPFC_DATA_READY, &phba->data_flags);
|
|
+ /* Preserve legacy behavior. */
|
|
+ if (!(phba->hba_flag & HBA_SP_QUEUE_EVT))
|
|
+ set_bit(LPFC_DATA_READY, &phba->data_flags);
|
|
} else {
|
|
if (phba->link_state >= LPFC_LINK_UP ||
|
|
phba->link_flag & LS_MDS_LOOPBACK) {
|
|
diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c
|
|
index 455f3ce9fda9..dc83498024dc 100644
|
|
--- a/drivers/scsi/lpfc/lpfc_sli.c
|
|
+++ b/drivers/scsi/lpfc/lpfc_sli.c
|
|
@@ -129,6 +129,8 @@ lpfc_sli4_wq_put(struct lpfc_queue *q, union lpfc_wqe *wqe)
|
|
/* set consumption flag every once in a while */
|
|
if (!((q->host_index + 1) % q->entry_repost))
|
|
bf_set(wqe_wqec, &wqe->generic.wqe_com, 1);
|
|
+ else
|
|
+ bf_set(wqe_wqec, &wqe->generic.wqe_com, 0);
|
|
if (q->phba->sli3_options & LPFC_SLI4_PHWQ_ENABLED)
|
|
bf_set(wqe_wqid, &wqe->generic.wqe_com, q->queue_id);
|
|
lpfc_sli_pcimem_bcopy(wqe, temp_wqe, q->entry_size);
|
|
diff --git a/drivers/scsi/mpt3sas/mpt3sas_base.c b/drivers/scsi/mpt3sas/mpt3sas_base.c
|
|
index 6efa739a1912..9b716c8c558a 100644
|
|
--- a/drivers/scsi/mpt3sas/mpt3sas_base.c
|
|
+++ b/drivers/scsi/mpt3sas/mpt3sas_base.c
|
|
@@ -1921,8 +1921,11 @@ _base_assign_reply_queues(struct MPT3SAS_ADAPTER *ioc)
|
|
continue;
|
|
}
|
|
|
|
- for_each_cpu(cpu, mask)
|
|
+ for_each_cpu_and(cpu, mask, cpu_online_mask) {
|
|
+ if (cpu >= ioc->cpu_msix_table_sz)
|
|
+ break;
|
|
ioc->cpu_msix_table[cpu] = reply_q->msix_index;
|
|
+ }
|
|
}
|
|
return;
|
|
}
|
|
diff --git a/drivers/scsi/mpt3sas/mpt3sas_scsih.c b/drivers/scsi/mpt3sas/mpt3sas_scsih.c
|
|
index 139219c994e9..ae5e579ac473 100644
|
|
--- a/drivers/scsi/mpt3sas/mpt3sas_scsih.c
|
|
+++ b/drivers/scsi/mpt3sas/mpt3sas_scsih.c
|
|
@@ -8941,7 +8941,7 @@ _scsih_probe(struct pci_dev *pdev, const struct pci_device_id *id)
|
|
snprintf(ioc->firmware_event_name, sizeof(ioc->firmware_event_name),
|
|
"fw_event_%s%d", ioc->driver_name, ioc->id);
|
|
ioc->firmware_event_thread = alloc_ordered_workqueue(
|
|
- ioc->firmware_event_name, WQ_MEM_RECLAIM);
|
|
+ ioc->firmware_event_name, 0);
|
|
if (!ioc->firmware_event_thread) {
|
|
pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
|
|
ioc->name, __FILE__, __LINE__, __func__);
|
|
diff --git a/drivers/scsi/mvsas/mv_94xx.c b/drivers/scsi/mvsas/mv_94xx.c
|
|
index 7de5d8d75480..eb5471bc7263 100644
|
|
--- a/drivers/scsi/mvsas/mv_94xx.c
|
|
+++ b/drivers/scsi/mvsas/mv_94xx.c
|
|
@@ -1080,16 +1080,16 @@ static int mvs_94xx_gpio_write(struct mvs_prv_info *mvs_prv,
|
|
void __iomem *regs = mvi->regs_ex - 0x10200;
|
|
|
|
int drive = (i/3) & (4-1); /* drive number on host */
|
|
- u32 block = mr32(MVS_SGPIO_DCTRL +
|
|
+ int driveshift = drive * 8; /* bit offset of drive */
|
|
+ u32 block = ioread32be(regs + MVS_SGPIO_DCTRL +
|
|
MVS_SGPIO_HOST_OFFSET * mvi->id);
|
|
|
|
-
|
|
/*
|
|
* if bit is set then create a mask with the first
|
|
* bit of the drive set in the mask ...
|
|
*/
|
|
- u32 bit = (write_data[i/8] & (1 << (i&(8-1)))) ?
|
|
- 1<<(24-drive*8) : 0;
|
|
+ u32 bit = get_unaligned_be32(write_data) & (1 << i) ?
|
|
+ 1 << driveshift : 0;
|
|
|
|
/*
|
|
* ... and then shift it to the right position based
|
|
@@ -1098,26 +1098,27 @@ static int mvs_94xx_gpio_write(struct mvs_prv_info *mvs_prv,
|
|
switch (i%3) {
|
|
case 0: /* activity */
|
|
block &= ~((0x7 << MVS_SGPIO_DCTRL_ACT_SHIFT)
|
|
- << (24-drive*8));
|
|
+ << driveshift);
|
|
/* hardwire activity bit to SOF */
|
|
block |= LED_BLINKA_SOF << (
|
|
MVS_SGPIO_DCTRL_ACT_SHIFT +
|
|
- (24-drive*8));
|
|
+ driveshift);
|
|
break;
|
|
case 1: /* id */
|
|
block &= ~((0x3 << MVS_SGPIO_DCTRL_LOC_SHIFT)
|
|
- << (24-drive*8));
|
|
+ << driveshift);
|
|
block |= bit << MVS_SGPIO_DCTRL_LOC_SHIFT;
|
|
break;
|
|
case 2: /* fail */
|
|
block &= ~((0x7 << MVS_SGPIO_DCTRL_ERR_SHIFT)
|
|
- << (24-drive*8));
|
|
+ << driveshift);
|
|
block |= bit << MVS_SGPIO_DCTRL_ERR_SHIFT;
|
|
break;
|
|
}
|
|
|
|
- mw32(MVS_SGPIO_DCTRL + MVS_SGPIO_HOST_OFFSET * mvi->id,
|
|
- block);
|
|
+ iowrite32be(block,
|
|
+ regs + MVS_SGPIO_DCTRL +
|
|
+ MVS_SGPIO_HOST_OFFSET * mvi->id);
|
|
|
|
}
|
|
|
|
@@ -1132,7 +1133,7 @@ static int mvs_94xx_gpio_write(struct mvs_prv_info *mvs_prv,
|
|
void __iomem *regs = mvi->regs_ex - 0x10200;
|
|
|
|
mw32(MVS_SGPIO_DCTRL + MVS_SGPIO_HOST_OFFSET * mvi->id,
|
|
- be32_to_cpu(((u32 *) write_data)[i]));
|
|
+ ((u32 *) write_data)[i]);
|
|
}
|
|
return reg_count;
|
|
}
|
|
diff --git a/drivers/scsi/qedi/qedi_fw.c b/drivers/scsi/qedi/qedi_fw.c
|
|
index 93d54acd4a22..2e5e04a7623f 100644
|
|
--- a/drivers/scsi/qedi/qedi_fw.c
|
|
+++ b/drivers/scsi/qedi/qedi_fw.c
|
|
@@ -769,6 +769,11 @@ static void qedi_process_cmd_cleanup_resp(struct qedi_ctx *qedi,
|
|
|
|
iscsi_cid = cqe->conn_id;
|
|
qedi_conn = qedi->cid_que.conn_cid_tbl[iscsi_cid];
|
|
+ if (!qedi_conn) {
|
|
+ QEDI_INFO(&qedi->dbg_ctx, QEDI_LOG_INFO,
|
|
+ "icid not found 0x%x\n", cqe->conn_id);
|
|
+ return;
|
|
+ }
|
|
|
|
/* Based on this itt get the corresponding qedi_cmd */
|
|
spin_lock_bh(&qedi_conn->tmf_work_lock);
|
|
diff --git a/drivers/scsi/qedi/qedi_main.c b/drivers/scsi/qedi/qedi_main.c
|
|
index cccc34adc0e0..1573749fe615 100644
|
|
--- a/drivers/scsi/qedi/qedi_main.c
|
|
+++ b/drivers/scsi/qedi/qedi_main.c
|
|
@@ -1840,8 +1840,8 @@ static ssize_t qedi_show_boot_ini_info(void *data, int type, char *buf)
|
|
|
|
switch (type) {
|
|
case ISCSI_BOOT_INI_INITIATOR_NAME:
|
|
- rc = snprintf(str, NVM_ISCSI_CFG_ISCSI_NAME_MAX_LEN, "%s\n",
|
|
- initiator->initiator_name.byte);
|
|
+ rc = sprintf(str, "%.*s\n", NVM_ISCSI_CFG_ISCSI_NAME_MAX_LEN,
|
|
+ initiator->initiator_name.byte);
|
|
break;
|
|
default:
|
|
rc = 0;
|
|
@@ -1908,8 +1908,8 @@ qedi_show_boot_tgt_info(struct qedi_ctx *qedi, int type,
|
|
|
|
switch (type) {
|
|
case ISCSI_BOOT_TGT_NAME:
|
|
- rc = snprintf(str, NVM_ISCSI_CFG_ISCSI_NAME_MAX_LEN, "%s\n",
|
|
- block->target[idx].target_name.byte);
|
|
+ rc = sprintf(str, "%.*s\n", NVM_ISCSI_CFG_ISCSI_NAME_MAX_LEN,
|
|
+ block->target[idx].target_name.byte);
|
|
break;
|
|
case ISCSI_BOOT_TGT_IP_ADDR:
|
|
if (ipv6_en)
|
|
@@ -1930,20 +1930,20 @@ qedi_show_boot_tgt_info(struct qedi_ctx *qedi, int type,
|
|
block->target[idx].lun.value[0]);
|
|
break;
|
|
case ISCSI_BOOT_TGT_CHAP_NAME:
|
|
- rc = snprintf(str, NVM_ISCSI_CFG_CHAP_NAME_MAX_LEN, "%s\n",
|
|
- chap_name);
|
|
+ rc = sprintf(str, "%.*s\n", NVM_ISCSI_CFG_CHAP_NAME_MAX_LEN,
|
|
+ chap_name);
|
|
break;
|
|
case ISCSI_BOOT_TGT_CHAP_SECRET:
|
|
- rc = snprintf(str, NVM_ISCSI_CFG_CHAP_PWD_MAX_LEN, "%s\n",
|
|
- chap_secret);
|
|
+ rc = sprintf(str, "%.*s\n", NVM_ISCSI_CFG_CHAP_NAME_MAX_LEN,
|
|
+ chap_secret);
|
|
break;
|
|
case ISCSI_BOOT_TGT_REV_CHAP_NAME:
|
|
- rc = snprintf(str, NVM_ISCSI_CFG_CHAP_NAME_MAX_LEN, "%s\n",
|
|
- mchap_name);
|
|
+ rc = sprintf(str, "%.*s\n", NVM_ISCSI_CFG_CHAP_NAME_MAX_LEN,
|
|
+ mchap_name);
|
|
break;
|
|
case ISCSI_BOOT_TGT_REV_CHAP_SECRET:
|
|
- rc = snprintf(str, NVM_ISCSI_CFG_CHAP_PWD_MAX_LEN, "%s\n",
|
|
- mchap_secret);
|
|
+ rc = sprintf(str, "%.*s\n", NVM_ISCSI_CFG_CHAP_NAME_MAX_LEN,
|
|
+ mchap_secret);
|
|
break;
|
|
case ISCSI_BOOT_TGT_FLAGS:
|
|
rc = snprintf(str, 3, "%hhd\n", SYSFS_FLAG_FW_SEL_BOOT);
|
|
diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c
|
|
index d95b879c2bca..13a00a42b3ca 100644
|
|
--- a/drivers/scsi/qla2xxx/qla_isr.c
|
|
+++ b/drivers/scsi/qla2xxx/qla_isr.c
|
|
@@ -272,7 +272,8 @@ qla2x00_mbx_completion(scsi_qla_host_t *vha, uint16_t mb0)
|
|
struct device_reg_2xxx __iomem *reg = &ha->iobase->isp;
|
|
|
|
/* Read all mbox registers? */
|
|
- mboxes = (1 << ha->mbx_count) - 1;
|
|
+ WARN_ON_ONCE(ha->mbx_count > 32);
|
|
+ mboxes = (1ULL << ha->mbx_count) - 1;
|
|
if (!ha->mcp)
|
|
ql_dbg(ql_dbg_async, vha, 0x5001, "MBX pointer ERROR.\n");
|
|
else
|
|
@@ -2821,7 +2822,8 @@ qla24xx_mbx_completion(scsi_qla_host_t *vha, uint16_t mb0)
|
|
struct device_reg_24xx __iomem *reg = &ha->iobase->isp24;
|
|
|
|
/* Read all mbox registers? */
|
|
- mboxes = (1 << ha->mbx_count) - 1;
|
|
+ WARN_ON_ONCE(ha->mbx_count > 32);
|
|
+ mboxes = (1ULL << ha->mbx_count) - 1;
|
|
if (!ha->mcp)
|
|
ql_dbg(ql_dbg_async, vha, 0x504e, "MBX pointer ERROR.\n");
|
|
else
|
|
diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c
|
|
index 8e7c0626f8b5..1be76695e692 100644
|
|
--- a/drivers/scsi/qla2xxx/qla_os.c
|
|
+++ b/drivers/scsi/qla2xxx/qla_os.c
|
|
@@ -3581,6 +3581,8 @@ qla2x00_remove_one(struct pci_dev *pdev)
|
|
}
|
|
qla2x00_wait_for_hba_ready(base_vha);
|
|
|
|
+ qla2x00_wait_for_sess_deletion(base_vha);
|
|
+
|
|
/*
|
|
* if UNLOAD flag is already set, then continue unload,
|
|
* where it was set first.
|
|
diff --git a/drivers/scsi/qla4xxx/ql4_def.h b/drivers/scsi/qla4xxx/ql4_def.h
|
|
index fc233717355f..817f312023a9 100644
|
|
--- a/drivers/scsi/qla4xxx/ql4_def.h
|
|
+++ b/drivers/scsi/qla4xxx/ql4_def.h
|
|
@@ -168,6 +168,8 @@
|
|
#define DEV_DB_NON_PERSISTENT 0
|
|
#define DEV_DB_PERSISTENT 1
|
|
|
|
+#define QL4_ISP_REG_DISCONNECT 0xffffffffU
|
|
+
|
|
#define COPY_ISID(dst_isid, src_isid) { \
|
|
int i, j; \
|
|
for (i = 0, j = ISID_SIZE - 1; i < ISID_SIZE;) \
|
|
diff --git a/drivers/scsi/qla4xxx/ql4_os.c b/drivers/scsi/qla4xxx/ql4_os.c
|
|
index 64c6fa563fdb..a6aa08d9a171 100644
|
|
--- a/drivers/scsi/qla4xxx/ql4_os.c
|
|
+++ b/drivers/scsi/qla4xxx/ql4_os.c
|
|
@@ -262,6 +262,24 @@ static struct iscsi_transport qla4xxx_iscsi_transport = {
|
|
|
|
static struct scsi_transport_template *qla4xxx_scsi_transport;
|
|
|
|
+static int qla4xxx_isp_check_reg(struct scsi_qla_host *ha)
|
|
+{
|
|
+ u32 reg_val = 0;
|
|
+ int rval = QLA_SUCCESS;
|
|
+
|
|
+ if (is_qla8022(ha))
|
|
+ reg_val = readl(&ha->qla4_82xx_reg->host_status);
|
|
+ else if (is_qla8032(ha) || is_qla8042(ha))
|
|
+ reg_val = qla4_8xxx_rd_direct(ha, QLA8XXX_PEG_ALIVE_COUNTER);
|
|
+ else
|
|
+ reg_val = readw(&ha->reg->ctrl_status);
|
|
+
|
|
+ if (reg_val == QL4_ISP_REG_DISCONNECT)
|
|
+ rval = QLA_ERROR;
|
|
+
|
|
+ return rval;
|
|
+}
|
|
+
|
|
static int qla4xxx_send_ping(struct Scsi_Host *shost, uint32_t iface_num,
|
|
uint32_t iface_type, uint32_t payload_size,
|
|
uint32_t pid, struct sockaddr *dst_addr)
|
|
@@ -9188,10 +9206,17 @@ static int qla4xxx_eh_abort(struct scsi_cmnd *cmd)
|
|
struct srb *srb = NULL;
|
|
int ret = SUCCESS;
|
|
int wait = 0;
|
|
+ int rval;
|
|
|
|
ql4_printk(KERN_INFO, ha, "scsi%ld:%d:%llu: Abort command issued cmd=%p, cdb=0x%x\n",
|
|
ha->host_no, id, lun, cmd, cmd->cmnd[0]);
|
|
|
|
+ rval = qla4xxx_isp_check_reg(ha);
|
|
+ if (rval != QLA_SUCCESS) {
|
|
+ ql4_printk(KERN_INFO, ha, "PCI/Register disconnect, exiting.\n");
|
|
+ return FAILED;
|
|
+ }
|
|
+
|
|
spin_lock_irqsave(&ha->hardware_lock, flags);
|
|
srb = (struct srb *) CMD_SP(cmd);
|
|
if (!srb) {
|
|
@@ -9243,6 +9268,7 @@ static int qla4xxx_eh_device_reset(struct scsi_cmnd *cmd)
|
|
struct scsi_qla_host *ha = to_qla_host(cmd->device->host);
|
|
struct ddb_entry *ddb_entry = cmd->device->hostdata;
|
|
int ret = FAILED, stat;
|
|
+ int rval;
|
|
|
|
if (!ddb_entry)
|
|
return ret;
|
|
@@ -9262,6 +9288,12 @@ static int qla4xxx_eh_device_reset(struct scsi_cmnd *cmd)
|
|
cmd, jiffies, cmd->request->timeout / HZ,
|
|
ha->dpc_flags, cmd->result, cmd->allowed));
|
|
|
|
+ rval = qla4xxx_isp_check_reg(ha);
|
|
+ if (rval != QLA_SUCCESS) {
|
|
+ ql4_printk(KERN_INFO, ha, "PCI/Register disconnect, exiting.\n");
|
|
+ return FAILED;
|
|
+ }
|
|
+
|
|
/* FIXME: wait for hba to go online */
|
|
stat = qla4xxx_reset_lun(ha, ddb_entry, cmd->device->lun);
|
|
if (stat != QLA_SUCCESS) {
|
|
@@ -9305,6 +9337,7 @@ static int qla4xxx_eh_target_reset(struct scsi_cmnd *cmd)
|
|
struct scsi_qla_host *ha = to_qla_host(cmd->device->host);
|
|
struct ddb_entry *ddb_entry = cmd->device->hostdata;
|
|
int stat, ret;
|
|
+ int rval;
|
|
|
|
if (!ddb_entry)
|
|
return FAILED;
|
|
@@ -9322,6 +9355,12 @@ static int qla4xxx_eh_target_reset(struct scsi_cmnd *cmd)
|
|
ha->host_no, cmd, jiffies, cmd->request->timeout / HZ,
|
|
ha->dpc_flags, cmd->result, cmd->allowed));
|
|
|
|
+ rval = qla4xxx_isp_check_reg(ha);
|
|
+ if (rval != QLA_SUCCESS) {
|
|
+ ql4_printk(KERN_INFO, ha, "PCI/Register disconnect, exiting.\n");
|
|
+ return FAILED;
|
|
+ }
|
|
+
|
|
stat = qla4xxx_reset_target(ha, ddb_entry);
|
|
if (stat != QLA_SUCCESS) {
|
|
starget_printk(KERN_INFO, scsi_target(cmd->device),
|
|
@@ -9376,9 +9415,16 @@ static int qla4xxx_eh_host_reset(struct scsi_cmnd *cmd)
|
|
{
|
|
int return_status = FAILED;
|
|
struct scsi_qla_host *ha;
|
|
+ int rval;
|
|
|
|
ha = to_qla_host(cmd->device->host);
|
|
|
|
+ rval = qla4xxx_isp_check_reg(ha);
|
|
+ if (rval != QLA_SUCCESS) {
|
|
+ ql4_printk(KERN_INFO, ha, "PCI/Register disconnect, exiting.\n");
|
|
+ return FAILED;
|
|
+ }
|
|
+
|
|
if ((is_qla8032(ha) || is_qla8042(ha)) && ql4xdontresethba)
|
|
qla4_83xx_set_idc_dontreset(ha);
|
|
|
|
diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c
|
|
index 359386730523..bfd8f12d4e9a 100644
|
|
--- a/drivers/scsi/scsi_lib.c
|
|
+++ b/drivers/scsi/scsi_lib.c
|
|
@@ -855,6 +855,17 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes)
|
|
/* for passthrough error may be set */
|
|
error = BLK_STS_OK;
|
|
}
|
|
+ /*
|
|
+ * Another corner case: the SCSI status byte is non-zero but 'good'.
|
|
+ * Example: PRE-FETCH command returns SAM_STAT_CONDITION_MET when
|
|
+ * it is able to fit nominated LBs in its cache (and SAM_STAT_GOOD
|
|
+ * if it can't fit). Treat SAM_STAT_CONDITION_MET and the related
|
|
+ * intermediate statuses (both obsolete in SAM-4) as good.
|
|
+ */
|
|
+ if (status_byte(result) && scsi_status_is_good(result)) {
|
|
+ result = 0;
|
|
+ error = BLK_STS_OK;
|
|
+ }
|
|
|
|
/*
|
|
* special case: failed zero length commands always need to
|
|
diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c
|
|
index 2f9912de2212..4a532318b211 100644
|
|
--- a/drivers/scsi/sd.c
|
|
+++ b/drivers/scsi/sd.c
|
|
@@ -2608,6 +2608,7 @@ sd_read_write_protect_flag(struct scsi_disk *sdkp, unsigned char *buffer)
|
|
int res;
|
|
struct scsi_device *sdp = sdkp->device;
|
|
struct scsi_mode_data data;
|
|
+ int disk_ro = get_disk_ro(sdkp->disk);
|
|
int old_wp = sdkp->write_prot;
|
|
|
|
set_disk_ro(sdkp->disk, 0);
|
|
@@ -2648,7 +2649,7 @@ sd_read_write_protect_flag(struct scsi_disk *sdkp, unsigned char *buffer)
|
|
"Test WP failed, assume Write Enabled\n");
|
|
} else {
|
|
sdkp->write_prot = ((data.device_specific & 0x80) != 0);
|
|
- set_disk_ro(sdkp->disk, sdkp->write_prot);
|
|
+ set_disk_ro(sdkp->disk, sdkp->write_prot || disk_ro);
|
|
if (sdkp->first_scan || old_wp != sdkp->write_prot) {
|
|
sd_printk(KERN_NOTICE, sdkp, "Write Protect is %s\n",
|
|
sdkp->write_prot ? "on" : "off");
|
|
diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c
|
|
index aa28874e8fb9..17a4cc138b00 100644
|
|
--- a/drivers/scsi/sg.c
|
|
+++ b/drivers/scsi/sg.c
|
|
@@ -1894,7 +1894,7 @@ sg_build_indirect(Sg_scatter_hold * schp, Sg_fd * sfp, int buff_size)
|
|
num = (rem_sz > scatter_elem_sz_prev) ?
|
|
scatter_elem_sz_prev : rem_sz;
|
|
|
|
- schp->pages[k] = alloc_pages(gfp_mask, order);
|
|
+ schp->pages[k] = alloc_pages(gfp_mask | __GFP_ZERO, order);
|
|
if (!schp->pages[k])
|
|
goto out;
|
|
|
|
diff --git a/drivers/scsi/storvsc_drv.c b/drivers/scsi/storvsc_drv.c
|
|
index a3e480e7a257..c44de0b4a995 100644
|
|
--- a/drivers/scsi/storvsc_drv.c
|
|
+++ b/drivers/scsi/storvsc_drv.c
|
|
@@ -1661,7 +1661,7 @@ static struct scsi_host_template scsi_driver = {
|
|
.eh_timed_out = storvsc_eh_timed_out,
|
|
.slave_alloc = storvsc_device_alloc,
|
|
.slave_configure = storvsc_device_configure,
|
|
- .cmd_per_lun = 255,
|
|
+ .cmd_per_lun = 2048,
|
|
.this_id = -1,
|
|
.use_clustering = ENABLE_CLUSTERING,
|
|
/* Make sure we dont get a sg segment crosses a page boundary */
|
|
diff --git a/drivers/scsi/sym53c8xx_2/sym_hipd.c b/drivers/scsi/sym53c8xx_2/sym_hipd.c
|
|
index ca360daa6a25..378af306fda1 100644
|
|
--- a/drivers/scsi/sym53c8xx_2/sym_hipd.c
|
|
+++ b/drivers/scsi/sym53c8xx_2/sym_hipd.c
|
|
@@ -536,7 +536,7 @@ sym_getsync(struct sym_hcb *np, u_char dt, u_char sfac, u_char *divp, u_char *fa
|
|
* Look for the greatest clock divisor that allows an
|
|
* input speed faster than the period.
|
|
*/
|
|
- while (div-- > 0)
|
|
+ while (--div > 0)
|
|
if (kpc >= (div_10M[div] << 2)) break;
|
|
|
|
/*
|
|
diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
|
|
index d344fef01f1d..3bb1f6cc297a 100644
|
|
--- a/drivers/scsi/ufs/ufshcd.c
|
|
+++ b/drivers/scsi/ufs/ufshcd.c
|
|
@@ -4347,6 +4347,8 @@ static int ufshcd_slave_alloc(struct scsi_device *sdev)
|
|
/* REPORT SUPPORTED OPERATION CODES is not supported */
|
|
sdev->no_report_opcodes = 1;
|
|
|
|
+ /* WRITE_SAME command is not supported */
|
|
+ sdev->no_write_same = 1;
|
|
|
|
ufshcd_set_queue_depth(sdev);
|
|
|
|
diff --git a/drivers/staging/fsl-dpaa2/ethernet/dpaa2-eth.c b/drivers/staging/fsl-dpaa2/ethernet/dpaa2-eth.c
|
|
index 8e84b2e7f5bd..b83d17db06bd 100644
|
|
--- a/drivers/staging/fsl-dpaa2/ethernet/dpaa2-eth.c
|
|
+++ b/drivers/staging/fsl-dpaa2/ethernet/dpaa2-eth.c
|
|
@@ -315,7 +315,7 @@ static int consume_frames(struct dpaa2_eth_channel *ch)
|
|
}
|
|
|
|
fd = dpaa2_dq_fd(dq);
|
|
- fq = (struct dpaa2_eth_fq *)dpaa2_dq_fqd_ctx(dq);
|
|
+ fq = (struct dpaa2_eth_fq *)(uintptr_t)dpaa2_dq_fqd_ctx(dq);
|
|
fq->stats.frames++;
|
|
|
|
fq->consume(priv, ch, fd, &ch->napi);
|
|
@@ -1888,7 +1888,7 @@ static int setup_rx_flow(struct dpaa2_eth_priv *priv,
|
|
queue.destination.id = fq->channel->dpcon_id;
|
|
queue.destination.type = DPNI_DEST_DPCON;
|
|
queue.destination.priority = 1;
|
|
- queue.user_context = (u64)fq;
|
|
+ queue.user_context = (u64)(uintptr_t)fq;
|
|
err = dpni_set_queue(priv->mc_io, 0, priv->mc_token,
|
|
DPNI_QUEUE_RX, 0, fq->flowid,
|
|
DPNI_QUEUE_OPT_USER_CTX | DPNI_QUEUE_OPT_DEST,
|
|
@@ -1940,7 +1940,7 @@ static int setup_tx_flow(struct dpaa2_eth_priv *priv,
|
|
queue.destination.id = fq->channel->dpcon_id;
|
|
queue.destination.type = DPNI_DEST_DPCON;
|
|
queue.destination.priority = 0;
|
|
- queue.user_context = (u64)fq;
|
|
+ queue.user_context = (u64)(uintptr_t)fq;
|
|
err = dpni_set_queue(priv->mc_io, 0, priv->mc_token,
|
|
DPNI_QUEUE_TX_CONFIRM, 0, fq->flowid,
|
|
DPNI_QUEUE_OPT_USER_CTX | DPNI_QUEUE_OPT_DEST,
|
|
diff --git a/drivers/staging/ks7010/ks_hostif.c b/drivers/staging/ks7010/ks_hostif.c
|
|
index 975dbbb3abd0..7da3eb4ca4be 100644
|
|
--- a/drivers/staging/ks7010/ks_hostif.c
|
|
+++ b/drivers/staging/ks7010/ks_hostif.c
|
|
@@ -242,9 +242,8 @@ int get_ap_information(struct ks_wlan_private *priv, struct ap_info_t *ap_info,
|
|
offset = 0;
|
|
|
|
while (bsize > offset) {
|
|
- /* DPRINTK(4, "Element ID=%d\n",*bp); */
|
|
- switch (*bp) {
|
|
- case 0: /* ssid */
|
|
+ switch (*bp) { /* Information Element ID */
|
|
+ case WLAN_EID_SSID:
|
|
if (*(bp + 1) <= SSID_MAX_SIZE) {
|
|
ap->ssid.size = *(bp + 1);
|
|
} else {
|
|
@@ -254,8 +253,8 @@ int get_ap_information(struct ks_wlan_private *priv, struct ap_info_t *ap_info,
|
|
}
|
|
memcpy(ap->ssid.body, bp + 2, ap->ssid.size);
|
|
break;
|
|
- case 1: /* rate */
|
|
- case 50: /* ext rate */
|
|
+ case WLAN_EID_SUPP_RATES:
|
|
+ case WLAN_EID_EXT_SUPP_RATES:
|
|
if ((*(bp + 1) + ap->rate_set.size) <=
|
|
RATE_SET_MAX_SIZE) {
|
|
memcpy(&ap->rate_set.body[ap->rate_set.size],
|
|
@@ -271,9 +270,9 @@ int get_ap_information(struct ks_wlan_private *priv, struct ap_info_t *ap_info,
|
|
(RATE_SET_MAX_SIZE - ap->rate_set.size);
|
|
}
|
|
break;
|
|
- case 3: /* DS parameter */
|
|
+ case WLAN_EID_DS_PARAMS:
|
|
break;
|
|
- case 48: /* RSN(WPA2) */
|
|
+ case WLAN_EID_RSN:
|
|
ap->rsn_ie.id = *bp;
|
|
if (*(bp + 1) <= RSN_IE_BODY_MAX) {
|
|
ap->rsn_ie.size = *(bp + 1);
|
|
@@ -284,8 +283,8 @@ int get_ap_information(struct ks_wlan_private *priv, struct ap_info_t *ap_info,
|
|
}
|
|
memcpy(ap->rsn_ie.body, bp + 2, ap->rsn_ie.size);
|
|
break;
|
|
- case 221: /* WPA */
|
|
- if (memcmp(bp + 2, "\x00\x50\xf2\x01", 4) == 0) { /* WPA OUI check */
|
|
+ case WLAN_EID_VENDOR_SPECIFIC: /* WPA */
|
|
+ if (memcmp(bp + 2, "\x00\x50\xf2\x01", 4) == 0) { /* WPA OUI check */
|
|
ap->wpa_ie.id = *bp;
|
|
if (*(bp + 1) <= RSN_IE_BODY_MAX) {
|
|
ap->wpa_ie.size = *(bp + 1);
|
|
@@ -300,18 +299,18 @@ int get_ap_information(struct ks_wlan_private *priv, struct ap_info_t *ap_info,
|
|
}
|
|
break;
|
|
|
|
- case 2: /* FH parameter */
|
|
- case 4: /* CF parameter */
|
|
- case 5: /* TIM */
|
|
- case 6: /* IBSS parameter */
|
|
- case 7: /* Country */
|
|
- case 42: /* ERP information */
|
|
- case 47: /* Reserve ID 47 Broadcom AP */
|
|
+ case WLAN_EID_FH_PARAMS:
|
|
+ case WLAN_EID_CF_PARAMS:
|
|
+ case WLAN_EID_TIM:
|
|
+ case WLAN_EID_IBSS_PARAMS:
|
|
+ case WLAN_EID_COUNTRY:
|
|
+ case WLAN_EID_ERP_INFO:
|
|
break;
|
|
default:
|
|
DPRINTK(4, "unknown Element ID=%d\n", *bp);
|
|
break;
|
|
}
|
|
+
|
|
offset += 2; /* id & size field */
|
|
offset += *(bp + 1); /* +size offset */
|
|
bp += (*(bp + 1) + 2); /* pointer update */
|
|
diff --git a/drivers/staging/ks7010/ks_hostif.h b/drivers/staging/ks7010/ks_hostif.h
|
|
index 5bae8d468e23..9ac317e4b507 100644
|
|
--- a/drivers/staging/ks7010/ks_hostif.h
|
|
+++ b/drivers/staging/ks7010/ks_hostif.h
|
|
@@ -13,6 +13,7 @@
|
|
#define _KS_HOSTIF_H_
|
|
|
|
#include <linux/compiler.h>
|
|
+#include <linux/ieee80211.h>
|
|
|
|
/*
|
|
* HOST-MAC I/F events
|
|
diff --git a/drivers/staging/lustre/lustre/include/obd.h b/drivers/staging/lustre/lustre/include/obd.h
|
|
index a986737ec010..82a499fb23bb 100644
|
|
--- a/drivers/staging/lustre/lustre/include/obd.h
|
|
+++ b/drivers/staging/lustre/lustre/include/obd.h
|
|
@@ -190,7 +190,7 @@ struct client_obd {
|
|
struct sptlrpc_flavor cl_flvr_mgc; /* fixed flavor of mgc->mgs */
|
|
|
|
/* the grant values are protected by loi_list_lock below */
|
|
- unsigned long cl_dirty_pages; /* all _dirty_ in pahges */
|
|
+ unsigned long cl_dirty_pages; /* all _dirty_ in pages */
|
|
unsigned long cl_dirty_max_pages; /* allowed w/o rpc */
|
|
unsigned long cl_dirty_transit; /* dirty synchronous */
|
|
unsigned long cl_avail_grant; /* bytes of credit for ost */
|
|
diff --git a/drivers/staging/lustre/lustre/lmv/lmv_obd.c b/drivers/staging/lustre/lustre/lmv/lmv_obd.c
|
|
index 6e16c930a021..c2aadb2d1fea 100644
|
|
--- a/drivers/staging/lustre/lustre/lmv/lmv_obd.c
|
|
+++ b/drivers/staging/lustre/lustre/lmv/lmv_obd.c
|
|
@@ -2694,7 +2694,7 @@ static int lmv_unpackmd(struct obd_export *exp, struct lmv_stripe_md **lsmp,
|
|
if (lsm && !lmm) {
|
|
int i;
|
|
|
|
- for (i = 1; i < lsm->lsm_md_stripe_count; i++) {
|
|
+ for (i = 0; i < lsm->lsm_md_stripe_count; i++) {
|
|
/*
|
|
* For migrating inode, the master stripe and master
|
|
* object will be the same, so do not need iput, see
|
|
diff --git a/drivers/staging/lustre/lustre/osc/osc_cache.c b/drivers/staging/lustre/lustre/osc/osc_cache.c
|
|
index e1207c227b79..c356d00d87a5 100644
|
|
--- a/drivers/staging/lustre/lustre/osc/osc_cache.c
|
|
+++ b/drivers/staging/lustre/lustre/osc/osc_cache.c
|
|
@@ -1528,7 +1528,7 @@ static int osc_enter_cache_try(struct client_obd *cli,
|
|
if (rc < 0)
|
|
return 0;
|
|
|
|
- if (cli->cl_dirty_pages <= cli->cl_dirty_max_pages &&
|
|
+ if (cli->cl_dirty_pages < cli->cl_dirty_max_pages &&
|
|
atomic_long_read(&obd_dirty_pages) + 1 <= obd_max_dirty_pages) {
|
|
osc_consume_write_grant(cli, &oap->oap_brw_page);
|
|
if (transient) {
|
|
diff --git a/drivers/staging/rtl8192u/r8192U_core.c b/drivers/staging/rtl8192u/r8192U_core.c
|
|
index 46b3f19e0878..db3eb7ec5809 100644
|
|
--- a/drivers/staging/rtl8192u/r8192U_core.c
|
|
+++ b/drivers/staging/rtl8192u/r8192U_core.c
|
|
@@ -1702,6 +1702,8 @@ static short rtl8192_usb_initendpoints(struct net_device *dev)
|
|
|
|
priv->rx_urb[16] = usb_alloc_urb(0, GFP_KERNEL);
|
|
priv->oldaddr = kmalloc(16, GFP_KERNEL);
|
|
+ if (!priv->oldaddr)
|
|
+ return -ENOMEM;
|
|
oldaddr = priv->oldaddr;
|
|
align = ((long)oldaddr) & 3;
|
|
if (align) {
|
|
diff --git a/drivers/staging/vc04_services/bcm2835-audio/bcm2835.c b/drivers/staging/vc04_services/bcm2835-audio/bcm2835.c
|
|
index 8f2d508183b2..9030d71a3d0b 100644
|
|
--- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835.c
|
|
+++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835.c
|
|
@@ -36,6 +36,10 @@ MODULE_PARM_DESC(enable_compat_alsa,
|
|
static void snd_devm_unregister_child(struct device *dev, void *res)
|
|
{
|
|
struct device *childdev = *(struct device **)res;
|
|
+ struct bcm2835_chip *chip = dev_get_drvdata(childdev);
|
|
+ struct snd_card *card = chip->card;
|
|
+
|
|
+ snd_card_free(card);
|
|
|
|
device_unregister(childdev);
|
|
}
|
|
@@ -61,6 +65,13 @@ static int snd_devm_add_child(struct device *dev, struct device *child)
|
|
return 0;
|
|
}
|
|
|
|
+static void snd_bcm2835_release(struct device *dev)
|
|
+{
|
|
+ struct bcm2835_chip *chip = dev_get_drvdata(dev);
|
|
+
|
|
+ kfree(chip);
|
|
+}
|
|
+
|
|
static struct device *
|
|
snd_create_device(struct device *parent,
|
|
struct device_driver *driver,
|
|
@@ -76,6 +87,7 @@ snd_create_device(struct device *parent,
|
|
device_initialize(device);
|
|
device->parent = parent;
|
|
device->driver = driver;
|
|
+ device->release = snd_bcm2835_release;
|
|
|
|
dev_set_name(device, "%s", name);
|
|
|
|
@@ -86,18 +98,19 @@ snd_create_device(struct device *parent,
|
|
return device;
|
|
}
|
|
|
|
-static int snd_bcm2835_free(struct bcm2835_chip *chip)
|
|
-{
|
|
- kfree(chip);
|
|
- return 0;
|
|
-}
|
|
-
|
|
/* component-destructor
|
|
* (see "Management of Cards and Components")
|
|
*/
|
|
static int snd_bcm2835_dev_free(struct snd_device *device)
|
|
{
|
|
- return snd_bcm2835_free(device->device_data);
|
|
+ struct bcm2835_chip *chip = device->device_data;
|
|
+ struct snd_card *card = chip->card;
|
|
+
|
|
+ /* TODO: free pcm, ctl */
|
|
+
|
|
+ snd_device_free(card, chip);
|
|
+
|
|
+ return 0;
|
|
}
|
|
|
|
/* chip-specific constructor
|
|
@@ -122,7 +135,7 @@ static int snd_bcm2835_create(struct snd_card *card,
|
|
|
|
err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops);
|
|
if (err) {
|
|
- snd_bcm2835_free(chip);
|
|
+ kfree(chip);
|
|
return err;
|
|
}
|
|
|
|
@@ -130,31 +143,14 @@ static int snd_bcm2835_create(struct snd_card *card,
|
|
return 0;
|
|
}
|
|
|
|
-static void snd_devm_card_free(struct device *dev, void *res)
|
|
+static struct snd_card *snd_bcm2835_card_new(struct device *dev)
|
|
{
|
|
- struct snd_card *snd_card = *(struct snd_card **)res;
|
|
-
|
|
- snd_card_free(snd_card);
|
|
-}
|
|
-
|
|
-static struct snd_card *snd_devm_card_new(struct device *dev)
|
|
-{
|
|
- struct snd_card **dr;
|
|
struct snd_card *card;
|
|
int ret;
|
|
|
|
- dr = devres_alloc(snd_devm_card_free, sizeof(*dr), GFP_KERNEL);
|
|
- if (!dr)
|
|
- return ERR_PTR(-ENOMEM);
|
|
-
|
|
ret = snd_card_new(dev, -1, NULL, THIS_MODULE, 0, &card);
|
|
- if (ret) {
|
|
- devres_free(dr);
|
|
+ if (ret)
|
|
return ERR_PTR(ret);
|
|
- }
|
|
-
|
|
- *dr = card;
|
|
- devres_add(dev, dr);
|
|
|
|
return card;
|
|
}
|
|
@@ -271,7 +267,7 @@ static int snd_add_child_device(struct device *device,
|
|
return PTR_ERR(child);
|
|
}
|
|
|
|
- card = snd_devm_card_new(child);
|
|
+ card = snd_bcm2835_card_new(child);
|
|
if (IS_ERR(card)) {
|
|
dev_err(child, "Failed to create card");
|
|
return PTR_ERR(card);
|
|
@@ -313,7 +309,7 @@ static int snd_add_child_device(struct device *device,
|
|
return err;
|
|
}
|
|
|
|
- dev_set_drvdata(child, card);
|
|
+ dev_set_drvdata(child, chip);
|
|
dev_info(child, "card created with %d channels\n", numchans);
|
|
|
|
return 0;
|
|
diff --git a/drivers/tty/serial/8250/8250_port.c b/drivers/tty/serial/8250/8250_port.c
|
|
index e32c51d549c3..be456ea27ab2 100644
|
|
--- a/drivers/tty/serial/8250/8250_port.c
|
|
+++ b/drivers/tty/serial/8250/8250_port.c
|
|
@@ -1874,7 +1874,8 @@ int serial8250_handle_irq(struct uart_port *port, unsigned int iir)
|
|
|
|
status = serial_port_in(port, UART_LSR);
|
|
|
|
- if (status & (UART_LSR_DR | UART_LSR_BI)) {
|
|
+ if (status & (UART_LSR_DR | UART_LSR_BI) &&
|
|
+ iir & UART_IIR_RDI) {
|
|
if (!up->dma || handle_rx_dma(up, iir))
|
|
status = serial8250_rx_chars(up, status);
|
|
}
|
|
diff --git a/drivers/tty/serial/altera_uart.c b/drivers/tty/serial/altera_uart.c
|
|
index 3e4b717670d7..59cb62de236b 100644
|
|
--- a/drivers/tty/serial/altera_uart.c
|
|
+++ b/drivers/tty/serial/altera_uart.c
|
|
@@ -331,7 +331,7 @@ static int altera_uart_startup(struct uart_port *port)
|
|
|
|
/* Enable RX interrupts now */
|
|
pp->imr = ALTERA_UART_CONTROL_RRDY_MSK;
|
|
- writel(pp->imr, port->membase + ALTERA_UART_CONTROL_REG);
|
|
+ altera_uart_writel(port, pp->imr, ALTERA_UART_CONTROL_REG);
|
|
|
|
spin_unlock_irqrestore(&port->lock, flags);
|
|
|
|
@@ -347,7 +347,7 @@ static void altera_uart_shutdown(struct uart_port *port)
|
|
|
|
/* Disable all interrupts now */
|
|
pp->imr = 0;
|
|
- writel(pp->imr, port->membase + ALTERA_UART_CONTROL_REG);
|
|
+ altera_uart_writel(port, pp->imr, ALTERA_UART_CONTROL_REG);
|
|
|
|
spin_unlock_irqrestore(&port->lock, flags);
|
|
|
|
@@ -436,7 +436,7 @@ static void altera_uart_console_putc(struct uart_port *port, int c)
|
|
ALTERA_UART_STATUS_TRDY_MSK))
|
|
cpu_relax();
|
|
|
|
- writel(c, port->membase + ALTERA_UART_TXDATA_REG);
|
|
+ altera_uart_writel(port, c, ALTERA_UART_TXDATA_REG);
|
|
}
|
|
|
|
static void altera_uart_console_write(struct console *co, const char *s,
|
|
@@ -506,13 +506,13 @@ static int __init altera_uart_earlycon_setup(struct earlycon_device *dev,
|
|
return -ENODEV;
|
|
|
|
/* Enable RX interrupts now */
|
|
- writel(ALTERA_UART_CONTROL_RRDY_MSK,
|
|
- port->membase + ALTERA_UART_CONTROL_REG);
|
|
+ altera_uart_writel(port, ALTERA_UART_CONTROL_RRDY_MSK,
|
|
+ ALTERA_UART_CONTROL_REG);
|
|
|
|
if (dev->baud) {
|
|
unsigned int baudclk = port->uartclk / dev->baud;
|
|
|
|
- writel(baudclk, port->membase + ALTERA_UART_DIVISOR_REG);
|
|
+ altera_uart_writel(port, baudclk, ALTERA_UART_DIVISOR_REG);
|
|
}
|
|
|
|
dev->con->write = altera_uart_earlycon_write;
|
|
diff --git a/drivers/tty/serial/arc_uart.c b/drivers/tty/serial/arc_uart.c
|
|
index 77fe306690c4..71e37abb6bcb 100644
|
|
--- a/drivers/tty/serial/arc_uart.c
|
|
+++ b/drivers/tty/serial/arc_uart.c
|
|
@@ -596,6 +596,11 @@ static int arc_serial_probe(struct platform_device *pdev)
|
|
if (dev_id < 0)
|
|
dev_id = 0;
|
|
|
|
+ if (dev_id >= ARRAY_SIZE(arc_uart_ports)) {
|
|
+ dev_err(&pdev->dev, "serial%d out of range\n", dev_id);
|
|
+ return -EINVAL;
|
|
+ }
|
|
+
|
|
uart = &arc_uart_ports[dev_id];
|
|
port = &uart->port;
|
|
|
|
diff --git a/drivers/tty/serial/fsl_lpuart.c b/drivers/tty/serial/fsl_lpuart.c
|
|
index f0252184291e..7a3db9378fa3 100644
|
|
--- a/drivers/tty/serial/fsl_lpuart.c
|
|
+++ b/drivers/tty/serial/fsl_lpuart.c
|
|
@@ -2151,6 +2151,10 @@ static int lpuart_probe(struct platform_device *pdev)
|
|
dev_err(&pdev->dev, "failed to get alias id, errno %d\n", ret);
|
|
return ret;
|
|
}
|
|
+ if (ret >= ARRAY_SIZE(lpuart_ports)) {
|
|
+ dev_err(&pdev->dev, "serial%d out of range\n", ret);
|
|
+ return -EINVAL;
|
|
+ }
|
|
sport->port.line = ret;
|
|
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
|
sport->port.membase = devm_ioremap_resource(&pdev->dev, res);
|
|
diff --git a/drivers/tty/serial/imx.c b/drivers/tty/serial/imx.c
|
|
index 521500c575c8..8deaf2ad8b34 100644
|
|
--- a/drivers/tty/serial/imx.c
|
|
+++ b/drivers/tty/serial/imx.c
|
|
@@ -2096,6 +2096,12 @@ static int serial_imx_probe(struct platform_device *pdev)
|
|
else if (ret < 0)
|
|
return ret;
|
|
|
|
+ if (sport->port.line >= ARRAY_SIZE(imx_ports)) {
|
|
+ dev_err(&pdev->dev, "serial%d out of range\n",
|
|
+ sport->port.line);
|
|
+ return -EINVAL;
|
|
+ }
|
|
+
|
|
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
|
base = devm_ioremap_resource(&pdev->dev, res);
|
|
if (IS_ERR(base))
|
|
diff --git a/drivers/tty/serial/mxs-auart.c b/drivers/tty/serial/mxs-auart.c
|
|
index be94246b6fcc..673c8fd7e34f 100644
|
|
--- a/drivers/tty/serial/mxs-auart.c
|
|
+++ b/drivers/tty/serial/mxs-auart.c
|
|
@@ -1667,6 +1667,10 @@ static int mxs_auart_probe(struct platform_device *pdev)
|
|
s->port.line = pdev->id < 0 ? 0 : pdev->id;
|
|
else if (ret < 0)
|
|
return ret;
|
|
+ if (s->port.line >= ARRAY_SIZE(auart_port)) {
|
|
+ dev_err(&pdev->dev, "serial%d out of range\n", s->port.line);
|
|
+ return -EINVAL;
|
|
+ }
|
|
|
|
if (of_id) {
|
|
pdev->id_entry = of_id->data;
|
|
diff --git a/drivers/tty/serial/samsung.c b/drivers/tty/serial/samsung.c
|
|
index 8aca18c4cdea..bedd4bdec4ab 100644
|
|
--- a/drivers/tty/serial/samsung.c
|
|
+++ b/drivers/tty/serial/samsung.c
|
|
@@ -1821,6 +1821,10 @@ static int s3c24xx_serial_probe(struct platform_device *pdev)
|
|
|
|
dbg("s3c24xx_serial_probe(%p) %d\n", pdev, index);
|
|
|
|
+ if (index >= ARRAY_SIZE(s3c24xx_serial_ports)) {
|
|
+ dev_err(&pdev->dev, "serial%d out of range\n", index);
|
|
+ return -EINVAL;
|
|
+ }
|
|
ourport = &s3c24xx_serial_ports[index];
|
|
|
|
ourport->drv_data = s3c24xx_get_driver_data(pdev);
|
|
diff --git a/drivers/tty/serial/sh-sci.c b/drivers/tty/serial/sh-sci.c
|
|
index 22f60239026c..8a58ee32ff61 100644
|
|
--- a/drivers/tty/serial/sh-sci.c
|
|
+++ b/drivers/tty/serial/sh-sci.c
|
|
@@ -3076,6 +3076,10 @@ static struct plat_sci_port *sci_parse_dt(struct platform_device *pdev,
|
|
dev_err(&pdev->dev, "failed to get alias id (%d)\n", id);
|
|
return NULL;
|
|
}
|
|
+ if (id >= ARRAY_SIZE(sci_ports)) {
|
|
+ dev_err(&pdev->dev, "serial%d out of range\n", id);
|
|
+ return NULL;
|
|
+ }
|
|
|
|
sp = &sci_ports[id];
|
|
*dev_id = id;
|
|
diff --git a/drivers/tty/serial/xilinx_uartps.c b/drivers/tty/serial/xilinx_uartps.c
|
|
index 31a630ae0870..21c35ad72b99 100644
|
|
--- a/drivers/tty/serial/xilinx_uartps.c
|
|
+++ b/drivers/tty/serial/xilinx_uartps.c
|
|
@@ -1115,7 +1115,7 @@ static struct uart_port *cdns_uart_get_port(int id)
|
|
struct uart_port *port;
|
|
|
|
/* Try the given port id if failed use default method */
|
|
- if (cdns_uart_port[id].mapbase != 0) {
|
|
+ if (id < CDNS_UART_NR_PORTS && cdns_uart_port[id].mapbase != 0) {
|
|
/* Find the next unused port */
|
|
for (id = 0; id < CDNS_UART_NR_PORTS; id++)
|
|
if (cdns_uart_port[id].mapbase == 0)
|
|
diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c
|
|
index 4149a965516e..22952d70b981 100644
|
|
--- a/drivers/usb/class/cdc-acm.c
|
|
+++ b/drivers/usb/class/cdc-acm.c
|
|
@@ -187,6 +187,7 @@ static int acm_wb_alloc(struct acm *acm)
|
|
wb = &acm->wb[wbn];
|
|
if (!wb->use) {
|
|
wb->use = 1;
|
|
+ wb->len = 0;
|
|
return wbn;
|
|
}
|
|
wbn = (wbn + 1) % ACM_NW;
|
|
@@ -818,16 +819,18 @@ static int acm_tty_write(struct tty_struct *tty,
|
|
static void acm_tty_flush_chars(struct tty_struct *tty)
|
|
{
|
|
struct acm *acm = tty->driver_data;
|
|
- struct acm_wb *cur = acm->putbuffer;
|
|
+ struct acm_wb *cur;
|
|
int err;
|
|
unsigned long flags;
|
|
|
|
+ spin_lock_irqsave(&acm->write_lock, flags);
|
|
+
|
|
+ cur = acm->putbuffer;
|
|
if (!cur) /* nothing to do */
|
|
- return;
|
|
+ goto out;
|
|
|
|
acm->putbuffer = NULL;
|
|
err = usb_autopm_get_interface_async(acm->control);
|
|
- spin_lock_irqsave(&acm->write_lock, flags);
|
|
if (err < 0) {
|
|
cur->use = 0;
|
|
acm->putbuffer = cur;
|
|
diff --git a/drivers/usb/dwc2/core.h b/drivers/usb/dwc2/core.h
|
|
index 8367d4f985c1..ec965ac5f1f5 100644
|
|
--- a/drivers/usb/dwc2/core.h
|
|
+++ b/drivers/usb/dwc2/core.h
|
|
@@ -216,7 +216,7 @@ struct dwc2_hsotg_ep {
|
|
unsigned char dir_in;
|
|
unsigned char index;
|
|
unsigned char mc;
|
|
- unsigned char interval;
|
|
+ u16 interval;
|
|
|
|
unsigned int halted:1;
|
|
unsigned int periodic:1;
|
|
diff --git a/drivers/usb/dwc2/gadget.c b/drivers/usb/dwc2/gadget.c
|
|
index 0d8e09ccb59c..6ef001a83fe2 100644
|
|
--- a/drivers/usb/dwc2/gadget.c
|
|
+++ b/drivers/usb/dwc2/gadget.c
|
|
@@ -3414,12 +3414,6 @@ void dwc2_hsotg_core_init_disconnected(struct dwc2_hsotg *hsotg,
|
|
dwc2_writel(dwc2_hsotg_ep0_mps(hsotg->eps_out[0]->ep.maxpacket) |
|
|
DXEPCTL_USBACTEP, hsotg->regs + DIEPCTL0);
|
|
|
|
- dwc2_hsotg_enqueue_setup(hsotg);
|
|
-
|
|
- dev_dbg(hsotg->dev, "EP0: DIEPCTL0=0x%08x, DOEPCTL0=0x%08x\n",
|
|
- dwc2_readl(hsotg->regs + DIEPCTL0),
|
|
- dwc2_readl(hsotg->regs + DOEPCTL0));
|
|
-
|
|
/* clear global NAKs */
|
|
val = DCTL_CGOUTNAK | DCTL_CGNPINNAK;
|
|
if (!is_usb_reset)
|
|
@@ -3430,6 +3424,12 @@ void dwc2_hsotg_core_init_disconnected(struct dwc2_hsotg *hsotg,
|
|
mdelay(3);
|
|
|
|
hsotg->lx_state = DWC2_L0;
|
|
+
|
|
+ dwc2_hsotg_enqueue_setup(hsotg);
|
|
+
|
|
+ dev_dbg(hsotg->dev, "EP0: DIEPCTL0=0x%08x, DOEPCTL0=0x%08x\n",
|
|
+ dwc2_readl(hsotg->regs + DIEPCTL0),
|
|
+ dwc2_readl(hsotg->regs + DOEPCTL0));
|
|
}
|
|
|
|
static void dwc2_hsotg_core_disconnect(struct dwc2_hsotg *hsotg)
|
|
diff --git a/drivers/usb/dwc2/hcd.c b/drivers/usb/dwc2/hcd.c
|
|
index 9bd60ec83ac6..87484f71b2ab 100644
|
|
--- a/drivers/usb/dwc2/hcd.c
|
|
+++ b/drivers/usb/dwc2/hcd.c
|
|
@@ -979,6 +979,24 @@ void dwc2_hc_halt(struct dwc2_hsotg *hsotg, struct dwc2_host_chan *chan,
|
|
|
|
if (dbg_hc(chan))
|
|
dev_vdbg(hsotg->dev, "%s()\n", __func__);
|
|
+
|
|
+ /*
|
|
+ * In buffer DMA or external DMA mode channel can't be halted
|
|
+ * for non-split periodic channels. At the end of the next
|
|
+ * uframe/frame (in the worst case), the core generates a channel
|
|
+ * halted and disables the channel automatically.
|
|
+ */
|
|
+ if ((hsotg->params.g_dma && !hsotg->params.g_dma_desc) ||
|
|
+ hsotg->hw_params.arch == GHWCFG2_EXT_DMA_ARCH) {
|
|
+ if (!chan->do_split &&
|
|
+ (chan->ep_type == USB_ENDPOINT_XFER_ISOC ||
|
|
+ chan->ep_type == USB_ENDPOINT_XFER_INT)) {
|
|
+ dev_err(hsotg->dev, "%s() Channel can't be halted\n",
|
|
+ __func__);
|
|
+ return;
|
|
+ }
|
|
+ }
|
|
+
|
|
if (halt_status == DWC2_HC_XFER_NO_HALT_STATUS)
|
|
dev_err(hsotg->dev, "!!! halt_status = %d !!!\n", halt_status);
|
|
|
|
@@ -2311,10 +2329,22 @@ static int dwc2_core_init(struct dwc2_hsotg *hsotg, bool initial_setup)
|
|
*/
|
|
static void dwc2_core_host_init(struct dwc2_hsotg *hsotg)
|
|
{
|
|
- u32 hcfg, hfir, otgctl;
|
|
+ u32 hcfg, hfir, otgctl, usbcfg;
|
|
|
|
dev_dbg(hsotg->dev, "%s(%p)\n", __func__, hsotg);
|
|
|
|
+ /* Set HS/FS Timeout Calibration to 7 (max available value).
|
|
+ * The number of PHY clocks that the application programs in
|
|
+ * this field is added to the high/full speed interpacket timeout
|
|
+ * duration in the core to account for any additional delays
|
|
+ * introduced by the PHY. This can be required, because the delay
|
|
+ * introduced by the PHY in generating the linestate condition
|
|
+ * can vary from one PHY to another.
|
|
+ */
|
|
+ usbcfg = dwc2_readl(hsotg->regs + GUSBCFG);
|
|
+ usbcfg |= GUSBCFG_TOUTCAL(7);
|
|
+ dwc2_writel(usbcfg, hsotg->regs + GUSBCFG);
|
|
+
|
|
/* Restart the Phy Clock */
|
|
dwc2_writel(0, hsotg->regs + PCGCTL);
|
|
|
|
diff --git a/drivers/usb/dwc3/Makefile b/drivers/usb/dwc3/Makefile
|
|
index 7ac725038f8d..025bc68094fc 100644
|
|
--- a/drivers/usb/dwc3/Makefile
|
|
+++ b/drivers/usb/dwc3/Makefile
|
|
@@ -6,7 +6,7 @@ obj-$(CONFIG_USB_DWC3) += dwc3.o
|
|
|
|
dwc3-y := core.o
|
|
|
|
-ifneq ($(CONFIG_FTRACE),)
|
|
+ifneq ($(CONFIG_TRACING),)
|
|
dwc3-y += trace.o
|
|
endif
|
|
|
|
diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c
|
|
index c3f3f1a89b0f..dca78bb20e5d 100644
|
|
--- a/drivers/usb/dwc3/core.c
|
|
+++ b/drivers/usb/dwc3/core.c
|
|
@@ -243,12 +243,26 @@ static int dwc3_core_soft_reset(struct dwc3 *dwc)
|
|
do {
|
|
reg = dwc3_readl(dwc->regs, DWC3_DCTL);
|
|
if (!(reg & DWC3_DCTL_CSFTRST))
|
|
- return 0;
|
|
+ goto done;
|
|
|
|
udelay(1);
|
|
} while (--retries);
|
|
|
|
+ phy_exit(dwc->usb3_generic_phy);
|
|
+ phy_exit(dwc->usb2_generic_phy);
|
|
+
|
|
return -ETIMEDOUT;
|
|
+
|
|
+done:
|
|
+ /*
|
|
+ * For DWC_usb31 controller, once DWC3_DCTL_CSFTRST bit is cleared,
|
|
+ * we must wait at least 50ms before accessing the PHY domain
|
|
+ * (synchronization delay). DWC_usb31 programming guide section 1.3.2.
|
|
+ */
|
|
+ if (dwc3_is_usb31(dwc))
|
|
+ msleep(50);
|
|
+
|
|
+ return 0;
|
|
}
|
|
|
|
/*
|
|
diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h
|
|
index fc28819253f7..b782ba58a7fc 100644
|
|
--- a/drivers/usb/dwc3/core.h
|
|
+++ b/drivers/usb/dwc3/core.h
|
|
@@ -249,6 +249,8 @@
|
|
#define DWC3_GUSB3PIPECTL_TX_DEEPH(n) ((n) << 1)
|
|
|
|
/* Global TX Fifo Size Register */
|
|
+#define DWC31_GTXFIFOSIZ_TXFRAMNUM BIT(15) /* DWC_usb31 only */
|
|
+#define DWC31_GTXFIFOSIZ_TXFDEF(n) ((n) & 0x7fff) /* DWC_usb31 only */
|
|
#define DWC3_GTXFIFOSIZ_TXFDEF(n) ((n) & 0xffff)
|
|
#define DWC3_GTXFIFOSIZ_TXFSTADDR(n) ((n) & 0xffff0000)
|
|
|
|
diff --git a/drivers/usb/dwc3/dwc3-omap.c b/drivers/usb/dwc3/dwc3-omap.c
|
|
index 3530795bbb8f..fdd0d5aa1f5e 100644
|
|
--- a/drivers/usb/dwc3/dwc3-omap.c
|
|
+++ b/drivers/usb/dwc3/dwc3-omap.c
|
|
@@ -590,9 +590,25 @@ static int dwc3_omap_resume(struct device *dev)
|
|
return 0;
|
|
}
|
|
|
|
+static void dwc3_omap_complete(struct device *dev)
|
|
+{
|
|
+ struct dwc3_omap *omap = dev_get_drvdata(dev);
|
|
+
|
|
+ if (extcon_get_state(omap->edev, EXTCON_USB))
|
|
+ dwc3_omap_set_mailbox(omap, OMAP_DWC3_VBUS_VALID);
|
|
+ else
|
|
+ dwc3_omap_set_mailbox(omap, OMAP_DWC3_VBUS_OFF);
|
|
+
|
|
+ if (extcon_get_state(omap->edev, EXTCON_USB_HOST))
|
|
+ dwc3_omap_set_mailbox(omap, OMAP_DWC3_ID_GROUND);
|
|
+ else
|
|
+ dwc3_omap_set_mailbox(omap, OMAP_DWC3_ID_FLOAT);
|
|
+}
|
|
+
|
|
static const struct dev_pm_ops dwc3_omap_dev_pm_ops = {
|
|
|
|
SET_SYSTEM_SLEEP_PM_OPS(dwc3_omap_suspend, dwc3_omap_resume)
|
|
+ .complete = dwc3_omap_complete,
|
|
};
|
|
|
|
#define DEV_PM_OPS (&dwc3_omap_dev_pm_ops)
|
|
diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c
|
|
index ed9346f0b000..940de04ed72a 100644
|
|
--- a/drivers/usb/gadget/composite.c
|
|
+++ b/drivers/usb/gadget/composite.c
|
|
@@ -1425,7 +1425,7 @@ static int count_ext_compat(struct usb_configuration *c)
|
|
return res;
|
|
}
|
|
|
|
-static void fill_ext_compat(struct usb_configuration *c, u8 *buf)
|
|
+static int fill_ext_compat(struct usb_configuration *c, u8 *buf)
|
|
{
|
|
int i, count;
|
|
|
|
@@ -1452,10 +1452,12 @@ static void fill_ext_compat(struct usb_configuration *c, u8 *buf)
|
|
buf += 23;
|
|
}
|
|
count += 24;
|
|
- if (count >= 4096)
|
|
- return;
|
|
+ if (count + 24 >= USB_COMP_EP0_OS_DESC_BUFSIZ)
|
|
+ return count;
|
|
}
|
|
}
|
|
+
|
|
+ return count;
|
|
}
|
|
|
|
static int count_ext_prop(struct usb_configuration *c, int interface)
|
|
@@ -1500,25 +1502,20 @@ static int fill_ext_prop(struct usb_configuration *c, int interface, u8 *buf)
|
|
struct usb_os_desc *d;
|
|
struct usb_os_desc_ext_prop *ext_prop;
|
|
int j, count, n, ret;
|
|
- u8 *start = buf;
|
|
|
|
f = c->interface[interface];
|
|
+ count = 10; /* header length */
|
|
for (j = 0; j < f->os_desc_n; ++j) {
|
|
if (interface != f->os_desc_table[j].if_id)
|
|
continue;
|
|
d = f->os_desc_table[j].os_desc;
|
|
if (d)
|
|
list_for_each_entry(ext_prop, &d->ext_prop, entry) {
|
|
- /* 4kB minus header length */
|
|
- n = buf - start;
|
|
- if (n >= 4086)
|
|
- return 0;
|
|
-
|
|
- count = ext_prop->data_len +
|
|
+ n = ext_prop->data_len +
|
|
ext_prop->name_len + 14;
|
|
- if (count > 4086 - n)
|
|
- return -EINVAL;
|
|
- usb_ext_prop_put_size(buf, count);
|
|
+ if (count + n >= USB_COMP_EP0_OS_DESC_BUFSIZ)
|
|
+ return count;
|
|
+ usb_ext_prop_put_size(buf, n);
|
|
usb_ext_prop_put_type(buf, ext_prop->type);
|
|
ret = usb_ext_prop_put_name(buf, ext_prop->name,
|
|
ext_prop->name_len);
|
|
@@ -1544,11 +1541,12 @@ static int fill_ext_prop(struct usb_configuration *c, int interface, u8 *buf)
|
|
default:
|
|
return -EINVAL;
|
|
}
|
|
- buf += count;
|
|
+ buf += n;
|
|
+ count += n;
|
|
}
|
|
}
|
|
|
|
- return 0;
|
|
+ return count;
|
|
}
|
|
|
|
/*
|
|
@@ -1830,6 +1828,7 @@ composite_setup(struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
|
|
req->complete = composite_setup_complete;
|
|
buf = req->buf;
|
|
os_desc_cfg = cdev->os_desc_config;
|
|
+ w_length = min_t(u16, w_length, USB_COMP_EP0_OS_DESC_BUFSIZ);
|
|
memset(buf, 0, w_length);
|
|
buf[5] = 0x01;
|
|
switch (ctrl->bRequestType & USB_RECIP_MASK) {
|
|
@@ -1853,8 +1852,8 @@ composite_setup(struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
|
|
count += 16; /* header */
|
|
put_unaligned_le32(count, buf);
|
|
buf += 16;
|
|
- fill_ext_compat(os_desc_cfg, buf);
|
|
- value = w_length;
|
|
+ value = fill_ext_compat(os_desc_cfg, buf);
|
|
+ value = min_t(u16, w_length, value);
|
|
}
|
|
break;
|
|
case USB_RECIP_INTERFACE:
|
|
@@ -1883,8 +1882,7 @@ composite_setup(struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
|
|
interface, buf);
|
|
if (value < 0)
|
|
return value;
|
|
-
|
|
- value = w_length;
|
|
+ value = min_t(u16, w_length, value);
|
|
}
|
|
break;
|
|
}
|
|
@@ -2159,8 +2157,8 @@ int composite_os_desc_req_prepare(struct usb_composite_dev *cdev,
|
|
goto end;
|
|
}
|
|
|
|
- /* OS feature descriptor length <= 4kB */
|
|
- cdev->os_desc_req->buf = kmalloc(4096, GFP_KERNEL);
|
|
+ cdev->os_desc_req->buf = kmalloc(USB_COMP_EP0_OS_DESC_BUFSIZ,
|
|
+ GFP_KERNEL);
|
|
if (!cdev->os_desc_req->buf) {
|
|
ret = -ENOMEM;
|
|
usb_ep_free_request(ep0, cdev->os_desc_req);
|
|
diff --git a/drivers/usb/gadget/function/f_fs.c b/drivers/usb/gadget/function/f_fs.c
|
|
index 0904cb6ce4de..7b53ac548b1a 100644
|
|
--- a/drivers/usb/gadget/function/f_fs.c
|
|
+++ b/drivers/usb/gadget/function/f_fs.c
|
|
@@ -759,9 +759,13 @@ static void ffs_user_copy_worker(struct work_struct *work)
|
|
bool kiocb_has_eventfd = io_data->kiocb->ki_flags & IOCB_EVENTFD;
|
|
|
|
if (io_data->read && ret > 0) {
|
|
+ mm_segment_t oldfs = get_fs();
|
|
+
|
|
+ set_fs(USER_DS);
|
|
use_mm(io_data->mm);
|
|
ret = ffs_copy_to_iter(io_data->buf, ret, &io_data->data);
|
|
unuse_mm(io_data->mm);
|
|
+ set_fs(oldfs);
|
|
}
|
|
|
|
io_data->kiocb->ki_complete(io_data->kiocb, ret, ret);
|
|
@@ -3239,7 +3243,7 @@ static int ffs_func_setup(struct usb_function *f,
|
|
__ffs_event_add(ffs, FUNCTIONFS_SETUP);
|
|
spin_unlock_irqrestore(&ffs->ev.waitq.lock, flags);
|
|
|
|
- return 0;
|
|
+ return USB_GADGET_DELAYED_STATUS;
|
|
}
|
|
|
|
static bool ffs_func_req_match(struct usb_function *f,
|
|
diff --git a/drivers/usb/gadget/function/f_uac2.c b/drivers/usb/gadget/function/f_uac2.c
|
|
index f05c3f3e6103..97cb2dfd6369 100644
|
|
--- a/drivers/usb/gadget/function/f_uac2.c
|
|
+++ b/drivers/usb/gadget/function/f_uac2.c
|
|
@@ -528,6 +528,8 @@ afunc_bind(struct usb_configuration *cfg, struct usb_function *fn)
|
|
dev_err(dev, "%s:%d Error!\n", __func__, __LINE__);
|
|
return ret;
|
|
}
|
|
+ iad_desc.bFirstInterface = ret;
|
|
+
|
|
std_ac_if_desc.bInterfaceNumber = ret;
|
|
uac2->ac_intf = ret;
|
|
uac2->ac_alt = 0;
|
|
diff --git a/drivers/usb/gadget/udc/core.c b/drivers/usb/gadget/udc/core.c
|
|
index 5bab09294a8a..ad315c4c6f35 100644
|
|
--- a/drivers/usb/gadget/udc/core.c
|
|
+++ b/drivers/usb/gadget/udc/core.c
|
|
@@ -191,8 +191,8 @@ EXPORT_SYMBOL_GPL(usb_ep_alloc_request);
|
|
void usb_ep_free_request(struct usb_ep *ep,
|
|
struct usb_request *req)
|
|
{
|
|
- ep->ops->free_request(ep, req);
|
|
trace_usb_ep_free_request(ep, req, 0);
|
|
+ ep->ops->free_request(ep, req);
|
|
}
|
|
EXPORT_SYMBOL_GPL(usb_ep_free_request);
|
|
|
|
diff --git a/drivers/usb/gadget/udc/fsl_udc_core.c b/drivers/usb/gadget/udc/fsl_udc_core.c
|
|
index 6f2f71c054be..7874c112f3fd 100644
|
|
--- a/drivers/usb/gadget/udc/fsl_udc_core.c
|
|
+++ b/drivers/usb/gadget/udc/fsl_udc_core.c
|
|
@@ -1309,7 +1309,7 @@ static void udc_reset_ep_queue(struct fsl_udc *udc, u8 pipe)
|
|
{
|
|
struct fsl_ep *ep = get_ep_by_pipe(udc, pipe);
|
|
|
|
- if (ep->name)
|
|
+ if (ep->ep.name)
|
|
nuke(ep, -ESHUTDOWN);
|
|
}
|
|
|
|
@@ -1697,7 +1697,7 @@ static void dtd_complete_irq(struct fsl_udc *udc)
|
|
curr_ep = get_ep_by_pipe(udc, i);
|
|
|
|
/* If the ep is configured */
|
|
- if (curr_ep->name == NULL) {
|
|
+ if (!curr_ep->ep.name) {
|
|
WARNING("Invalid EP?");
|
|
continue;
|
|
}
|
|
diff --git a/drivers/usb/gadget/udc/goku_udc.h b/drivers/usb/gadget/udc/goku_udc.h
|
|
index 86d2adafe149..64eb0f2b5ea0 100644
|
|
--- a/drivers/usb/gadget/udc/goku_udc.h
|
|
+++ b/drivers/usb/gadget/udc/goku_udc.h
|
|
@@ -28,7 +28,7 @@ struct goku_udc_regs {
|
|
# define INT_EP1DATASET 0x00040
|
|
# define INT_EP2DATASET 0x00080
|
|
# define INT_EP3DATASET 0x00100
|
|
-#define INT_EPnNAK(n) (0x00100 < (n)) /* 0 < n < 4 */
|
|
+#define INT_EPnNAK(n) (0x00100 << (n)) /* 0 < n < 4 */
|
|
# define INT_EP1NAK 0x00200
|
|
# define INT_EP2NAK 0x00400
|
|
# define INT_EP3NAK 0x00800
|
|
diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c
|
|
index 1099465b27f0..b4599aa428f3 100644
|
|
--- a/drivers/usb/host/ohci-hcd.c
|
|
+++ b/drivers/usb/host/ohci-hcd.c
|
|
@@ -446,7 +446,8 @@ static int ohci_init (struct ohci_hcd *ohci)
|
|
struct usb_hcd *hcd = ohci_to_hcd(ohci);
|
|
|
|
/* Accept arbitrarily long scatter-gather lists */
|
|
- hcd->self.sg_tablesize = ~0;
|
|
+ if (!(hcd->driver->flags & HCD_LOCAL_MEM))
|
|
+ hcd->self.sg_tablesize = ~0;
|
|
|
|
if (distrust_firmware)
|
|
ohci->flags |= OHCI_QUIRK_HUB_POWER;
|
|
diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c
|
|
index ccdc971283d0..efd7e4882d66 100644
|
|
--- a/drivers/usb/host/xhci-mem.c
|
|
+++ b/drivers/usb/host/xhci-mem.c
|
|
@@ -926,6 +926,8 @@ void xhci_free_virt_device(struct xhci_hcd *xhci, int slot_id)
|
|
if (dev->out_ctx)
|
|
xhci_free_container_ctx(xhci, dev->out_ctx);
|
|
|
|
+ if (dev->udev && dev->udev->slot_id)
|
|
+ dev->udev->slot_id = 0;
|
|
kfree(xhci->devs[slot_id]);
|
|
xhci->devs[slot_id] = NULL;
|
|
}
|
|
diff --git a/drivers/usb/host/xhci-plat.c b/drivers/usb/host/xhci-plat.c
|
|
index 7d9e085f7b85..830dd0dbbce0 100644
|
|
--- a/drivers/usb/host/xhci-plat.c
|
|
+++ b/drivers/usb/host/xhci-plat.c
|
|
@@ -355,7 +355,6 @@ static int __maybe_unused xhci_plat_suspend(struct device *dev)
|
|
{
|
|
struct usb_hcd *hcd = dev_get_drvdata(dev);
|
|
struct xhci_hcd *xhci = hcd_to_xhci(hcd);
|
|
- int ret;
|
|
|
|
/*
|
|
* xhci_suspend() needs `do_wakeup` to know whether host is allowed
|
|
@@ -365,12 +364,7 @@ static int __maybe_unused xhci_plat_suspend(struct device *dev)
|
|
* reconsider this when xhci_plat_suspend enlarges its scope, e.g.,
|
|
* also applies to runtime suspend.
|
|
*/
|
|
- ret = xhci_suspend(xhci, device_may_wakeup(dev));
|
|
-
|
|
- if (!device_may_wakeup(dev) && !IS_ERR(xhci->clk))
|
|
- clk_disable_unprepare(xhci->clk);
|
|
-
|
|
- return ret;
|
|
+ return xhci_suspend(xhci, device_may_wakeup(dev));
|
|
}
|
|
|
|
static int __maybe_unused xhci_plat_resume(struct device *dev)
|
|
@@ -379,9 +373,6 @@ static int __maybe_unused xhci_plat_resume(struct device *dev)
|
|
struct xhci_hcd *xhci = hcd_to_xhci(hcd);
|
|
int ret;
|
|
|
|
- if (!device_may_wakeup(dev) && !IS_ERR(xhci->clk))
|
|
- clk_prepare_enable(xhci->clk);
|
|
-
|
|
ret = xhci_priv_resume_quirk(hcd);
|
|
if (ret)
|
|
return ret;
|
|
diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c
|
|
index bcf315b32bff..d8b185b0d0f9 100644
|
|
--- a/drivers/usb/host/xhci.c
|
|
+++ b/drivers/usb/host/xhci.c
|
|
@@ -4764,6 +4764,7 @@ int xhci_gen_setup(struct usb_hcd *hcd, xhci_get_quirks_t get_quirks)
|
|
* quirks
|
|
*/
|
|
struct device *dev = hcd->self.sysdev;
|
|
+ unsigned int minor_rev;
|
|
int retval;
|
|
|
|
/* Accept arbitrarily long scatter-gather lists */
|
|
@@ -4791,12 +4792,19 @@ int xhci_gen_setup(struct usb_hcd *hcd, xhci_get_quirks_t get_quirks)
|
|
*/
|
|
hcd->has_tt = 1;
|
|
} else {
|
|
- /* Some 3.1 hosts return sbrn 0x30, can't rely on sbrn alone */
|
|
- if (xhci->sbrn == 0x31 || xhci->usb3_rhub.min_rev >= 1) {
|
|
- xhci_info(xhci, "Host supports USB 3.1 Enhanced SuperSpeed\n");
|
|
+ /*
|
|
+ * Some 3.1 hosts return sbrn 0x30, use xhci supported protocol
|
|
+ * minor revision instead of sbrn
|
|
+ */
|
|
+ minor_rev = xhci->usb3_rhub.min_rev;
|
|
+ if (minor_rev) {
|
|
hcd->speed = HCD_USB31;
|
|
hcd->self.root_hub->speed = USB_SPEED_SUPER_PLUS;
|
|
}
|
|
+ xhci_info(xhci, "Host supports USB 3.%x %s SuperSpeed\n",
|
|
+ minor_rev,
|
|
+ minor_rev ? "Enhanced" : "");
|
|
+
|
|
/* xHCI private pointer was set in xhci_pci_probe for the second
|
|
* registered roothub.
|
|
*/
|
|
diff --git a/drivers/usb/usbip/Kconfig b/drivers/usb/usbip/Kconfig
|
|
index eeefa29f8aa2..a20b65cb6678 100644
|
|
--- a/drivers/usb/usbip/Kconfig
|
|
+++ b/drivers/usb/usbip/Kconfig
|
|
@@ -27,7 +27,7 @@ config USBIP_VHCI_HCD
|
|
|
|
config USBIP_VHCI_HC_PORTS
|
|
int "Number of ports per USB/IP virtual host controller"
|
|
- range 1 31
|
|
+ range 1 15
|
|
default 8
|
|
depends on USBIP_VHCI_HCD
|
|
---help---
|
|
diff --git a/fs/ext2/inode.c b/fs/ext2/inode.c
|
|
index 1442a4c734c8..a7c87d593083 100644
|
|
--- a/fs/ext2/inode.c
|
|
+++ b/fs/ext2/inode.c
|
|
@@ -1261,21 +1261,11 @@ static void __ext2_truncate_blocks(struct inode *inode, loff_t offset)
|
|
|
|
static void ext2_truncate_blocks(struct inode *inode, loff_t offset)
|
|
{
|
|
- /*
|
|
- * XXX: it seems like a bug here that we don't allow
|
|
- * IS_APPEND inode to have blocks-past-i_size trimmed off.
|
|
- * review and fix this.
|
|
- *
|
|
- * Also would be nice to be able to handle IO errors and such,
|
|
- * but that's probably too much to ask.
|
|
- */
|
|
if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) ||
|
|
S_ISLNK(inode->i_mode)))
|
|
return;
|
|
if (ext2_inode_is_fast_symlink(inode))
|
|
return;
|
|
- if (IS_APPEND(inode) || IS_IMMUTABLE(inode))
|
|
- return;
|
|
|
|
dax_sem_down_write(EXT2_I(inode));
|
|
__ext2_truncate_blocks(inode, offset);
|
|
diff --git a/fs/hfsplus/super.c b/fs/hfsplus/super.c
|
|
index e5bb2de2262a..3cba08c931ee 100644
|
|
--- a/fs/hfsplus/super.c
|
|
+++ b/fs/hfsplus/super.c
|
|
@@ -588,6 +588,7 @@ static int hfsplus_fill_super(struct super_block *sb, void *data, int silent)
|
|
return 0;
|
|
|
|
out_put_hidden_dir:
|
|
+ cancel_delayed_work_sync(&sbi->sync_work);
|
|
iput(sbi->hidden_dir);
|
|
out_put_root:
|
|
dput(sb->s_root);
|
|
diff --git a/include/linux/u64_stats_sync.h b/include/linux/u64_stats_sync.h
|
|
index 5bdbd9f49395..07ee0f84a46c 100644
|
|
--- a/include/linux/u64_stats_sync.h
|
|
+++ b/include/linux/u64_stats_sync.h
|
|
@@ -90,6 +90,28 @@ static inline void u64_stats_update_end(struct u64_stats_sync *syncp)
|
|
#endif
|
|
}
|
|
|
|
+static inline unsigned long
|
|
+u64_stats_update_begin_irqsave(struct u64_stats_sync *syncp)
|
|
+{
|
|
+ unsigned long flags = 0;
|
|
+
|
|
+#if BITS_PER_LONG==32 && defined(CONFIG_SMP)
|
|
+ local_irq_save(flags);
|
|
+ write_seqcount_begin(&syncp->seq);
|
|
+#endif
|
|
+ return flags;
|
|
+}
|
|
+
|
|
+static inline void
|
|
+u64_stats_update_end_irqrestore(struct u64_stats_sync *syncp,
|
|
+ unsigned long flags)
|
|
+{
|
|
+#if BITS_PER_LONG==32 && defined(CONFIG_SMP)
|
|
+ write_seqcount_end(&syncp->seq);
|
|
+ local_irq_restore(flags);
|
|
+#endif
|
|
+}
|
|
+
|
|
static inline void u64_stats_update_begin_raw(struct u64_stats_sync *syncp)
|
|
{
|
|
#if BITS_PER_LONG==32 && defined(CONFIG_SMP)
|
|
diff --git a/include/linux/usb/composite.h b/include/linux/usb/composite.h
|
|
index f665d2ceac20..590d313b5f39 100644
|
|
--- a/include/linux/usb/composite.h
|
|
+++ b/include/linux/usb/composite.h
|
|
@@ -53,6 +53,9 @@
|
|
/* big enough to hold our biggest descriptor */
|
|
#define USB_COMP_EP0_BUFSIZ 1024
|
|
|
|
+/* OS feature descriptor length <= 4kB */
|
|
+#define USB_COMP_EP0_OS_DESC_BUFSIZ 4096
|
|
+
|
|
#define USB_MS_TO_HS_INTERVAL(x) (ilog2((x * 1000 / 125)) + 1)
|
|
struct usb_configuration;
|
|
|
|
diff --git a/include/scsi/scsi.h b/include/scsi/scsi.h
|
|
index cb85eddb47ea..eb7853c1a23b 100644
|
|
--- a/include/scsi/scsi.h
|
|
+++ b/include/scsi/scsi.h
|
|
@@ -47,6 +47,8 @@ static inline int scsi_status_is_good(int status)
|
|
*/
|
|
status &= 0xfe;
|
|
return ((status == SAM_STAT_GOOD) ||
|
|
+ (status == SAM_STAT_CONDITION_MET) ||
|
|
+ /* Next two "intermediate" statuses are obsolete in SAM-4 */
|
|
(status == SAM_STAT_INTERMEDIATE) ||
|
|
(status == SAM_STAT_INTERMEDIATE_CONDITION_MET) ||
|
|
/* FIXME: this is obsolete in SAM-3 */
|
|
diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h
|
|
index 51626b4175c0..3fab6c81917f 100644
|
|
--- a/include/uapi/linux/nl80211.h
|
|
+++ b/include/uapi/linux/nl80211.h
|
|
@@ -2604,6 +2604,8 @@ enum nl80211_attrs {
|
|
#define NL80211_ATTR_KEYS NL80211_ATTR_KEYS
|
|
#define NL80211_ATTR_FEATURE_FLAGS NL80211_ATTR_FEATURE_FLAGS
|
|
|
|
+#define NL80211_WIPHY_NAME_MAXLEN 128
|
|
+
|
|
#define NL80211_MAX_SUPP_RATES 32
|
|
#define NL80211_MAX_SUPP_HT_RATES 77
|
|
#define NL80211_MAX_SUPP_REG_RULES 64
|
|
diff --git a/net/core/dev.c b/net/core/dev.c
|
|
index e7d56c5adde6..6ca771f2f25b 100644
|
|
--- a/net/core/dev.c
|
|
+++ b/net/core/dev.c
|
|
@@ -2058,7 +2058,7 @@ static bool remove_xps_queue_cpu(struct net_device *dev,
|
|
int i, j;
|
|
|
|
for (i = count, j = offset; i--; j++) {
|
|
- if (!remove_xps_queue(dev_maps, cpu, j))
|
|
+ if (!remove_xps_queue(dev_maps, tci, j))
|
|
break;
|
|
}
|
|
|
|
diff --git a/net/core/sock.c b/net/core/sock.c
|
|
index ec6eb546b228..68d08ed5521e 100644
|
|
--- a/net/core/sock.c
|
|
+++ b/net/core/sock.c
|
|
@@ -1595,7 +1595,7 @@ void sk_destruct(struct sock *sk)
|
|
|
|
static void __sk_free(struct sock *sk)
|
|
{
|
|
- if (unlikely(sock_diag_has_destroy_listeners(sk) && sk->sk_net_refcnt))
|
|
+ if (unlikely(sk->sk_net_refcnt && sock_diag_has_destroy_listeners(sk)))
|
|
sock_diag_broadcast_destroy(sk);
|
|
else
|
|
sk_destruct(sk);
|
|
diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c
|
|
index e8e675be60ec..63d5d66e040a 100644
|
|
--- a/net/ipv4/ip_output.c
|
|
+++ b/net/ipv4/ip_output.c
|
|
@@ -1040,7 +1040,8 @@ static int __ip_append_data(struct sock *sk,
|
|
if (copy > length)
|
|
copy = length;
|
|
|
|
- if (!(rt->dst.dev->features&NETIF_F_SG)) {
|
|
+ if (!(rt->dst.dev->features&NETIF_F_SG) &&
|
|
+ skb_tailroom(skb) >= copy) {
|
|
unsigned int off;
|
|
|
|
off = skb->len;
|
|
diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c
|
|
index 83d11cd2eb65..abae5196cd3a 100644
|
|
--- a/net/ipv4/tcp_output.c
|
|
+++ b/net/ipv4/tcp_output.c
|
|
@@ -2814,8 +2814,10 @@ int __tcp_retransmit_skb(struct sock *sk, struct sk_buff *skb, int segs)
|
|
return -EBUSY;
|
|
|
|
if (before(TCP_SKB_CB(skb)->seq, tp->snd_una)) {
|
|
- if (before(TCP_SKB_CB(skb)->end_seq, tp->snd_una))
|
|
- BUG();
|
|
+ if (unlikely(before(TCP_SKB_CB(skb)->end_seq, tp->snd_una))) {
|
|
+ WARN_ON_ONCE(1);
|
|
+ return -EINVAL;
|
|
+ }
|
|
if (tcp_trim_head(sk, skb, tp->snd_una - TCP_SKB_CB(skb)->seq))
|
|
return -ENOMEM;
|
|
}
|
|
@@ -3312,6 +3314,7 @@ static void tcp_connect_init(struct sock *sk)
|
|
sock_reset_flag(sk, SOCK_DONE);
|
|
tp->snd_wnd = 0;
|
|
tcp_init_wl(tp, 0);
|
|
+ tcp_write_queue_purge(sk);
|
|
tp->snd_una = tp->write_seq;
|
|
tp->snd_sml = tp->write_seq;
|
|
tp->snd_up = tp->write_seq;
|
|
diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c
|
|
index ffbb81609016..0f2d74885bcb 100644
|
|
--- a/net/ipv6/ip6_output.c
|
|
+++ b/net/ipv6/ip6_output.c
|
|
@@ -1488,7 +1488,8 @@ static int __ip6_append_data(struct sock *sk,
|
|
if (copy > length)
|
|
copy = length;
|
|
|
|
- if (!(rt->dst.dev->features&NETIF_F_SG)) {
|
|
+ if (!(rt->dst.dev->features&NETIF_F_SG) &&
|
|
+ skb_tailroom(skb) >= copy) {
|
|
unsigned int off;
|
|
|
|
off = skb->len;
|
|
diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c
|
|
index 3994b71f8197..8351faabba62 100644
|
|
--- a/net/packet/af_packet.c
|
|
+++ b/net/packet/af_packet.c
|
|
@@ -2912,13 +2912,15 @@ static int packet_snd(struct socket *sock, struct msghdr *msg, size_t len)
|
|
if (skb == NULL)
|
|
goto out_unlock;
|
|
|
|
- skb_set_network_header(skb, reserve);
|
|
+ skb_reset_network_header(skb);
|
|
|
|
err = -EINVAL;
|
|
if (sock->type == SOCK_DGRAM) {
|
|
offset = dev_hard_header(skb, dev, ntohs(proto), addr, NULL, len);
|
|
if (unlikely(offset < 0))
|
|
goto out_free;
|
|
+ } else if (reserve) {
|
|
+ skb_push(skb, reserve);
|
|
}
|
|
|
|
/* Returns -EFAULT on error */
|
|
diff --git a/net/sched/act_vlan.c b/net/sched/act_vlan.c
|
|
index 16eb067a8d8f..5c10a0fce35b 100644
|
|
--- a/net/sched/act_vlan.c
|
|
+++ b/net/sched/act_vlan.c
|
|
@@ -154,6 +154,8 @@ static int tcf_vlan_init(struct net *net, struct nlattr *nla,
|
|
case htons(ETH_P_8021AD):
|
|
break;
|
|
default:
|
|
+ if (exists)
|
|
+ tcf_idr_release(*a, bind);
|
|
return -EPROTONOSUPPORT;
|
|
}
|
|
} else {
|
|
diff --git a/net/sched/sch_red.c b/net/sched/sch_red.c
|
|
index d87c41e82917..c453b8d81c9e 100644
|
|
--- a/net/sched/sch_red.c
|
|
+++ b/net/sched/sch_red.c
|
|
@@ -191,10 +191,11 @@ static int red_change(struct Qdisc *sch, struct nlattr *opt)
|
|
child = fifo_create_dflt(sch, &bfifo_qdisc_ops, ctl->limit);
|
|
if (IS_ERR(child))
|
|
return PTR_ERR(child);
|
|
- }
|
|
|
|
- if (child != &noop_qdisc)
|
|
+ /* child is fifo, no need to check for noop_qdisc */
|
|
qdisc_hash_add(child, true);
|
|
+ }
|
|
+
|
|
sch_tree_lock(sch);
|
|
q->flags = ctl->flags;
|
|
q->limit = ctl->limit;
|
|
diff --git a/net/sched/sch_tbf.c b/net/sched/sch_tbf.c
|
|
index 120f4f365967..b36ecb58aa6e 100644
|
|
--- a/net/sched/sch_tbf.c
|
|
+++ b/net/sched/sch_tbf.c
|
|
@@ -388,6 +388,9 @@ static int tbf_change(struct Qdisc *sch, struct nlattr *opt)
|
|
err = PTR_ERR(child);
|
|
goto done;
|
|
}
|
|
+
|
|
+ /* child is fifo, no need to check for noop_qdisc */
|
|
+ qdisc_hash_add(child, true);
|
|
}
|
|
|
|
sch_tree_lock(sch);
|
|
@@ -396,8 +399,6 @@ static int tbf_change(struct Qdisc *sch, struct nlattr *opt)
|
|
q->qdisc->qstats.backlog);
|
|
qdisc_destroy(q->qdisc);
|
|
q->qdisc = child;
|
|
- if (child != &noop_qdisc)
|
|
- qdisc_hash_add(child, true);
|
|
}
|
|
q->limit = qopt->limit;
|
|
if (tb[TCA_TBF_PBURST])
|
|
diff --git a/net/smc/smc_pnet.c b/net/smc/smc_pnet.c
|
|
index 74568cdbca70..d7b88b2d1b22 100644
|
|
--- a/net/smc/smc_pnet.c
|
|
+++ b/net/smc/smc_pnet.c
|
|
@@ -245,40 +245,45 @@ static struct smc_ib_device *smc_pnet_find_ib(char *ib_name)
|
|
static int smc_pnet_fill_entry(struct net *net, struct smc_pnetentry *pnetelem,
|
|
struct nlattr *tb[])
|
|
{
|
|
- char *string, *ibname = NULL;
|
|
- int rc = 0;
|
|
+ char *string, *ibname;
|
|
+ int rc;
|
|
|
|
memset(pnetelem, 0, sizeof(*pnetelem));
|
|
INIT_LIST_HEAD(&pnetelem->list);
|
|
- if (tb[SMC_PNETID_NAME]) {
|
|
- string = (char *)nla_data(tb[SMC_PNETID_NAME]);
|
|
- if (!smc_pnetid_valid(string, pnetelem->pnet_name)) {
|
|
- rc = -EINVAL;
|
|
- goto error;
|
|
- }
|
|
- }
|
|
- if (tb[SMC_PNETID_ETHNAME]) {
|
|
- string = (char *)nla_data(tb[SMC_PNETID_ETHNAME]);
|
|
- pnetelem->ndev = dev_get_by_name(net, string);
|
|
- if (!pnetelem->ndev)
|
|
- return -ENOENT;
|
|
- }
|
|
- if (tb[SMC_PNETID_IBNAME]) {
|
|
- ibname = (char *)nla_data(tb[SMC_PNETID_IBNAME]);
|
|
- ibname = strim(ibname);
|
|
- pnetelem->smcibdev = smc_pnet_find_ib(ibname);
|
|
- if (!pnetelem->smcibdev) {
|
|
- rc = -ENOENT;
|
|
- goto error;
|
|
- }
|
|
- }
|
|
- if (tb[SMC_PNETID_IBPORT]) {
|
|
- pnetelem->ib_port = nla_get_u8(tb[SMC_PNETID_IBPORT]);
|
|
- if (pnetelem->ib_port > SMC_MAX_PORTS) {
|
|
- rc = -EINVAL;
|
|
- goto error;
|
|
- }
|
|
- }
|
|
+
|
|
+ rc = -EINVAL;
|
|
+ if (!tb[SMC_PNETID_NAME])
|
|
+ goto error;
|
|
+ string = (char *)nla_data(tb[SMC_PNETID_NAME]);
|
|
+ if (!smc_pnetid_valid(string, pnetelem->pnet_name))
|
|
+ goto error;
|
|
+
|
|
+ rc = -EINVAL;
|
|
+ if (!tb[SMC_PNETID_ETHNAME])
|
|
+ goto error;
|
|
+ rc = -ENOENT;
|
|
+ string = (char *)nla_data(tb[SMC_PNETID_ETHNAME]);
|
|
+ pnetelem->ndev = dev_get_by_name(net, string);
|
|
+ if (!pnetelem->ndev)
|
|
+ goto error;
|
|
+
|
|
+ rc = -EINVAL;
|
|
+ if (!tb[SMC_PNETID_IBNAME])
|
|
+ goto error;
|
|
+ rc = -ENOENT;
|
|
+ ibname = (char *)nla_data(tb[SMC_PNETID_IBNAME]);
|
|
+ ibname = strim(ibname);
|
|
+ pnetelem->smcibdev = smc_pnet_find_ib(ibname);
|
|
+ if (!pnetelem->smcibdev)
|
|
+ goto error;
|
|
+
|
|
+ rc = -EINVAL;
|
|
+ if (!tb[SMC_PNETID_IBPORT])
|
|
+ goto error;
|
|
+ pnetelem->ib_port = nla_get_u8(tb[SMC_PNETID_IBPORT]);
|
|
+ if (pnetelem->ib_port < 1 || pnetelem->ib_port > SMC_MAX_PORTS)
|
|
+ goto error;
|
|
+
|
|
return 0;
|
|
|
|
error:
|
|
@@ -307,6 +312,8 @@ static int smc_pnet_get(struct sk_buff *skb, struct genl_info *info)
|
|
void *hdr;
|
|
int rc;
|
|
|
|
+ if (!info->attrs[SMC_PNETID_NAME])
|
|
+ return -EINVAL;
|
|
pnetelem = smc_pnet_find_pnetid(
|
|
(char *)nla_data(info->attrs[SMC_PNETID_NAME]));
|
|
if (!pnetelem)
|
|
@@ -359,6 +366,8 @@ static int smc_pnet_add(struct sk_buff *skb, struct genl_info *info)
|
|
|
|
static int smc_pnet_del(struct sk_buff *skb, struct genl_info *info)
|
|
{
|
|
+ if (!info->attrs[SMC_PNETID_NAME])
|
|
+ return -EINVAL;
|
|
return smc_pnet_remove_by_pnetid(
|
|
(char *)nla_data(info->attrs[SMC_PNETID_NAME]));
|
|
}
|
|
diff --git a/net/wireless/core.c b/net/wireless/core.c
|
|
index 33ce0484b2a0..45cbade9ad68 100644
|
|
--- a/net/wireless/core.c
|
|
+++ b/net/wireless/core.c
|
|
@@ -95,6 +95,9 @@ static int cfg80211_dev_check_name(struct cfg80211_registered_device *rdev,
|
|
|
|
ASSERT_RTNL();
|
|
|
|
+ if (strlen(newname) > NL80211_WIPHY_NAME_MAXLEN)
|
|
+ return -EINVAL;
|
|
+
|
|
/* prohibit calling the thing phy%d when %d is not its number */
|
|
sscanf(newname, PHY_NAME "%d%n", &wiphy_idx, &taken);
|
|
if (taken == strlen(newname) && wiphy_idx != rdev->wiphy_idx) {
|
|
diff --git a/sound/soc/codecs/hdmi-codec.c b/sound/soc/codecs/hdmi-codec.c
|
|
index 3abf82563408..cf3b905b4ead 100644
|
|
--- a/sound/soc/codecs/hdmi-codec.c
|
|
+++ b/sound/soc/codecs/hdmi-codec.c
|
|
@@ -801,12 +801,7 @@ static int hdmi_codec_probe(struct platform_device *pdev)
|
|
|
|
static int hdmi_codec_remove(struct platform_device *pdev)
|
|
{
|
|
- struct device *dev = &pdev->dev;
|
|
- struct hdmi_codec_priv *hcp;
|
|
-
|
|
- hcp = dev_get_drvdata(dev);
|
|
- kfree(hcp->chmap_info);
|
|
- snd_soc_unregister_codec(dev);
|
|
+ snd_soc_unregister_codec(&pdev->dev);
|
|
|
|
return 0;
|
|
}
|
|
diff --git a/sound/soc/rockchip/Kconfig b/sound/soc/rockchip/Kconfig
|
|
index b0825370d262..957046ac6c8c 100644
|
|
--- a/sound/soc/rockchip/Kconfig
|
|
+++ b/sound/soc/rockchip/Kconfig
|
|
@@ -56,6 +56,9 @@ config SND_SOC_RK3288_HDMI_ANALOG
|
|
depends on SND_SOC_ROCKCHIP && I2C && GPIOLIB && CLKDEV_LOOKUP
|
|
select SND_SOC_ROCKCHIP_I2S
|
|
select SND_SOC_HDMI_CODEC
|
|
+ select SND_SOC_ES8328_I2C
|
|
+ select SND_SOC_ES8328_SPI if SPI_MASTER
|
|
+ select DRM_DW_HDMI_I2S_AUDIO if DRM_DW_HDMI
|
|
help
|
|
Say Y or M here if you want to add support for SoC audio on Rockchip
|
|
RK3288 boards using an analog output and the built-in HDMI audio.
|
|
diff --git a/sound/soc/samsung/i2s.c b/sound/soc/samsung/i2s.c
|
|
index 10a4da06c0a1..f058f2bdd519 100644
|
|
--- a/sound/soc/samsung/i2s.c
|
|
+++ b/sound/soc/samsung/i2s.c
|
|
@@ -653,8 +653,12 @@ static int i2s_set_fmt(struct snd_soc_dai *dai,
|
|
tmp |= mod_slave;
|
|
break;
|
|
case SND_SOC_DAIFMT_CBS_CFS:
|
|
- /* Set default source clock in Master mode */
|
|
- if (i2s->rclk_srcrate == 0)
|
|
+ /*
|
|
+ * Set default source clock in Master mode, only when the
|
|
+ * CLK_I2S_RCLK_SRC clock is not exposed so we ensure any
|
|
+ * clock configuration assigned in DT is not overwritten.
|
|
+ */
|
|
+ if (i2s->rclk_srcrate == 0 && i2s->clk_data.clks == NULL)
|
|
i2s_set_sysclk(dai, SAMSUNG_I2S_RCLKSRC_0,
|
|
0, SND_SOC_CLOCK_IN);
|
|
break;
|
|
@@ -878,6 +882,11 @@ static int config_setup(struct i2s_dai *i2s)
|
|
return 0;
|
|
|
|
if (!(i2s->quirks & QUIRK_NO_MUXPSR)) {
|
|
+ struct clk *rclksrc = i2s->clk_table[CLK_I2S_RCLK_SRC];
|
|
+
|
|
+ if (i2s->rclk_srcrate == 0 && rclksrc && !IS_ERR(rclksrc))
|
|
+ i2s->rclk_srcrate = clk_get_rate(rclksrc);
|
|
+
|
|
psr = i2s->rclk_srcrate / i2s->frmclk / rfs;
|
|
writel(((psr - 1) << 8) | PSR_PSREN, i2s->addr + I2SPSR);
|
|
dev_dbg(&i2s->pdev->dev,
|
|
diff --git a/sound/soc/samsung/odroid.c b/sound/soc/samsung/odroid.c
|
|
index 44b6de5a331a..06a31a9585a0 100644
|
|
--- a/sound/soc/samsung/odroid.c
|
|
+++ b/sound/soc/samsung/odroid.c
|
|
@@ -36,23 +36,26 @@ static int odroid_card_hw_params(struct snd_pcm_substream *substream,
|
|
{
|
|
struct snd_soc_pcm_runtime *rtd = substream->private_data;
|
|
struct odroid_priv *priv = snd_soc_card_get_drvdata(rtd->card);
|
|
- unsigned int pll_freq, rclk_freq;
|
|
+ unsigned int pll_freq, rclk_freq, rfs;
|
|
int ret;
|
|
|
|
switch (params_rate(params)) {
|
|
- case 32000:
|
|
case 64000:
|
|
- pll_freq = 131072006U;
|
|
+ pll_freq = 196608001U;
|
|
+ rfs = 384;
|
|
break;
|
|
case 44100:
|
|
case 88200:
|
|
case 176400:
|
|
pll_freq = 180633609U;
|
|
+ rfs = 512;
|
|
break;
|
|
+ case 32000:
|
|
case 48000:
|
|
case 96000:
|
|
case 192000:
|
|
pll_freq = 196608001U;
|
|
+ rfs = 512;
|
|
break;
|
|
default:
|
|
return -EINVAL;
|
|
@@ -67,7 +70,7 @@ static int odroid_card_hw_params(struct snd_pcm_substream *substream,
|
|
* frequency values due to the EPLL output frequency not being exact
|
|
* multiple of the audio sampling rate.
|
|
*/
|
|
- rclk_freq = params_rate(params) * 256 + 1;
|
|
+ rclk_freq = params_rate(params) * rfs + 1;
|
|
|
|
ret = clk_set_rate(priv->sclk_i2s, rclk_freq);
|
|
if (ret < 0)
|
|
diff --git a/sound/soc/soc-topology.c b/sound/soc/soc-topology.c
|
|
index 782c580b7aa3..e5049fbfc4f1 100644
|
|
--- a/sound/soc/soc-topology.c
|
|
+++ b/sound/soc/soc-topology.c
|
|
@@ -1276,6 +1276,9 @@ static struct snd_kcontrol_new *soc_tplg_dapm_widget_dmixer_create(
|
|
kfree(sm);
|
|
continue;
|
|
}
|
|
+
|
|
+ /* create any TLV data */
|
|
+ soc_tplg_create_tlv(tplg, &kc[i], &mc->hdr);
|
|
}
|
|
return kc;
|
|
|
|
diff --git a/sound/usb/quirks.c b/sound/usb/quirks.c
|
|
index 58f94f399efb..ad14d6b78bdc 100644
|
|
--- a/sound/usb/quirks.c
|
|
+++ b/sound/usb/quirks.c
|
|
@@ -1155,24 +1155,27 @@ bool snd_usb_get_sample_rate_quirk(struct snd_usb_audio *chip)
|
|
return false;
|
|
}
|
|
|
|
-/* Marantz/Denon USB DACs need a vendor cmd to switch
|
|
+/* ITF-USB DSD based DACs need a vendor cmd to switch
|
|
* between PCM and native DSD mode
|
|
+ * (2 altsets version)
|
|
*/
|
|
-static bool is_marantz_denon_dac(unsigned int id)
|
|
+static bool is_itf_usb_dsd_2alts_dac(unsigned int id)
|
|
{
|
|
switch (id) {
|
|
case USB_ID(0x154e, 0x1003): /* Denon DA-300USB */
|
|
case USB_ID(0x154e, 0x3005): /* Marantz HD-DAC1 */
|
|
case USB_ID(0x154e, 0x3006): /* Marantz SA-14S1 */
|
|
+ case USB_ID(0x1852, 0x5065): /* Luxman DA-06 */
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
-/* TEAC UD-501/UD-503/NT-503 USB DACs need a vendor cmd to switch
|
|
- * between PCM/DOP and native DSD mode
|
|
+/* ITF-USB DSD based DACs need a vendor cmd to switch
|
|
+ * between PCM and native DSD mode
|
|
+ * (3 altsets version)
|
|
*/
|
|
-static bool is_teac_dsd_dac(unsigned int id)
|
|
+static bool is_itf_usb_dsd_3alts_dac(unsigned int id)
|
|
{
|
|
switch (id) {
|
|
case USB_ID(0x0644, 0x8043): /* TEAC UD-501/UD-503/NT-503 */
|
|
@@ -1189,7 +1192,7 @@ int snd_usb_select_mode_quirk(struct snd_usb_substream *subs,
|
|
struct usb_device *dev = subs->dev;
|
|
int err;
|
|
|
|
- if (is_marantz_denon_dac(subs->stream->chip->usb_id)) {
|
|
+ if (is_itf_usb_dsd_2alts_dac(subs->stream->chip->usb_id)) {
|
|
/* First switch to alt set 0, otherwise the mode switch cmd
|
|
* will not be accepted by the DAC
|
|
*/
|
|
@@ -1210,7 +1213,7 @@ int snd_usb_select_mode_quirk(struct snd_usb_substream *subs,
|
|
break;
|
|
}
|
|
mdelay(20);
|
|
- } else if (is_teac_dsd_dac(subs->stream->chip->usb_id)) {
|
|
+ } else if (is_itf_usb_dsd_3alts_dac(subs->stream->chip->usb_id)) {
|
|
/* Vendor mode switch cmd is required. */
|
|
switch (fmt->altsetting) {
|
|
case 3: /* DSD mode (DSD_U32) requested */
|
|
@@ -1306,10 +1309,10 @@ void snd_usb_ctl_msg_quirk(struct usb_device *dev, unsigned int pipe,
|
|
(requesttype & USB_TYPE_MASK) == USB_TYPE_CLASS)
|
|
mdelay(20);
|
|
|
|
- /* Marantz/Denon devices with USB DAC functionality need a delay
|
|
+ /* ITF-USB DSD based DACs functionality need a delay
|
|
* after each class compliant request
|
|
*/
|
|
- if (is_marantz_denon_dac(chip->usb_id)
|
|
+ if (is_itf_usb_dsd_2alts_dac(chip->usb_id)
|
|
&& (requesttype & USB_TYPE_MASK) == USB_TYPE_CLASS)
|
|
mdelay(20);
|
|
|
|
@@ -1396,14 +1399,14 @@ u64 snd_usb_interface_dsd_format_quirks(struct snd_usb_audio *chip,
|
|
break;
|
|
}
|
|
|
|
- /* Denon/Marantz devices with USB DAC functionality */
|
|
- if (is_marantz_denon_dac(chip->usb_id)) {
|
|
+ /* ITF-USB DSD based DACs (2 altsets version) */
|
|
+ if (is_itf_usb_dsd_2alts_dac(chip->usb_id)) {
|
|
if (fp->altsetting == 2)
|
|
return SNDRV_PCM_FMTBIT_DSD_U32_BE;
|
|
}
|
|
|
|
- /* TEAC devices with USB DAC functionality */
|
|
- if (is_teac_dsd_dac(chip->usb_id)) {
|
|
+ /* ITF-USB DSD based DACs (3 altsets version) */
|
|
+ if (is_itf_usb_dsd_3alts_dac(chip->usb_id)) {
|
|
if (fp->altsetting == 3)
|
|
return SNDRV_PCM_FMTBIT_DSD_U32_BE;
|
|
}
|