diff --git a/Documentation/admin-guide/security-bugs.rst b/Documentation/admin-guide/security-bugs.rst index 30187d49dc2c7..67161e1b0f0bd 100644 --- a/Documentation/admin-guide/security-bugs.rst +++ b/Documentation/admin-guide/security-bugs.rst @@ -56,31 +56,28 @@ information submitted to the security list and any followup discussions of the report are treated confidentially even after the embargo has been lifted, in perpetuity. -Coordination ------------- - -Fixes for sensitive bugs, such as those that might lead to privilege -escalations, may need to be coordinated with the private - mailing list so that distribution vendors -are well prepared to issue a fixed kernel upon public disclosure of the -upstream fix. Distros will need some time to test the proposed patch and -will generally request at least a few days of embargo, and vendor update -publication prefers to happen Tuesday through Thursday. When appropriate, -the security team can assist with this coordination, or the reporter can -include linux-distros from the start. In this case, remember to prefix -the email Subject line with "[vs]" as described in the linux-distros wiki: - +Coordination with other groups +------------------------------ + +The kernel security team strongly recommends that reporters of potential +security issues NEVER contact the "linux-distros" mailing list until +AFTER discussing it with the kernel security team. Do not Cc: both +lists at once. You may contact the linux-distros mailing list after a +fix has been agreed on and you fully understand the requirements that +doing so will impose on you and the kernel community. + +The different lists have different goals and the linux-distros rules do +not contribute to actually fixing any potential security problems. CVE assignment -------------- -The security team does not normally assign CVEs, nor do we require them -for reports or fixes, as this can needlessly complicate the process and -may delay the bug handling. If a reporter wishes to have a CVE identifier -assigned ahead of public disclosure, they will need to contact the private -linux-distros list, described above. When such a CVE identifier is known -before a patch is provided, it is desirable to mention it in the commit -message if the reporter agrees. +The security team does not assign CVEs, nor do we require them for +reports or fixes, as this can needlessly complicate the process and may +delay the bug handling. If a reporter wishes to have a CVE identifier +assigned, they should find one by themselves, for example by contacting +MITRE directly. However under no circumstances will a patch inclusion +be delayed to wait for a CVE identifier to arrive. Non-disclosure agreements ------------------------- diff --git a/MAINTAINERS b/MAINTAINERS index 3d3d7f5d1c3f1..59003315a9597 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1180,7 +1180,7 @@ N: owl F: arch/arm/mach-actions/ F: arch/arm/boot/dts/owl-* F: arch/arm64/boot/dts/actions/ -F: drivers/clocksource/owl-* +F: drivers/clocksource/timer-owl* F: drivers/pinctrl/actions/* F: drivers/soc/actions/ F: include/dt-bindings/power/owl-* @@ -1603,7 +1603,7 @@ L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) S: Maintained F: arch/arm/boot/dts/lpc43* F: drivers/clk/nxp/clk-lpc18xx* -F: drivers/clocksource/time-lpc32xx.c +F: drivers/clocksource/timer-lpc32xx.c F: drivers/i2c/busses/i2c-lpc2k.c F: drivers/memory/pl172.c F: drivers/mtd/spi-nor/nxp-spifi.c @@ -2219,7 +2219,7 @@ F: arch/arm/mach-vexpress/ F: */*/vexpress* F: */*/*/vexpress* F: drivers/clk/versatile/clk-vexpress-osc.c -F: drivers/clocksource/versatile.c +F: drivers/clocksource/timer-versatile.c N: mps2 ARM/VFP SUPPORT @@ -2241,7 +2241,7 @@ M: Tony Prisk L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) S: Maintained F: arch/arm/mach-vt8500/ -F: drivers/clocksource/vt8500_timer.c +F: drivers/clocksource/timer-vt8500.c F: drivers/i2c/busses/i2c-wmt.c F: drivers/mmc/host/wmt-sdmmc.c F: drivers/pwm/pwm-vt8500.c @@ -2306,7 +2306,7 @@ F: drivers/cpuidle/cpuidle-zynq.c F: drivers/block/xsysace.c N: zynq N: xilinx -F: drivers/clocksource/cadence_ttc_timer.c +F: drivers/clocksource/timer-cadence-ttc.c F: drivers/i2c/busses/i2c-cadence.c F: drivers/mmc/host/sdhci-of-arasan.c F: drivers/edac/synopsys_edac.c diff --git a/Makefile b/Makefile index 5cd8768fc083f..f110fc4f127fa 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ # SPDX-License-Identifier: GPL-2.0 VERSION = 4 PATCHLEVEL = 19 -SUBLEVEL = 290 +SUBLEVEL = 291 EXTRAVERSION = NAME = "People's Front" diff --git a/arch/arc/include/asm/entry-arcv2.h b/arch/arc/include/asm/entry-arcv2.h index 225e7df2d8ed8..0733752ce7fe8 100644 --- a/arch/arc/include/asm/entry-arcv2.h +++ b/arch/arc/include/asm/entry-arcv2.h @@ -7,232 +7,252 @@ #include #include /* For THREAD_SIZE */ +/* + * Interrupt/Exception stack layout (pt_regs) for ARCv2 + * (End of struct aligned to end of page [unless nested]) + * + * INTERRUPT EXCEPTION + * + * manual --------------------- manual + * | orig_r0 | + * | event/ECR | + * | bta | + * | user_r25 | + * | gp | + * | fp | + * | sp | + * | r12 | + * | r30 | + * | r58 | + * | r59 | + * hw autosave --------------------- + * optional | r0 | + * | r1 | + * ~ ~ + * | r9 | + * | r10 | + * | r11 | + * | blink | + * | lpe | + * | lps | + * | lpc | + * | ei base | + * | ldi base | + * | jli base | + * --------------------- + * hw autosave | pc / eret | + * mandatory | stat32 / erstatus | + * --------------------- + */ + /*------------------------------------------------------------------------*/ -.macro INTERRUPT_PROLOGUE called_from +.macro INTERRUPT_PROLOGUE - ; Before jumping to Interrupt Vector, hardware micro-ops did following: + ; (A) Before jumping to Interrupt Vector, hardware micro-ops did following: ; 1. SP auto-switched to kernel mode stack - ; 2. STATUS32.Z flag set to U mode at time of interrupt (U:1, K:0) - ; 3. Auto saved: r0-r11, blink, LPE,LPS,LPC, JLI,LDI,EI, PC, STAT32 + ; 2. STATUS32.Z flag set if in U mode at time of interrupt (U:1,K:0) + ; 3. Auto save: (mandatory) Push PC and STAT32 on stack + ; hardware does even if CONFIG_ARC_IRQ_NO_AUTOSAVE + ; 4. Auto save: (optional) r0-r11, blink, LPE,LPS,LPC, JLI,LDI,EI ; - ; Now manually save: r12, sp, fp, gp, r25 + ; (B) Manually saved some regs: r12,r25,r30, sp,fp,gp, ACCL pair #ifdef CONFIG_ARC_IRQ_NO_AUTOSAVE -.ifnc \called_from, exception - st.as r9, [sp, -10] ; save r9 in it's final stack slot - sub sp, sp, 12 ; skip JLI, LDI, EI - - PUSH lp_count - PUSHAX lp_start - PUSHAX lp_end - PUSH blink - - PUSH r11 - PUSH r10 - - sub sp, sp, 4 ; skip r9 - - PUSH r8 - PUSH r7 - PUSH r6 - PUSH r5 - PUSH r4 - PUSH r3 - PUSH r2 - PUSH r1 - PUSH r0 -.endif -#endif + ; carve pt_regs on stack (case #3), PC/STAT32 already on stack + sub sp, sp, SZ_PT_REGS - 8 -#ifdef CONFIG_ARC_HAS_ACCL_REGS - PUSH r59 - PUSH r58 + __SAVE_REGFILE_HARD +#else + ; carve pt_regs on stack (case #4), which grew partially already + sub sp, sp, PT_r0 #endif - PUSH r30 - PUSH r12 + __SAVE_REGFILE_SOFT +.endm + +/*------------------------------------------------------------------------*/ +.macro EXCEPTION_PROLOGUE + + ; (A) Before jumping to Exception Vector, hardware micro-ops did following: + ; 1. SP auto-switched to kernel mode stack + ; 2. STATUS32.Z flag set if in U mode at time of exception (U:1,K:0) + ; + ; (B) Manually save the complete reg file below + + sub sp, sp, SZ_PT_REGS ; carve pt_regs + + ; _HARD saves r10 clobbered by _SOFT as scratch hence comes first + + __SAVE_REGFILE_HARD + __SAVE_REGFILE_SOFT + + st r0, [sp] ; orig_r0 + + lr r10, [eret] + lr r11, [erstatus] + ST2 r10, r11, PT_ret + + lr r10, [ecr] + lr r11, [erbta] + ST2 r10, r11, PT_event + mov r9, r10 + + ; OUTPUT: r9 has ECR +.endm + +/*------------------------------------------------------------------------ + * This macro saves the registers manually which would normally be autosaved + * by hardware on taken interrupts. It is used by + * - exception handlers (which don't have autosave) + * - interrupt autosave disabled due to CONFIG_ARC_IRQ_NO_AUTOSAVE + */ +.macro __SAVE_REGFILE_HARD + + ST2 r0, r1, PT_r0 + ST2 r2, r3, PT_r2 + ST2 r4, r5, PT_r4 + ST2 r6, r7, PT_r6 + ST2 r8, r9, PT_r8 + ST2 r10, r11, PT_r10 + + st blink, [sp, PT_blink] + + lr r10, [lp_end] + lr r11, [lp_start] + ST2 r10, r11, PT_lpe + + st lp_count, [sp, PT_lpc] + + ; skip JLI, LDI, EI for now +.endm + +/*------------------------------------------------------------------------ + * This macros saves a bunch of other registers which can't be autosaved for + * various reasons: + * - r12: the last caller saved scratch reg since hardware saves in pairs so r0-r11 + * - r30: free reg, used by gcc as scratch + * - ACCL/ACCH pair when they exist + */ +.macro __SAVE_REGFILE_SOFT + + ST2 gp, fp, PT_r26 ; gp (r26), fp (r27) + + st r12, [sp, PT_sp + 4] + st r30, [sp, PT_sp + 8] ; Saving pt_regs->sp correctly requires some extra work due to the way ; Auto stack switch works ; - U mode: retrieve it from AUX_USER_SP ; - K mode: add the offset from current SP where H/w starts auto push ; - ; Utilize the fact that Z bit is set if Intr taken in U mode - mov.nz r9, sp - add.nz r9, r9, SZ_PT_REGS - PT_sp - 4 - bnz 1f + ; 1. Utilize the fact that Z bit is set if Intr taken in U mode + ; 2. Upon entry SP is always saved (for any inspection, unwinding etc), + ; but on return, restored only if U mode - lr r9, [AUX_USER_SP] -1: - PUSH r9 ; SP + lr r10, [AUX_USER_SP] ; U mode SP + + ; ISA requires ADD.nz to have same dest and src reg operands + mov.nz r10, sp + add.nz r10, r10, SZ_PT_REGS ; K mode SP - PUSH fp - PUSH gp + st r10, [sp, PT_sp] ; SP (pt_regs->sp) #ifdef CONFIG_ARC_CURR_IN_REG - PUSH r25 ; user_r25 + st r25, [sp, PT_user_r25] GET_CURR_TASK_ON_CPU r25 -#else - sub sp, sp, 4 #endif -.ifnc \called_from, exception - sub sp, sp, 12 ; BTA/ECR/orig_r0 placeholder per pt_regs -.endif +#ifdef CONFIG_ARC_HAS_ACCL_REGS + ST2 r58, r59, PT_sp + 12 +#endif .endm /*------------------------------------------------------------------------*/ -.macro INTERRUPT_EPILOGUE called_from +.macro __RESTORE_REGFILE_SOFT -.ifnc \called_from, exception - add sp, sp, 12 ; skip BTA/ECR/orig_r0 placeholderss -.endif + LD2 gp, fp, PT_r26 ; gp (r26), fp (r27) -#ifdef CONFIG_ARC_CURR_IN_REG - POP r25 -#else - add sp, sp, 4 -#endif + ld r12, [sp, PT_sp + 4] + ld r30, [sp, PT_sp + 8] - POP gp - POP fp - - ; Don't touch AUX_USER_SP if returning to K mode (Z bit set) - ; (Z bit set on K mode is inverse of INTERRUPT_PROLOGUE) - add.z sp, sp, 4 + ; Restore SP (into AUX_USER_SP) only if returning to U mode + ; - for K mode, it will be implicitly restored as stack is unwound + ; - Z flag set on K is inverse of what hardware does on interrupt entry + ; but that doesn't really matter bz 1f - POPAX AUX_USER_SP + ld r10, [sp, PT_sp] ; SP (pt_regs->sp) + sr r10, [AUX_USER_SP] 1: - POP r12 - POP r30 -#ifdef CONFIG_ARC_HAS_ACCL_REGS - POP r58 - POP r59 +#ifdef CONFIG_ARC_CURR_IN_REG + ld r25, [sp, PT_user_r25] #endif -#ifdef CONFIG_ARC_IRQ_NO_AUTOSAVE -.ifnc \called_from, exception - POP r0 - POP r1 - POP r2 - POP r3 - POP r4 - POP r5 - POP r6 - POP r7 - POP r8 - POP r9 - POP r10 - POP r11 - - POP blink - POPAX lp_end - POPAX lp_start - - POP r9 - mov lp_count, r9 - - add sp, sp, 12 ; skip JLI, LDI, EI - ld.as r9, [sp, -10] ; reload r9 which got clobbered -.endif +#ifdef CONFIG_ARC_HAS_ACCL_REGS + LD2 r58, r59, PT_sp + 12 #endif +.endm +/*------------------------------------------------------------------------*/ +.macro __RESTORE_REGFILE_HARD + + ld blink, [sp, PT_blink] + + LD2 r10, r11, PT_lpe + sr r10, [lp_end] + sr r11, [lp_start] + + ld r10, [sp, PT_lpc] ; lp_count can't be target of LD + mov lp_count, r10 + + LD2 r0, r1, PT_r0 + LD2 r2, r3, PT_r2 + LD2 r4, r5, PT_r4 + LD2 r6, r7, PT_r6 + LD2 r8, r9, PT_r8 + LD2 r10, r11, PT_r10 .endm + /*------------------------------------------------------------------------*/ -.macro EXCEPTION_PROLOGUE +.macro INTERRUPT_EPILOGUE - ; Before jumping to Exception Vector, hardware micro-ops did following: - ; 1. SP auto-switched to kernel mode stack - ; 2. STATUS32.Z flag set to U mode at time of interrupt (U:1,K:0) - ; - ; Now manually save the complete reg file - - PUSH r9 ; freeup a register: slot of erstatus - - PUSHAX eret - sub sp, sp, 12 ; skip JLI, LDI, EI - PUSH lp_count - PUSHAX lp_start - PUSHAX lp_end - PUSH blink - - PUSH r11 - PUSH r10 - - ld.as r9, [sp, 10] ; load stashed r9 (status32 stack slot) - lr r10, [erstatus] - st.as r10, [sp, 10] ; save status32 at it's right stack slot - - PUSH r9 - PUSH r8 - PUSH r7 - PUSH r6 - PUSH r5 - PUSH r4 - PUSH r3 - PUSH r2 - PUSH r1 - PUSH r0 - - ; -- for interrupts, regs above are auto-saved by h/w in that order -- - ; Now do what ISR prologue does (manually save r12, sp, fp, gp, r25) - ; - ; Set Z flag if this was from U mode (expected by INTERRUPT_PROLOGUE) - ; Although H/w exception micro-ops do set Z flag for U mode (just like - ; for interrupts), it could get clobbered in case we soft land here from - ; a TLB Miss exception handler (tlbex.S) + ; INPUT: r0 has STAT32 of calling context + ; INPUT: Z flag set if returning to K mode - and r10, r10, STATUS_U_MASK - xor.f 0, r10, STATUS_U_MASK + ; _SOFT clobbers r10 restored by _HARD hence the order - INTERRUPT_PROLOGUE exception + __RESTORE_REGFILE_SOFT - PUSHAX erbta - PUSHAX ecr ; r9 contains ECR, expected by EV_Trap +#ifdef CONFIG_ARC_IRQ_NO_AUTOSAVE + __RESTORE_REGFILE_HARD + add sp, sp, SZ_PT_REGS - 8 +#else + add sp, sp, PT_r0 +#endif - PUSH r0 ; orig_r0 .endm /*------------------------------------------------------------------------*/ .macro EXCEPTION_EPILOGUE - ; Assumes r0 has PT_status32 - btst r0, STATUS_U_BIT ; Z flag set if K, used in INTERRUPT_EPILOGUE - - add sp, sp, 8 ; orig_r0/ECR don't need restoring - POPAX erbta - - INTERRUPT_EPILOGUE exception + ; INPUT: r0 has STAT32 of calling context - POP r0 - POP r1 - POP r2 - POP r3 - POP r4 - POP r5 - POP r6 - POP r7 - POP r8 - POP r9 - POP r10 - POP r11 + btst r0, STATUS_U_BIT ; Z flag set if K, used in restoring SP - POP blink - POPAX lp_end - POPAX lp_start + ld r10, [sp, PT_event + 4] + sr r10, [erbta] - POP r9 - mov lp_count, r9 + LD2 r10, r11, PT_ret + sr r10, [eret] + sr r11, [erstatus] - add sp, sp, 12 ; skip JLI, LDI, EI - POPAX eret - POPAX erstatus + __RESTORE_REGFILE_SOFT + __RESTORE_REGFILE_HARD - ld.as r9, [sp, -12] ; reload r9 which got clobbered + add sp, sp, SZ_PT_REGS .endm .macro FAKE_RET_FROM_EXCPN diff --git a/arch/arc/include/asm/linkage.h b/arch/arc/include/asm/linkage.h index 07c8e1a6c56e2..b89ca8b4d5975 100644 --- a/arch/arc/include/asm/linkage.h +++ b/arch/arc/include/asm/linkage.h @@ -11,12 +11,30 @@ #include -#ifdef __ASSEMBLY__ - #define ASM_NL ` /* use '`' to mark new line in macro */ #define __ALIGN .align 4 #define __ALIGN_STR __stringify(__ALIGN) +#ifdef __ASSEMBLY__ + +.macro ST2 e, o, off +#ifdef CONFIG_ARC_HAS_LL64 + std \e, [sp, \off] +#else + st \e, [sp, \off] + st \o, [sp, \off+4] +#endif +.endm + +.macro LD2 e, o, off +#ifdef CONFIG_ARC_HAS_LL64 + ldd \e, [sp, \off] +#else + ld \e, [sp, \off] + ld \o, [sp, \off+4] +#endif +.endm + /* annotation for data we want in DCCM - if enabled in .config */ .macro ARCFP_DATA nm #ifdef CONFIG_ARC_HAS_DCCM diff --git a/arch/arc/kernel/asm-offsets.c b/arch/arc/kernel/asm-offsets.c index ecaf34e9235c2..e90dccecfd833 100644 --- a/arch/arc/kernel/asm-offsets.c +++ b/arch/arc/kernel/asm-offsets.c @@ -58,7 +58,14 @@ int main(void) DEFINE(PT_r5, offsetof(struct pt_regs, r5)); DEFINE(PT_r6, offsetof(struct pt_regs, r6)); DEFINE(PT_r7, offsetof(struct pt_regs, r7)); + DEFINE(PT_r8, offsetof(struct pt_regs, r8)); + DEFINE(PT_r10, offsetof(struct pt_regs, r10)); + DEFINE(PT_r26, offsetof(struct pt_regs, r26)); DEFINE(PT_ret, offsetof(struct pt_regs, ret)); + DEFINE(PT_blink, offsetof(struct pt_regs, blink)); + DEFINE(PT_lpe, offsetof(struct pt_regs, lp_end)); + DEFINE(PT_lpc, offsetof(struct pt_regs, lp_count)); + DEFINE(PT_user_r25, offsetof(struct pt_regs, user_r25)); DEFINE(SZ_CALLEE_REGS, sizeof(struct callee_regs)); DEFINE(SZ_PT_REGS, sizeof(struct pt_regs)); diff --git a/arch/arc/kernel/entry-arcv2.S b/arch/arc/kernel/entry-arcv2.S index 562089d62d9d6..6cbf0ee8a20a7 100644 --- a/arch/arc/kernel/entry-arcv2.S +++ b/arch/arc/kernel/entry-arcv2.S @@ -70,7 +70,7 @@ reserved: ENTRY(handle_interrupt) - INTERRUPT_PROLOGUE irq + INTERRUPT_PROLOGUE # irq control APIs local_irq_save/restore/disable/enable fiddle with # global interrupt enable bits in STATUS32 (.IE for 1 prio, .E[] for 2 prio) @@ -226,7 +226,7 @@ debug_marker_l1: bset.nz r11, r11, AUX_IRQ_ACT_BIT_U ; NZ means U sr r11, [AUX_IRQ_ACT] - INTERRUPT_EPILOGUE irq + INTERRUPT_EPILOGUE rtie ;####### Return from Exception / pure kernel mode ####### diff --git a/arch/arc/mm/tlbex.S b/arch/arc/mm/tlbex.S index 0e1e47a67c736..e50cac799a518 100644 --- a/arch/arc/mm/tlbex.S +++ b/arch/arc/mm/tlbex.S @@ -396,6 +396,17 @@ EV_TLBMissD_fast_ret: ; additional label for VDK OS-kit instrumentation ;-------- Common routine to call Linux Page Fault Handler ----------- do_slow_path_pf: +#ifdef CONFIG_ISA_ARCV2 + ; Set Z flag if exception in U mode. Hardware micro-ops do this on any + ; taken interrupt/exception, and thus is already the case at the entry + ; above, but ensuing code would have already clobbered. + ; EXCEPTION_PROLOGUE called in slow path, relies on correct Z flag set + + lr r2, [erstatus] + and r2, r2, STATUS_U_MASK + bxor.f 0, r2, STATUS_U_BIT +#endif + ; Restore the 4-scratch regs saved by fast path miss handler TLBMISS_RESTORE_REGS diff --git a/arch/arm/boot/dts/bcm5301x.dtsi b/arch/arm/boot/dts/bcm5301x.dtsi index 6edc4bd1e7eaf..a6406a347690e 100644 --- a/arch/arm/boot/dts/bcm5301x.dtsi +++ b/arch/arm/boot/dts/bcm5301x.dtsi @@ -468,7 +468,6 @@ "spi_lr_session_done", "spi_lr_overread"; clocks = <&iprocmed>; - clock-names = "iprocmed"; num-cs = <2>; #address-cells = <1>; #size-cells = <0>; diff --git a/arch/arm/boot/dts/imx6qdl.dtsi b/arch/arm/boot/dts/imx6qdl.dtsi index d91cc532d0e2c..fcd7e4dc949a1 100644 --- a/arch/arm/boot/dts/imx6qdl.dtsi +++ b/arch/arm/boot/dts/imx6qdl.dtsi @@ -46,6 +46,10 @@ spi1 = &ecspi2; spi2 = &ecspi3; spi3 = &ecspi4; + usb0 = &usbotg; + usb1 = &usbh1; + usb2 = &usbh2; + usb3 = &usbh3; usbphy0 = &usbphy1; usbphy1 = &usbphy2; }; diff --git a/arch/arm/boot/dts/imx6sl.dtsi b/arch/arm/boot/dts/imx6sl.dtsi index afde0ed6d71af..b00f791471c66 100644 --- a/arch/arm/boot/dts/imx6sl.dtsi +++ b/arch/arm/boot/dts/imx6sl.dtsi @@ -32,6 +32,9 @@ spi1 = &ecspi2; spi2 = &ecspi3; spi3 = &ecspi4; + usb0 = &usbotg1; + usb1 = &usbotg2; + usb2 = &usbh; usbphy0 = &usbphy1; usbphy1 = &usbphy2; }; diff --git a/arch/arm/boot/dts/imx6sll.dtsi b/arch/arm/boot/dts/imx6sll.dtsi index d7d092a5522a3..9f0c82d79a361 100644 --- a/arch/arm/boot/dts/imx6sll.dtsi +++ b/arch/arm/boot/dts/imx6sll.dtsi @@ -36,6 +36,8 @@ spi1 = &ecspi2; spi3 = &ecspi3; spi4 = &ecspi4; + usb0 = &usbotg1; + usb1 = &usbotg2; usbphy0 = &usbphy1; usbphy1 = &usbphy2; }; @@ -49,20 +51,18 @@ device_type = "cpu"; reg = <0>; next-level-cache = <&L2>; - operating-points = < + operating-points = /* kHz uV */ - 996000 1275000 - 792000 1175000 - 396000 1075000 - 198000 975000 - >; - fsl,soc-operating-points = < + <996000 1275000>, + <792000 1175000>, + <396000 1075000>, + <198000 975000>; + fsl,soc-operating-points = /* ARM kHz SOC-PU uV */ - 996000 1175000 - 792000 1175000 - 396000 1175000 - 198000 1175000 - >; + <996000 1175000>, + <792000 1175000>, + <396000 1175000>, + <198000 1175000>; clock-latency = <61036>; /* two CLK32 periods */ clocks = <&clks IMX6SLL_CLK_ARM>, <&clks IMX6SLL_CLK_PLL2_PFD2>, @@ -271,7 +271,7 @@ status = "disabled"; }; - ssi1: ssi-controller@2028000 { + ssi1: ssi@2028000 { compatible = "fsl,imx6sl-ssi", "fsl,imx51-ssi"; reg = <0x02028000 0x4000>; interrupts = ; @@ -284,7 +284,7 @@ status = "disabled"; }; - ssi2: ssi-controller@202c000 { + ssi2: ssi@202c000 { compatible = "fsl,imx6sl-ssi", "fsl,imx51-ssi"; reg = <0x0202c000 0x4000>; interrupts = ; @@ -297,7 +297,7 @@ status = "disabled"; }; - ssi3: ssi-controller@2030000 { + ssi3: ssi@2030000 { compatible = "fsl,imx6sl-ssi", "fsl,imx51-ssi"; reg = <0x02030000 0x4000>; interrupts = ; @@ -518,7 +518,7 @@ reg = <0x020ca000 0x1000>; interrupts = ; clocks = <&clks IMX6SLL_CLK_USBPHY2>; - phy-reg_3p0-supply = <®_3p0>; + phy-3p0-supply = <®_3p0>; fsl,anatop = <&anatop>; }; diff --git a/arch/arm/boot/dts/imx6sx.dtsi b/arch/arm/boot/dts/imx6sx.dtsi index b9ab1118be30b..a0c0e631ebbe6 100644 --- a/arch/arm/boot/dts/imx6sx.dtsi +++ b/arch/arm/boot/dts/imx6sx.dtsi @@ -49,6 +49,9 @@ spi2 = &ecspi3; spi3 = &ecspi4; spi4 = &ecspi5; + usb0 = &usbotg1; + usb1 = &usbotg2; + usb2 = &usbh; usbphy0 = &usbphy1; usbphy1 = &usbphy2; }; diff --git a/arch/arm/boot/dts/imx6ul.dtsi b/arch/arm/boot/dts/imx6ul.dtsi index 334638ff50750..dcb187995f760 100644 --- a/arch/arm/boot/dts/imx6ul.dtsi +++ b/arch/arm/boot/dts/imx6ul.dtsi @@ -47,6 +47,8 @@ spi1 = &ecspi2; spi2 = &ecspi3; spi3 = &ecspi4; + usb0 = &usbotg1; + usb1 = &usbotg2; usbphy0 = &usbphy1; usbphy1 = &usbphy2; }; diff --git a/arch/arm/boot/dts/imx7d.dtsi b/arch/arm/boot/dts/imx7d.dtsi index 7234e8330a576..34904f7eeb133 100644 --- a/arch/arm/boot/dts/imx7d.dtsi +++ b/arch/arm/boot/dts/imx7d.dtsi @@ -7,6 +7,12 @@ #include / { + aliases { + usb0 = &usbotg1; + usb1 = &usbotg2; + usb2 = &usbh; + }; + cpus { cpu0: cpu@0 { clock-frequency = <996000000>; diff --git a/arch/arm/boot/dts/imx7s.dtsi b/arch/arm/boot/dts/imx7s.dtsi index 7eaf96b425bed..8a6d698e253d2 100644 --- a/arch/arm/boot/dts/imx7s.dtsi +++ b/arch/arm/boot/dts/imx7s.dtsi @@ -46,6 +46,8 @@ spi1 = &ecspi2; spi2 = &ecspi3; spi3 = &ecspi4; + usb0 = &usbotg1; + usb1 = &usbh; }; cpus { diff --git a/arch/arm/mach-ep93xx/timer-ep93xx.c b/arch/arm/mach-ep93xx/timer-ep93xx.c index de998830f534f..b07956883e165 100644 --- a/arch/arm/mach-ep93xx/timer-ep93xx.c +++ b/arch/arm/mach-ep93xx/timer-ep93xx.c @@ -9,6 +9,7 @@ #include #include #include "soc.h" +#include "platform.h" /************************************************************************* * Timer handling for EP93xx @@ -60,7 +61,7 @@ static u64 notrace ep93xx_read_sched_clock(void) return ret; } -u64 ep93xx_clocksource_read(struct clocksource *c) +static u64 ep93xx_clocksource_read(struct clocksource *c) { u64 ret; diff --git a/arch/arm/mach-orion5x/board-dt.c b/arch/arm/mach-orion5x/board-dt.c index 3d36f1d951964..3f651df3a71cf 100644 --- a/arch/arm/mach-orion5x/board-dt.c +++ b/arch/arm/mach-orion5x/board-dt.c @@ -63,6 +63,9 @@ static void __init orion5x_dt_init(void) if (of_machine_is_compatible("maxtor,shared-storage-2")) mss2_init(); + if (of_machine_is_compatible("lacie,d2-network")) + d2net_init(); + of_platform_default_populate(NULL, orion5x_auxdata_lookup, NULL); } diff --git a/arch/arm/mach-orion5x/common.h b/arch/arm/mach-orion5x/common.h index eb96009e21c4c..b9cfdb4564568 100644 --- a/arch/arm/mach-orion5x/common.h +++ b/arch/arm/mach-orion5x/common.h @@ -75,6 +75,12 @@ extern void mss2_init(void); static inline void mss2_init(void) {} #endif +#ifdef CONFIG_MACH_D2NET_DT +void d2net_init(void); +#else +static inline void d2net_init(void) {} +#endif + /***************************************************************************** * Helpers to access Orion registers ****************************************************************************/ diff --git a/arch/arm/mach-sa1100/assabet.c b/arch/arm/mach-sa1100/assabet.c index 575ec085cffaf..73bedccedb581 100644 --- a/arch/arm/mach-sa1100/assabet.c +++ b/arch/arm/mach-sa1100/assabet.c @@ -570,7 +570,7 @@ static void __init map_sa1100_gpio_regs( void ) */ static void __init get_assabet_scr(void) { - unsigned long uninitialized_var(scr), i; + unsigned long scr, i; GPDR |= 0x3fc; /* Configure GPIO 9:2 as outputs */ GPSR = 0x3fc; /* Write 0xFF to GPIO 9:2 */ diff --git a/arch/arm/probes/kprobes/checkers-common.c b/arch/arm/probes/kprobes/checkers-common.c index 971119c294741..aa10e5e46ebb2 100644 --- a/arch/arm/probes/kprobes/checkers-common.c +++ b/arch/arm/probes/kprobes/checkers-common.c @@ -48,7 +48,7 @@ enum probes_insn checker_stack_use_imm_0xx(probes_opcode_t insn, * Different from other insn uses imm8, the real addressing offset of * STRD in T32 encoding should be imm8 * 4. See ARMARM description. */ -enum probes_insn checker_stack_use_t32strd(probes_opcode_t insn, +static enum probes_insn checker_stack_use_t32strd(probes_opcode_t insn, struct arch_probes_insn *asi, const struct decode_header *h) { diff --git a/arch/arm/probes/kprobes/core.c b/arch/arm/probes/kprobes/core.c index 62da8e2211e4b..0a7090a65bcad 100644 --- a/arch/arm/probes/kprobes/core.c +++ b/arch/arm/probes/kprobes/core.c @@ -239,7 +239,7 @@ singlestep(struct kprobe *p, struct pt_regs *regs, struct kprobe_ctlblk *kcb) * kprobe, and that level is reserved for user kprobe handlers, so we can't * risk encountering a new kprobe in an interrupt handler. */ -void __kprobes kprobe_handler(struct pt_regs *regs) +static void __kprobes kprobe_handler(struct pt_regs *regs) { struct kprobe *p, *cur; struct kprobe_ctlblk *kcb; diff --git a/arch/arm/probes/kprobes/opt-arm.c b/arch/arm/probes/kprobes/opt-arm.c index cf08cb7267670..1516c340a0766 100644 --- a/arch/arm/probes/kprobes/opt-arm.c +++ b/arch/arm/probes/kprobes/opt-arm.c @@ -158,8 +158,6 @@ __arch_remove_optimized_kprobe(struct optimized_kprobe *op, int dirty) } } -extern void kprobe_handler(struct pt_regs *regs); - static void optimized_callback(struct optimized_kprobe *op, struct pt_regs *regs) { diff --git a/arch/arm/probes/kprobes/test-core.c b/arch/arm/probes/kprobes/test-core.c index cc237fa9b90fb..1c86c5d980c5b 100644 --- a/arch/arm/probes/kprobes/test-core.c +++ b/arch/arm/probes/kprobes/test-core.c @@ -723,7 +723,7 @@ static const char coverage_register_lookup[16] = { [REG_TYPE_NOSPPCX] = COVERAGE_ANY_REG | COVERAGE_SP, }; -unsigned coverage_start_registers(const struct decode_header *h) +static unsigned coverage_start_registers(const struct decode_header *h) { unsigned regs = 0; int i; diff --git a/arch/arm/probes/kprobes/test-core.h b/arch/arm/probes/kprobes/test-core.h index 94285203e9f74..459ebda077139 100644 --- a/arch/arm/probes/kprobes/test-core.h +++ b/arch/arm/probes/kprobes/test-core.h @@ -456,3 +456,7 @@ void kprobe_thumb32_test_cases(void); #else void kprobe_arm_test_cases(void); #endif + +void __kprobes_test_case_start(void); +void __kprobes_test_case_end_16(void); +void __kprobes_test_case_end_32(void); diff --git a/arch/arm64/boot/dts/altera/socfpga_stratix10_socdk.dts b/arch/arm64/boot/dts/altera/socfpga_stratix10_socdk.dts index 636bab51de38d..40a54b55ababd 100644 --- a/arch/arm64/boot/dts/altera/socfpga_stratix10_socdk.dts +++ b/arch/arm64/boot/dts/altera/socfpga_stratix10_socdk.dts @@ -125,7 +125,7 @@ status = "okay"; clock-frequency = <100000>; i2c-sda-falling-time-ns = <890>; /* hcnt */ - i2c-sdl-falling-time-ns = <890>; /* lcnt */ + i2c-scl-falling-time-ns = <890>; /* lcnt */ adc@14 { compatible = "lltc,ltc2497"; diff --git a/arch/arm64/boot/dts/renesas/ulcb-kf.dtsi b/arch/arm64/boot/dts/renesas/ulcb-kf.dtsi index 8bf3091a899c8..5abffdaf4077e 100644 --- a/arch/arm64/boot/dts/renesas/ulcb-kf.dtsi +++ b/arch/arm64/boot/dts/renesas/ulcb-kf.dtsi @@ -165,7 +165,7 @@ }; scif1_pins: scif1 { - groups = "scif1_data_b", "scif1_ctrl"; + groups = "scif1_data_b"; function = "scif1"; }; @@ -178,7 +178,6 @@ &scif1 { pinctrl-0 = <&scif1_pins>; pinctrl-names = "default"; - uart-has-rtscts; status = "okay"; }; diff --git a/arch/ia64/kernel/process.c b/arch/ia64/kernel/process.c index 968b5f33e725e..1a8e20652e7ce 100644 --- a/arch/ia64/kernel/process.c +++ b/arch/ia64/kernel/process.c @@ -444,7 +444,7 @@ static void do_copy_task_regs (struct task_struct *task, struct unw_frame_info *info, void *arg) { unsigned long mask, sp, nat_bits = 0, ar_rnat, urbs_end, cfm; - unsigned long uninitialized_var(ip); /* GCC be quiet */ + unsigned long ip; elf_greg_t *dst = arg; struct pt_regs *pt; char nat; diff --git a/arch/ia64/mm/discontig.c b/arch/ia64/mm/discontig.c index db3104c9fac53..33f68be018a22 100644 --- a/arch/ia64/mm/discontig.c +++ b/arch/ia64/mm/discontig.c @@ -181,7 +181,7 @@ static void *per_cpu_node_setup(void *cpu_data, int node) void __init setup_per_cpu_areas(void) { struct pcpu_alloc_info *ai; - struct pcpu_group_info *uninitialized_var(gi); + struct pcpu_group_info *gi; unsigned int *cpu_map; void *base; unsigned long base_offset; diff --git a/arch/ia64/mm/tlb.c b/arch/ia64/mm/tlb.c index acf10eb9da15c..02470929fb393 100644 --- a/arch/ia64/mm/tlb.c +++ b/arch/ia64/mm/tlb.c @@ -339,7 +339,7 @@ EXPORT_SYMBOL(flush_tlb_range); void ia64_tlb_init(void) { - ia64_ptce_info_t uninitialized_var(ptce_info); /* GCC be quiet */ + ia64_ptce_info_t ptce_info; u64 tr_pgbits; long status; pal_vm_info_1_u_t vm_info_1; diff --git a/arch/powerpc/Kconfig.debug b/arch/powerpc/Kconfig.debug index ffe0cf0f0bea2..923b3b794d13f 100644 --- a/arch/powerpc/Kconfig.debug +++ b/arch/powerpc/Kconfig.debug @@ -232,7 +232,7 @@ config PPC_EARLY_DEBUG_40x config PPC_EARLY_DEBUG_CPM bool "Early serial debugging for Freescale CPM-based serial ports" - depends on SERIAL_CPM + depends on SERIAL_CPM=y help Select this to enable early debugging for Freescale chips using a CPM-based serial port. This assumes that the bootwrapper diff --git a/arch/powerpc/include/asm/word-at-a-time.h b/arch/powerpc/include/asm/word-at-a-time.h index f3f4710d4ff52..99129b0cd8b8a 100644 --- a/arch/powerpc/include/asm/word-at-a-time.h +++ b/arch/powerpc/include/asm/word-at-a-time.h @@ -34,7 +34,7 @@ static inline long find_zero(unsigned long mask) return leading_zero_bits >> 3; } -static inline bool has_zero(unsigned long val, unsigned long *data, const struct word_at_a_time *c) +static inline unsigned long has_zero(unsigned long val, unsigned long *data, const struct word_at_a_time *c) { unsigned long rhs = val | c->low_bits; *data = rhs; diff --git a/arch/powerpc/mm/init_64.c b/arch/powerpc/mm/init_64.c index a5091c0347475..aff86679af961 100644 --- a/arch/powerpc/mm/init_64.c +++ b/arch/powerpc/mm/init_64.c @@ -266,8 +266,7 @@ void __ref vmemmap_free(unsigned long start, unsigned long end, start = _ALIGN_DOWN(start, page_size); if (altmap) { alt_start = altmap->base_pfn; - alt_end = altmap->base_pfn + altmap->reserve + - altmap->free + altmap->alloc + altmap->align; + alt_end = altmap->base_pfn + altmap->reserve + altmap->free; } pr_debug("vmemmap_free %lx...%lx\n", start, end); diff --git a/arch/powerpc/platforms/52xx/mpc52xx_pic.c b/arch/powerpc/platforms/52xx/mpc52xx_pic.c index fc98912f42cf6..76a8102bdb987 100644 --- a/arch/powerpc/platforms/52xx/mpc52xx_pic.c +++ b/arch/powerpc/platforms/52xx/mpc52xx_pic.c @@ -340,7 +340,7 @@ static int mpc52xx_irqhost_map(struct irq_domain *h, unsigned int virq, { int l1irq; int l2irq; - struct irq_chip *uninitialized_var(irqchip); + struct irq_chip *irqchip; void *hndlr; int type; u32 reg; diff --git a/arch/s390/kernel/smp.c b/arch/s390/kernel/smp.c index bce678c7179c8..f272b662301e4 100644 --- a/arch/s390/kernel/smp.c +++ b/arch/s390/kernel/smp.c @@ -145,7 +145,7 @@ static int pcpu_sigp_retry(struct pcpu *pcpu, u8 order, u32 parm) static inline int pcpu_stopped(struct pcpu *pcpu) { - u32 uninitialized_var(status); + u32 status; if (__pcpu_sigp(pcpu->address, SIGP_SENSE, 0, &status) != SIGP_CC_STATUS_STORED) diff --git a/arch/s390/kernel/sthyi.c b/arch/s390/kernel/sthyi.c index 888cc2f166db7..ce6084e28d904 100644 --- a/arch/s390/kernel/sthyi.c +++ b/arch/s390/kernel/sthyi.c @@ -460,9 +460,9 @@ static int sthyi_update_cache(u64 *rc) * * Fills the destination with system information returned by the STHYI * instruction. The data is generated by emulation or execution of STHYI, - * if available. The return value is the condition code that would be - * returned, the rc parameter is the return code which is passed in - * register R2 + 1. + * if available. The return value is either a negative error value or + * the condition code that would be returned, the rc parameter is the + * return code which is passed in register R2 + 1. */ int sthyi_fill(void *dst, u64 *rc) { diff --git a/arch/s390/kvm/intercept.c b/arch/s390/kvm/intercept.c index a389fa85cca2d..5450d43d26ea5 100644 --- a/arch/s390/kvm/intercept.c +++ b/arch/s390/kvm/intercept.c @@ -360,8 +360,8 @@ static int handle_partial_execution(struct kvm_vcpu *vcpu) */ int handle_sthyi(struct kvm_vcpu *vcpu) { - int reg1, reg2, r = 0; - u64 code, addr, cc = 0, rc = 0; + int reg1, reg2, cc = 0, r = 0; + u64 code, addr, rc = 0; struct sthyi_sctns *sctns = NULL; if (!test_kvm_facility(vcpu->kvm, 74)) @@ -392,7 +392,10 @@ int handle_sthyi(struct kvm_vcpu *vcpu) return -ENOMEM; cc = sthyi_fill(sctns, &rc); - + if (cc < 0) { + free_page((unsigned long)sctns); + return cc; + } out: if (!cc) { r = write_guest(vcpu, addr, reg2, sctns, PAGE_SIZE); diff --git a/arch/s390/kvm/kvm-s390.c b/arch/s390/kvm/kvm-s390.c index 3aade928c18dd..92041d442d2e6 100644 --- a/arch/s390/kvm/kvm-s390.c +++ b/arch/s390/kvm/kvm-s390.c @@ -1716,6 +1716,10 @@ static unsigned long kvm_s390_next_dirty_cmma(struct kvm_memslots *slots, ms = slots->memslots + slotidx; ofs = 0; } + + if (cur_gfn < ms->base_gfn) + ofs = 0; + ofs = find_next_bit(kvm_second_dirty_bitmap(ms), ms->npages, ofs); while ((slotidx > 0) && (ofs >= ms->npages)) { slotidx--; diff --git a/arch/sh/drivers/dma/dma-sh.c b/arch/sh/drivers/dma/dma-sh.c index afde2a7d3eb35..e0679d8a9b34b 100644 --- a/arch/sh/drivers/dma/dma-sh.c +++ b/arch/sh/drivers/dma/dma-sh.c @@ -21,6 +21,18 @@ #include #include +/* + * Some of the SoCs feature two DMAC modules. In such a case, the channels are + * distributed equally among them. + */ +#ifdef SH_DMAC_BASE1 +#define SH_DMAC_NR_MD_CH (CONFIG_NR_ONCHIP_DMA_CHANNELS / 2) +#else +#define SH_DMAC_NR_MD_CH CONFIG_NR_ONCHIP_DMA_CHANNELS +#endif + +#define SH_DMAC_CH_SZ 0x10 + /* * Define the default configuration for dual address memory-memory transfer. * The 0x400 value represents auto-request, external->external. @@ -32,7 +44,7 @@ static unsigned long dma_find_base(unsigned int chan) unsigned long base = SH_DMAC_BASE0; #ifdef SH_DMAC_BASE1 - if (chan >= 6) + if (chan >= SH_DMAC_NR_MD_CH) base = SH_DMAC_BASE1; #endif @@ -43,13 +55,13 @@ static unsigned long dma_base_addr(unsigned int chan) { unsigned long base = dma_find_base(chan); - /* Normalize offset calculation */ - if (chan >= 9) - chan -= 6; - if (chan >= 4) - base += 0x10; + chan = (chan % SH_DMAC_NR_MD_CH) * SH_DMAC_CH_SZ; + + /* DMAOR is placed inside the channel register space. Step over it. */ + if (chan >= DMAOR) + base += SH_DMAC_CH_SZ; - return base + (chan * 0x10); + return base + chan; } #ifdef CONFIG_SH_DMA_IRQ_MULTI @@ -253,12 +265,11 @@ static int sh_dmac_get_dma_residue(struct dma_channel *chan) #define NR_DMAOR 1 #endif -/* - * DMAOR bases are broken out amongst channel groups. DMAOR0 manages - * channels 0 - 5, DMAOR1 6 - 11 (optional). - */ -#define dmaor_read_reg(n) __raw_readw(dma_find_base((n)*6)) -#define dmaor_write_reg(n, data) __raw_writew(data, dma_find_base(n)*6) +#define dmaor_read_reg(n) __raw_readw(dma_find_base((n) * \ + SH_DMAC_NR_MD_CH) + DMAOR) +#define dmaor_write_reg(n, data) __raw_writew(data, \ + dma_find_base((n) * \ + SH_DMAC_NR_MD_CH) + DMAOR) static inline int dmaor_reset(int no) { diff --git a/arch/sh/kernel/cpu/sh2/probe.c b/arch/sh/kernel/cpu/sh2/probe.c index a5bd036426789..75dcb1d6bc62f 100644 --- a/arch/sh/kernel/cpu/sh2/probe.c +++ b/arch/sh/kernel/cpu/sh2/probe.c @@ -24,7 +24,7 @@ static int __init scan_cache(unsigned long node, const char *uname, if (!of_flat_dt_is_compatible(node, "jcore,cache")) return 0; - j2_ccr_base = (u32 __iomem *)of_flat_dt_translate_address(node); + j2_ccr_base = ioremap(of_flat_dt_translate_address(node), 4); return 1; } diff --git a/arch/x86/kernel/quirks.c b/arch/x86/kernel/quirks.c index 736348ead4218..2ecf1dcc86b20 100644 --- a/arch/x86/kernel/quirks.c +++ b/arch/x86/kernel/quirks.c @@ -96,7 +96,7 @@ static void ich_force_hpet_resume(void) static void ich_force_enable_hpet(struct pci_dev *dev) { u32 val; - u32 uninitialized_var(rcba); + u32 rcba; int err = 0; if (hpet_address || force_hpet_address) @@ -186,7 +186,7 @@ static void hpet_print_force_info(void) static void old_ich_force_hpet_resume(void) { u32 val; - u32 uninitialized_var(gen_cntl); + u32 gen_cntl; if (!force_hpet_address || !cached_dev) return; @@ -208,7 +208,7 @@ static void old_ich_force_hpet_resume(void) static void old_ich_force_enable_hpet(struct pci_dev *dev) { u32 val; - u32 uninitialized_var(gen_cntl); + u32 gen_cntl; if (hpet_address || force_hpet_address) return; @@ -299,7 +299,7 @@ static void vt8237_force_hpet_resume(void) static void vt8237_force_enable_hpet(struct pci_dev *dev) { - u32 uninitialized_var(val); + u32 val; if (hpet_address || force_hpet_address) return; @@ -430,7 +430,7 @@ static void nvidia_force_hpet_resume(void) static void nvidia_force_enable_hpet(struct pci_dev *dev) { - u32 uninitialized_var(val); + u32 val; if (hpet_address || force_hpet_address) return; diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c index 1f1298f6cbc26..2e4f6a1ebca56 100644 --- a/arch/x86/kernel/smpboot.c +++ b/arch/x86/kernel/smpboot.c @@ -96,6 +96,17 @@ DEFINE_PER_CPU_READ_MOSTLY(cpumask_var_t, cpu_llc_shared_map); DEFINE_PER_CPU_READ_MOSTLY(struct cpuinfo_x86, cpu_info); EXPORT_PER_CPU_SYMBOL(cpu_info); +struct mwait_cpu_dead { + unsigned int control; + unsigned int status; +}; + +/* + * Cache line aligned data for mwait_play_dead(). Separate on purpose so + * that it's unlikely to be touched by other CPUs. + */ +static DEFINE_PER_CPU_ALIGNED(struct mwait_cpu_dead, mwait_cpu_dead); + /* Logical package management. We might want to allocate that dynamically */ unsigned int __max_logical_packages __read_mostly; EXPORT_SYMBOL(__max_logical_packages); @@ -1595,10 +1606,10 @@ static bool wakeup_cpu0(void) */ static inline void mwait_play_dead(void) { + struct mwait_cpu_dead *md = this_cpu_ptr(&mwait_cpu_dead); unsigned int eax, ebx, ecx, edx; unsigned int highest_cstate = 0; unsigned int highest_subcstate = 0; - void *mwait_ptr; int i; if (boot_cpu_data.x86_vendor == X86_VENDOR_AMD) @@ -1632,13 +1643,6 @@ static inline void mwait_play_dead(void) (highest_subcstate - 1); } - /* - * This should be a memory location in a cache line which is - * unlikely to be touched by other processors. The actual - * content is immaterial as it is not actually modified in any way. - */ - mwait_ptr = ¤t_thread_info()->flags; - wbinvd(); while (1) { @@ -1650,9 +1654,9 @@ static inline void mwait_play_dead(void) * case where we return around the loop. */ mb(); - clflush(mwait_ptr); + clflush(md); mb(); - __monitor(mwait_ptr, 0, 0); + __monitor(md, 0, 0); mb(); __mwait(eax, 0); /* diff --git a/arch/xtensa/platforms/iss/network.c b/arch/xtensa/platforms/iss/network.c index d027dddc41cad..f49329aabec80 100644 --- a/arch/xtensa/platforms/iss/network.c +++ b/arch/xtensa/platforms/iss/network.c @@ -236,7 +236,7 @@ static int tuntap_probe(struct iss_net_private *lp, int index, char *init) init += sizeof(TRANSPORT_TUNTAP_NAME) - 1; if (*init == ',') { - rem = split_if_spec(init + 1, &mac_str, &dev_name); + rem = split_if_spec(init + 1, &mac_str, &dev_name, NULL); if (rem != NULL) { pr_err("%s: extra garbage on specification : '%s'\n", dev->name, rem); diff --git a/drivers/acpi/acpi_pad.c b/drivers/acpi/acpi_pad.c index 552c1f725b6cf..40188632958cd 100644 --- a/drivers/acpi/acpi_pad.c +++ b/drivers/acpi/acpi_pad.c @@ -95,7 +95,7 @@ static void round_robin_cpu(unsigned int tsk_index) cpumask_var_t tmp; int cpu; unsigned long min_weight = -1; - unsigned long uninitialized_var(preferred_cpu); + unsigned long preferred_cpu; if (!alloc_cpumask_var(&tmp, GFP_KERNEL)) return; diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c index 957f6b28bceaa..2295b74714e15 100644 --- a/drivers/ata/libata-scsi.c +++ b/drivers/ata/libata-scsi.c @@ -178,7 +178,7 @@ static ssize_t ata_scsi_park_show(struct device *device, struct ata_link *link; struct ata_device *dev; unsigned long now; - unsigned int uninitialized_var(msecs); + unsigned int msecs; int rc = 0; ap = ata_shost_to_port(sdev->host); diff --git a/drivers/ata/pata_ns87415.c b/drivers/ata/pata_ns87415.c index 84c6b225b56e9..9ee4aefca8675 100644 --- a/drivers/ata/pata_ns87415.c +++ b/drivers/ata/pata_ns87415.c @@ -260,7 +260,7 @@ static u8 ns87560_check_status(struct ata_port *ap) * LOCKING: * Inherited from caller. */ -void ns87560_tf_read(struct ata_port *ap, struct ata_taskfile *tf) +static void ns87560_tf_read(struct ata_port *ap, struct ata_taskfile *tf) { struct ata_ioports *ioaddr = &ap->ioaddr; diff --git a/drivers/atm/zatm.c b/drivers/atm/zatm.c index d5c76b50d3575..88f810745fd89 100644 --- a/drivers/atm/zatm.c +++ b/drivers/atm/zatm.c @@ -939,7 +939,7 @@ static int open_tx_first(struct atm_vcc *vcc) vcc->qos.txtp.max_pcr >= ATM_OC3_PCR); if (unlimited && zatm_dev->ubr != -1) zatm_vcc->shaper = zatm_dev->ubr; else { - int uninitialized_var(pcr); + int pcr; if (unlimited) vcc->qos.txtp.max_sdu = ATM_MAX_AAL5_PDU; if ((zatm_vcc->shaper = alloc_shaper(vcc->dev,&pcr, diff --git a/drivers/base/arch_topology.c b/drivers/base/arch_topology.c index e7cb0c6ade81e..d89f618231cb1 100644 --- a/drivers/base/arch_topology.c +++ b/drivers/base/arch_topology.c @@ -44,7 +44,7 @@ static ssize_t cpu_capacity_show(struct device *dev, { struct cpu *cpu = container_of(dev, struct cpu, dev); - return sprintf(buf, "%lu\n", topology_get_cpu_scale(NULL, cpu->dev.id)); + return sysfs_emit(buf, "%lu\n", topology_get_cpu_scale(NULL, cpu->dev.id)); } static ssize_t cpu_capacity_store(struct device *dev, diff --git a/drivers/base/cacheinfo.c b/drivers/base/cacheinfo.c index ce015ce2977c4..51eb403f89de6 100644 --- a/drivers/base/cacheinfo.c +++ b/drivers/base/cacheinfo.c @@ -372,7 +372,7 @@ static ssize_t size_show(struct device *dev, { struct cacheinfo *this_leaf = dev_get_drvdata(dev); - return sprintf(buf, "%uK\n", this_leaf->size >> 10); + return sysfs_emit(buf, "%uK\n", this_leaf->size >> 10); } static ssize_t shared_cpumap_show_func(struct device *dev, bool list, char *buf) @@ -402,11 +402,11 @@ static ssize_t type_show(struct device *dev, switch (this_leaf->type) { case CACHE_TYPE_DATA: - return sprintf(buf, "Data\n"); + return sysfs_emit(buf, "Data\n"); case CACHE_TYPE_INST: - return sprintf(buf, "Instruction\n"); + return sysfs_emit(buf, "Instruction\n"); case CACHE_TYPE_UNIFIED: - return sprintf(buf, "Unified\n"); + return sysfs_emit(buf, "Unified\n"); default: return -EINVAL; } @@ -420,11 +420,11 @@ static ssize_t allocation_policy_show(struct device *dev, int n = 0; if ((ci_attr & CACHE_READ_ALLOCATE) && (ci_attr & CACHE_WRITE_ALLOCATE)) - n = sprintf(buf, "ReadWriteAllocate\n"); + n = sysfs_emit(buf, "ReadWriteAllocate\n"); else if (ci_attr & CACHE_READ_ALLOCATE) - n = sprintf(buf, "ReadAllocate\n"); + n = sysfs_emit(buf, "ReadAllocate\n"); else if (ci_attr & CACHE_WRITE_ALLOCATE) - n = sprintf(buf, "WriteAllocate\n"); + n = sysfs_emit(buf, "WriteAllocate\n"); return n; } @@ -436,9 +436,9 @@ static ssize_t write_policy_show(struct device *dev, int n = 0; if (ci_attr & CACHE_WRITE_THROUGH) - n = sprintf(buf, "WriteThrough\n"); + n = sysfs_emit(buf, "WriteThrough\n"); else if (ci_attr & CACHE_WRITE_BACK) - n = sprintf(buf, "WriteBack\n"); + n = sysfs_emit(buf, "WriteBack\n"); return n; } diff --git a/drivers/base/core.c b/drivers/base/core.c index 6e380ad9d08ad..0332800dffd86 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c @@ -994,7 +994,7 @@ ssize_t device_show_ulong(struct device *dev, char *buf) { struct dev_ext_attribute *ea = to_ext_attr(attr); - return snprintf(buf, PAGE_SIZE, "%lx\n", *(unsigned long *)(ea->var)); + return sysfs_emit(buf, "%lx\n", *(unsigned long *)(ea->var)); } EXPORT_SYMBOL_GPL(device_show_ulong); @@ -1019,7 +1019,7 @@ ssize_t device_show_int(struct device *dev, { struct dev_ext_attribute *ea = to_ext_attr(attr); - return snprintf(buf, PAGE_SIZE, "%d\n", *(int *)(ea->var)); + return sysfs_emit(buf, "%d\n", *(int *)(ea->var)); } EXPORT_SYMBOL_GPL(device_show_int); @@ -1040,7 +1040,7 @@ ssize_t device_show_bool(struct device *dev, struct device_attribute *attr, { struct dev_ext_attribute *ea = to_ext_attr(attr); - return snprintf(buf, PAGE_SIZE, "%d\n", *(bool *)(ea->var)); + return sysfs_emit(buf, "%d\n", *(bool *)(ea->var)); } EXPORT_SYMBOL_GPL(device_show_bool); @@ -1273,7 +1273,7 @@ static ssize_t online_show(struct device *dev, struct device_attribute *attr, device_lock(dev); val = !dev->offline; device_unlock(dev); - return sprintf(buf, "%u\n", val); + return sysfs_emit(buf, "%u\n", val); } static ssize_t online_store(struct device *dev, struct device_attribute *attr, diff --git a/drivers/base/cpu.c b/drivers/base/cpu.c index b1bb6f43f8962..607fc189e57c5 100644 --- a/drivers/base/cpu.c +++ b/drivers/base/cpu.c @@ -156,7 +156,7 @@ static ssize_t show_crash_notes(struct device *dev, struct device_attribute *att * operation should be safe. No locking required. */ addr = per_cpu_ptr_to_phys(per_cpu_ptr(crash_notes, cpunum)); - rc = sprintf(buf, "%Lx\n", addr); + rc = sysfs_emit(buf, "%Lx\n", addr); return rc; } static DEVICE_ATTR(crash_notes, 0400, show_crash_notes, NULL); @@ -167,7 +167,7 @@ static ssize_t show_crash_notes_size(struct device *dev, { ssize_t rc; - rc = sprintf(buf, "%zu\n", sizeof(note_buf_t)); + rc = sysfs_emit(buf, "%zu\n", sizeof(note_buf_t)); return rc; } static DEVICE_ATTR(crash_notes_size, 0400, show_crash_notes_size, NULL); @@ -264,7 +264,7 @@ static ssize_t print_cpus_offline(struct device *dev, nr_cpu_ids, total_cpus-1); } - n += snprintf(&buf[n], len - n, "\n"); + n += sysfs_emit(&buf[n], "\n"); return n; } static DEVICE_ATTR(offline, 0444, print_cpus_offline, NULL); @@ -272,7 +272,7 @@ static DEVICE_ATTR(offline, 0444, print_cpus_offline, NULL); static ssize_t print_cpus_isolated(struct device *dev, struct device_attribute *attr, char *buf) { - int n = 0, len = PAGE_SIZE-2; + int n = 0; cpumask_var_t isolated; if (!alloc_cpumask_var(&isolated, GFP_KERNEL)) @@ -280,7 +280,7 @@ static ssize_t print_cpus_isolated(struct device *dev, cpumask_andnot(isolated, cpu_possible_mask, housekeeping_cpumask(HK_FLAG_DOMAIN)); - n = scnprintf(buf, len, "%*pbl\n", cpumask_pr_args(isolated)); + n = sysfs_emit(buf, "%*pbl\n", cpumask_pr_args(isolated)); free_cpumask_var(isolated); @@ -292,9 +292,9 @@ static DEVICE_ATTR(isolated, 0444, print_cpus_isolated, NULL); static ssize_t print_cpus_nohz_full(struct device *dev, struct device_attribute *attr, char *buf) { - int n = 0, len = PAGE_SIZE-2; + int n = 0; - n = scnprintf(buf, len, "%*pbl\n", cpumask_pr_args(tick_nohz_full_mask)); + n = sysfs_emit(buf, "%*pbl\n", cpumask_pr_args(tick_nohz_full_mask)); return n; } @@ -328,7 +328,7 @@ static ssize_t print_cpu_modalias(struct device *dev, ssize_t n; u32 i; - n = sprintf(buf, "cpu:type:" CPU_FEATURE_TYPEFMT ":feature:", + n = sysfs_emit(buf, "cpu:type:" CPU_FEATURE_TYPEFMT ":feature:", CPU_FEATURE_TYPEVAL); for (i = 0; i < MAX_CPU_FEATURES; i++) @@ -520,56 +520,56 @@ static void __init cpu_dev_register_generic(void) ssize_t __weak cpu_show_meltdown(struct device *dev, struct device_attribute *attr, char *buf) { - return sprintf(buf, "Not affected\n"); + return sysfs_emit(buf, "Not affected\n"); } ssize_t __weak cpu_show_spectre_v1(struct device *dev, struct device_attribute *attr, char *buf) { - return sprintf(buf, "Not affected\n"); + return sysfs_emit(buf, "Not affected\n"); } ssize_t __weak cpu_show_spectre_v2(struct device *dev, struct device_attribute *attr, char *buf) { - return sprintf(buf, "Not affected\n"); + return sysfs_emit(buf, "Not affected\n"); } ssize_t __weak cpu_show_spec_store_bypass(struct device *dev, struct device_attribute *attr, char *buf) { - return sprintf(buf, "Not affected\n"); + return sysfs_emit(buf, "Not affected\n"); } ssize_t __weak cpu_show_l1tf(struct device *dev, struct device_attribute *attr, char *buf) { - return sprintf(buf, "Not affected\n"); + return sysfs_emit(buf, "Not affected\n"); } ssize_t __weak cpu_show_mds(struct device *dev, struct device_attribute *attr, char *buf) { - return sprintf(buf, "Not affected\n"); + return sysfs_emit(buf, "Not affected\n"); } ssize_t __weak cpu_show_tsx_async_abort(struct device *dev, struct device_attribute *attr, char *buf) { - return sprintf(buf, "Not affected\n"); + return sysfs_emit(buf, "Not affected\n"); } ssize_t __weak cpu_show_itlb_multihit(struct device *dev, struct device_attribute *attr, char *buf) { - return sprintf(buf, "Not affected\n"); + return sysfs_emit(buf, "Not affected\n"); } ssize_t __weak cpu_show_srbds(struct device *dev, struct device_attribute *attr, char *buf) { - return sprintf(buf, "Not affected\n"); + return sysfs_emit(buf, "Not affected\n"); } ssize_t __weak cpu_show_mmio_stale_data(struct device *dev, diff --git a/drivers/base/firmware_loader/fallback.c b/drivers/base/firmware_loader/fallback.c index 821e27bda4ca2..2116926cc1d57 100644 --- a/drivers/base/firmware_loader/fallback.c +++ b/drivers/base/firmware_loader/fallback.c @@ -215,7 +215,7 @@ static ssize_t firmware_loading_show(struct device *dev, loading = fw_sysfs_loading(fw_sysfs->fw_priv); mutex_unlock(&fw_lock); - return sprintf(buf, "%d\n", loading); + return sysfs_emit(buf, "%d\n", loading); } /* one pages buffer should be mapped/unmapped only once */ diff --git a/drivers/base/memory.c b/drivers/base/memory.c index e270abc86d468..5dbe00a5c7c14 100644 --- a/drivers/base/memory.c +++ b/drivers/base/memory.c @@ -121,7 +121,7 @@ static ssize_t show_mem_start_phys_index(struct device *dev, unsigned long phys_index; phys_index = mem->start_section_nr / sections_per_block; - return sprintf(buf, "%08lx\n", phys_index); + return sysfs_emit(buf, "%08lx\n", phys_index); } /* @@ -145,7 +145,7 @@ static ssize_t show_mem_removable(struct device *dev, } out: - return sprintf(buf, "%d\n", ret); + return sysfs_emit(buf, "%d\n", ret); } /* @@ -163,17 +163,17 @@ static ssize_t show_mem_state(struct device *dev, */ switch (mem->state) { case MEM_ONLINE: - len = sprintf(buf, "online\n"); + len = sysfs_emit(buf, "online\n"); break; case MEM_OFFLINE: - len = sprintf(buf, "offline\n"); + len = sysfs_emit(buf, "offline\n"); break; case MEM_GOING_OFFLINE: - len = sprintf(buf, "going-offline\n"); + len = sysfs_emit(buf, "going-offline\n"); break; default: - len = sprintf(buf, "ERROR-UNKNOWN-%ld\n", - mem->state); + len = sysfs_emit(buf, "ERROR-UNKNOWN-%ld\n", + mem->state); WARN_ON(1); break; } @@ -384,7 +384,7 @@ static ssize_t show_phys_device(struct device *dev, struct device_attribute *attr, char *buf) { struct memory_block *mem = to_memory_block(dev); - return sprintf(buf, "%d\n", mem->phys_device); + return sysfs_emit(buf, "%d\n", mem->phys_device); } #ifdef CONFIG_MEMORY_HOTREMOVE @@ -422,7 +422,7 @@ static ssize_t show_valid_zones(struct device *dev, */ if (!test_pages_in_a_zone(start_pfn, start_pfn + nr_pages, &valid_start_pfn, &valid_end_pfn)) - return sprintf(buf, "none\n"); + return sysfs_emit(buf, "none\n"); start_pfn = valid_start_pfn; strcat(buf, page_zone(pfn_to_page(start_pfn))->name); goto out; @@ -456,7 +456,7 @@ static ssize_t print_block_size(struct device *dev, struct device_attribute *attr, char *buf) { - return sprintf(buf, "%lx\n", get_memory_block_size()); + return sysfs_emit(buf, "%lx\n", get_memory_block_size()); } static DEVICE_ATTR(block_size_bytes, 0444, print_block_size, NULL); @@ -470,9 +470,9 @@ show_auto_online_blocks(struct device *dev, struct device_attribute *attr, char *buf) { if (memhp_auto_online) - return sprintf(buf, "online\n"); + return sysfs_emit(buf, "online\n"); else - return sprintf(buf, "offline\n"); + return sysfs_emit(buf, "offline\n"); } static ssize_t diff --git a/drivers/base/node.c b/drivers/base/node.c index 60c2e32f9f614..8defeace001ec 100644 --- a/drivers/base/node.c +++ b/drivers/base/node.c @@ -69,7 +69,7 @@ static ssize_t node_read_meminfo(struct device *dev, struct sysinfo i; si_meminfo_node(&i, nid); - n = sprintf(buf, + n = sysfs_emit(buf, "Node %d MemTotal: %8lu kB\n" "Node %d MemFree: %8lu kB\n" "Node %d MemUsed: %8lu kB\n" @@ -96,7 +96,7 @@ static ssize_t node_read_meminfo(struct device *dev, nid, K(sum_zone_node_page_state(nid, NR_MLOCK))); #ifdef CONFIG_HIGHMEM - n += sprintf(buf + n, + n += sysfs_emit(buf + n, "Node %d HighTotal: %8lu kB\n" "Node %d HighFree: %8lu kB\n" "Node %d LowTotal: %8lu kB\n" @@ -106,7 +106,7 @@ static ssize_t node_read_meminfo(struct device *dev, nid, K(i.totalram - i.totalhigh), nid, K(i.freeram - i.freehigh)); #endif - n += sprintf(buf + n, + n += sysfs_emit(buf + n, "Node %d Dirty: %8lu kB\n" "Node %d Writeback: %8lu kB\n" "Node %d FilePages: %8lu kB\n" @@ -162,19 +162,19 @@ static DEVICE_ATTR(meminfo, S_IRUGO, node_read_meminfo, NULL); static ssize_t node_read_numastat(struct device *dev, struct device_attribute *attr, char *buf) { - return sprintf(buf, - "numa_hit %lu\n" - "numa_miss %lu\n" - "numa_foreign %lu\n" - "interleave_hit %lu\n" - "local_node %lu\n" - "other_node %lu\n", - sum_zone_numa_state(dev->id, NUMA_HIT), - sum_zone_numa_state(dev->id, NUMA_MISS), - sum_zone_numa_state(dev->id, NUMA_FOREIGN), - sum_zone_numa_state(dev->id, NUMA_INTERLEAVE_HIT), - sum_zone_numa_state(dev->id, NUMA_LOCAL), - sum_zone_numa_state(dev->id, NUMA_OTHER)); + return sysfs_emit(buf, + "numa_hit %lu\n" + "numa_miss %lu\n" + "numa_foreign %lu\n" + "interleave_hit %lu\n" + "local_node %lu\n" + "other_node %lu\n", + sum_zone_numa_state(dev->id, NUMA_HIT), + sum_zone_numa_state(dev->id, NUMA_MISS), + sum_zone_numa_state(dev->id, NUMA_FOREIGN), + sum_zone_numa_state(dev->id, NUMA_INTERLEAVE_HIT), + sum_zone_numa_state(dev->id, NUMA_LOCAL), + sum_zone_numa_state(dev->id, NUMA_OTHER)); } static DEVICE_ATTR(numastat, S_IRUGO, node_read_numastat, NULL); @@ -612,7 +612,7 @@ static ssize_t print_nodes_state(enum node_states state, char *buf) { int n; - n = scnprintf(buf, PAGE_SIZE - 1, "%*pbl", + n = sysfs_emit(buf, "%*pbl", nodemask_pr_args(&node_states[state])); buf[n++] = '\n'; buf[n] = '\0'; diff --git a/drivers/base/platform.c b/drivers/base/platform.c index 2f89e618b142c..1819da6889a71 100644 --- a/drivers/base/platform.c +++ b/drivers/base/platform.c @@ -927,7 +927,7 @@ static ssize_t driver_override_show(struct device *dev, ssize_t len; device_lock(dev); - len = sprintf(buf, "%s\n", pdev->driver_override); + len = sysfs_emit(buf, "%s\n", pdev->driver_override); device_unlock(dev); return len; } diff --git a/drivers/base/power/domain.c b/drivers/base/power/domain.c index e865aa4b25047..b32d3cf4f670d 100644 --- a/drivers/base/power/domain.c +++ b/drivers/base/power/domain.c @@ -2433,10 +2433,10 @@ static int genpd_parse_state(struct genpd_power_state *genpd_state, err = of_property_read_u32(state_node, "min-residency-us", &residency); if (!err) - genpd_state->residency_ns = 1000 * residency; + genpd_state->residency_ns = 1000LL * residency; - genpd_state->power_on_latency_ns = 1000 * exit_latency; - genpd_state->power_off_latency_ns = 1000 * entry_latency; + genpd_state->power_on_latency_ns = 1000LL * exit_latency; + genpd_state->power_off_latency_ns = 1000LL * entry_latency; genpd_state->fwnode = &state_node->fwnode; return 0; diff --git a/drivers/base/power/power.h b/drivers/base/power/power.h index c511def48b486..3f9934bd6137d 100644 --- a/drivers/base/power/power.h +++ b/drivers/base/power/power.h @@ -24,8 +24,11 @@ extern void pm_runtime_remove(struct device *dev); #define WAKE_IRQ_DEDICATED_ALLOCATED BIT(0) #define WAKE_IRQ_DEDICATED_MANAGED BIT(1) +#define WAKE_IRQ_DEDICATED_REVERSE BIT(2) #define WAKE_IRQ_DEDICATED_MASK (WAKE_IRQ_DEDICATED_ALLOCATED | \ - WAKE_IRQ_DEDICATED_MANAGED) + WAKE_IRQ_DEDICATED_MANAGED | \ + WAKE_IRQ_DEDICATED_REVERSE) +#define WAKE_IRQ_DEDICATED_ENABLED BIT(3) struct wake_irq { struct device *dev; @@ -38,7 +41,8 @@ extern void dev_pm_arm_wake_irq(struct wake_irq *wirq); extern void dev_pm_disarm_wake_irq(struct wake_irq *wirq); extern void dev_pm_enable_wake_irq_check(struct device *dev, bool can_change_status); -extern void dev_pm_disable_wake_irq_check(struct device *dev); +extern void dev_pm_disable_wake_irq_check(struct device *dev, bool cond_disable); +extern void dev_pm_enable_wake_irq_complete(struct device *dev); #ifdef CONFIG_PM_SLEEP diff --git a/drivers/base/power/runtime.c b/drivers/base/power/runtime.c index 911bb8a4bf6df..ab0898c33880a 100644 --- a/drivers/base/power/runtime.c +++ b/drivers/base/power/runtime.c @@ -606,6 +606,8 @@ static int rpm_suspend(struct device *dev, int rpmflags) if (retval) goto fail; + dev_pm_enable_wake_irq_complete(dev); + no_callback: __update_runtime_status(dev, RPM_SUSPENDED); pm_runtime_deactivate_timer(dev); @@ -640,7 +642,7 @@ static int rpm_suspend(struct device *dev, int rpmflags) return retval; fail: - dev_pm_disable_wake_irq_check(dev); + dev_pm_disable_wake_irq_check(dev, true); __update_runtime_status(dev, RPM_ACTIVE); dev->power.deferred_resume = false; wake_up_all(&dev->power.wait_queue); @@ -823,7 +825,7 @@ static int rpm_resume(struct device *dev, int rpmflags) callback = RPM_GET_CALLBACK(dev, runtime_resume); - dev_pm_disable_wake_irq_check(dev); + dev_pm_disable_wake_irq_check(dev, false); retval = rpm_callback(callback, dev); if (retval) { __update_runtime_status(dev, RPM_SUSPENDED); diff --git a/drivers/base/power/sysfs.c b/drivers/base/power/sysfs.c index d713738ce7967..c61b50aa1d818 100644 --- a/drivers/base/power/sysfs.c +++ b/drivers/base/power/sysfs.c @@ -101,7 +101,7 @@ static const char ctrl_on[] = "on"; static ssize_t control_show(struct device *dev, struct device_attribute *attr, char *buf) { - return sprintf(buf, "%s\n", + return sysfs_emit(buf, "%s\n", dev->power.runtime_auto ? ctrl_auto : ctrl_on); } @@ -127,7 +127,7 @@ static ssize_t runtime_active_time_show(struct device *dev, int ret; spin_lock_irq(&dev->power.lock); update_pm_runtime_accounting(dev); - ret = sprintf(buf, "%i\n", jiffies_to_msecs(dev->power.active_jiffies)); + ret = sysfs_emit(buf, "%i\n", jiffies_to_msecs(dev->power.active_jiffies)); spin_unlock_irq(&dev->power.lock); return ret; } @@ -140,7 +140,7 @@ static ssize_t runtime_suspended_time_show(struct device *dev, int ret; spin_lock_irq(&dev->power.lock); update_pm_runtime_accounting(dev); - ret = sprintf(buf, "%i\n", + ret = sysfs_emit(buf, "%i\n", jiffies_to_msecs(dev->power.suspended_jiffies)); spin_unlock_irq(&dev->power.lock); return ret; @@ -175,7 +175,7 @@ static ssize_t runtime_status_show(struct device *dev, return -EIO; } } - return sprintf(buf, p); + return sysfs_emit(buf, p); } static DEVICE_ATTR_RO(runtime_status); @@ -185,7 +185,7 @@ static ssize_t autosuspend_delay_ms_show(struct device *dev, { if (!dev->power.use_autosuspend) return -EIO; - return sprintf(buf, "%d\n", dev->power.autosuspend_delay); + return sysfs_emit(buf, "%d\n", dev->power.autosuspend_delay); } static ssize_t autosuspend_delay_ms_store(struct device *dev, @@ -214,11 +214,11 @@ static ssize_t pm_qos_resume_latency_us_show(struct device *dev, s32 value = dev_pm_qos_requested_resume_latency(dev); if (value == 0) - return sprintf(buf, "n/a\n"); + return sysfs_emit(buf, "n/a\n"); if (value == PM_QOS_RESUME_LATENCY_NO_CONSTRAINT) value = 0; - return sprintf(buf, "%d\n", value); + return sysfs_emit(buf, "%d\n", value); } static ssize_t pm_qos_resume_latency_us_store(struct device *dev, @@ -258,11 +258,11 @@ static ssize_t pm_qos_latency_tolerance_us_show(struct device *dev, s32 value = dev_pm_qos_get_user_latency_tolerance(dev); if (value < 0) - return sprintf(buf, "auto\n"); + return sysfs_emit(buf, "auto\n"); if (value == PM_QOS_LATENCY_ANY) - return sprintf(buf, "any\n"); + return sysfs_emit(buf, "any\n"); - return sprintf(buf, "%d\n", value); + return sysfs_emit(buf, "%d\n", value); } static ssize_t pm_qos_latency_tolerance_us_store(struct device *dev, @@ -294,8 +294,8 @@ static ssize_t pm_qos_no_power_off_show(struct device *dev, struct device_attribute *attr, char *buf) { - return sprintf(buf, "%d\n", !!(dev_pm_qos_requested_flags(dev) - & PM_QOS_FLAG_NO_POWER_OFF)); + return sysfs_emit(buf, "%d\n", !!(dev_pm_qos_requested_flags(dev) + & PM_QOS_FLAG_NO_POWER_OFF)); } static ssize_t pm_qos_no_power_off_store(struct device *dev, @@ -323,9 +323,9 @@ static const char _disabled[] = "disabled"; static ssize_t wakeup_show(struct device *dev, struct device_attribute *attr, char *buf) { - return sprintf(buf, "%s\n", device_can_wakeup(dev) - ? (device_may_wakeup(dev) ? _enabled : _disabled) - : ""); + return sysfs_emit(buf, "%s\n", device_can_wakeup(dev) + ? (device_may_wakeup(dev) ? _enabled : _disabled) + : ""); } static ssize_t wakeup_store(struct device *dev, struct device_attribute *attr, @@ -511,7 +511,7 @@ static DEVICE_ATTR_RO(wakeup_prevent_sleep_time_ms); static ssize_t runtime_usage_show(struct device *dev, struct device_attribute *attr, char *buf) { - return sprintf(buf, "%d\n", atomic_read(&dev->power.usage_count)); + return sysfs_emit(buf, "%d\n", atomic_read(&dev->power.usage_count)); } static DEVICE_ATTR_RO(runtime_usage); @@ -519,8 +519,8 @@ static ssize_t runtime_active_kids_show(struct device *dev, struct device_attribute *attr, char *buf) { - return sprintf(buf, "%d\n", dev->power.ignore_children ? - 0 : atomic_read(&dev->power.child_count)); + return sysfs_emit(buf, "%d\n", dev->power.ignore_children ? + 0 : atomic_read(&dev->power.child_count)); } static DEVICE_ATTR_RO(runtime_active_kids); @@ -528,12 +528,12 @@ static ssize_t runtime_enabled_show(struct device *dev, struct device_attribute *attr, char *buf) { if (dev->power.disable_depth && (dev->power.runtime_auto == false)) - return sprintf(buf, "disabled & forbidden\n"); + return sysfs_emit(buf, "disabled & forbidden\n"); if (dev->power.disable_depth) - return sprintf(buf, "disabled\n"); + return sysfs_emit(buf, "disabled\n"); if (dev->power.runtime_auto == false) - return sprintf(buf, "forbidden\n"); - return sprintf(buf, "enabled\n"); + return sysfs_emit(buf, "forbidden\n"); + return sysfs_emit(buf, "enabled\n"); } static DEVICE_ATTR_RO(runtime_enabled); @@ -541,9 +541,9 @@ static DEVICE_ATTR_RO(runtime_enabled); static ssize_t async_show(struct device *dev, struct device_attribute *attr, char *buf) { - return sprintf(buf, "%s\n", - device_async_suspend_enabled(dev) ? - _enabled : _disabled); + return sysfs_emit(buf, "%s\n", + device_async_suspend_enabled(dev) ? + _enabled : _disabled); } static ssize_t async_store(struct device *dev, struct device_attribute *attr, diff --git a/drivers/base/power/wakeirq.c b/drivers/base/power/wakeirq.c index b8fa5c0f2d132..e7ba514999163 100644 --- a/drivers/base/power/wakeirq.c +++ b/drivers/base/power/wakeirq.c @@ -156,24 +156,7 @@ static irqreturn_t handle_threaded_wake_irq(int irq, void *_wirq) return IRQ_HANDLED; } -/** - * dev_pm_set_dedicated_wake_irq - Request a dedicated wake-up interrupt - * @dev: Device entry - * @irq: Device wake-up interrupt - * - * Unless your hardware has separate wake-up interrupts in addition - * to the device IO interrupts, you don't need this. - * - * Sets up a threaded interrupt handler for a device that has - * a dedicated wake-up interrupt in addition to the device IO - * interrupt. - * - * The interrupt starts disabled, and needs to be managed for - * the device by the bus code or the device driver using - * dev_pm_enable_wake_irq() and dev_pm_disable_wake_irq() - * functions. - */ -int dev_pm_set_dedicated_wake_irq(struct device *dev, int irq) +static int __dev_pm_set_dedicated_wake_irq(struct device *dev, int irq, unsigned int flag) { struct wake_irq *wirq; int err; @@ -211,7 +194,7 @@ int dev_pm_set_dedicated_wake_irq(struct device *dev, int irq) if (err) goto err_free_irq; - wirq->status = WAKE_IRQ_DEDICATED_ALLOCATED; + wirq->status = WAKE_IRQ_DEDICATED_ALLOCATED | flag; return err; @@ -224,8 +207,57 @@ err_free: return err; } + + +/** + * dev_pm_set_dedicated_wake_irq - Request a dedicated wake-up interrupt + * @dev: Device entry + * @irq: Device wake-up interrupt + * + * Unless your hardware has separate wake-up interrupts in addition + * to the device IO interrupts, you don't need this. + * + * Sets up a threaded interrupt handler for a device that has + * a dedicated wake-up interrupt in addition to the device IO + * interrupt. + * + * The interrupt starts disabled, and needs to be managed for + * the device by the bus code or the device driver using + * dev_pm_enable_wake_irq*() and dev_pm_disable_wake_irq*() + * functions. + */ +int dev_pm_set_dedicated_wake_irq(struct device *dev, int irq) +{ + return __dev_pm_set_dedicated_wake_irq(dev, irq, 0); +} EXPORT_SYMBOL_GPL(dev_pm_set_dedicated_wake_irq); +/** + * dev_pm_set_dedicated_wake_irq_reverse - Request a dedicated wake-up interrupt + * with reverse enable ordering + * @dev: Device entry + * @irq: Device wake-up interrupt + * + * Unless your hardware has separate wake-up interrupts in addition + * to the device IO interrupts, you don't need this. + * + * Sets up a threaded interrupt handler for a device that has a dedicated + * wake-up interrupt in addition to the device IO interrupt. It sets + * the status of WAKE_IRQ_DEDICATED_REVERSE to tell rpm_suspend() + * to enable dedicated wake-up interrupt after running the runtime suspend + * callback for @dev. + * + * The interrupt starts disabled, and needs to be managed for + * the device by the bus code or the device driver using + * dev_pm_enable_wake_irq*() and dev_pm_disable_wake_irq*() + * functions. + */ +int dev_pm_set_dedicated_wake_irq_reverse(struct device *dev, int irq) +{ + return __dev_pm_set_dedicated_wake_irq(dev, irq, WAKE_IRQ_DEDICATED_REVERSE); +} +EXPORT_SYMBOL_GPL(dev_pm_set_dedicated_wake_irq_reverse); + /** * dev_pm_enable_wake_irq - Enable device wake-up interrupt * @dev: Device @@ -296,25 +328,56 @@ void dev_pm_enable_wake_irq_check(struct device *dev, return; enable: - enable_irq(wirq->irq); + if (!can_change_status || !(wirq->status & WAKE_IRQ_DEDICATED_REVERSE)) { + enable_irq(wirq->irq); + wirq->status |= WAKE_IRQ_DEDICATED_ENABLED; + } } /** * dev_pm_disable_wake_irq_check - Checks and disables wake-up interrupt * @dev: Device + * @cond_disable: if set, also check WAKE_IRQ_DEDICATED_REVERSE * * Disables wake-up interrupt conditionally based on status. * Should be only called from rpm_suspend() and rpm_resume() path. */ -void dev_pm_disable_wake_irq_check(struct device *dev) +void dev_pm_disable_wake_irq_check(struct device *dev, bool cond_disable) { struct wake_irq *wirq = dev->power.wakeirq; if (!wirq || !((wirq->status & WAKE_IRQ_DEDICATED_MASK))) return; - if (wirq->status & WAKE_IRQ_DEDICATED_MANAGED) + if (cond_disable && (wirq->status & WAKE_IRQ_DEDICATED_REVERSE)) + return; + + if (wirq->status & WAKE_IRQ_DEDICATED_MANAGED) { + wirq->status &= ~WAKE_IRQ_DEDICATED_ENABLED; disable_irq_nosync(wirq->irq); + } +} + +/** + * dev_pm_enable_wake_irq_complete - enable wake IRQ not enabled before + * @dev: Device using the wake IRQ + * + * Enable wake IRQ conditionally based on status, mainly used if want to + * enable wake IRQ after running ->runtime_suspend() which depends on + * WAKE_IRQ_DEDICATED_REVERSE. + * + * Should be only called from rpm_suspend() path. + */ +void dev_pm_enable_wake_irq_complete(struct device *dev) +{ + struct wake_irq *wirq = dev->power.wakeirq; + + if (!wirq || !(wirq->status & WAKE_IRQ_DEDICATED_MASK)) + return; + + if (wirq->status & WAKE_IRQ_DEDICATED_MANAGED && + wirq->status & WAKE_IRQ_DEDICATED_REVERSE) + enable_irq(wirq->irq); } /** @@ -331,7 +394,7 @@ void dev_pm_arm_wake_irq(struct wake_irq *wirq) if (device_may_wakeup(wirq->dev)) { if (wirq->status & WAKE_IRQ_DEDICATED_ALLOCATED && - !pm_runtime_status_suspended(wirq->dev)) + !(wirq->status & WAKE_IRQ_DEDICATED_ENABLED)) enable_irq(wirq->irq); enable_irq_wake(wirq->irq); @@ -354,7 +417,7 @@ void dev_pm_disarm_wake_irq(struct wake_irq *wirq) disable_irq_wake(wirq->irq); if (wirq->status & WAKE_IRQ_DEDICATED_ALLOCATED && - !pm_runtime_status_suspended(wirq->dev)) + !(wirq->status & WAKE_IRQ_DEDICATED_ENABLED)) disable_irq_nosync(wirq->irq); } } diff --git a/drivers/base/soc.c b/drivers/base/soc.c index 7e91894a380b5..23bc9eb794a26 100644 --- a/drivers/base/soc.c +++ b/drivers/base/soc.c @@ -72,13 +72,13 @@ static ssize_t soc_info_get(struct device *dev, struct soc_device *soc_dev = container_of(dev, struct soc_device, dev); if (attr == &dev_attr_machine) - return sprintf(buf, "%s\n", soc_dev->attr->machine); + return sysfs_emit(buf, "%s\n", soc_dev->attr->machine); if (attr == &dev_attr_family) - return sprintf(buf, "%s\n", soc_dev->attr->family); + return sysfs_emit(buf, "%s\n", soc_dev->attr->family); if (attr == &dev_attr_revision) - return sprintf(buf, "%s\n", soc_dev->attr->revision); + return sysfs_emit(buf, "%s\n", soc_dev->attr->revision); if (attr == &dev_attr_soc_id) - return sprintf(buf, "%s\n", soc_dev->attr->soc_id); + return sysfs_emit(buf, "%s\n", soc_dev->attr->soc_id); return -EINVAL; diff --git a/drivers/block/drbd/drbd_nl.c b/drivers/block/drbd/drbd_nl.c index 3f403aab55e1e..b4c2a2c2769bd 100644 --- a/drivers/block/drbd/drbd_nl.c +++ b/drivers/block/drbd/drbd_nl.c @@ -3394,7 +3394,7 @@ int drbd_adm_dump_devices(struct sk_buff *skb, struct netlink_callback *cb) { struct nlattr *resource_filter; struct drbd_resource *resource; - struct drbd_device *uninitialized_var(device); + struct drbd_device *device; int minor, err, retcode; struct drbd_genlmsghdr *dh; struct device_info device_info; @@ -3483,7 +3483,7 @@ int drbd_adm_dump_connections(struct sk_buff *skb, struct netlink_callback *cb) { struct nlattr *resource_filter; struct drbd_resource *resource = NULL, *next_resource; - struct drbd_connection *uninitialized_var(connection); + struct drbd_connection *connection; int err = 0, retcode; struct drbd_genlmsghdr *dh; struct connection_info connection_info; @@ -3645,7 +3645,7 @@ int drbd_adm_dump_peer_devices(struct sk_buff *skb, struct netlink_callback *cb) { struct nlattr *resource_filter; struct drbd_resource *resource; - struct drbd_device *uninitialized_var(device); + struct drbd_device *device; struct drbd_peer_device *peer_device = NULL; int minor, err, retcode; struct drbd_genlmsghdr *dh; diff --git a/drivers/block/loop.c b/drivers/block/loop.c index 12eb48980df7b..2e6c3f658894e 100644 --- a/drivers/block/loop.c +++ b/drivers/block/loop.c @@ -1991,7 +1991,8 @@ static int loop_add(struct loop_device **l, int i) lo->tag_set.queue_depth = 128; lo->tag_set.numa_node = NUMA_NO_NODE; lo->tag_set.cmd_size = sizeof(struct loop_cmd); - lo->tag_set.flags = BLK_MQ_F_SHOULD_MERGE | BLK_MQ_F_SG_MERGE; + lo->tag_set.flags = BLK_MQ_F_SHOULD_MERGE | BLK_MQ_F_SG_MERGE | + BLK_MQ_F_NO_SCHED; lo->tag_set.driver_data = lo; err = blk_mq_alloc_tag_set(&lo->tag_set); diff --git a/drivers/block/nbd.c b/drivers/block/nbd.c index 28024248a7b53..5a07964a1e676 100644 --- a/drivers/block/nbd.c +++ b/drivers/block/nbd.c @@ -1646,7 +1646,8 @@ static int nbd_dev_add(int index) if (err == -ENOSPC) err = -EEXIST; } else { - err = idr_alloc(&nbd_index_idr, nbd, 0, 0, GFP_KERNEL); + err = idr_alloc(&nbd_index_idr, nbd, 0, + (MINORMASK >> part_shift) + 1, GFP_KERNEL); if (err >= 0) index = err; } diff --git a/drivers/char/hw_random/imx-rngc.c b/drivers/char/hw_random/imx-rngc.c index dc9b8f377907f..084f7e4254eba 100644 --- a/drivers/char/hw_random/imx-rngc.c +++ b/drivers/char/hw_random/imx-rngc.c @@ -105,7 +105,7 @@ static int imx_rngc_self_test(struct imx_rngc *rngc) cmd = readl(rngc->base + RNGC_COMMAND); writel(cmd | RNGC_CMD_SELF_TEST, rngc->base + RNGC_COMMAND); - ret = wait_for_completion_timeout(&rngc->rng_op_done, RNGC_TIMEOUT); + ret = wait_for_completion_timeout(&rngc->rng_op_done, msecs_to_jiffies(RNGC_TIMEOUT)); if (!ret) { imx_rngc_irq_mask_clear(rngc); return -ETIMEDOUT; @@ -188,9 +188,7 @@ static int imx_rngc_init(struct hwrng *rng) cmd = readl(rngc->base + RNGC_COMMAND); writel(cmd | RNGC_CMD_SEED, rngc->base + RNGC_COMMAND); - ret = wait_for_completion_timeout(&rngc->rng_op_done, - RNGC_TIMEOUT); - + ret = wait_for_completion_timeout(&rngc->rng_op_done, msecs_to_jiffies(RNGC_TIMEOUT)); if (!ret) { imx_rngc_irq_mask_clear(rngc); return -ETIMEDOUT; diff --git a/drivers/char/hw_random/virtio-rng.c b/drivers/char/hw_random/virtio-rng.c index 7abd604e938c2..58884d8752011 100644 --- a/drivers/char/hw_random/virtio-rng.c +++ b/drivers/char/hw_random/virtio-rng.c @@ -17,6 +17,7 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ +#include #include #include #include @@ -30,71 +31,111 @@ static DEFINE_IDA(rng_index_ida); struct virtrng_info { struct hwrng hwrng; struct virtqueue *vq; - struct completion have_data; char name[25]; - unsigned int data_avail; int index; - bool busy; bool hwrng_register_done; bool hwrng_removed; + /* data transfer */ + struct completion have_data; + unsigned int data_avail; + unsigned int data_idx; + /* minimal size returned by rng_buffer_size() */ +#if SMP_CACHE_BYTES < 32 + u8 data[32]; +#else + u8 data[SMP_CACHE_BYTES]; +#endif }; static void random_recv_done(struct virtqueue *vq) { struct virtrng_info *vi = vq->vdev->priv; + unsigned int len; /* We can get spurious callbacks, e.g. shared IRQs + virtio_pci. */ - if (!virtqueue_get_buf(vi->vq, &vi->data_avail)) + if (!virtqueue_get_buf(vi->vq, &len)) return; + smp_store_release(&vi->data_avail, len); complete(&vi->have_data); } -/* The host will fill any buffer we give it with sweet, sweet randomness. */ -static void register_buffer(struct virtrng_info *vi, u8 *buf, size_t size) +static void request_entropy(struct virtrng_info *vi) { struct scatterlist sg; - sg_init_one(&sg, buf, size); + reinit_completion(&vi->have_data); + vi->data_idx = 0; + + sg_init_one(&sg, vi->data, sizeof(vi->data)); /* There should always be room for one buffer. */ - virtqueue_add_inbuf(vi->vq, &sg, 1, buf, GFP_KERNEL); + virtqueue_add_inbuf(vi->vq, &sg, 1, vi->data, GFP_KERNEL); virtqueue_kick(vi->vq); } +static unsigned int copy_data(struct virtrng_info *vi, void *buf, + unsigned int size) +{ + size = min_t(unsigned int, size, vi->data_avail); + memcpy(buf, vi->data + vi->data_idx, size); + vi->data_idx += size; + vi->data_avail -= size; + if (vi->data_avail == 0) + request_entropy(vi); + return size; +} + static int virtio_read(struct hwrng *rng, void *buf, size_t size, bool wait) { int ret; struct virtrng_info *vi = (struct virtrng_info *)rng->priv; + unsigned int chunk; + size_t read; if (vi->hwrng_removed) return -ENODEV; - if (!vi->busy) { - vi->busy = true; - reinit_completion(&vi->have_data); - register_buffer(vi, buf, size); + read = 0; + + /* copy available data */ + if (smp_load_acquire(&vi->data_avail)) { + chunk = copy_data(vi, buf, size); + size -= chunk; + read += chunk; } if (!wait) - return 0; - - ret = wait_for_completion_killable(&vi->have_data); - if (ret < 0) - return ret; + return read; + + /* We have already copied available entropy, + * so either size is 0 or data_avail is 0 + */ + while (size != 0) { + /* data_avail is 0 but a request is pending */ + ret = wait_for_completion_killable(&vi->have_data); + if (ret < 0) + return ret; + /* if vi->data_avail is 0, we have been interrupted + * by a cleanup, but buffer stays in the queue + */ + if (vi->data_avail == 0) + return read; - vi->busy = false; + chunk = copy_data(vi, buf + read, size); + size -= chunk; + read += chunk; + } - return vi->data_avail; + return read; } static void virtio_cleanup(struct hwrng *rng) { struct virtrng_info *vi = (struct virtrng_info *)rng->priv; - if (vi->busy) - wait_for_completion(&vi->have_data); + complete(&vi->have_data); } static int probe_common(struct virtio_device *vdev) @@ -130,6 +171,9 @@ static int probe_common(struct virtio_device *vdev) goto err_find; } + /* we always have a pending entropy request */ + request_entropy(vi); + return 0; err_find: @@ -145,9 +189,9 @@ static void remove_common(struct virtio_device *vdev) vi->hwrng_removed = true; vi->data_avail = 0; + vi->data_idx = 0; complete(&vi->have_data); vdev->config->reset(vdev); - vi->busy = false; if (vi->hwrng_register_done) hwrng_unregister(&vi->hwrng); vdev->config->del_vqs(vdev); diff --git a/drivers/char/tpm/tpm_tis_core.c b/drivers/char/tpm/tpm_tis_core.c index c95ce9323d77a..430a9eac67e19 100644 --- a/drivers/char/tpm/tpm_tis_core.c +++ b/drivers/char/tpm/tpm_tis_core.c @@ -270,6 +270,7 @@ static int tpm_tis_recv(struct tpm_chip *chip, u8 *buf, size_t count) int size = 0; int status; u32 expected; + int rc; if (count < TPM_HEADER_SIZE) { size = -EIO; @@ -289,8 +290,13 @@ static int tpm_tis_recv(struct tpm_chip *chip, u8 *buf, size_t count) goto out; } - size += recv_data(chip, &buf[TPM_HEADER_SIZE], - expected - TPM_HEADER_SIZE); + rc = recv_data(chip, &buf[TPM_HEADER_SIZE], + expected - TPM_HEADER_SIZE); + if (rc < 0) { + size = rc; + goto out; + } + size += rc; if (size < expected) { dev_err(&chip->dev, "Unable to read remainder of result\n"); size = -ETIME; diff --git a/drivers/char/tpm/tpm_vtpm_proxy.c b/drivers/char/tpm/tpm_vtpm_proxy.c index ecbb63f8d2318..05c77812b6501 100644 --- a/drivers/char/tpm/tpm_vtpm_proxy.c +++ b/drivers/char/tpm/tpm_vtpm_proxy.c @@ -700,37 +700,21 @@ static struct miscdevice vtpmx_miscdev = { .fops = &vtpmx_fops, }; -static int vtpmx_init(void) -{ - return misc_register(&vtpmx_miscdev); -} - -static void vtpmx_cleanup(void) -{ - misc_deregister(&vtpmx_miscdev); -} - static int __init vtpm_module_init(void) { int rc; - rc = vtpmx_init(); - if (rc) { - pr_err("couldn't create vtpmx device\n"); - return rc; - } - workqueue = create_workqueue("tpm-vtpm"); if (!workqueue) { pr_err("couldn't create workqueue\n"); - rc = -ENOMEM; - goto err_vtpmx_cleanup; + return -ENOMEM; } - return 0; - -err_vtpmx_cleanup: - vtpmx_cleanup(); + rc = misc_register(&vtpmx_miscdev); + if (rc) { + pr_err("couldn't create vtpmx device\n"); + destroy_workqueue(workqueue); + } return rc; } @@ -738,7 +722,7 @@ err_vtpmx_cleanup: static void __exit vtpm_module_exit(void) { destroy_workqueue(workqueue); - vtpmx_cleanup(); + misc_deregister(&vtpmx_miscdev); } module_init(vtpm_module_init); diff --git a/drivers/clk/clk-gate.c b/drivers/clk/clk-gate.c index dd82485e09a1f..c110f5d40b588 100644 --- a/drivers/clk/clk-gate.c +++ b/drivers/clk/clk-gate.c @@ -43,7 +43,7 @@ static void clk_gate_endisable(struct clk_hw *hw, int enable) { struct clk_gate *gate = to_clk_gate(hw); int set = gate->flags & CLK_GATE_SET_TO_DISABLE ? 1 : 0; - unsigned long uninitialized_var(flags); + unsigned long flags; u32 reg; set ^= enable; diff --git a/drivers/clocksource/Makefile b/drivers/clocksource/Makefile index db51b2427e8a6..e33b21d3f9d8b 100644 --- a/drivers/clocksource/Makefile +++ b/drivers/clocksource/Makefile @@ -23,8 +23,8 @@ obj-$(CONFIG_FTTMR010_TIMER) += timer-fttmr010.o obj-$(CONFIG_ROCKCHIP_TIMER) += rockchip_timer.o obj-$(CONFIG_CLKSRC_NOMADIK_MTU) += nomadik-mtu.o obj-$(CONFIG_CLKSRC_DBX500_PRCMU) += clksrc-dbx500-prcmu.o -obj-$(CONFIG_ARMADA_370_XP_TIMER) += time-armada-370-xp.o -obj-$(CONFIG_ORION_TIMER) += time-orion.o +obj-$(CONFIG_ARMADA_370_XP_TIMER) += timer-armada-370-xp.o +obj-$(CONFIG_ORION_TIMER) += timer-orion.o obj-$(CONFIG_BCM2835_TIMER) += bcm2835_timer.o obj-$(CONFIG_CLPS711X_TIMER) += clps711x-timer.o obj-$(CONFIG_ATLAS7_TIMER) += timer-atlas7.o @@ -36,25 +36,25 @@ obj-$(CONFIG_SUN4I_TIMER) += sun4i_timer.o obj-$(CONFIG_SUN5I_HSTIMER) += timer-sun5i.o obj-$(CONFIG_MESON6_TIMER) += meson6_timer.o obj-$(CONFIG_TEGRA_TIMER) += tegra20_timer.o -obj-$(CONFIG_VT8500_TIMER) += vt8500_timer.o -obj-$(CONFIG_NSPIRE_TIMER) += zevio-timer.o +obj-$(CONFIG_VT8500_TIMER) += timer-vt8500.o +obj-$(CONFIG_NSPIRE_TIMER) += timer-zevio.o obj-$(CONFIG_BCM_KONA_TIMER) += bcm_kona_timer.o -obj-$(CONFIG_CADENCE_TTC_TIMER) += cadence_ttc_timer.o -obj-$(CONFIG_CLKSRC_EFM32) += time-efm32.o +obj-$(CONFIG_CADENCE_TTC_TIMER) += timer-cadence-ttc.o +obj-$(CONFIG_CLKSRC_EFM32) += timer-efm32.o obj-$(CONFIG_CLKSRC_STM32) += timer-stm32.o obj-$(CONFIG_CLKSRC_EXYNOS_MCT) += exynos_mct.o -obj-$(CONFIG_CLKSRC_LPC32XX) += time-lpc32xx.o +obj-$(CONFIG_CLKSRC_LPC32XX) += timer-lpc32xx.o obj-$(CONFIG_CLKSRC_MPS2) += mps2-timer.o obj-$(CONFIG_CLKSRC_SAMSUNG_PWM) += samsung_pwm_timer.o -obj-$(CONFIG_FSL_FTM_TIMER) += fsl_ftm_timer.o -obj-$(CONFIG_VF_PIT_TIMER) += vf_pit_timer.o -obj-$(CONFIG_CLKSRC_QCOM) += qcom-timer.o +obj-$(CONFIG_FSL_FTM_TIMER) += timer-fsl-ftm.o +obj-$(CONFIG_VF_PIT_TIMER) += timer-vf-pit.o +obj-$(CONFIG_CLKSRC_QCOM) += timer-qcom.o obj-$(CONFIG_MTK_TIMER) += timer-mediatek.o -obj-$(CONFIG_CLKSRC_PISTACHIO) += time-pistachio.o +obj-$(CONFIG_CLKSRC_PISTACHIO) += timer-pistachio.o obj-$(CONFIG_CLKSRC_TI_32K) += timer-ti-32k.o obj-$(CONFIG_CLKSRC_NPS) += timer-nps.o obj-$(CONFIG_OXNAS_RPS_TIMER) += timer-oxnas-rps.o -obj-$(CONFIG_OWL_TIMER) += owl-timer.o +obj-$(CONFIG_OWL_TIMER) += timer-owl.o obj-$(CONFIG_SPRD_TIMER) += timer-sprd.o obj-$(CONFIG_NPCM7XX_TIMER) += timer-npcm7xx.o @@ -66,7 +66,7 @@ obj-$(CONFIG_ARM_TIMER_SP804) += timer-sp804.o obj-$(CONFIG_ARCH_HAS_TICK_BROADCAST) += dummy_timer.o obj-$(CONFIG_KEYSTONE_TIMER) += timer-keystone.o obj-$(CONFIG_INTEGRATOR_AP_TIMER) += timer-integrator-ap.o -obj-$(CONFIG_CLKSRC_VERSATILE) += versatile.o +obj-$(CONFIG_CLKSRC_VERSATILE) += timer-versatile.o obj-$(CONFIG_CLKSRC_MIPS_GIC) += mips-gic-timer.o obj-$(CONFIG_CLKSRC_TANGO_XTAL) += tango_xtal.o obj-$(CONFIG_CLKSRC_IMX_GPT) += timer-imx-gpt.o diff --git a/drivers/clocksource/cadence_ttc_timer.c b/drivers/clocksource/cadence_ttc_timer.c deleted file mode 100644 index a7eb858a84a0f..0000000000000 --- a/drivers/clocksource/cadence_ttc_timer.c +++ /dev/null @@ -1,543 +0,0 @@ -/* - * This file contains driver for the Cadence Triple Timer Counter Rev 06 - * - * Copyright (C) 2011-2013 Xilinx - * - * based on arch/mips/kernel/time.c timer driver - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -/* - * This driver configures the 2 16/32-bit count-up timers as follows: - * - * T1: Timer 1, clocksource for generic timekeeping - * T2: Timer 2, clockevent source for hrtimers - * T3: Timer 3, - * - * The input frequency to the timer module for emulation is 2.5MHz which is - * common to all the timer channels (T1, T2, and T3). With a pre-scaler of 32, - * the timers are clocked at 78.125KHz (12.8 us resolution). - - * The input frequency to the timer module in silicon is configurable and - * obtained from device tree. The pre-scaler of 32 is used. - */ - -/* - * Timer Register Offset Definitions of Timer 1, Increment base address by 4 - * and use same offsets for Timer 2 - */ -#define TTC_CLK_CNTRL_OFFSET 0x00 /* Clock Control Reg, RW */ -#define TTC_CNT_CNTRL_OFFSET 0x0C /* Counter Control Reg, RW */ -#define TTC_COUNT_VAL_OFFSET 0x18 /* Counter Value Reg, RO */ -#define TTC_INTR_VAL_OFFSET 0x24 /* Interval Count Reg, RW */ -#define TTC_ISR_OFFSET 0x54 /* Interrupt Status Reg, RO */ -#define TTC_IER_OFFSET 0x60 /* Interrupt Enable Reg, RW */ - -#define TTC_CNT_CNTRL_DISABLE_MASK 0x1 - -#define TTC_CLK_CNTRL_CSRC_MASK (1 << 5) /* clock source */ -#define TTC_CLK_CNTRL_PSV_MASK 0x1e -#define TTC_CLK_CNTRL_PSV_SHIFT 1 - -/* - * Setup the timers to use pre-scaling, using a fixed value for now that will - * work across most input frequency, but it may need to be more dynamic - */ -#define PRESCALE_EXPONENT 11 /* 2 ^ PRESCALE_EXPONENT = PRESCALE */ -#define PRESCALE 2048 /* The exponent must match this */ -#define CLK_CNTRL_PRESCALE ((PRESCALE_EXPONENT - 1) << 1) -#define CLK_CNTRL_PRESCALE_EN 1 -#define CNT_CNTRL_RESET (1 << 4) - -#define MAX_F_ERR 50 - -/** - * struct ttc_timer - This definition defines local timer structure - * - * @base_addr: Base address of timer - * @freq: Timer input clock frequency - * @clk: Associated clock source - * @clk_rate_change_nb Notifier block for clock rate changes - */ -struct ttc_timer { - void __iomem *base_addr; - unsigned long freq; - struct clk *clk; - struct notifier_block clk_rate_change_nb; -}; - -#define to_ttc_timer(x) \ - container_of(x, struct ttc_timer, clk_rate_change_nb) - -struct ttc_timer_clocksource { - u32 scale_clk_ctrl_reg_old; - u32 scale_clk_ctrl_reg_new; - struct ttc_timer ttc; - struct clocksource cs; -}; - -#define to_ttc_timer_clksrc(x) \ - container_of(x, struct ttc_timer_clocksource, cs) - -struct ttc_timer_clockevent { - struct ttc_timer ttc; - struct clock_event_device ce; -}; - -#define to_ttc_timer_clkevent(x) \ - container_of(x, struct ttc_timer_clockevent, ce) - -static void __iomem *ttc_sched_clock_val_reg; - -/** - * ttc_set_interval - Set the timer interval value - * - * @timer: Pointer to the timer instance - * @cycles: Timer interval ticks - **/ -static void ttc_set_interval(struct ttc_timer *timer, - unsigned long cycles) -{ - u32 ctrl_reg; - - /* Disable the counter, set the counter value and re-enable counter */ - ctrl_reg = readl_relaxed(timer->base_addr + TTC_CNT_CNTRL_OFFSET); - ctrl_reg |= TTC_CNT_CNTRL_DISABLE_MASK; - writel_relaxed(ctrl_reg, timer->base_addr + TTC_CNT_CNTRL_OFFSET); - - writel_relaxed(cycles, timer->base_addr + TTC_INTR_VAL_OFFSET); - - /* - * Reset the counter (0x10) so that it starts from 0, one-shot - * mode makes this needed for timing to be right. - */ - ctrl_reg |= CNT_CNTRL_RESET; - ctrl_reg &= ~TTC_CNT_CNTRL_DISABLE_MASK; - writel_relaxed(ctrl_reg, timer->base_addr + TTC_CNT_CNTRL_OFFSET); -} - -/** - * ttc_clock_event_interrupt - Clock event timer interrupt handler - * - * @irq: IRQ number of the Timer - * @dev_id: void pointer to the ttc_timer instance - * - * returns: Always IRQ_HANDLED - success - **/ -static irqreturn_t ttc_clock_event_interrupt(int irq, void *dev_id) -{ - struct ttc_timer_clockevent *ttce = dev_id; - struct ttc_timer *timer = &ttce->ttc; - - /* Acknowledge the interrupt and call event handler */ - readl_relaxed(timer->base_addr + TTC_ISR_OFFSET); - - ttce->ce.event_handler(&ttce->ce); - - return IRQ_HANDLED; -} - -/** - * __ttc_clocksource_read - Reads the timer counter register - * - * returns: Current timer counter register value - **/ -static u64 __ttc_clocksource_read(struct clocksource *cs) -{ - struct ttc_timer *timer = &to_ttc_timer_clksrc(cs)->ttc; - - return (u64)readl_relaxed(timer->base_addr + - TTC_COUNT_VAL_OFFSET); -} - -static u64 notrace ttc_sched_clock_read(void) -{ - return readl_relaxed(ttc_sched_clock_val_reg); -} - -/** - * ttc_set_next_event - Sets the time interval for next event - * - * @cycles: Timer interval ticks - * @evt: Address of clock event instance - * - * returns: Always 0 - success - **/ -static int ttc_set_next_event(unsigned long cycles, - struct clock_event_device *evt) -{ - struct ttc_timer_clockevent *ttce = to_ttc_timer_clkevent(evt); - struct ttc_timer *timer = &ttce->ttc; - - ttc_set_interval(timer, cycles); - return 0; -} - -/** - * ttc_set_{shutdown|oneshot|periodic} - Sets the state of timer - * - * @evt: Address of clock event instance - **/ -static int ttc_shutdown(struct clock_event_device *evt) -{ - struct ttc_timer_clockevent *ttce = to_ttc_timer_clkevent(evt); - struct ttc_timer *timer = &ttce->ttc; - u32 ctrl_reg; - - ctrl_reg = readl_relaxed(timer->base_addr + TTC_CNT_CNTRL_OFFSET); - ctrl_reg |= TTC_CNT_CNTRL_DISABLE_MASK; - writel_relaxed(ctrl_reg, timer->base_addr + TTC_CNT_CNTRL_OFFSET); - return 0; -} - -static int ttc_set_periodic(struct clock_event_device *evt) -{ - struct ttc_timer_clockevent *ttce = to_ttc_timer_clkevent(evt); - struct ttc_timer *timer = &ttce->ttc; - - ttc_set_interval(timer, - DIV_ROUND_CLOSEST(ttce->ttc.freq, PRESCALE * HZ)); - return 0; -} - -static int ttc_resume(struct clock_event_device *evt) -{ - struct ttc_timer_clockevent *ttce = to_ttc_timer_clkevent(evt); - struct ttc_timer *timer = &ttce->ttc; - u32 ctrl_reg; - - ctrl_reg = readl_relaxed(timer->base_addr + TTC_CNT_CNTRL_OFFSET); - ctrl_reg &= ~TTC_CNT_CNTRL_DISABLE_MASK; - writel_relaxed(ctrl_reg, timer->base_addr + TTC_CNT_CNTRL_OFFSET); - return 0; -} - -static int ttc_rate_change_clocksource_cb(struct notifier_block *nb, - unsigned long event, void *data) -{ - struct clk_notifier_data *ndata = data; - struct ttc_timer *ttc = to_ttc_timer(nb); - struct ttc_timer_clocksource *ttccs = container_of(ttc, - struct ttc_timer_clocksource, ttc); - - switch (event) { - case PRE_RATE_CHANGE: - { - u32 psv; - unsigned long factor, rate_low, rate_high; - - if (ndata->new_rate > ndata->old_rate) { - factor = DIV_ROUND_CLOSEST(ndata->new_rate, - ndata->old_rate); - rate_low = ndata->old_rate; - rate_high = ndata->new_rate; - } else { - factor = DIV_ROUND_CLOSEST(ndata->old_rate, - ndata->new_rate); - rate_low = ndata->new_rate; - rate_high = ndata->old_rate; - } - - if (!is_power_of_2(factor)) - return NOTIFY_BAD; - - if (abs(rate_high - (factor * rate_low)) > MAX_F_ERR) - return NOTIFY_BAD; - - factor = __ilog2_u32(factor); - - /* - * store timer clock ctrl register so we can restore it in case - * of an abort. - */ - ttccs->scale_clk_ctrl_reg_old = - readl_relaxed(ttccs->ttc.base_addr + - TTC_CLK_CNTRL_OFFSET); - - psv = (ttccs->scale_clk_ctrl_reg_old & - TTC_CLK_CNTRL_PSV_MASK) >> - TTC_CLK_CNTRL_PSV_SHIFT; - if (ndata->new_rate < ndata->old_rate) - psv -= factor; - else - psv += factor; - - /* prescaler within legal range? */ - if (psv & ~(TTC_CLK_CNTRL_PSV_MASK >> TTC_CLK_CNTRL_PSV_SHIFT)) - return NOTIFY_BAD; - - ttccs->scale_clk_ctrl_reg_new = ttccs->scale_clk_ctrl_reg_old & - ~TTC_CLK_CNTRL_PSV_MASK; - ttccs->scale_clk_ctrl_reg_new |= psv << TTC_CLK_CNTRL_PSV_SHIFT; - - - /* scale down: adjust divider in post-change notification */ - if (ndata->new_rate < ndata->old_rate) - return NOTIFY_DONE; - - /* scale up: adjust divider now - before frequency change */ - writel_relaxed(ttccs->scale_clk_ctrl_reg_new, - ttccs->ttc.base_addr + TTC_CLK_CNTRL_OFFSET); - break; - } - case POST_RATE_CHANGE: - /* scale up: pre-change notification did the adjustment */ - if (ndata->new_rate > ndata->old_rate) - return NOTIFY_OK; - - /* scale down: adjust divider now - after frequency change */ - writel_relaxed(ttccs->scale_clk_ctrl_reg_new, - ttccs->ttc.base_addr + TTC_CLK_CNTRL_OFFSET); - break; - - case ABORT_RATE_CHANGE: - /* we have to undo the adjustment in case we scale up */ - if (ndata->new_rate < ndata->old_rate) - return NOTIFY_OK; - - /* restore original register value */ - writel_relaxed(ttccs->scale_clk_ctrl_reg_old, - ttccs->ttc.base_addr + TTC_CLK_CNTRL_OFFSET); - /* fall through */ - default: - return NOTIFY_DONE; - } - - return NOTIFY_DONE; -} - -static int __init ttc_setup_clocksource(struct clk *clk, void __iomem *base, - u32 timer_width) -{ - struct ttc_timer_clocksource *ttccs; - int err; - - ttccs = kzalloc(sizeof(*ttccs), GFP_KERNEL); - if (!ttccs) - return -ENOMEM; - - ttccs->ttc.clk = clk; - - err = clk_prepare_enable(ttccs->ttc.clk); - if (err) { - kfree(ttccs); - return err; - } - - ttccs->ttc.freq = clk_get_rate(ttccs->ttc.clk); - - ttccs->ttc.clk_rate_change_nb.notifier_call = - ttc_rate_change_clocksource_cb; - ttccs->ttc.clk_rate_change_nb.next = NULL; - - err = clk_notifier_register(ttccs->ttc.clk, - &ttccs->ttc.clk_rate_change_nb); - if (err) - pr_warn("Unable to register clock notifier.\n"); - - ttccs->ttc.base_addr = base; - ttccs->cs.name = "ttc_clocksource"; - ttccs->cs.rating = 200; - ttccs->cs.read = __ttc_clocksource_read; - ttccs->cs.mask = CLOCKSOURCE_MASK(timer_width); - ttccs->cs.flags = CLOCK_SOURCE_IS_CONTINUOUS; - - /* - * Setup the clock source counter to be an incrementing counter - * with no interrupt and it rolls over at 0xFFFF. Pre-scale - * it by 32 also. Let it start running now. - */ - writel_relaxed(0x0, ttccs->ttc.base_addr + TTC_IER_OFFSET); - writel_relaxed(CLK_CNTRL_PRESCALE | CLK_CNTRL_PRESCALE_EN, - ttccs->ttc.base_addr + TTC_CLK_CNTRL_OFFSET); - writel_relaxed(CNT_CNTRL_RESET, - ttccs->ttc.base_addr + TTC_CNT_CNTRL_OFFSET); - - err = clocksource_register_hz(&ttccs->cs, ttccs->ttc.freq / PRESCALE); - if (err) { - kfree(ttccs); - return err; - } - - ttc_sched_clock_val_reg = base + TTC_COUNT_VAL_OFFSET; - sched_clock_register(ttc_sched_clock_read, timer_width, - ttccs->ttc.freq / PRESCALE); - - return 0; -} - -static int ttc_rate_change_clockevent_cb(struct notifier_block *nb, - unsigned long event, void *data) -{ - struct clk_notifier_data *ndata = data; - struct ttc_timer *ttc = to_ttc_timer(nb); - struct ttc_timer_clockevent *ttcce = container_of(ttc, - struct ttc_timer_clockevent, ttc); - - switch (event) { - case POST_RATE_CHANGE: - /* update cached frequency */ - ttc->freq = ndata->new_rate; - - clockevents_update_freq(&ttcce->ce, ndata->new_rate / PRESCALE); - - /* fall through */ - case PRE_RATE_CHANGE: - case ABORT_RATE_CHANGE: - default: - return NOTIFY_DONE; - } -} - -static int __init ttc_setup_clockevent(struct clk *clk, - void __iomem *base, u32 irq) -{ - struct ttc_timer_clockevent *ttcce; - int err; - - ttcce = kzalloc(sizeof(*ttcce), GFP_KERNEL); - if (!ttcce) - return -ENOMEM; - - ttcce->ttc.clk = clk; - - err = clk_prepare_enable(ttcce->ttc.clk); - if (err) - goto out_kfree; - - ttcce->ttc.clk_rate_change_nb.notifier_call = - ttc_rate_change_clockevent_cb; - ttcce->ttc.clk_rate_change_nb.next = NULL; - - err = clk_notifier_register(ttcce->ttc.clk, - &ttcce->ttc.clk_rate_change_nb); - if (err) { - pr_warn("Unable to register clock notifier.\n"); - goto out_kfree; - } - - ttcce->ttc.freq = clk_get_rate(ttcce->ttc.clk); - - ttcce->ttc.base_addr = base; - ttcce->ce.name = "ttc_clockevent"; - ttcce->ce.features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT; - ttcce->ce.set_next_event = ttc_set_next_event; - ttcce->ce.set_state_shutdown = ttc_shutdown; - ttcce->ce.set_state_periodic = ttc_set_periodic; - ttcce->ce.set_state_oneshot = ttc_shutdown; - ttcce->ce.tick_resume = ttc_resume; - ttcce->ce.rating = 200; - ttcce->ce.irq = irq; - ttcce->ce.cpumask = cpu_possible_mask; - - /* - * Setup the clock event timer to be an interval timer which - * is prescaled by 32 using the interval interrupt. Leave it - * disabled for now. - */ - writel_relaxed(0x23, ttcce->ttc.base_addr + TTC_CNT_CNTRL_OFFSET); - writel_relaxed(CLK_CNTRL_PRESCALE | CLK_CNTRL_PRESCALE_EN, - ttcce->ttc.base_addr + TTC_CLK_CNTRL_OFFSET); - writel_relaxed(0x1, ttcce->ttc.base_addr + TTC_IER_OFFSET); - - err = request_irq(irq, ttc_clock_event_interrupt, - IRQF_TIMER, ttcce->ce.name, ttcce); - if (err) - goto out_kfree; - - clockevents_config_and_register(&ttcce->ce, - ttcce->ttc.freq / PRESCALE, 1, 0xfffe); - - return 0; - -out_kfree: - kfree(ttcce); - return err; -} - -/** - * ttc_timer_init - Initialize the timer - * - * Initializes the timer hardware and register the clock source and clock event - * timers with Linux kernal timer framework - */ -static int __init ttc_timer_init(struct device_node *timer) -{ - unsigned int irq; - void __iomem *timer_baseaddr; - struct clk *clk_cs, *clk_ce; - static int initialized; - int clksel, ret; - u32 timer_width = 16; - - if (initialized) - return 0; - - initialized = 1; - - /* - * Get the 1st Triple Timer Counter (TTC) block from the device tree - * and use it. Note that the event timer uses the interrupt and it's the - * 2nd TTC hence the irq_of_parse_and_map(,1) - */ - timer_baseaddr = of_iomap(timer, 0); - if (!timer_baseaddr) { - pr_err("ERROR: invalid timer base address\n"); - return -ENXIO; - } - - irq = irq_of_parse_and_map(timer, 1); - if (irq <= 0) { - pr_err("ERROR: invalid interrupt number\n"); - return -EINVAL; - } - - of_property_read_u32(timer, "timer-width", &timer_width); - - clksel = readl_relaxed(timer_baseaddr + TTC_CLK_CNTRL_OFFSET); - clksel = !!(clksel & TTC_CLK_CNTRL_CSRC_MASK); - clk_cs = of_clk_get(timer, clksel); - if (IS_ERR(clk_cs)) { - pr_err("ERROR: timer input clock not found\n"); - return PTR_ERR(clk_cs); - } - - clksel = readl_relaxed(timer_baseaddr + 4 + TTC_CLK_CNTRL_OFFSET); - clksel = !!(clksel & TTC_CLK_CNTRL_CSRC_MASK); - clk_ce = of_clk_get(timer, clksel); - if (IS_ERR(clk_ce)) { - pr_err("ERROR: timer input clock not found\n"); - return PTR_ERR(clk_ce); - } - - ret = ttc_setup_clocksource(clk_cs, timer_baseaddr, timer_width); - if (ret) - return ret; - - ret = ttc_setup_clockevent(clk_ce, timer_baseaddr + 4, irq); - if (ret) - return ret; - - pr_info("%s #0 at %p, irq=%d\n", timer->name, timer_baseaddr, irq); - - return 0; -} - -TIMER_OF_DECLARE(ttc, "cdns,ttc", ttc_timer_init); diff --git a/drivers/clocksource/fsl_ftm_timer.c b/drivers/clocksource/fsl_ftm_timer.c deleted file mode 100644 index 846d18daf893b..0000000000000 --- a/drivers/clocksource/fsl_ftm_timer.c +++ /dev/null @@ -1,376 +0,0 @@ -/* - * Freescale FlexTimer Module (FTM) timer driver. - * - * Copyright 2014 Freescale Semiconductor, Inc. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define FTM_SC 0x00 -#define FTM_SC_CLK_SHIFT 3 -#define FTM_SC_CLK_MASK (0x3 << FTM_SC_CLK_SHIFT) -#define FTM_SC_CLK(c) ((c) << FTM_SC_CLK_SHIFT) -#define FTM_SC_PS_MASK 0x7 -#define FTM_SC_TOIE BIT(6) -#define FTM_SC_TOF BIT(7) - -#define FTM_CNT 0x04 -#define FTM_MOD 0x08 -#define FTM_CNTIN 0x4C - -#define FTM_PS_MAX 7 - -struct ftm_clock_device { - void __iomem *clksrc_base; - void __iomem *clkevt_base; - unsigned long periodic_cyc; - unsigned long ps; - bool big_endian; -}; - -static struct ftm_clock_device *priv; - -static inline u32 ftm_readl(void __iomem *addr) -{ - if (priv->big_endian) - return ioread32be(addr); - else - return ioread32(addr); -} - -static inline void ftm_writel(u32 val, void __iomem *addr) -{ - if (priv->big_endian) - iowrite32be(val, addr); - else - iowrite32(val, addr); -} - -static inline void ftm_counter_enable(void __iomem *base) -{ - u32 val; - - /* select and enable counter clock source */ - val = ftm_readl(base + FTM_SC); - val &= ~(FTM_SC_PS_MASK | FTM_SC_CLK_MASK); - val |= priv->ps | FTM_SC_CLK(1); - ftm_writel(val, base + FTM_SC); -} - -static inline void ftm_counter_disable(void __iomem *base) -{ - u32 val; - - /* disable counter clock source */ - val = ftm_readl(base + FTM_SC); - val &= ~(FTM_SC_PS_MASK | FTM_SC_CLK_MASK); - ftm_writel(val, base + FTM_SC); -} - -static inline void ftm_irq_acknowledge(void __iomem *base) -{ - u32 val; - - val = ftm_readl(base + FTM_SC); - val &= ~FTM_SC_TOF; - ftm_writel(val, base + FTM_SC); -} - -static inline void ftm_irq_enable(void __iomem *base) -{ - u32 val; - - val = ftm_readl(base + FTM_SC); - val |= FTM_SC_TOIE; - ftm_writel(val, base + FTM_SC); -} - -static inline void ftm_irq_disable(void __iomem *base) -{ - u32 val; - - val = ftm_readl(base + FTM_SC); - val &= ~FTM_SC_TOIE; - ftm_writel(val, base + FTM_SC); -} - -static inline void ftm_reset_counter(void __iomem *base) -{ - /* - * The CNT register contains the FTM counter value. - * Reset clears the CNT register. Writing any value to COUNT - * updates the counter with its initial value, CNTIN. - */ - ftm_writel(0x00, base + FTM_CNT); -} - -static u64 notrace ftm_read_sched_clock(void) -{ - return ftm_readl(priv->clksrc_base + FTM_CNT); -} - -static int ftm_set_next_event(unsigned long delta, - struct clock_event_device *unused) -{ - /* - * The CNNIN and MOD are all double buffer registers, writing - * to the MOD register latches the value into a buffer. The MOD - * register is updated with the value of its write buffer with - * the following scenario: - * a, the counter source clock is diabled. - */ - ftm_counter_disable(priv->clkevt_base); - - /* Force the value of CNTIN to be loaded into the FTM counter */ - ftm_reset_counter(priv->clkevt_base); - - /* - * The counter increments until the value of MOD is reached, - * at which point the counter is reloaded with the value of CNTIN. - * The TOF (the overflow flag) bit is set when the FTM counter - * changes from MOD to CNTIN. So we should using the delta - 1. - */ - ftm_writel(delta - 1, priv->clkevt_base + FTM_MOD); - - ftm_counter_enable(priv->clkevt_base); - - ftm_irq_enable(priv->clkevt_base); - - return 0; -} - -static int ftm_set_oneshot(struct clock_event_device *evt) -{ - ftm_counter_disable(priv->clkevt_base); - return 0; -} - -static int ftm_set_periodic(struct clock_event_device *evt) -{ - ftm_set_next_event(priv->periodic_cyc, evt); - return 0; -} - -static irqreturn_t ftm_evt_interrupt(int irq, void *dev_id) -{ - struct clock_event_device *evt = dev_id; - - ftm_irq_acknowledge(priv->clkevt_base); - - if (likely(clockevent_state_oneshot(evt))) { - ftm_irq_disable(priv->clkevt_base); - ftm_counter_disable(priv->clkevt_base); - } - - evt->event_handler(evt); - - return IRQ_HANDLED; -} - -static struct clock_event_device ftm_clockevent = { - .name = "Freescale ftm timer", - .features = CLOCK_EVT_FEAT_PERIODIC | - CLOCK_EVT_FEAT_ONESHOT, - .set_state_periodic = ftm_set_periodic, - .set_state_oneshot = ftm_set_oneshot, - .set_next_event = ftm_set_next_event, - .rating = 300, -}; - -static struct irqaction ftm_timer_irq = { - .name = "Freescale ftm timer", - .flags = IRQF_TIMER | IRQF_IRQPOLL, - .handler = ftm_evt_interrupt, - .dev_id = &ftm_clockevent, -}; - -static int __init ftm_clockevent_init(unsigned long freq, int irq) -{ - int err; - - ftm_writel(0x00, priv->clkevt_base + FTM_CNTIN); - ftm_writel(~0u, priv->clkevt_base + FTM_MOD); - - ftm_reset_counter(priv->clkevt_base); - - err = setup_irq(irq, &ftm_timer_irq); - if (err) { - pr_err("ftm: setup irq failed: %d\n", err); - return err; - } - - ftm_clockevent.cpumask = cpumask_of(0); - ftm_clockevent.irq = irq; - - clockevents_config_and_register(&ftm_clockevent, - freq / (1 << priv->ps), - 1, 0xffff); - - ftm_counter_enable(priv->clkevt_base); - - return 0; -} - -static int __init ftm_clocksource_init(unsigned long freq) -{ - int err; - - ftm_writel(0x00, priv->clksrc_base + FTM_CNTIN); - ftm_writel(~0u, priv->clksrc_base + FTM_MOD); - - ftm_reset_counter(priv->clksrc_base); - - sched_clock_register(ftm_read_sched_clock, 16, freq / (1 << priv->ps)); - err = clocksource_mmio_init(priv->clksrc_base + FTM_CNT, "fsl-ftm", - freq / (1 << priv->ps), 300, 16, - clocksource_mmio_readl_up); - if (err) { - pr_err("ftm: init clock source mmio failed: %d\n", err); - return err; - } - - ftm_counter_enable(priv->clksrc_base); - - return 0; -} - -static int __init __ftm_clk_init(struct device_node *np, char *cnt_name, - char *ftm_name) -{ - struct clk *clk; - int err; - - clk = of_clk_get_by_name(np, cnt_name); - if (IS_ERR(clk)) { - pr_err("ftm: Cannot get \"%s\": %ld\n", cnt_name, PTR_ERR(clk)); - return PTR_ERR(clk); - } - err = clk_prepare_enable(clk); - if (err) { - pr_err("ftm: clock failed to prepare+enable \"%s\": %d\n", - cnt_name, err); - return err; - } - - clk = of_clk_get_by_name(np, ftm_name); - if (IS_ERR(clk)) { - pr_err("ftm: Cannot get \"%s\": %ld\n", ftm_name, PTR_ERR(clk)); - return PTR_ERR(clk); - } - err = clk_prepare_enable(clk); - if (err) - pr_err("ftm: clock failed to prepare+enable \"%s\": %d\n", - ftm_name, err); - - return clk_get_rate(clk); -} - -static unsigned long __init ftm_clk_init(struct device_node *np) -{ - long freq; - - freq = __ftm_clk_init(np, "ftm-evt-counter-en", "ftm-evt"); - if (freq <= 0) - return 0; - - freq = __ftm_clk_init(np, "ftm-src-counter-en", "ftm-src"); - if (freq <= 0) - return 0; - - return freq; -} - -static int __init ftm_calc_closest_round_cyc(unsigned long freq) -{ - priv->ps = 0; - - /* The counter register is only using the lower 16 bits, and - * if the 'freq' value is to big here, then the periodic_cyc - * may exceed 0xFFFF. - */ - do { - priv->periodic_cyc = DIV_ROUND_CLOSEST(freq, - HZ * (1 << priv->ps++)); - } while (priv->periodic_cyc > 0xFFFF); - - if (priv->ps > FTM_PS_MAX) { - pr_err("ftm: the prescaler is %lu > %d\n", - priv->ps, FTM_PS_MAX); - return -EINVAL; - } - - return 0; -} - -static int __init ftm_timer_init(struct device_node *np) -{ - unsigned long freq; - int ret, irq; - - priv = kzalloc(sizeof(*priv), GFP_KERNEL); - if (!priv) - return -ENOMEM; - - ret = -ENXIO; - priv->clkevt_base = of_iomap(np, 0); - if (!priv->clkevt_base) { - pr_err("ftm: unable to map event timer registers\n"); - goto err_clkevt; - } - - priv->clksrc_base = of_iomap(np, 1); - if (!priv->clksrc_base) { - pr_err("ftm: unable to map source timer registers\n"); - goto err_clksrc; - } - - ret = -EINVAL; - irq = irq_of_parse_and_map(np, 0); - if (irq <= 0) { - pr_err("ftm: unable to get IRQ from DT, %d\n", irq); - goto err; - } - - priv->big_endian = of_property_read_bool(np, "big-endian"); - - freq = ftm_clk_init(np); - if (!freq) - goto err; - - ret = ftm_calc_closest_round_cyc(freq); - if (ret) - goto err; - - ret = ftm_clocksource_init(freq); - if (ret) - goto err; - - ret = ftm_clockevent_init(freq, irq); - if (ret) - goto err; - - return 0; - -err: - iounmap(priv->clksrc_base); -err_clksrc: - iounmap(priv->clkevt_base); -err_clkevt: - kfree(priv); - return ret; -} -TIMER_OF_DECLARE(flextimer, "fsl,ftm-timer", ftm_timer_init); diff --git a/drivers/clocksource/owl-timer.c b/drivers/clocksource/owl-timer.c deleted file mode 100644 index ea00a5e8f95d2..0000000000000 --- a/drivers/clocksource/owl-timer.c +++ /dev/null @@ -1,173 +0,0 @@ -/* - * Actions Semi Owl timer - * - * Copyright 2012 Actions Semi Inc. - * Author: Actions Semi, Inc. - * - * Copyright (c) 2017 SUSE Linux GmbH - * Author: Andreas Färber - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define OWL_Tx_CTL 0x0 -#define OWL_Tx_CMP 0x4 -#define OWL_Tx_VAL 0x8 - -#define OWL_Tx_CTL_PD BIT(0) -#define OWL_Tx_CTL_INTEN BIT(1) -#define OWL_Tx_CTL_EN BIT(2) - -static void __iomem *owl_timer_base; -static void __iomem *owl_clksrc_base; -static void __iomem *owl_clkevt_base; - -static inline void owl_timer_reset(void __iomem *base) -{ - writel(0, base + OWL_Tx_CTL); - writel(0, base + OWL_Tx_VAL); - writel(0, base + OWL_Tx_CMP); -} - -static inline void owl_timer_set_enabled(void __iomem *base, bool enabled) -{ - u32 ctl = readl(base + OWL_Tx_CTL); - - /* PD bit is cleared when set */ - ctl &= ~OWL_Tx_CTL_PD; - - if (enabled) - ctl |= OWL_Tx_CTL_EN; - else - ctl &= ~OWL_Tx_CTL_EN; - - writel(ctl, base + OWL_Tx_CTL); -} - -static u64 notrace owl_timer_sched_read(void) -{ - return (u64)readl(owl_clksrc_base + OWL_Tx_VAL); -} - -static int owl_timer_set_state_shutdown(struct clock_event_device *evt) -{ - owl_timer_set_enabled(owl_clkevt_base, false); - - return 0; -} - -static int owl_timer_set_state_oneshot(struct clock_event_device *evt) -{ - owl_timer_reset(owl_clkevt_base); - - return 0; -} - -static int owl_timer_tick_resume(struct clock_event_device *evt) -{ - return 0; -} - -static int owl_timer_set_next_event(unsigned long evt, - struct clock_event_device *ev) -{ - void __iomem *base = owl_clkevt_base; - - owl_timer_set_enabled(base, false); - writel(OWL_Tx_CTL_INTEN, base + OWL_Tx_CTL); - writel(0, base + OWL_Tx_VAL); - writel(evt, base + OWL_Tx_CMP); - owl_timer_set_enabled(base, true); - - return 0; -} - -static struct clock_event_device owl_clockevent = { - .name = "owl_tick", - .rating = 200, - .features = CLOCK_EVT_FEAT_ONESHOT | - CLOCK_EVT_FEAT_DYNIRQ, - .set_state_shutdown = owl_timer_set_state_shutdown, - .set_state_oneshot = owl_timer_set_state_oneshot, - .tick_resume = owl_timer_tick_resume, - .set_next_event = owl_timer_set_next_event, -}; - -static irqreturn_t owl_timer1_interrupt(int irq, void *dev_id) -{ - struct clock_event_device *evt = (struct clock_event_device *)dev_id; - - writel(OWL_Tx_CTL_PD, owl_clkevt_base + OWL_Tx_CTL); - - evt->event_handler(evt); - - return IRQ_HANDLED; -} - -static int __init owl_timer_init(struct device_node *node) -{ - struct clk *clk; - unsigned long rate; - int timer1_irq, ret; - - owl_timer_base = of_io_request_and_map(node, 0, "owl-timer"); - if (IS_ERR(owl_timer_base)) { - pr_err("Can't map timer registers\n"); - return PTR_ERR(owl_timer_base); - } - - owl_clksrc_base = owl_timer_base + 0x08; - owl_clkevt_base = owl_timer_base + 0x14; - - timer1_irq = of_irq_get_byname(node, "timer1"); - if (timer1_irq <= 0) { - pr_err("Can't parse timer1 IRQ\n"); - return -EINVAL; - } - - clk = of_clk_get(node, 0); - if (IS_ERR(clk)) - return PTR_ERR(clk); - - rate = clk_get_rate(clk); - - owl_timer_reset(owl_clksrc_base); - owl_timer_set_enabled(owl_clksrc_base, true); - - sched_clock_register(owl_timer_sched_read, 32, rate); - clocksource_mmio_init(owl_clksrc_base + OWL_Tx_VAL, node->name, - rate, 200, 32, clocksource_mmio_readl_up); - - owl_timer_reset(owl_clkevt_base); - - ret = request_irq(timer1_irq, owl_timer1_interrupt, IRQF_TIMER, - "owl-timer", &owl_clockevent); - if (ret) { - pr_err("failed to request irq %d\n", timer1_irq); - return ret; - } - - owl_clockevent.cpumask = cpumask_of(0); - owl_clockevent.irq = timer1_irq; - - clockevents_config_and_register(&owl_clockevent, rate, - 0xf, 0xffffffff); - - return 0; -} -TIMER_OF_DECLARE(owl_s500, "actions,s500-timer", owl_timer_init); -TIMER_OF_DECLARE(owl_s700, "actions,s700-timer", owl_timer_init); -TIMER_OF_DECLARE(owl_s900, "actions,s900-timer", owl_timer_init); diff --git a/drivers/clocksource/qcom-timer.c b/drivers/clocksource/qcom-timer.c deleted file mode 100644 index 89816f89ff3f4..0000000000000 --- a/drivers/clocksource/qcom-timer.c +++ /dev/null @@ -1,258 +0,0 @@ -/* - * - * Copyright (C) 2007 Google, Inc. - * Copyright (c) 2009-2012,2014, The Linux Foundation. All rights reserved. - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#define TIMER_MATCH_VAL 0x0000 -#define TIMER_COUNT_VAL 0x0004 -#define TIMER_ENABLE 0x0008 -#define TIMER_ENABLE_CLR_ON_MATCH_EN BIT(1) -#define TIMER_ENABLE_EN BIT(0) -#define TIMER_CLEAR 0x000C -#define DGT_CLK_CTL 0x10 -#define DGT_CLK_CTL_DIV_4 0x3 -#define TIMER_STS_GPT0_CLR_PEND BIT(10) - -#define GPT_HZ 32768 - -static void __iomem *event_base; -static void __iomem *sts_base; - -static irqreturn_t msm_timer_interrupt(int irq, void *dev_id) -{ - struct clock_event_device *evt = dev_id; - /* Stop the timer tick */ - if (clockevent_state_oneshot(evt)) { - u32 ctrl = readl_relaxed(event_base + TIMER_ENABLE); - ctrl &= ~TIMER_ENABLE_EN; - writel_relaxed(ctrl, event_base + TIMER_ENABLE); - } - evt->event_handler(evt); - return IRQ_HANDLED; -} - -static int msm_timer_set_next_event(unsigned long cycles, - struct clock_event_device *evt) -{ - u32 ctrl = readl_relaxed(event_base + TIMER_ENABLE); - - ctrl &= ~TIMER_ENABLE_EN; - writel_relaxed(ctrl, event_base + TIMER_ENABLE); - - writel_relaxed(ctrl, event_base + TIMER_CLEAR); - writel_relaxed(cycles, event_base + TIMER_MATCH_VAL); - - if (sts_base) - while (readl_relaxed(sts_base) & TIMER_STS_GPT0_CLR_PEND) - cpu_relax(); - - writel_relaxed(ctrl | TIMER_ENABLE_EN, event_base + TIMER_ENABLE); - return 0; -} - -static int msm_timer_shutdown(struct clock_event_device *evt) -{ - u32 ctrl; - - ctrl = readl_relaxed(event_base + TIMER_ENABLE); - ctrl &= ~(TIMER_ENABLE_EN | TIMER_ENABLE_CLR_ON_MATCH_EN); - writel_relaxed(ctrl, event_base + TIMER_ENABLE); - return 0; -} - -static struct clock_event_device __percpu *msm_evt; - -static void __iomem *source_base; - -static notrace u64 msm_read_timer_count(struct clocksource *cs) -{ - return readl_relaxed(source_base + TIMER_COUNT_VAL); -} - -static struct clocksource msm_clocksource = { - .name = "dg_timer", - .rating = 300, - .read = msm_read_timer_count, - .mask = CLOCKSOURCE_MASK(32), - .flags = CLOCK_SOURCE_IS_CONTINUOUS, -}; - -static int msm_timer_irq; -static int msm_timer_has_ppi; - -static int msm_local_timer_starting_cpu(unsigned int cpu) -{ - struct clock_event_device *evt = per_cpu_ptr(msm_evt, cpu); - int err; - - evt->irq = msm_timer_irq; - evt->name = "msm_timer"; - evt->features = CLOCK_EVT_FEAT_ONESHOT; - evt->rating = 200; - evt->set_state_shutdown = msm_timer_shutdown; - evt->set_state_oneshot = msm_timer_shutdown; - evt->tick_resume = msm_timer_shutdown; - evt->set_next_event = msm_timer_set_next_event; - evt->cpumask = cpumask_of(cpu); - - clockevents_config_and_register(evt, GPT_HZ, 4, 0xffffffff); - - if (msm_timer_has_ppi) { - enable_percpu_irq(evt->irq, IRQ_TYPE_EDGE_RISING); - } else { - err = request_irq(evt->irq, msm_timer_interrupt, - IRQF_TIMER | IRQF_NOBALANCING | - IRQF_TRIGGER_RISING, "gp_timer", evt); - if (err) - pr_err("request_irq failed\n"); - } - - return 0; -} - -static int msm_local_timer_dying_cpu(unsigned int cpu) -{ - struct clock_event_device *evt = per_cpu_ptr(msm_evt, cpu); - - evt->set_state_shutdown(evt); - disable_percpu_irq(evt->irq); - return 0; -} - -static u64 notrace msm_sched_clock_read(void) -{ - return msm_clocksource.read(&msm_clocksource); -} - -static unsigned long msm_read_current_timer(void) -{ - return msm_clocksource.read(&msm_clocksource); -} - -static struct delay_timer msm_delay_timer = { - .read_current_timer = msm_read_current_timer, -}; - -static int __init msm_timer_init(u32 dgt_hz, int sched_bits, int irq, - bool percpu) -{ - struct clocksource *cs = &msm_clocksource; - int res = 0; - - msm_timer_irq = irq; - msm_timer_has_ppi = percpu; - - msm_evt = alloc_percpu(struct clock_event_device); - if (!msm_evt) { - pr_err("memory allocation failed for clockevents\n"); - goto err; - } - - if (percpu) - res = request_percpu_irq(irq, msm_timer_interrupt, - "gp_timer", msm_evt); - - if (res) { - pr_err("request_percpu_irq failed\n"); - } else { - /* Install and invoke hotplug callbacks */ - res = cpuhp_setup_state(CPUHP_AP_QCOM_TIMER_STARTING, - "clockevents/qcom/timer:starting", - msm_local_timer_starting_cpu, - msm_local_timer_dying_cpu); - if (res) { - free_percpu_irq(irq, msm_evt); - goto err; - } - } - -err: - writel_relaxed(TIMER_ENABLE_EN, source_base + TIMER_ENABLE); - res = clocksource_register_hz(cs, dgt_hz); - if (res) - pr_err("clocksource_register failed\n"); - sched_clock_register(msm_sched_clock_read, sched_bits, dgt_hz); - msm_delay_timer.freq = dgt_hz; - register_current_timer_delay(&msm_delay_timer); - - return res; -} - -static int __init msm_dt_timer_init(struct device_node *np) -{ - u32 freq; - int irq, ret; - struct resource res; - u32 percpu_offset; - void __iomem *base; - void __iomem *cpu0_base; - - base = of_iomap(np, 0); - if (!base) { - pr_err("Failed to map event base\n"); - return -ENXIO; - } - - /* We use GPT0 for the clockevent */ - irq = irq_of_parse_and_map(np, 1); - if (irq <= 0) { - pr_err("Can't get irq\n"); - return -EINVAL; - } - - /* We use CPU0's DGT for the clocksource */ - if (of_property_read_u32(np, "cpu-offset", &percpu_offset)) - percpu_offset = 0; - - ret = of_address_to_resource(np, 0, &res); - if (ret) { - pr_err("Failed to parse DGT resource\n"); - return ret; - } - - cpu0_base = ioremap(res.start + percpu_offset, resource_size(&res)); - if (!cpu0_base) { - pr_err("Failed to map source base\n"); - return -EINVAL; - } - - if (of_property_read_u32(np, "clock-frequency", &freq)) { - pr_err("Unknown frequency\n"); - return -EINVAL; - } - - event_base = base + 0x4; - sts_base = base + 0x88; - source_base = cpu0_base + 0x24; - freq /= 4; - writel_relaxed(DGT_CLK_CTL_DIV_4, source_base + DGT_CLK_CTL); - - return msm_timer_init(freq, 32, irq, !!percpu_offset); -} -TIMER_OF_DECLARE(kpss_timer, "qcom,kpss-timer", msm_dt_timer_init); -TIMER_OF_DECLARE(scss_timer, "qcom,scss-timer", msm_dt_timer_init); diff --git a/drivers/clocksource/time-armada-370-xp.c b/drivers/clocksource/time-armada-370-xp.c deleted file mode 100644 index edf1a46269f10..0000000000000 --- a/drivers/clocksource/time-armada-370-xp.c +++ /dev/null @@ -1,416 +0,0 @@ -/* - * Marvell Armada 370/XP SoC timer handling. - * - * Copyright (C) 2012 Marvell - * - * Lior Amsalem - * Gregory CLEMENT - * Thomas Petazzoni - * - * This file is licensed under the terms of the GNU General Public - * License version 2. This program is licensed "as is" without any - * warranty of any kind, whether express or implied. - * - * Timer 0 is used as free-running clocksource, while timer 1 is - * used as clock_event_device. - * - * --- - * Clocksource driver for Armada 370 and Armada XP SoC. - * This driver implements one compatible string for each SoC, given - * each has its own characteristics: - * - * * Armada 370 has no 25 MHz fixed timer. - * - * * Armada XP cannot work properly without such 25 MHz fixed timer as - * doing otherwise leads to using a clocksource whose frequency varies - * when doing cpufreq frequency changes. - * - * See Documentation/devicetree/bindings/timer/marvell,armada-370-xp-timer.txt - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -/* - * Timer block registers. - */ -#define TIMER_CTRL_OFF 0x0000 -#define TIMER0_EN BIT(0) -#define TIMER0_RELOAD_EN BIT(1) -#define TIMER0_25MHZ BIT(11) -#define TIMER0_DIV(div) ((div) << 19) -#define TIMER1_EN BIT(2) -#define TIMER1_RELOAD_EN BIT(3) -#define TIMER1_25MHZ BIT(12) -#define TIMER1_DIV(div) ((div) << 22) -#define TIMER_EVENTS_STATUS 0x0004 -#define TIMER0_CLR_MASK (~0x1) -#define TIMER1_CLR_MASK (~0x100) -#define TIMER0_RELOAD_OFF 0x0010 -#define TIMER0_VAL_OFF 0x0014 -#define TIMER1_RELOAD_OFF 0x0018 -#define TIMER1_VAL_OFF 0x001c - -#define LCL_TIMER_EVENTS_STATUS 0x0028 -/* Global timers are connected to the coherency fabric clock, and the - below divider reduces their incrementing frequency. */ -#define TIMER_DIVIDER_SHIFT 5 -#define TIMER_DIVIDER (1 << TIMER_DIVIDER_SHIFT) - -/* - * SoC-specific data. - */ -static void __iomem *timer_base, *local_base; -static unsigned int timer_clk; -static bool timer25Mhz = true; -static u32 enable_mask; - -/* - * Number of timer ticks per jiffy. - */ -static u32 ticks_per_jiffy; - -static struct clock_event_device __percpu *armada_370_xp_evt; - -static void local_timer_ctrl_clrset(u32 clr, u32 set) -{ - writel((readl(local_base + TIMER_CTRL_OFF) & ~clr) | set, - local_base + TIMER_CTRL_OFF); -} - -static u64 notrace armada_370_xp_read_sched_clock(void) -{ - return ~readl(timer_base + TIMER0_VAL_OFF); -} - -/* - * Clockevent handling. - */ -static int -armada_370_xp_clkevt_next_event(unsigned long delta, - struct clock_event_device *dev) -{ - /* - * Clear clockevent timer interrupt. - */ - writel(TIMER0_CLR_MASK, local_base + LCL_TIMER_EVENTS_STATUS); - - /* - * Setup new clockevent timer value. - */ - writel(delta, local_base + TIMER0_VAL_OFF); - - /* - * Enable the timer. - */ - local_timer_ctrl_clrset(TIMER0_RELOAD_EN, enable_mask); - return 0; -} - -static int armada_370_xp_clkevt_shutdown(struct clock_event_device *evt) -{ - /* - * Disable timer. - */ - local_timer_ctrl_clrset(TIMER0_EN, 0); - - /* - * ACK pending timer interrupt. - */ - writel(TIMER0_CLR_MASK, local_base + LCL_TIMER_EVENTS_STATUS); - return 0; -} - -static int armada_370_xp_clkevt_set_periodic(struct clock_event_device *evt) -{ - /* - * Setup timer to fire at 1/HZ intervals. - */ - writel(ticks_per_jiffy - 1, local_base + TIMER0_RELOAD_OFF); - writel(ticks_per_jiffy - 1, local_base + TIMER0_VAL_OFF); - - /* - * Enable timer. - */ - local_timer_ctrl_clrset(0, TIMER0_RELOAD_EN | enable_mask); - return 0; -} - -static int armada_370_xp_clkevt_irq; - -static irqreturn_t armada_370_xp_timer_interrupt(int irq, void *dev_id) -{ - /* - * ACK timer interrupt and call event handler. - */ - struct clock_event_device *evt = dev_id; - - writel(TIMER0_CLR_MASK, local_base + LCL_TIMER_EVENTS_STATUS); - evt->event_handler(evt); - - return IRQ_HANDLED; -} - -/* - * Setup the local clock events for a CPU. - */ -static int armada_370_xp_timer_starting_cpu(unsigned int cpu) -{ - struct clock_event_device *evt = per_cpu_ptr(armada_370_xp_evt, cpu); - u32 clr = 0, set = 0; - - if (timer25Mhz) - set = TIMER0_25MHZ; - else - clr = TIMER0_25MHZ; - local_timer_ctrl_clrset(clr, set); - - evt->name = "armada_370_xp_per_cpu_tick", - evt->features = CLOCK_EVT_FEAT_ONESHOT | - CLOCK_EVT_FEAT_PERIODIC; - evt->shift = 32, - evt->rating = 300, - evt->set_next_event = armada_370_xp_clkevt_next_event, - evt->set_state_shutdown = armada_370_xp_clkevt_shutdown; - evt->set_state_periodic = armada_370_xp_clkevt_set_periodic; - evt->set_state_oneshot = armada_370_xp_clkevt_shutdown; - evt->tick_resume = armada_370_xp_clkevt_shutdown; - evt->irq = armada_370_xp_clkevt_irq; - evt->cpumask = cpumask_of(cpu); - - clockevents_config_and_register(evt, timer_clk, 1, 0xfffffffe); - enable_percpu_irq(evt->irq, 0); - - return 0; -} - -static int armada_370_xp_timer_dying_cpu(unsigned int cpu) -{ - struct clock_event_device *evt = per_cpu_ptr(armada_370_xp_evt, cpu); - - evt->set_state_shutdown(evt); - disable_percpu_irq(evt->irq); - return 0; -} - -static u32 timer0_ctrl_reg, timer0_local_ctrl_reg; - -static int armada_370_xp_timer_suspend(void) -{ - timer0_ctrl_reg = readl(timer_base + TIMER_CTRL_OFF); - timer0_local_ctrl_reg = readl(local_base + TIMER_CTRL_OFF); - return 0; -} - -static void armada_370_xp_timer_resume(void) -{ - writel(0xffffffff, timer_base + TIMER0_VAL_OFF); - writel(0xffffffff, timer_base + TIMER0_RELOAD_OFF); - writel(timer0_ctrl_reg, timer_base + TIMER_CTRL_OFF); - writel(timer0_local_ctrl_reg, local_base + TIMER_CTRL_OFF); -} - -static struct syscore_ops armada_370_xp_timer_syscore_ops = { - .suspend = armada_370_xp_timer_suspend, - .resume = armada_370_xp_timer_resume, -}; - -static unsigned long armada_370_delay_timer_read(void) -{ - return ~readl(timer_base + TIMER0_VAL_OFF); -} - -static struct delay_timer armada_370_delay_timer = { - .read_current_timer = armada_370_delay_timer_read, -}; - -static int __init armada_370_xp_timer_common_init(struct device_node *np) -{ - u32 clr = 0, set = 0; - int res; - - timer_base = of_iomap(np, 0); - if (!timer_base) { - pr_err("Failed to iomap\n"); - return -ENXIO; - } - - local_base = of_iomap(np, 1); - if (!local_base) { - pr_err("Failed to iomap\n"); - return -ENXIO; - } - - if (timer25Mhz) { - set = TIMER0_25MHZ; - enable_mask = TIMER0_EN; - } else { - clr = TIMER0_25MHZ; - enable_mask = TIMER0_EN | TIMER0_DIV(TIMER_DIVIDER_SHIFT); - } - atomic_io_modify(timer_base + TIMER_CTRL_OFF, clr | set, set); - local_timer_ctrl_clrset(clr, set); - - /* - * We use timer 0 as clocksource, and private(local) timer 0 - * for clockevents - */ - armada_370_xp_clkevt_irq = irq_of_parse_and_map(np, 4); - - ticks_per_jiffy = (timer_clk + HZ / 2) / HZ; - - /* - * Setup free-running clocksource timer (interrupts - * disabled). - */ - writel(0xffffffff, timer_base + TIMER0_VAL_OFF); - writel(0xffffffff, timer_base + TIMER0_RELOAD_OFF); - - atomic_io_modify(timer_base + TIMER_CTRL_OFF, - TIMER0_RELOAD_EN | enable_mask, - TIMER0_RELOAD_EN | enable_mask); - - armada_370_delay_timer.freq = timer_clk; - register_current_timer_delay(&armada_370_delay_timer); - - /* - * Set scale and timer for sched_clock. - */ - sched_clock_register(armada_370_xp_read_sched_clock, 32, timer_clk); - - res = clocksource_mmio_init(timer_base + TIMER0_VAL_OFF, - "armada_370_xp_clocksource", - timer_clk, 300, 32, clocksource_mmio_readl_down); - if (res) { - pr_err("Failed to initialize clocksource mmio\n"); - return res; - } - - armada_370_xp_evt = alloc_percpu(struct clock_event_device); - if (!armada_370_xp_evt) - return -ENOMEM; - - /* - * Setup clockevent timer (interrupt-driven). - */ - res = request_percpu_irq(armada_370_xp_clkevt_irq, - armada_370_xp_timer_interrupt, - "armada_370_xp_per_cpu_tick", - armada_370_xp_evt); - /* Immediately configure the timer on the boot CPU */ - if (res) { - pr_err("Failed to request percpu irq\n"); - return res; - } - - res = cpuhp_setup_state(CPUHP_AP_ARMADA_TIMER_STARTING, - "clockevents/armada:starting", - armada_370_xp_timer_starting_cpu, - armada_370_xp_timer_dying_cpu); - if (res) { - pr_err("Failed to setup hotplug state and timer\n"); - return res; - } - - register_syscore_ops(&armada_370_xp_timer_syscore_ops); - - return 0; -} - -static int __init armada_xp_timer_init(struct device_node *np) -{ - struct clk *clk = of_clk_get_by_name(np, "fixed"); - int ret; - - if (IS_ERR(clk)) { - pr_err("Failed to get clock\n"); - return PTR_ERR(clk); - } - - ret = clk_prepare_enable(clk); - if (ret) - return ret; - - timer_clk = clk_get_rate(clk); - - return armada_370_xp_timer_common_init(np); -} -TIMER_OF_DECLARE(armada_xp, "marvell,armada-xp-timer", - armada_xp_timer_init); - -static int __init armada_375_timer_init(struct device_node *np) -{ - struct clk *clk; - int ret; - - clk = of_clk_get_by_name(np, "fixed"); - if (!IS_ERR(clk)) { - ret = clk_prepare_enable(clk); - if (ret) - return ret; - timer_clk = clk_get_rate(clk); - } else { - - /* - * This fallback is required in order to retain proper - * devicetree backwards compatibility. - */ - clk = of_clk_get(np, 0); - - /* Must have at least a clock */ - if (IS_ERR(clk)) { - pr_err("Failed to get clock\n"); - return PTR_ERR(clk); - } - - ret = clk_prepare_enable(clk); - if (ret) - return ret; - - timer_clk = clk_get_rate(clk) / TIMER_DIVIDER; - timer25Mhz = false; - } - - return armada_370_xp_timer_common_init(np); -} -TIMER_OF_DECLARE(armada_375, "marvell,armada-375-timer", - armada_375_timer_init); - -static int __init armada_370_timer_init(struct device_node *np) -{ - struct clk *clk; - int ret; - - clk = of_clk_get(np, 0); - if (IS_ERR(clk)) { - pr_err("Failed to get clock\n"); - return PTR_ERR(clk); - } - - ret = clk_prepare_enable(clk); - if (ret) - return ret; - - timer_clk = clk_get_rate(clk) / TIMER_DIVIDER; - timer25Mhz = false; - - return armada_370_xp_timer_common_init(np); -} -TIMER_OF_DECLARE(armada_370, "marvell,armada-370-timer", - armada_370_timer_init); diff --git a/drivers/clocksource/time-efm32.c b/drivers/clocksource/time-efm32.c deleted file mode 100644 index 257e810ec1ad1..0000000000000 --- a/drivers/clocksource/time-efm32.c +++ /dev/null @@ -1,287 +0,0 @@ -/* - * Copyright (C) 2013 Pengutronix - * Uwe Kleine-Koenig - * - * This program is free software; you can redistribute it and/or modify it under - * the terms of the GNU General Public License version 2 as published by the - * Free Software Foundation. - */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define TIMERn_CTRL 0x00 -#define TIMERn_CTRL_PRESC(val) (((val) & 0xf) << 24) -#define TIMERn_CTRL_PRESC_1024 TIMERn_CTRL_PRESC(10) -#define TIMERn_CTRL_CLKSEL(val) (((val) & 0x3) << 16) -#define TIMERn_CTRL_CLKSEL_PRESCHFPERCLK TIMERn_CTRL_CLKSEL(0) -#define TIMERn_CTRL_OSMEN 0x00000010 -#define TIMERn_CTRL_MODE(val) (((val) & 0x3) << 0) -#define TIMERn_CTRL_MODE_UP TIMERn_CTRL_MODE(0) -#define TIMERn_CTRL_MODE_DOWN TIMERn_CTRL_MODE(1) - -#define TIMERn_CMD 0x04 -#define TIMERn_CMD_START 0x00000001 -#define TIMERn_CMD_STOP 0x00000002 - -#define TIMERn_IEN 0x0c -#define TIMERn_IF 0x10 -#define TIMERn_IFS 0x14 -#define TIMERn_IFC 0x18 -#define TIMERn_IRQ_UF 0x00000002 - -#define TIMERn_TOP 0x1c -#define TIMERn_CNT 0x24 - -struct efm32_clock_event_ddata { - struct clock_event_device evtdev; - void __iomem *base; - unsigned periodic_top; -}; - -static int efm32_clock_event_shutdown(struct clock_event_device *evtdev) -{ - struct efm32_clock_event_ddata *ddata = - container_of(evtdev, struct efm32_clock_event_ddata, evtdev); - - writel_relaxed(TIMERn_CMD_STOP, ddata->base + TIMERn_CMD); - return 0; -} - -static int efm32_clock_event_set_oneshot(struct clock_event_device *evtdev) -{ - struct efm32_clock_event_ddata *ddata = - container_of(evtdev, struct efm32_clock_event_ddata, evtdev); - - writel_relaxed(TIMERn_CMD_STOP, ddata->base + TIMERn_CMD); - writel_relaxed(TIMERn_CTRL_PRESC_1024 | - TIMERn_CTRL_CLKSEL_PRESCHFPERCLK | - TIMERn_CTRL_OSMEN | - TIMERn_CTRL_MODE_DOWN, - ddata->base + TIMERn_CTRL); - return 0; -} - -static int efm32_clock_event_set_periodic(struct clock_event_device *evtdev) -{ - struct efm32_clock_event_ddata *ddata = - container_of(evtdev, struct efm32_clock_event_ddata, evtdev); - - writel_relaxed(TIMERn_CMD_STOP, ddata->base + TIMERn_CMD); - writel_relaxed(ddata->periodic_top, ddata->base + TIMERn_TOP); - writel_relaxed(TIMERn_CTRL_PRESC_1024 | - TIMERn_CTRL_CLKSEL_PRESCHFPERCLK | - TIMERn_CTRL_MODE_DOWN, - ddata->base + TIMERn_CTRL); - writel_relaxed(TIMERn_CMD_START, ddata->base + TIMERn_CMD); - return 0; -} - -static int efm32_clock_event_set_next_event(unsigned long evt, - struct clock_event_device *evtdev) -{ - struct efm32_clock_event_ddata *ddata = - container_of(evtdev, struct efm32_clock_event_ddata, evtdev); - - writel_relaxed(TIMERn_CMD_STOP, ddata->base + TIMERn_CMD); - writel_relaxed(evt, ddata->base + TIMERn_CNT); - writel_relaxed(TIMERn_CMD_START, ddata->base + TIMERn_CMD); - - return 0; -} - -static irqreturn_t efm32_clock_event_handler(int irq, void *dev_id) -{ - struct efm32_clock_event_ddata *ddata = dev_id; - - writel_relaxed(TIMERn_IRQ_UF, ddata->base + TIMERn_IFC); - - ddata->evtdev.event_handler(&ddata->evtdev); - - return IRQ_HANDLED; -} - -static struct efm32_clock_event_ddata clock_event_ddata = { - .evtdev = { - .name = "efm32 clockevent", - .features = CLOCK_EVT_FEAT_ONESHOT | CLOCK_EVT_FEAT_PERIODIC, - .set_state_shutdown = efm32_clock_event_shutdown, - .set_state_periodic = efm32_clock_event_set_periodic, - .set_state_oneshot = efm32_clock_event_set_oneshot, - .set_next_event = efm32_clock_event_set_next_event, - .rating = 200, - }, -}; - -static struct irqaction efm32_clock_event_irq = { - .name = "efm32 clockevent", - .flags = IRQF_TIMER, - .handler = efm32_clock_event_handler, - .dev_id = &clock_event_ddata, -}; - -static int __init efm32_clocksource_init(struct device_node *np) -{ - struct clk *clk; - void __iomem *base; - unsigned long rate; - int ret; - - clk = of_clk_get(np, 0); - if (IS_ERR(clk)) { - ret = PTR_ERR(clk); - pr_err("failed to get clock for clocksource (%d)\n", ret); - goto err_clk_get; - } - - ret = clk_prepare_enable(clk); - if (ret) { - pr_err("failed to enable timer clock for clocksource (%d)\n", - ret); - goto err_clk_enable; - } - rate = clk_get_rate(clk); - - base = of_iomap(np, 0); - if (!base) { - ret = -EADDRNOTAVAIL; - pr_err("failed to map registers for clocksource\n"); - goto err_iomap; - } - - writel_relaxed(TIMERn_CTRL_PRESC_1024 | - TIMERn_CTRL_CLKSEL_PRESCHFPERCLK | - TIMERn_CTRL_MODE_UP, base + TIMERn_CTRL); - writel_relaxed(TIMERn_CMD_START, base + TIMERn_CMD); - - ret = clocksource_mmio_init(base + TIMERn_CNT, "efm32 timer", - DIV_ROUND_CLOSEST(rate, 1024), 200, 16, - clocksource_mmio_readl_up); - if (ret) { - pr_err("failed to init clocksource (%d)\n", ret); - goto err_clocksource_init; - } - - return 0; - -err_clocksource_init: - - iounmap(base); -err_iomap: - - clk_disable_unprepare(clk); -err_clk_enable: - - clk_put(clk); -err_clk_get: - - return ret; -} - -static int __init efm32_clockevent_init(struct device_node *np) -{ - struct clk *clk; - void __iomem *base; - unsigned long rate; - int irq; - int ret; - - clk = of_clk_get(np, 0); - if (IS_ERR(clk)) { - ret = PTR_ERR(clk); - pr_err("failed to get clock for clockevent (%d)\n", ret); - goto err_clk_get; - } - - ret = clk_prepare_enable(clk); - if (ret) { - pr_err("failed to enable timer clock for clockevent (%d)\n", - ret); - goto err_clk_enable; - } - rate = clk_get_rate(clk); - - base = of_iomap(np, 0); - if (!base) { - ret = -EADDRNOTAVAIL; - pr_err("failed to map registers for clockevent\n"); - goto err_iomap; - } - - irq = irq_of_parse_and_map(np, 0); - if (!irq) { - ret = -ENOENT; - pr_err("failed to get irq for clockevent\n"); - goto err_get_irq; - } - - writel_relaxed(TIMERn_IRQ_UF, base + TIMERn_IEN); - - clock_event_ddata.base = base; - clock_event_ddata.periodic_top = DIV_ROUND_CLOSEST(rate, 1024 * HZ); - - clockevents_config_and_register(&clock_event_ddata.evtdev, - DIV_ROUND_CLOSEST(rate, 1024), - 0xf, 0xffff); - - ret = setup_irq(irq, &efm32_clock_event_irq); - if (ret) { - pr_err("Failed setup irq\n"); - goto err_setup_irq; - } - - return 0; - -err_setup_irq: -err_get_irq: - - iounmap(base); -err_iomap: - - clk_disable_unprepare(clk); -err_clk_enable: - - clk_put(clk); -err_clk_get: - - return ret; -} - -/* - * This function asserts that we have exactly one clocksource and one - * clock_event_device in the end. - */ -static int __init efm32_timer_init(struct device_node *np) -{ - static int has_clocksource, has_clockevent; - int ret = 0; - - if (!has_clocksource) { - ret = efm32_clocksource_init(np); - if (!ret) { - has_clocksource = 1; - return 0; - } - } - - if (!has_clockevent) { - ret = efm32_clockevent_init(np); - if (!ret) { - has_clockevent = 1; - return 0; - } - } - - return ret; -} -TIMER_OF_DECLARE(efm32compat, "efm32,timer", efm32_timer_init); -TIMER_OF_DECLARE(efm32, "energymicro,efm32-timer", efm32_timer_init); diff --git a/drivers/clocksource/time-lpc32xx.c b/drivers/clocksource/time-lpc32xx.c deleted file mode 100644 index d51a62a79ef76..0000000000000 --- a/drivers/clocksource/time-lpc32xx.c +++ /dev/null @@ -1,314 +0,0 @@ -/* - * Clocksource driver for NXP LPC32xx/18xx/43xx timer - * - * Copyright (C) 2015 Joachim Eastwood - * - * Based on: - * time-efm32 Copyright (C) 2013 Pengutronix - * mach-lpc32xx/timer.c Copyright (C) 2009 - 2010 NXP Semiconductors - * - * This file is licensed under the terms of the GNU General Public - * License version 2. This program is licensed "as is" without any - * warranty of any kind, whether express or implied. - * - */ - -#define pr_fmt(fmt) "%s: " fmt, __func__ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define LPC32XX_TIMER_IR 0x000 -#define LPC32XX_TIMER_IR_MR0INT BIT(0) -#define LPC32XX_TIMER_TCR 0x004 -#define LPC32XX_TIMER_TCR_CEN BIT(0) -#define LPC32XX_TIMER_TCR_CRST BIT(1) -#define LPC32XX_TIMER_TC 0x008 -#define LPC32XX_TIMER_PR 0x00c -#define LPC32XX_TIMER_MCR 0x014 -#define LPC32XX_TIMER_MCR_MR0I BIT(0) -#define LPC32XX_TIMER_MCR_MR0R BIT(1) -#define LPC32XX_TIMER_MCR_MR0S BIT(2) -#define LPC32XX_TIMER_MR0 0x018 -#define LPC32XX_TIMER_CTCR 0x070 - -struct lpc32xx_clock_event_ddata { - struct clock_event_device evtdev; - void __iomem *base; - u32 ticks_per_jiffy; -}; - -/* Needed for the sched clock */ -static void __iomem *clocksource_timer_counter; - -static u64 notrace lpc32xx_read_sched_clock(void) -{ - return readl(clocksource_timer_counter); -} - -static unsigned long lpc32xx_delay_timer_read(void) -{ - return readl(clocksource_timer_counter); -} - -static struct delay_timer lpc32xx_delay_timer = { - .read_current_timer = lpc32xx_delay_timer_read, -}; - -static int lpc32xx_clkevt_next_event(unsigned long delta, - struct clock_event_device *evtdev) -{ - struct lpc32xx_clock_event_ddata *ddata = - container_of(evtdev, struct lpc32xx_clock_event_ddata, evtdev); - - /* - * Place timer in reset and program the delta in the match - * channel 0 (MR0). When the timer counter matches the value - * in MR0 register the match will trigger an interrupt. - * After setup the timer is released from reset and enabled. - */ - writel_relaxed(LPC32XX_TIMER_TCR_CRST, ddata->base + LPC32XX_TIMER_TCR); - writel_relaxed(delta, ddata->base + LPC32XX_TIMER_MR0); - writel_relaxed(LPC32XX_TIMER_TCR_CEN, ddata->base + LPC32XX_TIMER_TCR); - - return 0; -} - -static int lpc32xx_clkevt_shutdown(struct clock_event_device *evtdev) -{ - struct lpc32xx_clock_event_ddata *ddata = - container_of(evtdev, struct lpc32xx_clock_event_ddata, evtdev); - - /* Disable the timer */ - writel_relaxed(0, ddata->base + LPC32XX_TIMER_TCR); - - return 0; -} - -static int lpc32xx_clkevt_oneshot(struct clock_event_device *evtdev) -{ - struct lpc32xx_clock_event_ddata *ddata = - container_of(evtdev, struct lpc32xx_clock_event_ddata, evtdev); - - /* - * When using oneshot, we must also disable the timer - * to wait for the first call to set_next_event(). - */ - writel_relaxed(0, ddata->base + LPC32XX_TIMER_TCR); - - /* Enable interrupt, reset on match and stop on match (MCR). */ - writel_relaxed(LPC32XX_TIMER_MCR_MR0I | LPC32XX_TIMER_MCR_MR0R | - LPC32XX_TIMER_MCR_MR0S, ddata->base + LPC32XX_TIMER_MCR); - return 0; -} - -static int lpc32xx_clkevt_periodic(struct clock_event_device *evtdev) -{ - struct lpc32xx_clock_event_ddata *ddata = - container_of(evtdev, struct lpc32xx_clock_event_ddata, evtdev); - - /* Enable interrupt and reset on match. */ - writel_relaxed(LPC32XX_TIMER_MCR_MR0I | LPC32XX_TIMER_MCR_MR0R, - ddata->base + LPC32XX_TIMER_MCR); - - /* - * Place timer in reset and program the delta in the match - * channel 0 (MR0). - */ - writel_relaxed(LPC32XX_TIMER_TCR_CRST, ddata->base + LPC32XX_TIMER_TCR); - writel_relaxed(ddata->ticks_per_jiffy, ddata->base + LPC32XX_TIMER_MR0); - writel_relaxed(LPC32XX_TIMER_TCR_CEN, ddata->base + LPC32XX_TIMER_TCR); - - return 0; -} - -static irqreturn_t lpc32xx_clock_event_handler(int irq, void *dev_id) -{ - struct lpc32xx_clock_event_ddata *ddata = dev_id; - - /* Clear match on channel 0 */ - writel_relaxed(LPC32XX_TIMER_IR_MR0INT, ddata->base + LPC32XX_TIMER_IR); - - ddata->evtdev.event_handler(&ddata->evtdev); - - return IRQ_HANDLED; -} - -static struct lpc32xx_clock_event_ddata lpc32xx_clk_event_ddata = { - .evtdev = { - .name = "lpc3220 clockevent", - .features = CLOCK_EVT_FEAT_ONESHOT | - CLOCK_EVT_FEAT_PERIODIC, - .rating = 300, - .set_next_event = lpc32xx_clkevt_next_event, - .set_state_shutdown = lpc32xx_clkevt_shutdown, - .set_state_oneshot = lpc32xx_clkevt_oneshot, - .set_state_periodic = lpc32xx_clkevt_periodic, - }, -}; - -static int __init lpc32xx_clocksource_init(struct device_node *np) -{ - void __iomem *base; - unsigned long rate; - struct clk *clk; - int ret; - - clk = of_clk_get_by_name(np, "timerclk"); - if (IS_ERR(clk)) { - pr_err("clock get failed (%ld)\n", PTR_ERR(clk)); - return PTR_ERR(clk); - } - - ret = clk_prepare_enable(clk); - if (ret) { - pr_err("clock enable failed (%d)\n", ret); - goto err_clk_enable; - } - - base = of_iomap(np, 0); - if (!base) { - pr_err("unable to map registers\n"); - ret = -EADDRNOTAVAIL; - goto err_iomap; - } - - /* - * Disable and reset timer then set it to free running timer - * mode (CTCR) with no prescaler (PR) or match operations (MCR). - * After setup the timer is released from reset and enabled. - */ - writel_relaxed(LPC32XX_TIMER_TCR_CRST, base + LPC32XX_TIMER_TCR); - writel_relaxed(0, base + LPC32XX_TIMER_PR); - writel_relaxed(0, base + LPC32XX_TIMER_MCR); - writel_relaxed(0, base + LPC32XX_TIMER_CTCR); - writel_relaxed(LPC32XX_TIMER_TCR_CEN, base + LPC32XX_TIMER_TCR); - - rate = clk_get_rate(clk); - ret = clocksource_mmio_init(base + LPC32XX_TIMER_TC, "lpc3220 timer", - rate, 300, 32, clocksource_mmio_readl_up); - if (ret) { - pr_err("failed to init clocksource (%d)\n", ret); - goto err_clocksource_init; - } - - clocksource_timer_counter = base + LPC32XX_TIMER_TC; - lpc32xx_delay_timer.freq = rate; - register_current_timer_delay(&lpc32xx_delay_timer); - sched_clock_register(lpc32xx_read_sched_clock, 32, rate); - - return 0; - -err_clocksource_init: - iounmap(base); -err_iomap: - clk_disable_unprepare(clk); -err_clk_enable: - clk_put(clk); - return ret; -} - -static int __init lpc32xx_clockevent_init(struct device_node *np) -{ - void __iomem *base; - unsigned long rate; - struct clk *clk; - int ret, irq; - - clk = of_clk_get_by_name(np, "timerclk"); - if (IS_ERR(clk)) { - pr_err("clock get failed (%ld)\n", PTR_ERR(clk)); - return PTR_ERR(clk); - } - - ret = clk_prepare_enable(clk); - if (ret) { - pr_err("clock enable failed (%d)\n", ret); - goto err_clk_enable; - } - - base = of_iomap(np, 0); - if (!base) { - pr_err("unable to map registers\n"); - ret = -EADDRNOTAVAIL; - goto err_iomap; - } - - irq = irq_of_parse_and_map(np, 0); - if (!irq) { - pr_err("get irq failed\n"); - ret = -ENOENT; - goto err_irq; - } - - /* - * Disable timer and clear any pending interrupt (IR) on match - * channel 0 (MR0). Clear the prescaler as it's not used. - */ - writel_relaxed(0, base + LPC32XX_TIMER_TCR); - writel_relaxed(0, base + LPC32XX_TIMER_PR); - writel_relaxed(0, base + LPC32XX_TIMER_CTCR); - writel_relaxed(LPC32XX_TIMER_IR_MR0INT, base + LPC32XX_TIMER_IR); - - rate = clk_get_rate(clk); - lpc32xx_clk_event_ddata.base = base; - lpc32xx_clk_event_ddata.ticks_per_jiffy = DIV_ROUND_CLOSEST(rate, HZ); - clockevents_config_and_register(&lpc32xx_clk_event_ddata.evtdev, - rate, 1, -1); - - ret = request_irq(irq, lpc32xx_clock_event_handler, - IRQF_TIMER | IRQF_IRQPOLL, "lpc3220 clockevent", - &lpc32xx_clk_event_ddata); - if (ret) { - pr_err("request irq failed\n"); - goto err_irq; - } - - return 0; - -err_irq: - iounmap(base); -err_iomap: - clk_disable_unprepare(clk); -err_clk_enable: - clk_put(clk); - return ret; -} - -/* - * This function asserts that we have exactly one clocksource and one - * clock_event_device in the end. - */ -static int __init lpc32xx_timer_init(struct device_node *np) -{ - static int has_clocksource, has_clockevent; - int ret = 0; - - if (!has_clocksource) { - ret = lpc32xx_clocksource_init(np); - if (!ret) { - has_clocksource = 1; - return 0; - } - } - - if (!has_clockevent) { - ret = lpc32xx_clockevent_init(np); - if (!ret) { - has_clockevent = 1; - return 0; - } - } - - return ret; -} -TIMER_OF_DECLARE(lpc32xx_timer, "nxp,lpc3220-timer", lpc32xx_timer_init); diff --git a/drivers/clocksource/time-orion.c b/drivers/clocksource/time-orion.c deleted file mode 100644 index 12202067fe4b8..0000000000000 --- a/drivers/clocksource/time-orion.c +++ /dev/null @@ -1,192 +0,0 @@ -/* - * Marvell Orion SoC timer handling. - * - * Sebastian Hesselbarth - * - * This file is licensed under the terms of the GNU General Public - * License version 2. This program is licensed "as is" without any - * warranty of any kind, whether express or implied. - * - * Timer 0 is used as free-running clocksource, while timer 1 is - * used as clock_event_device. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define TIMER_CTRL 0x00 -#define TIMER0_EN BIT(0) -#define TIMER0_RELOAD_EN BIT(1) -#define TIMER1_EN BIT(2) -#define TIMER1_RELOAD_EN BIT(3) -#define TIMER0_RELOAD 0x10 -#define TIMER0_VAL 0x14 -#define TIMER1_RELOAD 0x18 -#define TIMER1_VAL 0x1c - -#define ORION_ONESHOT_MIN 1 -#define ORION_ONESHOT_MAX 0xfffffffe - -static void __iomem *timer_base; - -static unsigned long notrace orion_read_timer(void) -{ - return ~readl(timer_base + TIMER0_VAL); -} - -static struct delay_timer orion_delay_timer = { - .read_current_timer = orion_read_timer, -}; - -static void orion_delay_timer_init(unsigned long rate) -{ - orion_delay_timer.freq = rate; - register_current_timer_delay(&orion_delay_timer); -} - -/* - * Free-running clocksource handling. - */ -static u64 notrace orion_read_sched_clock(void) -{ - return ~readl(timer_base + TIMER0_VAL); -} - -/* - * Clockevent handling. - */ -static u32 ticks_per_jiffy; - -static int orion_clkevt_next_event(unsigned long delta, - struct clock_event_device *dev) -{ - /* setup and enable one-shot timer */ - writel(delta, timer_base + TIMER1_VAL); - atomic_io_modify(timer_base + TIMER_CTRL, - TIMER1_RELOAD_EN | TIMER1_EN, TIMER1_EN); - - return 0; -} - -static int orion_clkevt_shutdown(struct clock_event_device *dev) -{ - /* disable timer */ - atomic_io_modify(timer_base + TIMER_CTRL, - TIMER1_RELOAD_EN | TIMER1_EN, 0); - return 0; -} - -static int orion_clkevt_set_periodic(struct clock_event_device *dev) -{ - /* setup and enable periodic timer at 1/HZ intervals */ - writel(ticks_per_jiffy - 1, timer_base + TIMER1_RELOAD); - writel(ticks_per_jiffy - 1, timer_base + TIMER1_VAL); - atomic_io_modify(timer_base + TIMER_CTRL, - TIMER1_RELOAD_EN | TIMER1_EN, - TIMER1_RELOAD_EN | TIMER1_EN); - return 0; -} - -static struct clock_event_device orion_clkevt = { - .name = "orion_event", - .features = CLOCK_EVT_FEAT_ONESHOT | - CLOCK_EVT_FEAT_PERIODIC, - .shift = 32, - .rating = 300, - .set_next_event = orion_clkevt_next_event, - .set_state_shutdown = orion_clkevt_shutdown, - .set_state_periodic = orion_clkevt_set_periodic, - .set_state_oneshot = orion_clkevt_shutdown, - .tick_resume = orion_clkevt_shutdown, -}; - -static irqreturn_t orion_clkevt_irq_handler(int irq, void *dev_id) -{ - orion_clkevt.event_handler(&orion_clkevt); - return IRQ_HANDLED; -} - -static struct irqaction orion_clkevt_irq = { - .name = "orion_event", - .flags = IRQF_TIMER, - .handler = orion_clkevt_irq_handler, -}; - -static int __init orion_timer_init(struct device_node *np) -{ - unsigned long rate; - struct clk *clk; - int irq, ret; - - /* timer registers are shared with watchdog timer */ - timer_base = of_iomap(np, 0); - if (!timer_base) { - pr_err("%s: unable to map resource\n", np->name); - return -ENXIO; - } - - clk = of_clk_get(np, 0); - if (IS_ERR(clk)) { - pr_err("%s: unable to get clk\n", np->name); - return PTR_ERR(clk); - } - - ret = clk_prepare_enable(clk); - if (ret) { - pr_err("Failed to prepare clock\n"); - return ret; - } - - /* we are only interested in timer1 irq */ - irq = irq_of_parse_and_map(np, 1); - if (irq <= 0) { - pr_err("%s: unable to parse timer1 irq\n", np->name); - return -EINVAL; - } - - rate = clk_get_rate(clk); - - /* setup timer0 as free-running clocksource */ - writel(~0, timer_base + TIMER0_VAL); - writel(~0, timer_base + TIMER0_RELOAD); - atomic_io_modify(timer_base + TIMER_CTRL, - TIMER0_RELOAD_EN | TIMER0_EN, - TIMER0_RELOAD_EN | TIMER0_EN); - - ret = clocksource_mmio_init(timer_base + TIMER0_VAL, - "orion_clocksource", rate, 300, 32, - clocksource_mmio_readl_down); - if (ret) { - pr_err("Failed to initialize mmio timer\n"); - return ret; - } - - sched_clock_register(orion_read_sched_clock, 32, rate); - - /* setup timer1 as clockevent timer */ - ret = setup_irq(irq, &orion_clkevt_irq); - if (ret) { - pr_err("%s: unable to setup irq\n", np->name); - return ret; - } - - ticks_per_jiffy = (clk_get_rate(clk) + HZ/2) / HZ; - orion_clkevt.cpumask = cpumask_of(0); - orion_clkevt.irq = irq; - clockevents_config_and_register(&orion_clkevt, rate, - ORION_ONESHOT_MIN, ORION_ONESHOT_MAX); - - - orion_delay_timer_init(rate); - - return 0; -} -TIMER_OF_DECLARE(orion_timer, "marvell,orion-timer", orion_timer_init); diff --git a/drivers/clocksource/time-pistachio.c b/drivers/clocksource/time-pistachio.c deleted file mode 100644 index a2dd85d0c1d75..0000000000000 --- a/drivers/clocksource/time-pistachio.c +++ /dev/null @@ -1,218 +0,0 @@ -/* - * Pistachio clocksource based on general-purpose timers - * - * Copyright (C) 2015 Imagination Technologies - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - */ - -#define pr_fmt(fmt) "%s: " fmt, __func__ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* Top level reg */ -#define CR_TIMER_CTRL_CFG 0x00 -#define TIMER_ME_GLOBAL BIT(0) -#define CR_TIMER_REV 0x10 - -/* Timer specific registers */ -#define TIMER_CFG 0x20 -#define TIMER_ME_LOCAL BIT(0) -#define TIMER_RELOAD_VALUE 0x24 -#define TIMER_CURRENT_VALUE 0x28 -#define TIMER_CURRENT_OVERFLOW_VALUE 0x2C -#define TIMER_IRQ_STATUS 0x30 -#define TIMER_IRQ_CLEAR 0x34 -#define TIMER_IRQ_MASK 0x38 - -#define PERIP_TIMER_CONTROL 0x90 - -/* Timer specific configuration Values */ -#define RELOAD_VALUE 0xffffffff - -struct pistachio_clocksource { - void __iomem *base; - raw_spinlock_t lock; - struct clocksource cs; -}; - -static struct pistachio_clocksource pcs_gpt; - -#define to_pistachio_clocksource(cs) \ - container_of(cs, struct pistachio_clocksource, cs) - -static inline u32 gpt_readl(void __iomem *base, u32 offset, u32 gpt_id) -{ - return readl(base + 0x20 * gpt_id + offset); -} - -static inline void gpt_writel(void __iomem *base, u32 value, u32 offset, - u32 gpt_id) -{ - writel(value, base + 0x20 * gpt_id + offset); -} - -static u64 notrace -pistachio_clocksource_read_cycles(struct clocksource *cs) -{ - struct pistachio_clocksource *pcs = to_pistachio_clocksource(cs); - u32 counter, overflw; - unsigned long flags; - - /* - * The counter value is only refreshed after the overflow value is read. - * And they must be read in strict order, hence raw spin lock added. - */ - - raw_spin_lock_irqsave(&pcs->lock, flags); - overflw = gpt_readl(pcs->base, TIMER_CURRENT_OVERFLOW_VALUE, 0); - counter = gpt_readl(pcs->base, TIMER_CURRENT_VALUE, 0); - raw_spin_unlock_irqrestore(&pcs->lock, flags); - - return (u64)~counter; -} - -static u64 notrace pistachio_read_sched_clock(void) -{ - return pistachio_clocksource_read_cycles(&pcs_gpt.cs); -} - -static void pistachio_clksrc_set_mode(struct clocksource *cs, int timeridx, - int enable) -{ - struct pistachio_clocksource *pcs = to_pistachio_clocksource(cs); - u32 val; - - val = gpt_readl(pcs->base, TIMER_CFG, timeridx); - if (enable) - val |= TIMER_ME_LOCAL; - else - val &= ~TIMER_ME_LOCAL; - - gpt_writel(pcs->base, val, TIMER_CFG, timeridx); -} - -static void pistachio_clksrc_enable(struct clocksource *cs, int timeridx) -{ - struct pistachio_clocksource *pcs = to_pistachio_clocksource(cs); - - /* Disable GPT local before loading reload value */ - pistachio_clksrc_set_mode(cs, timeridx, false); - gpt_writel(pcs->base, RELOAD_VALUE, TIMER_RELOAD_VALUE, timeridx); - pistachio_clksrc_set_mode(cs, timeridx, true); -} - -static void pistachio_clksrc_disable(struct clocksource *cs, int timeridx) -{ - /* Disable GPT local */ - pistachio_clksrc_set_mode(cs, timeridx, false); -} - -static int pistachio_clocksource_enable(struct clocksource *cs) -{ - pistachio_clksrc_enable(cs, 0); - return 0; -} - -static void pistachio_clocksource_disable(struct clocksource *cs) -{ - pistachio_clksrc_disable(cs, 0); -} - -/* Desirable clock source for pistachio platform */ -static struct pistachio_clocksource pcs_gpt = { - .cs = { - .name = "gptimer", - .rating = 300, - .enable = pistachio_clocksource_enable, - .disable = pistachio_clocksource_disable, - .read = pistachio_clocksource_read_cycles, - .mask = CLOCKSOURCE_MASK(32), - .flags = CLOCK_SOURCE_IS_CONTINUOUS | - CLOCK_SOURCE_SUSPEND_NONSTOP, - }, -}; - -static int __init pistachio_clksrc_of_init(struct device_node *node) -{ - struct clk *sys_clk, *fast_clk; - struct regmap *periph_regs; - unsigned long rate; - int ret; - - pcs_gpt.base = of_iomap(node, 0); - if (!pcs_gpt.base) { - pr_err("cannot iomap\n"); - return -ENXIO; - } - - periph_regs = syscon_regmap_lookup_by_phandle(node, "img,cr-periph"); - if (IS_ERR(periph_regs)) { - pr_err("cannot get peripheral regmap (%ld)\n", - PTR_ERR(periph_regs)); - return PTR_ERR(periph_regs); - } - - /* Switch to using the fast counter clock */ - ret = regmap_update_bits(periph_regs, PERIP_TIMER_CONTROL, - 0xf, 0x0); - if (ret) - return ret; - - sys_clk = of_clk_get_by_name(node, "sys"); - if (IS_ERR(sys_clk)) { - pr_err("clock get failed (%ld)\n", PTR_ERR(sys_clk)); - return PTR_ERR(sys_clk); - } - - fast_clk = of_clk_get_by_name(node, "fast"); - if (IS_ERR(fast_clk)) { - pr_err("clock get failed (%lu)\n", PTR_ERR(fast_clk)); - return PTR_ERR(fast_clk); - } - - ret = clk_prepare_enable(sys_clk); - if (ret < 0) { - pr_err("failed to enable clock (%d)\n", ret); - return ret; - } - - ret = clk_prepare_enable(fast_clk); - if (ret < 0) { - pr_err("failed to enable clock (%d)\n", ret); - clk_disable_unprepare(sys_clk); - return ret; - } - - rate = clk_get_rate(fast_clk); - - /* Disable irq's for clocksource usage */ - gpt_writel(pcs_gpt.base, 0, TIMER_IRQ_MASK, 0); - gpt_writel(pcs_gpt.base, 0, TIMER_IRQ_MASK, 1); - gpt_writel(pcs_gpt.base, 0, TIMER_IRQ_MASK, 2); - gpt_writel(pcs_gpt.base, 0, TIMER_IRQ_MASK, 3); - - /* Enable timer block */ - writel(TIMER_ME_GLOBAL, pcs_gpt.base); - - raw_spin_lock_init(&pcs_gpt.lock); - sched_clock_register(pistachio_read_sched_clock, 32, rate); - return clocksource_register_hz(&pcs_gpt.cs, rate); -} -TIMER_OF_DECLARE(pistachio_gptimer, "img,pistachio-gptimer", - pistachio_clksrc_of_init); diff --git a/drivers/clocksource/timer-armada-370-xp.c b/drivers/clocksource/timer-armada-370-xp.c new file mode 100644 index 0000000000000..edf1a46269f10 --- /dev/null +++ b/drivers/clocksource/timer-armada-370-xp.c @@ -0,0 +1,416 @@ +/* + * Marvell Armada 370/XP SoC timer handling. + * + * Copyright (C) 2012 Marvell + * + * Lior Amsalem + * Gregory CLEMENT + * Thomas Petazzoni + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + * + * Timer 0 is used as free-running clocksource, while timer 1 is + * used as clock_event_device. + * + * --- + * Clocksource driver for Armada 370 and Armada XP SoC. + * This driver implements one compatible string for each SoC, given + * each has its own characteristics: + * + * * Armada 370 has no 25 MHz fixed timer. + * + * * Armada XP cannot work properly without such 25 MHz fixed timer as + * doing otherwise leads to using a clocksource whose frequency varies + * when doing cpufreq frequency changes. + * + * See Documentation/devicetree/bindings/timer/marvell,armada-370-xp-timer.txt + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +/* + * Timer block registers. + */ +#define TIMER_CTRL_OFF 0x0000 +#define TIMER0_EN BIT(0) +#define TIMER0_RELOAD_EN BIT(1) +#define TIMER0_25MHZ BIT(11) +#define TIMER0_DIV(div) ((div) << 19) +#define TIMER1_EN BIT(2) +#define TIMER1_RELOAD_EN BIT(3) +#define TIMER1_25MHZ BIT(12) +#define TIMER1_DIV(div) ((div) << 22) +#define TIMER_EVENTS_STATUS 0x0004 +#define TIMER0_CLR_MASK (~0x1) +#define TIMER1_CLR_MASK (~0x100) +#define TIMER0_RELOAD_OFF 0x0010 +#define TIMER0_VAL_OFF 0x0014 +#define TIMER1_RELOAD_OFF 0x0018 +#define TIMER1_VAL_OFF 0x001c + +#define LCL_TIMER_EVENTS_STATUS 0x0028 +/* Global timers are connected to the coherency fabric clock, and the + below divider reduces their incrementing frequency. */ +#define TIMER_DIVIDER_SHIFT 5 +#define TIMER_DIVIDER (1 << TIMER_DIVIDER_SHIFT) + +/* + * SoC-specific data. + */ +static void __iomem *timer_base, *local_base; +static unsigned int timer_clk; +static bool timer25Mhz = true; +static u32 enable_mask; + +/* + * Number of timer ticks per jiffy. + */ +static u32 ticks_per_jiffy; + +static struct clock_event_device __percpu *armada_370_xp_evt; + +static void local_timer_ctrl_clrset(u32 clr, u32 set) +{ + writel((readl(local_base + TIMER_CTRL_OFF) & ~clr) | set, + local_base + TIMER_CTRL_OFF); +} + +static u64 notrace armada_370_xp_read_sched_clock(void) +{ + return ~readl(timer_base + TIMER0_VAL_OFF); +} + +/* + * Clockevent handling. + */ +static int +armada_370_xp_clkevt_next_event(unsigned long delta, + struct clock_event_device *dev) +{ + /* + * Clear clockevent timer interrupt. + */ + writel(TIMER0_CLR_MASK, local_base + LCL_TIMER_EVENTS_STATUS); + + /* + * Setup new clockevent timer value. + */ + writel(delta, local_base + TIMER0_VAL_OFF); + + /* + * Enable the timer. + */ + local_timer_ctrl_clrset(TIMER0_RELOAD_EN, enable_mask); + return 0; +} + +static int armada_370_xp_clkevt_shutdown(struct clock_event_device *evt) +{ + /* + * Disable timer. + */ + local_timer_ctrl_clrset(TIMER0_EN, 0); + + /* + * ACK pending timer interrupt. + */ + writel(TIMER0_CLR_MASK, local_base + LCL_TIMER_EVENTS_STATUS); + return 0; +} + +static int armada_370_xp_clkevt_set_periodic(struct clock_event_device *evt) +{ + /* + * Setup timer to fire at 1/HZ intervals. + */ + writel(ticks_per_jiffy - 1, local_base + TIMER0_RELOAD_OFF); + writel(ticks_per_jiffy - 1, local_base + TIMER0_VAL_OFF); + + /* + * Enable timer. + */ + local_timer_ctrl_clrset(0, TIMER0_RELOAD_EN | enable_mask); + return 0; +} + +static int armada_370_xp_clkevt_irq; + +static irqreturn_t armada_370_xp_timer_interrupt(int irq, void *dev_id) +{ + /* + * ACK timer interrupt and call event handler. + */ + struct clock_event_device *evt = dev_id; + + writel(TIMER0_CLR_MASK, local_base + LCL_TIMER_EVENTS_STATUS); + evt->event_handler(evt); + + return IRQ_HANDLED; +} + +/* + * Setup the local clock events for a CPU. + */ +static int armada_370_xp_timer_starting_cpu(unsigned int cpu) +{ + struct clock_event_device *evt = per_cpu_ptr(armada_370_xp_evt, cpu); + u32 clr = 0, set = 0; + + if (timer25Mhz) + set = TIMER0_25MHZ; + else + clr = TIMER0_25MHZ; + local_timer_ctrl_clrset(clr, set); + + evt->name = "armada_370_xp_per_cpu_tick", + evt->features = CLOCK_EVT_FEAT_ONESHOT | + CLOCK_EVT_FEAT_PERIODIC; + evt->shift = 32, + evt->rating = 300, + evt->set_next_event = armada_370_xp_clkevt_next_event, + evt->set_state_shutdown = armada_370_xp_clkevt_shutdown; + evt->set_state_periodic = armada_370_xp_clkevt_set_periodic; + evt->set_state_oneshot = armada_370_xp_clkevt_shutdown; + evt->tick_resume = armada_370_xp_clkevt_shutdown; + evt->irq = armada_370_xp_clkevt_irq; + evt->cpumask = cpumask_of(cpu); + + clockevents_config_and_register(evt, timer_clk, 1, 0xfffffffe); + enable_percpu_irq(evt->irq, 0); + + return 0; +} + +static int armada_370_xp_timer_dying_cpu(unsigned int cpu) +{ + struct clock_event_device *evt = per_cpu_ptr(armada_370_xp_evt, cpu); + + evt->set_state_shutdown(evt); + disable_percpu_irq(evt->irq); + return 0; +} + +static u32 timer0_ctrl_reg, timer0_local_ctrl_reg; + +static int armada_370_xp_timer_suspend(void) +{ + timer0_ctrl_reg = readl(timer_base + TIMER_CTRL_OFF); + timer0_local_ctrl_reg = readl(local_base + TIMER_CTRL_OFF); + return 0; +} + +static void armada_370_xp_timer_resume(void) +{ + writel(0xffffffff, timer_base + TIMER0_VAL_OFF); + writel(0xffffffff, timer_base + TIMER0_RELOAD_OFF); + writel(timer0_ctrl_reg, timer_base + TIMER_CTRL_OFF); + writel(timer0_local_ctrl_reg, local_base + TIMER_CTRL_OFF); +} + +static struct syscore_ops armada_370_xp_timer_syscore_ops = { + .suspend = armada_370_xp_timer_suspend, + .resume = armada_370_xp_timer_resume, +}; + +static unsigned long armada_370_delay_timer_read(void) +{ + return ~readl(timer_base + TIMER0_VAL_OFF); +} + +static struct delay_timer armada_370_delay_timer = { + .read_current_timer = armada_370_delay_timer_read, +}; + +static int __init armada_370_xp_timer_common_init(struct device_node *np) +{ + u32 clr = 0, set = 0; + int res; + + timer_base = of_iomap(np, 0); + if (!timer_base) { + pr_err("Failed to iomap\n"); + return -ENXIO; + } + + local_base = of_iomap(np, 1); + if (!local_base) { + pr_err("Failed to iomap\n"); + return -ENXIO; + } + + if (timer25Mhz) { + set = TIMER0_25MHZ; + enable_mask = TIMER0_EN; + } else { + clr = TIMER0_25MHZ; + enable_mask = TIMER0_EN | TIMER0_DIV(TIMER_DIVIDER_SHIFT); + } + atomic_io_modify(timer_base + TIMER_CTRL_OFF, clr | set, set); + local_timer_ctrl_clrset(clr, set); + + /* + * We use timer 0 as clocksource, and private(local) timer 0 + * for clockevents + */ + armada_370_xp_clkevt_irq = irq_of_parse_and_map(np, 4); + + ticks_per_jiffy = (timer_clk + HZ / 2) / HZ; + + /* + * Setup free-running clocksource timer (interrupts + * disabled). + */ + writel(0xffffffff, timer_base + TIMER0_VAL_OFF); + writel(0xffffffff, timer_base + TIMER0_RELOAD_OFF); + + atomic_io_modify(timer_base + TIMER_CTRL_OFF, + TIMER0_RELOAD_EN | enable_mask, + TIMER0_RELOAD_EN | enable_mask); + + armada_370_delay_timer.freq = timer_clk; + register_current_timer_delay(&armada_370_delay_timer); + + /* + * Set scale and timer for sched_clock. + */ + sched_clock_register(armada_370_xp_read_sched_clock, 32, timer_clk); + + res = clocksource_mmio_init(timer_base + TIMER0_VAL_OFF, + "armada_370_xp_clocksource", + timer_clk, 300, 32, clocksource_mmio_readl_down); + if (res) { + pr_err("Failed to initialize clocksource mmio\n"); + return res; + } + + armada_370_xp_evt = alloc_percpu(struct clock_event_device); + if (!armada_370_xp_evt) + return -ENOMEM; + + /* + * Setup clockevent timer (interrupt-driven). + */ + res = request_percpu_irq(armada_370_xp_clkevt_irq, + armada_370_xp_timer_interrupt, + "armada_370_xp_per_cpu_tick", + armada_370_xp_evt); + /* Immediately configure the timer on the boot CPU */ + if (res) { + pr_err("Failed to request percpu irq\n"); + return res; + } + + res = cpuhp_setup_state(CPUHP_AP_ARMADA_TIMER_STARTING, + "clockevents/armada:starting", + armada_370_xp_timer_starting_cpu, + armada_370_xp_timer_dying_cpu); + if (res) { + pr_err("Failed to setup hotplug state and timer\n"); + return res; + } + + register_syscore_ops(&armada_370_xp_timer_syscore_ops); + + return 0; +} + +static int __init armada_xp_timer_init(struct device_node *np) +{ + struct clk *clk = of_clk_get_by_name(np, "fixed"); + int ret; + + if (IS_ERR(clk)) { + pr_err("Failed to get clock\n"); + return PTR_ERR(clk); + } + + ret = clk_prepare_enable(clk); + if (ret) + return ret; + + timer_clk = clk_get_rate(clk); + + return armada_370_xp_timer_common_init(np); +} +TIMER_OF_DECLARE(armada_xp, "marvell,armada-xp-timer", + armada_xp_timer_init); + +static int __init armada_375_timer_init(struct device_node *np) +{ + struct clk *clk; + int ret; + + clk = of_clk_get_by_name(np, "fixed"); + if (!IS_ERR(clk)) { + ret = clk_prepare_enable(clk); + if (ret) + return ret; + timer_clk = clk_get_rate(clk); + } else { + + /* + * This fallback is required in order to retain proper + * devicetree backwards compatibility. + */ + clk = of_clk_get(np, 0); + + /* Must have at least a clock */ + if (IS_ERR(clk)) { + pr_err("Failed to get clock\n"); + return PTR_ERR(clk); + } + + ret = clk_prepare_enable(clk); + if (ret) + return ret; + + timer_clk = clk_get_rate(clk) / TIMER_DIVIDER; + timer25Mhz = false; + } + + return armada_370_xp_timer_common_init(np); +} +TIMER_OF_DECLARE(armada_375, "marvell,armada-375-timer", + armada_375_timer_init); + +static int __init armada_370_timer_init(struct device_node *np) +{ + struct clk *clk; + int ret; + + clk = of_clk_get(np, 0); + if (IS_ERR(clk)) { + pr_err("Failed to get clock\n"); + return PTR_ERR(clk); + } + + ret = clk_prepare_enable(clk); + if (ret) + return ret; + + timer_clk = clk_get_rate(clk) / TIMER_DIVIDER; + timer25Mhz = false; + + return armada_370_xp_timer_common_init(np); +} +TIMER_OF_DECLARE(armada_370, "marvell,armada-370-timer", + armada_370_timer_init); diff --git a/drivers/clocksource/timer-cadence-ttc.c b/drivers/clocksource/timer-cadence-ttc.c new file mode 100644 index 0000000000000..16b9bfb257564 --- /dev/null +++ b/drivers/clocksource/timer-cadence-ttc.c @@ -0,0 +1,560 @@ +/* + * This file contains driver for the Cadence Triple Timer Counter Rev 06 + * + * Copyright (C) 2011-2013 Xilinx + * + * based on arch/mips/kernel/time.c timer driver + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * This driver configures the 2 16/32-bit count-up timers as follows: + * + * T1: Timer 1, clocksource for generic timekeeping + * T2: Timer 2, clockevent source for hrtimers + * T3: Timer 3, + * + * The input frequency to the timer module for emulation is 2.5MHz which is + * common to all the timer channels (T1, T2, and T3). With a pre-scaler of 32, + * the timers are clocked at 78.125KHz (12.8 us resolution). + + * The input frequency to the timer module in silicon is configurable and + * obtained from device tree. The pre-scaler of 32 is used. + */ + +/* + * Timer Register Offset Definitions of Timer 1, Increment base address by 4 + * and use same offsets for Timer 2 + */ +#define TTC_CLK_CNTRL_OFFSET 0x00 /* Clock Control Reg, RW */ +#define TTC_CNT_CNTRL_OFFSET 0x0C /* Counter Control Reg, RW */ +#define TTC_COUNT_VAL_OFFSET 0x18 /* Counter Value Reg, RO */ +#define TTC_INTR_VAL_OFFSET 0x24 /* Interval Count Reg, RW */ +#define TTC_ISR_OFFSET 0x54 /* Interrupt Status Reg, RO */ +#define TTC_IER_OFFSET 0x60 /* Interrupt Enable Reg, RW */ + +#define TTC_CNT_CNTRL_DISABLE_MASK 0x1 + +#define TTC_CLK_CNTRL_CSRC_MASK (1 << 5) /* clock source */ +#define TTC_CLK_CNTRL_PSV_MASK 0x1e +#define TTC_CLK_CNTRL_PSV_SHIFT 1 + +/* + * Setup the timers to use pre-scaling, using a fixed value for now that will + * work across most input frequency, but it may need to be more dynamic + */ +#define PRESCALE_EXPONENT 11 /* 2 ^ PRESCALE_EXPONENT = PRESCALE */ +#define PRESCALE 2048 /* The exponent must match this */ +#define CLK_CNTRL_PRESCALE ((PRESCALE_EXPONENT - 1) << 1) +#define CLK_CNTRL_PRESCALE_EN 1 +#define CNT_CNTRL_RESET (1 << 4) + +#define MAX_F_ERR 50 + +/** + * struct ttc_timer - This definition defines local timer structure + * + * @base_addr: Base address of timer + * @freq: Timer input clock frequency + * @clk: Associated clock source + * @clk_rate_change_nb Notifier block for clock rate changes + */ +struct ttc_timer { + void __iomem *base_addr; + unsigned long freq; + struct clk *clk; + struct notifier_block clk_rate_change_nb; +}; + +#define to_ttc_timer(x) \ + container_of(x, struct ttc_timer, clk_rate_change_nb) + +struct ttc_timer_clocksource { + u32 scale_clk_ctrl_reg_old; + u32 scale_clk_ctrl_reg_new; + struct ttc_timer ttc; + struct clocksource cs; +}; + +#define to_ttc_timer_clksrc(x) \ + container_of(x, struct ttc_timer_clocksource, cs) + +struct ttc_timer_clockevent { + struct ttc_timer ttc; + struct clock_event_device ce; +}; + +#define to_ttc_timer_clkevent(x) \ + container_of(x, struct ttc_timer_clockevent, ce) + +static void __iomem *ttc_sched_clock_val_reg; + +/** + * ttc_set_interval - Set the timer interval value + * + * @timer: Pointer to the timer instance + * @cycles: Timer interval ticks + **/ +static void ttc_set_interval(struct ttc_timer *timer, + unsigned long cycles) +{ + u32 ctrl_reg; + + /* Disable the counter, set the counter value and re-enable counter */ + ctrl_reg = readl_relaxed(timer->base_addr + TTC_CNT_CNTRL_OFFSET); + ctrl_reg |= TTC_CNT_CNTRL_DISABLE_MASK; + writel_relaxed(ctrl_reg, timer->base_addr + TTC_CNT_CNTRL_OFFSET); + + writel_relaxed(cycles, timer->base_addr + TTC_INTR_VAL_OFFSET); + + /* + * Reset the counter (0x10) so that it starts from 0, one-shot + * mode makes this needed for timing to be right. + */ + ctrl_reg |= CNT_CNTRL_RESET; + ctrl_reg &= ~TTC_CNT_CNTRL_DISABLE_MASK; + writel_relaxed(ctrl_reg, timer->base_addr + TTC_CNT_CNTRL_OFFSET); +} + +/** + * ttc_clock_event_interrupt - Clock event timer interrupt handler + * + * @irq: IRQ number of the Timer + * @dev_id: void pointer to the ttc_timer instance + * + * returns: Always IRQ_HANDLED - success + **/ +static irqreturn_t ttc_clock_event_interrupt(int irq, void *dev_id) +{ + struct ttc_timer_clockevent *ttce = dev_id; + struct ttc_timer *timer = &ttce->ttc; + + /* Acknowledge the interrupt and call event handler */ + readl_relaxed(timer->base_addr + TTC_ISR_OFFSET); + + ttce->ce.event_handler(&ttce->ce); + + return IRQ_HANDLED; +} + +/** + * __ttc_clocksource_read - Reads the timer counter register + * + * returns: Current timer counter register value + **/ +static u64 __ttc_clocksource_read(struct clocksource *cs) +{ + struct ttc_timer *timer = &to_ttc_timer_clksrc(cs)->ttc; + + return (u64)readl_relaxed(timer->base_addr + + TTC_COUNT_VAL_OFFSET); +} + +static u64 notrace ttc_sched_clock_read(void) +{ + return readl_relaxed(ttc_sched_clock_val_reg); +} + +/** + * ttc_set_next_event - Sets the time interval for next event + * + * @cycles: Timer interval ticks + * @evt: Address of clock event instance + * + * returns: Always 0 - success + **/ +static int ttc_set_next_event(unsigned long cycles, + struct clock_event_device *evt) +{ + struct ttc_timer_clockevent *ttce = to_ttc_timer_clkevent(evt); + struct ttc_timer *timer = &ttce->ttc; + + ttc_set_interval(timer, cycles); + return 0; +} + +/** + * ttc_set_{shutdown|oneshot|periodic} - Sets the state of timer + * + * @evt: Address of clock event instance + **/ +static int ttc_shutdown(struct clock_event_device *evt) +{ + struct ttc_timer_clockevent *ttce = to_ttc_timer_clkevent(evt); + struct ttc_timer *timer = &ttce->ttc; + u32 ctrl_reg; + + ctrl_reg = readl_relaxed(timer->base_addr + TTC_CNT_CNTRL_OFFSET); + ctrl_reg |= TTC_CNT_CNTRL_DISABLE_MASK; + writel_relaxed(ctrl_reg, timer->base_addr + TTC_CNT_CNTRL_OFFSET); + return 0; +} + +static int ttc_set_periodic(struct clock_event_device *evt) +{ + struct ttc_timer_clockevent *ttce = to_ttc_timer_clkevent(evt); + struct ttc_timer *timer = &ttce->ttc; + + ttc_set_interval(timer, + DIV_ROUND_CLOSEST(ttce->ttc.freq, PRESCALE * HZ)); + return 0; +} + +static int ttc_resume(struct clock_event_device *evt) +{ + struct ttc_timer_clockevent *ttce = to_ttc_timer_clkevent(evt); + struct ttc_timer *timer = &ttce->ttc; + u32 ctrl_reg; + + ctrl_reg = readl_relaxed(timer->base_addr + TTC_CNT_CNTRL_OFFSET); + ctrl_reg &= ~TTC_CNT_CNTRL_DISABLE_MASK; + writel_relaxed(ctrl_reg, timer->base_addr + TTC_CNT_CNTRL_OFFSET); + return 0; +} + +static int ttc_rate_change_clocksource_cb(struct notifier_block *nb, + unsigned long event, void *data) +{ + struct clk_notifier_data *ndata = data; + struct ttc_timer *ttc = to_ttc_timer(nb); + struct ttc_timer_clocksource *ttccs = container_of(ttc, + struct ttc_timer_clocksource, ttc); + + switch (event) { + case PRE_RATE_CHANGE: + { + u32 psv; + unsigned long factor, rate_low, rate_high; + + if (ndata->new_rate > ndata->old_rate) { + factor = DIV_ROUND_CLOSEST(ndata->new_rate, + ndata->old_rate); + rate_low = ndata->old_rate; + rate_high = ndata->new_rate; + } else { + factor = DIV_ROUND_CLOSEST(ndata->old_rate, + ndata->new_rate); + rate_low = ndata->new_rate; + rate_high = ndata->old_rate; + } + + if (!is_power_of_2(factor)) + return NOTIFY_BAD; + + if (abs(rate_high - (factor * rate_low)) > MAX_F_ERR) + return NOTIFY_BAD; + + factor = __ilog2_u32(factor); + + /* + * store timer clock ctrl register so we can restore it in case + * of an abort. + */ + ttccs->scale_clk_ctrl_reg_old = + readl_relaxed(ttccs->ttc.base_addr + + TTC_CLK_CNTRL_OFFSET); + + psv = (ttccs->scale_clk_ctrl_reg_old & + TTC_CLK_CNTRL_PSV_MASK) >> + TTC_CLK_CNTRL_PSV_SHIFT; + if (ndata->new_rate < ndata->old_rate) + psv -= factor; + else + psv += factor; + + /* prescaler within legal range? */ + if (psv & ~(TTC_CLK_CNTRL_PSV_MASK >> TTC_CLK_CNTRL_PSV_SHIFT)) + return NOTIFY_BAD; + + ttccs->scale_clk_ctrl_reg_new = ttccs->scale_clk_ctrl_reg_old & + ~TTC_CLK_CNTRL_PSV_MASK; + ttccs->scale_clk_ctrl_reg_new |= psv << TTC_CLK_CNTRL_PSV_SHIFT; + + + /* scale down: adjust divider in post-change notification */ + if (ndata->new_rate < ndata->old_rate) + return NOTIFY_DONE; + + /* scale up: adjust divider now - before frequency change */ + writel_relaxed(ttccs->scale_clk_ctrl_reg_new, + ttccs->ttc.base_addr + TTC_CLK_CNTRL_OFFSET); + break; + } + case POST_RATE_CHANGE: + /* scale up: pre-change notification did the adjustment */ + if (ndata->new_rate > ndata->old_rate) + return NOTIFY_OK; + + /* scale down: adjust divider now - after frequency change */ + writel_relaxed(ttccs->scale_clk_ctrl_reg_new, + ttccs->ttc.base_addr + TTC_CLK_CNTRL_OFFSET); + break; + + case ABORT_RATE_CHANGE: + /* we have to undo the adjustment in case we scale up */ + if (ndata->new_rate < ndata->old_rate) + return NOTIFY_OK; + + /* restore original register value */ + writel_relaxed(ttccs->scale_clk_ctrl_reg_old, + ttccs->ttc.base_addr + TTC_CLK_CNTRL_OFFSET); + /* fall through */ + default: + return NOTIFY_DONE; + } + + return NOTIFY_DONE; +} + +static int __init ttc_setup_clocksource(struct clk *clk, void __iomem *base, + u32 timer_width) +{ + struct ttc_timer_clocksource *ttccs; + int err; + + ttccs = kzalloc(sizeof(*ttccs), GFP_KERNEL); + if (!ttccs) + return -ENOMEM; + + ttccs->ttc.clk = clk; + + err = clk_prepare_enable(ttccs->ttc.clk); + if (err) { + kfree(ttccs); + return err; + } + + ttccs->ttc.freq = clk_get_rate(ttccs->ttc.clk); + + ttccs->ttc.clk_rate_change_nb.notifier_call = + ttc_rate_change_clocksource_cb; + ttccs->ttc.clk_rate_change_nb.next = NULL; + + err = clk_notifier_register(ttccs->ttc.clk, + &ttccs->ttc.clk_rate_change_nb); + if (err) + pr_warn("Unable to register clock notifier.\n"); + + ttccs->ttc.base_addr = base; + ttccs->cs.name = "ttc_clocksource"; + ttccs->cs.rating = 200; + ttccs->cs.read = __ttc_clocksource_read; + ttccs->cs.mask = CLOCKSOURCE_MASK(timer_width); + ttccs->cs.flags = CLOCK_SOURCE_IS_CONTINUOUS; + + /* + * Setup the clock source counter to be an incrementing counter + * with no interrupt and it rolls over at 0xFFFF. Pre-scale + * it by 32 also. Let it start running now. + */ + writel_relaxed(0x0, ttccs->ttc.base_addr + TTC_IER_OFFSET); + writel_relaxed(CLK_CNTRL_PRESCALE | CLK_CNTRL_PRESCALE_EN, + ttccs->ttc.base_addr + TTC_CLK_CNTRL_OFFSET); + writel_relaxed(CNT_CNTRL_RESET, + ttccs->ttc.base_addr + TTC_CNT_CNTRL_OFFSET); + + err = clocksource_register_hz(&ttccs->cs, ttccs->ttc.freq / PRESCALE); + if (err) { + kfree(ttccs); + return err; + } + + ttc_sched_clock_val_reg = base + TTC_COUNT_VAL_OFFSET; + sched_clock_register(ttc_sched_clock_read, timer_width, + ttccs->ttc.freq / PRESCALE); + + return 0; +} + +static int ttc_rate_change_clockevent_cb(struct notifier_block *nb, + unsigned long event, void *data) +{ + struct clk_notifier_data *ndata = data; + struct ttc_timer *ttc = to_ttc_timer(nb); + struct ttc_timer_clockevent *ttcce = container_of(ttc, + struct ttc_timer_clockevent, ttc); + + switch (event) { + case POST_RATE_CHANGE: + /* update cached frequency */ + ttc->freq = ndata->new_rate; + + clockevents_update_freq(&ttcce->ce, ndata->new_rate / PRESCALE); + + /* fall through */ + case PRE_RATE_CHANGE: + case ABORT_RATE_CHANGE: + default: + return NOTIFY_DONE; + } +} + +static int __init ttc_setup_clockevent(struct clk *clk, + void __iomem *base, u32 irq) +{ + struct ttc_timer_clockevent *ttcce; + int err; + + ttcce = kzalloc(sizeof(*ttcce), GFP_KERNEL); + if (!ttcce) + return -ENOMEM; + + ttcce->ttc.clk = clk; + + err = clk_prepare_enable(ttcce->ttc.clk); + if (err) + goto out_kfree; + + ttcce->ttc.clk_rate_change_nb.notifier_call = + ttc_rate_change_clockevent_cb; + ttcce->ttc.clk_rate_change_nb.next = NULL; + + err = clk_notifier_register(ttcce->ttc.clk, + &ttcce->ttc.clk_rate_change_nb); + if (err) { + pr_warn("Unable to register clock notifier.\n"); + goto out_kfree; + } + + ttcce->ttc.freq = clk_get_rate(ttcce->ttc.clk); + + ttcce->ttc.base_addr = base; + ttcce->ce.name = "ttc_clockevent"; + ttcce->ce.features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT; + ttcce->ce.set_next_event = ttc_set_next_event; + ttcce->ce.set_state_shutdown = ttc_shutdown; + ttcce->ce.set_state_periodic = ttc_set_periodic; + ttcce->ce.set_state_oneshot = ttc_shutdown; + ttcce->ce.tick_resume = ttc_resume; + ttcce->ce.rating = 200; + ttcce->ce.irq = irq; + ttcce->ce.cpumask = cpu_possible_mask; + + /* + * Setup the clock event timer to be an interval timer which + * is prescaled by 32 using the interval interrupt. Leave it + * disabled for now. + */ + writel_relaxed(0x23, ttcce->ttc.base_addr + TTC_CNT_CNTRL_OFFSET); + writel_relaxed(CLK_CNTRL_PRESCALE | CLK_CNTRL_PRESCALE_EN, + ttcce->ttc.base_addr + TTC_CLK_CNTRL_OFFSET); + writel_relaxed(0x1, ttcce->ttc.base_addr + TTC_IER_OFFSET); + + err = request_irq(irq, ttc_clock_event_interrupt, + IRQF_TIMER, ttcce->ce.name, ttcce); + if (err) + goto out_kfree; + + clockevents_config_and_register(&ttcce->ce, + ttcce->ttc.freq / PRESCALE, 1, 0xfffe); + + return 0; + +out_kfree: + kfree(ttcce); + return err; +} + +static int __init ttc_timer_probe(struct platform_device *pdev) +{ + unsigned int irq; + void __iomem *timer_baseaddr; + struct clk *clk_cs, *clk_ce; + static int initialized; + int clksel, ret; + u32 timer_width = 16; + struct device_node *timer = pdev->dev.of_node; + + if (initialized) + return 0; + + initialized = 1; + + /* + * Get the 1st Triple Timer Counter (TTC) block from the device tree + * and use it. Note that the event timer uses the interrupt and it's the + * 2nd TTC hence the irq_of_parse_and_map(,1) + */ + timer_baseaddr = devm_of_iomap(&pdev->dev, timer, 0, NULL); + if (IS_ERR(timer_baseaddr)) { + pr_err("ERROR: invalid timer base address\n"); + return PTR_ERR(timer_baseaddr); + } + + irq = irq_of_parse_and_map(timer, 1); + if (irq <= 0) { + pr_err("ERROR: invalid interrupt number\n"); + return -EINVAL; + } + + of_property_read_u32(timer, "timer-width", &timer_width); + + clksel = readl_relaxed(timer_baseaddr + TTC_CLK_CNTRL_OFFSET); + clksel = !!(clksel & TTC_CLK_CNTRL_CSRC_MASK); + clk_cs = of_clk_get(timer, clksel); + if (IS_ERR(clk_cs)) { + pr_err("ERROR: timer input clock not found\n"); + return PTR_ERR(clk_cs); + } + + clksel = readl_relaxed(timer_baseaddr + 4 + TTC_CLK_CNTRL_OFFSET); + clksel = !!(clksel & TTC_CLK_CNTRL_CSRC_MASK); + clk_ce = of_clk_get(timer, clksel); + if (IS_ERR(clk_ce)) { + pr_err("ERROR: timer input clock not found\n"); + ret = PTR_ERR(clk_ce); + goto put_clk_cs; + } + + ret = ttc_setup_clocksource(clk_cs, timer_baseaddr, timer_width); + if (ret) + goto put_clk_ce; + + ret = ttc_setup_clockevent(clk_ce, timer_baseaddr + 4, irq); + if (ret) + goto put_clk_ce; + + pr_info("%s #0 at %p, irq=%d\n", timer->name, timer_baseaddr, irq); + + return 0; + +put_clk_ce: + clk_put(clk_ce); +put_clk_cs: + clk_put(clk_cs); + return ret; +} + +static const struct of_device_id ttc_timer_of_match[] = { + {.compatible = "cdns,ttc"}, + {}, +}; + +MODULE_DEVICE_TABLE(of, ttc_timer_of_match); + +static struct platform_driver ttc_timer_driver = { + .driver = { + .name = "cdns_ttc_timer", + .of_match_table = ttc_timer_of_match, + }, +}; +builtin_platform_driver_probe(ttc_timer_driver, ttc_timer_probe); diff --git a/drivers/clocksource/timer-efm32.c b/drivers/clocksource/timer-efm32.c new file mode 100644 index 0000000000000..257e810ec1ad1 --- /dev/null +++ b/drivers/clocksource/timer-efm32.c @@ -0,0 +1,287 @@ +/* + * Copyright (C) 2013 Pengutronix + * Uwe Kleine-Koenig + * + * This program is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License version 2 as published by the + * Free Software Foundation. + */ + +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define TIMERn_CTRL 0x00 +#define TIMERn_CTRL_PRESC(val) (((val) & 0xf) << 24) +#define TIMERn_CTRL_PRESC_1024 TIMERn_CTRL_PRESC(10) +#define TIMERn_CTRL_CLKSEL(val) (((val) & 0x3) << 16) +#define TIMERn_CTRL_CLKSEL_PRESCHFPERCLK TIMERn_CTRL_CLKSEL(0) +#define TIMERn_CTRL_OSMEN 0x00000010 +#define TIMERn_CTRL_MODE(val) (((val) & 0x3) << 0) +#define TIMERn_CTRL_MODE_UP TIMERn_CTRL_MODE(0) +#define TIMERn_CTRL_MODE_DOWN TIMERn_CTRL_MODE(1) + +#define TIMERn_CMD 0x04 +#define TIMERn_CMD_START 0x00000001 +#define TIMERn_CMD_STOP 0x00000002 + +#define TIMERn_IEN 0x0c +#define TIMERn_IF 0x10 +#define TIMERn_IFS 0x14 +#define TIMERn_IFC 0x18 +#define TIMERn_IRQ_UF 0x00000002 + +#define TIMERn_TOP 0x1c +#define TIMERn_CNT 0x24 + +struct efm32_clock_event_ddata { + struct clock_event_device evtdev; + void __iomem *base; + unsigned periodic_top; +}; + +static int efm32_clock_event_shutdown(struct clock_event_device *evtdev) +{ + struct efm32_clock_event_ddata *ddata = + container_of(evtdev, struct efm32_clock_event_ddata, evtdev); + + writel_relaxed(TIMERn_CMD_STOP, ddata->base + TIMERn_CMD); + return 0; +} + +static int efm32_clock_event_set_oneshot(struct clock_event_device *evtdev) +{ + struct efm32_clock_event_ddata *ddata = + container_of(evtdev, struct efm32_clock_event_ddata, evtdev); + + writel_relaxed(TIMERn_CMD_STOP, ddata->base + TIMERn_CMD); + writel_relaxed(TIMERn_CTRL_PRESC_1024 | + TIMERn_CTRL_CLKSEL_PRESCHFPERCLK | + TIMERn_CTRL_OSMEN | + TIMERn_CTRL_MODE_DOWN, + ddata->base + TIMERn_CTRL); + return 0; +} + +static int efm32_clock_event_set_periodic(struct clock_event_device *evtdev) +{ + struct efm32_clock_event_ddata *ddata = + container_of(evtdev, struct efm32_clock_event_ddata, evtdev); + + writel_relaxed(TIMERn_CMD_STOP, ddata->base + TIMERn_CMD); + writel_relaxed(ddata->periodic_top, ddata->base + TIMERn_TOP); + writel_relaxed(TIMERn_CTRL_PRESC_1024 | + TIMERn_CTRL_CLKSEL_PRESCHFPERCLK | + TIMERn_CTRL_MODE_DOWN, + ddata->base + TIMERn_CTRL); + writel_relaxed(TIMERn_CMD_START, ddata->base + TIMERn_CMD); + return 0; +} + +static int efm32_clock_event_set_next_event(unsigned long evt, + struct clock_event_device *evtdev) +{ + struct efm32_clock_event_ddata *ddata = + container_of(evtdev, struct efm32_clock_event_ddata, evtdev); + + writel_relaxed(TIMERn_CMD_STOP, ddata->base + TIMERn_CMD); + writel_relaxed(evt, ddata->base + TIMERn_CNT); + writel_relaxed(TIMERn_CMD_START, ddata->base + TIMERn_CMD); + + return 0; +} + +static irqreturn_t efm32_clock_event_handler(int irq, void *dev_id) +{ + struct efm32_clock_event_ddata *ddata = dev_id; + + writel_relaxed(TIMERn_IRQ_UF, ddata->base + TIMERn_IFC); + + ddata->evtdev.event_handler(&ddata->evtdev); + + return IRQ_HANDLED; +} + +static struct efm32_clock_event_ddata clock_event_ddata = { + .evtdev = { + .name = "efm32 clockevent", + .features = CLOCK_EVT_FEAT_ONESHOT | CLOCK_EVT_FEAT_PERIODIC, + .set_state_shutdown = efm32_clock_event_shutdown, + .set_state_periodic = efm32_clock_event_set_periodic, + .set_state_oneshot = efm32_clock_event_set_oneshot, + .set_next_event = efm32_clock_event_set_next_event, + .rating = 200, + }, +}; + +static struct irqaction efm32_clock_event_irq = { + .name = "efm32 clockevent", + .flags = IRQF_TIMER, + .handler = efm32_clock_event_handler, + .dev_id = &clock_event_ddata, +}; + +static int __init efm32_clocksource_init(struct device_node *np) +{ + struct clk *clk; + void __iomem *base; + unsigned long rate; + int ret; + + clk = of_clk_get(np, 0); + if (IS_ERR(clk)) { + ret = PTR_ERR(clk); + pr_err("failed to get clock for clocksource (%d)\n", ret); + goto err_clk_get; + } + + ret = clk_prepare_enable(clk); + if (ret) { + pr_err("failed to enable timer clock for clocksource (%d)\n", + ret); + goto err_clk_enable; + } + rate = clk_get_rate(clk); + + base = of_iomap(np, 0); + if (!base) { + ret = -EADDRNOTAVAIL; + pr_err("failed to map registers for clocksource\n"); + goto err_iomap; + } + + writel_relaxed(TIMERn_CTRL_PRESC_1024 | + TIMERn_CTRL_CLKSEL_PRESCHFPERCLK | + TIMERn_CTRL_MODE_UP, base + TIMERn_CTRL); + writel_relaxed(TIMERn_CMD_START, base + TIMERn_CMD); + + ret = clocksource_mmio_init(base + TIMERn_CNT, "efm32 timer", + DIV_ROUND_CLOSEST(rate, 1024), 200, 16, + clocksource_mmio_readl_up); + if (ret) { + pr_err("failed to init clocksource (%d)\n", ret); + goto err_clocksource_init; + } + + return 0; + +err_clocksource_init: + + iounmap(base); +err_iomap: + + clk_disable_unprepare(clk); +err_clk_enable: + + clk_put(clk); +err_clk_get: + + return ret; +} + +static int __init efm32_clockevent_init(struct device_node *np) +{ + struct clk *clk; + void __iomem *base; + unsigned long rate; + int irq; + int ret; + + clk = of_clk_get(np, 0); + if (IS_ERR(clk)) { + ret = PTR_ERR(clk); + pr_err("failed to get clock for clockevent (%d)\n", ret); + goto err_clk_get; + } + + ret = clk_prepare_enable(clk); + if (ret) { + pr_err("failed to enable timer clock for clockevent (%d)\n", + ret); + goto err_clk_enable; + } + rate = clk_get_rate(clk); + + base = of_iomap(np, 0); + if (!base) { + ret = -EADDRNOTAVAIL; + pr_err("failed to map registers for clockevent\n"); + goto err_iomap; + } + + irq = irq_of_parse_and_map(np, 0); + if (!irq) { + ret = -ENOENT; + pr_err("failed to get irq for clockevent\n"); + goto err_get_irq; + } + + writel_relaxed(TIMERn_IRQ_UF, base + TIMERn_IEN); + + clock_event_ddata.base = base; + clock_event_ddata.periodic_top = DIV_ROUND_CLOSEST(rate, 1024 * HZ); + + clockevents_config_and_register(&clock_event_ddata.evtdev, + DIV_ROUND_CLOSEST(rate, 1024), + 0xf, 0xffff); + + ret = setup_irq(irq, &efm32_clock_event_irq); + if (ret) { + pr_err("Failed setup irq\n"); + goto err_setup_irq; + } + + return 0; + +err_setup_irq: +err_get_irq: + + iounmap(base); +err_iomap: + + clk_disable_unprepare(clk); +err_clk_enable: + + clk_put(clk); +err_clk_get: + + return ret; +} + +/* + * This function asserts that we have exactly one clocksource and one + * clock_event_device in the end. + */ +static int __init efm32_timer_init(struct device_node *np) +{ + static int has_clocksource, has_clockevent; + int ret = 0; + + if (!has_clocksource) { + ret = efm32_clocksource_init(np); + if (!ret) { + has_clocksource = 1; + return 0; + } + } + + if (!has_clockevent) { + ret = efm32_clockevent_init(np); + if (!ret) { + has_clockevent = 1; + return 0; + } + } + + return ret; +} +TIMER_OF_DECLARE(efm32compat, "efm32,timer", efm32_timer_init); +TIMER_OF_DECLARE(efm32, "energymicro,efm32-timer", efm32_timer_init); diff --git a/drivers/clocksource/timer-fsl-ftm.c b/drivers/clocksource/timer-fsl-ftm.c new file mode 100644 index 0000000000000..846d18daf893b --- /dev/null +++ b/drivers/clocksource/timer-fsl-ftm.c @@ -0,0 +1,376 @@ +/* + * Freescale FlexTimer Module (FTM) timer driver. + * + * Copyright 2014 Freescale Semiconductor, Inc. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define FTM_SC 0x00 +#define FTM_SC_CLK_SHIFT 3 +#define FTM_SC_CLK_MASK (0x3 << FTM_SC_CLK_SHIFT) +#define FTM_SC_CLK(c) ((c) << FTM_SC_CLK_SHIFT) +#define FTM_SC_PS_MASK 0x7 +#define FTM_SC_TOIE BIT(6) +#define FTM_SC_TOF BIT(7) + +#define FTM_CNT 0x04 +#define FTM_MOD 0x08 +#define FTM_CNTIN 0x4C + +#define FTM_PS_MAX 7 + +struct ftm_clock_device { + void __iomem *clksrc_base; + void __iomem *clkevt_base; + unsigned long periodic_cyc; + unsigned long ps; + bool big_endian; +}; + +static struct ftm_clock_device *priv; + +static inline u32 ftm_readl(void __iomem *addr) +{ + if (priv->big_endian) + return ioread32be(addr); + else + return ioread32(addr); +} + +static inline void ftm_writel(u32 val, void __iomem *addr) +{ + if (priv->big_endian) + iowrite32be(val, addr); + else + iowrite32(val, addr); +} + +static inline void ftm_counter_enable(void __iomem *base) +{ + u32 val; + + /* select and enable counter clock source */ + val = ftm_readl(base + FTM_SC); + val &= ~(FTM_SC_PS_MASK | FTM_SC_CLK_MASK); + val |= priv->ps | FTM_SC_CLK(1); + ftm_writel(val, base + FTM_SC); +} + +static inline void ftm_counter_disable(void __iomem *base) +{ + u32 val; + + /* disable counter clock source */ + val = ftm_readl(base + FTM_SC); + val &= ~(FTM_SC_PS_MASK | FTM_SC_CLK_MASK); + ftm_writel(val, base + FTM_SC); +} + +static inline void ftm_irq_acknowledge(void __iomem *base) +{ + u32 val; + + val = ftm_readl(base + FTM_SC); + val &= ~FTM_SC_TOF; + ftm_writel(val, base + FTM_SC); +} + +static inline void ftm_irq_enable(void __iomem *base) +{ + u32 val; + + val = ftm_readl(base + FTM_SC); + val |= FTM_SC_TOIE; + ftm_writel(val, base + FTM_SC); +} + +static inline void ftm_irq_disable(void __iomem *base) +{ + u32 val; + + val = ftm_readl(base + FTM_SC); + val &= ~FTM_SC_TOIE; + ftm_writel(val, base + FTM_SC); +} + +static inline void ftm_reset_counter(void __iomem *base) +{ + /* + * The CNT register contains the FTM counter value. + * Reset clears the CNT register. Writing any value to COUNT + * updates the counter with its initial value, CNTIN. + */ + ftm_writel(0x00, base + FTM_CNT); +} + +static u64 notrace ftm_read_sched_clock(void) +{ + return ftm_readl(priv->clksrc_base + FTM_CNT); +} + +static int ftm_set_next_event(unsigned long delta, + struct clock_event_device *unused) +{ + /* + * The CNNIN and MOD are all double buffer registers, writing + * to the MOD register latches the value into a buffer. The MOD + * register is updated with the value of its write buffer with + * the following scenario: + * a, the counter source clock is diabled. + */ + ftm_counter_disable(priv->clkevt_base); + + /* Force the value of CNTIN to be loaded into the FTM counter */ + ftm_reset_counter(priv->clkevt_base); + + /* + * The counter increments until the value of MOD is reached, + * at which point the counter is reloaded with the value of CNTIN. + * The TOF (the overflow flag) bit is set when the FTM counter + * changes from MOD to CNTIN. So we should using the delta - 1. + */ + ftm_writel(delta - 1, priv->clkevt_base + FTM_MOD); + + ftm_counter_enable(priv->clkevt_base); + + ftm_irq_enable(priv->clkevt_base); + + return 0; +} + +static int ftm_set_oneshot(struct clock_event_device *evt) +{ + ftm_counter_disable(priv->clkevt_base); + return 0; +} + +static int ftm_set_periodic(struct clock_event_device *evt) +{ + ftm_set_next_event(priv->periodic_cyc, evt); + return 0; +} + +static irqreturn_t ftm_evt_interrupt(int irq, void *dev_id) +{ + struct clock_event_device *evt = dev_id; + + ftm_irq_acknowledge(priv->clkevt_base); + + if (likely(clockevent_state_oneshot(evt))) { + ftm_irq_disable(priv->clkevt_base); + ftm_counter_disable(priv->clkevt_base); + } + + evt->event_handler(evt); + + return IRQ_HANDLED; +} + +static struct clock_event_device ftm_clockevent = { + .name = "Freescale ftm timer", + .features = CLOCK_EVT_FEAT_PERIODIC | + CLOCK_EVT_FEAT_ONESHOT, + .set_state_periodic = ftm_set_periodic, + .set_state_oneshot = ftm_set_oneshot, + .set_next_event = ftm_set_next_event, + .rating = 300, +}; + +static struct irqaction ftm_timer_irq = { + .name = "Freescale ftm timer", + .flags = IRQF_TIMER | IRQF_IRQPOLL, + .handler = ftm_evt_interrupt, + .dev_id = &ftm_clockevent, +}; + +static int __init ftm_clockevent_init(unsigned long freq, int irq) +{ + int err; + + ftm_writel(0x00, priv->clkevt_base + FTM_CNTIN); + ftm_writel(~0u, priv->clkevt_base + FTM_MOD); + + ftm_reset_counter(priv->clkevt_base); + + err = setup_irq(irq, &ftm_timer_irq); + if (err) { + pr_err("ftm: setup irq failed: %d\n", err); + return err; + } + + ftm_clockevent.cpumask = cpumask_of(0); + ftm_clockevent.irq = irq; + + clockevents_config_and_register(&ftm_clockevent, + freq / (1 << priv->ps), + 1, 0xffff); + + ftm_counter_enable(priv->clkevt_base); + + return 0; +} + +static int __init ftm_clocksource_init(unsigned long freq) +{ + int err; + + ftm_writel(0x00, priv->clksrc_base + FTM_CNTIN); + ftm_writel(~0u, priv->clksrc_base + FTM_MOD); + + ftm_reset_counter(priv->clksrc_base); + + sched_clock_register(ftm_read_sched_clock, 16, freq / (1 << priv->ps)); + err = clocksource_mmio_init(priv->clksrc_base + FTM_CNT, "fsl-ftm", + freq / (1 << priv->ps), 300, 16, + clocksource_mmio_readl_up); + if (err) { + pr_err("ftm: init clock source mmio failed: %d\n", err); + return err; + } + + ftm_counter_enable(priv->clksrc_base); + + return 0; +} + +static int __init __ftm_clk_init(struct device_node *np, char *cnt_name, + char *ftm_name) +{ + struct clk *clk; + int err; + + clk = of_clk_get_by_name(np, cnt_name); + if (IS_ERR(clk)) { + pr_err("ftm: Cannot get \"%s\": %ld\n", cnt_name, PTR_ERR(clk)); + return PTR_ERR(clk); + } + err = clk_prepare_enable(clk); + if (err) { + pr_err("ftm: clock failed to prepare+enable \"%s\": %d\n", + cnt_name, err); + return err; + } + + clk = of_clk_get_by_name(np, ftm_name); + if (IS_ERR(clk)) { + pr_err("ftm: Cannot get \"%s\": %ld\n", ftm_name, PTR_ERR(clk)); + return PTR_ERR(clk); + } + err = clk_prepare_enable(clk); + if (err) + pr_err("ftm: clock failed to prepare+enable \"%s\": %d\n", + ftm_name, err); + + return clk_get_rate(clk); +} + +static unsigned long __init ftm_clk_init(struct device_node *np) +{ + long freq; + + freq = __ftm_clk_init(np, "ftm-evt-counter-en", "ftm-evt"); + if (freq <= 0) + return 0; + + freq = __ftm_clk_init(np, "ftm-src-counter-en", "ftm-src"); + if (freq <= 0) + return 0; + + return freq; +} + +static int __init ftm_calc_closest_round_cyc(unsigned long freq) +{ + priv->ps = 0; + + /* The counter register is only using the lower 16 bits, and + * if the 'freq' value is to big here, then the periodic_cyc + * may exceed 0xFFFF. + */ + do { + priv->periodic_cyc = DIV_ROUND_CLOSEST(freq, + HZ * (1 << priv->ps++)); + } while (priv->periodic_cyc > 0xFFFF); + + if (priv->ps > FTM_PS_MAX) { + pr_err("ftm: the prescaler is %lu > %d\n", + priv->ps, FTM_PS_MAX); + return -EINVAL; + } + + return 0; +} + +static int __init ftm_timer_init(struct device_node *np) +{ + unsigned long freq; + int ret, irq; + + priv = kzalloc(sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + ret = -ENXIO; + priv->clkevt_base = of_iomap(np, 0); + if (!priv->clkevt_base) { + pr_err("ftm: unable to map event timer registers\n"); + goto err_clkevt; + } + + priv->clksrc_base = of_iomap(np, 1); + if (!priv->clksrc_base) { + pr_err("ftm: unable to map source timer registers\n"); + goto err_clksrc; + } + + ret = -EINVAL; + irq = irq_of_parse_and_map(np, 0); + if (irq <= 0) { + pr_err("ftm: unable to get IRQ from DT, %d\n", irq); + goto err; + } + + priv->big_endian = of_property_read_bool(np, "big-endian"); + + freq = ftm_clk_init(np); + if (!freq) + goto err; + + ret = ftm_calc_closest_round_cyc(freq); + if (ret) + goto err; + + ret = ftm_clocksource_init(freq); + if (ret) + goto err; + + ret = ftm_clockevent_init(freq, irq); + if (ret) + goto err; + + return 0; + +err: + iounmap(priv->clksrc_base); +err_clksrc: + iounmap(priv->clkevt_base); +err_clkevt: + kfree(priv); + return ret; +} +TIMER_OF_DECLARE(flextimer, "fsl,ftm-timer", ftm_timer_init); diff --git a/drivers/clocksource/timer-lpc32xx.c b/drivers/clocksource/timer-lpc32xx.c new file mode 100644 index 0000000000000..d51a62a79ef76 --- /dev/null +++ b/drivers/clocksource/timer-lpc32xx.c @@ -0,0 +1,314 @@ +/* + * Clocksource driver for NXP LPC32xx/18xx/43xx timer + * + * Copyright (C) 2015 Joachim Eastwood + * + * Based on: + * time-efm32 Copyright (C) 2013 Pengutronix + * mach-lpc32xx/timer.c Copyright (C) 2009 - 2010 NXP Semiconductors + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + * + */ + +#define pr_fmt(fmt) "%s: " fmt, __func__ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define LPC32XX_TIMER_IR 0x000 +#define LPC32XX_TIMER_IR_MR0INT BIT(0) +#define LPC32XX_TIMER_TCR 0x004 +#define LPC32XX_TIMER_TCR_CEN BIT(0) +#define LPC32XX_TIMER_TCR_CRST BIT(1) +#define LPC32XX_TIMER_TC 0x008 +#define LPC32XX_TIMER_PR 0x00c +#define LPC32XX_TIMER_MCR 0x014 +#define LPC32XX_TIMER_MCR_MR0I BIT(0) +#define LPC32XX_TIMER_MCR_MR0R BIT(1) +#define LPC32XX_TIMER_MCR_MR0S BIT(2) +#define LPC32XX_TIMER_MR0 0x018 +#define LPC32XX_TIMER_CTCR 0x070 + +struct lpc32xx_clock_event_ddata { + struct clock_event_device evtdev; + void __iomem *base; + u32 ticks_per_jiffy; +}; + +/* Needed for the sched clock */ +static void __iomem *clocksource_timer_counter; + +static u64 notrace lpc32xx_read_sched_clock(void) +{ + return readl(clocksource_timer_counter); +} + +static unsigned long lpc32xx_delay_timer_read(void) +{ + return readl(clocksource_timer_counter); +} + +static struct delay_timer lpc32xx_delay_timer = { + .read_current_timer = lpc32xx_delay_timer_read, +}; + +static int lpc32xx_clkevt_next_event(unsigned long delta, + struct clock_event_device *evtdev) +{ + struct lpc32xx_clock_event_ddata *ddata = + container_of(evtdev, struct lpc32xx_clock_event_ddata, evtdev); + + /* + * Place timer in reset and program the delta in the match + * channel 0 (MR0). When the timer counter matches the value + * in MR0 register the match will trigger an interrupt. + * After setup the timer is released from reset and enabled. + */ + writel_relaxed(LPC32XX_TIMER_TCR_CRST, ddata->base + LPC32XX_TIMER_TCR); + writel_relaxed(delta, ddata->base + LPC32XX_TIMER_MR0); + writel_relaxed(LPC32XX_TIMER_TCR_CEN, ddata->base + LPC32XX_TIMER_TCR); + + return 0; +} + +static int lpc32xx_clkevt_shutdown(struct clock_event_device *evtdev) +{ + struct lpc32xx_clock_event_ddata *ddata = + container_of(evtdev, struct lpc32xx_clock_event_ddata, evtdev); + + /* Disable the timer */ + writel_relaxed(0, ddata->base + LPC32XX_TIMER_TCR); + + return 0; +} + +static int lpc32xx_clkevt_oneshot(struct clock_event_device *evtdev) +{ + struct lpc32xx_clock_event_ddata *ddata = + container_of(evtdev, struct lpc32xx_clock_event_ddata, evtdev); + + /* + * When using oneshot, we must also disable the timer + * to wait for the first call to set_next_event(). + */ + writel_relaxed(0, ddata->base + LPC32XX_TIMER_TCR); + + /* Enable interrupt, reset on match and stop on match (MCR). */ + writel_relaxed(LPC32XX_TIMER_MCR_MR0I | LPC32XX_TIMER_MCR_MR0R | + LPC32XX_TIMER_MCR_MR0S, ddata->base + LPC32XX_TIMER_MCR); + return 0; +} + +static int lpc32xx_clkevt_periodic(struct clock_event_device *evtdev) +{ + struct lpc32xx_clock_event_ddata *ddata = + container_of(evtdev, struct lpc32xx_clock_event_ddata, evtdev); + + /* Enable interrupt and reset on match. */ + writel_relaxed(LPC32XX_TIMER_MCR_MR0I | LPC32XX_TIMER_MCR_MR0R, + ddata->base + LPC32XX_TIMER_MCR); + + /* + * Place timer in reset and program the delta in the match + * channel 0 (MR0). + */ + writel_relaxed(LPC32XX_TIMER_TCR_CRST, ddata->base + LPC32XX_TIMER_TCR); + writel_relaxed(ddata->ticks_per_jiffy, ddata->base + LPC32XX_TIMER_MR0); + writel_relaxed(LPC32XX_TIMER_TCR_CEN, ddata->base + LPC32XX_TIMER_TCR); + + return 0; +} + +static irqreturn_t lpc32xx_clock_event_handler(int irq, void *dev_id) +{ + struct lpc32xx_clock_event_ddata *ddata = dev_id; + + /* Clear match on channel 0 */ + writel_relaxed(LPC32XX_TIMER_IR_MR0INT, ddata->base + LPC32XX_TIMER_IR); + + ddata->evtdev.event_handler(&ddata->evtdev); + + return IRQ_HANDLED; +} + +static struct lpc32xx_clock_event_ddata lpc32xx_clk_event_ddata = { + .evtdev = { + .name = "lpc3220 clockevent", + .features = CLOCK_EVT_FEAT_ONESHOT | + CLOCK_EVT_FEAT_PERIODIC, + .rating = 300, + .set_next_event = lpc32xx_clkevt_next_event, + .set_state_shutdown = lpc32xx_clkevt_shutdown, + .set_state_oneshot = lpc32xx_clkevt_oneshot, + .set_state_periodic = lpc32xx_clkevt_periodic, + }, +}; + +static int __init lpc32xx_clocksource_init(struct device_node *np) +{ + void __iomem *base; + unsigned long rate; + struct clk *clk; + int ret; + + clk = of_clk_get_by_name(np, "timerclk"); + if (IS_ERR(clk)) { + pr_err("clock get failed (%ld)\n", PTR_ERR(clk)); + return PTR_ERR(clk); + } + + ret = clk_prepare_enable(clk); + if (ret) { + pr_err("clock enable failed (%d)\n", ret); + goto err_clk_enable; + } + + base = of_iomap(np, 0); + if (!base) { + pr_err("unable to map registers\n"); + ret = -EADDRNOTAVAIL; + goto err_iomap; + } + + /* + * Disable and reset timer then set it to free running timer + * mode (CTCR) with no prescaler (PR) or match operations (MCR). + * After setup the timer is released from reset and enabled. + */ + writel_relaxed(LPC32XX_TIMER_TCR_CRST, base + LPC32XX_TIMER_TCR); + writel_relaxed(0, base + LPC32XX_TIMER_PR); + writel_relaxed(0, base + LPC32XX_TIMER_MCR); + writel_relaxed(0, base + LPC32XX_TIMER_CTCR); + writel_relaxed(LPC32XX_TIMER_TCR_CEN, base + LPC32XX_TIMER_TCR); + + rate = clk_get_rate(clk); + ret = clocksource_mmio_init(base + LPC32XX_TIMER_TC, "lpc3220 timer", + rate, 300, 32, clocksource_mmio_readl_up); + if (ret) { + pr_err("failed to init clocksource (%d)\n", ret); + goto err_clocksource_init; + } + + clocksource_timer_counter = base + LPC32XX_TIMER_TC; + lpc32xx_delay_timer.freq = rate; + register_current_timer_delay(&lpc32xx_delay_timer); + sched_clock_register(lpc32xx_read_sched_clock, 32, rate); + + return 0; + +err_clocksource_init: + iounmap(base); +err_iomap: + clk_disable_unprepare(clk); +err_clk_enable: + clk_put(clk); + return ret; +} + +static int __init lpc32xx_clockevent_init(struct device_node *np) +{ + void __iomem *base; + unsigned long rate; + struct clk *clk; + int ret, irq; + + clk = of_clk_get_by_name(np, "timerclk"); + if (IS_ERR(clk)) { + pr_err("clock get failed (%ld)\n", PTR_ERR(clk)); + return PTR_ERR(clk); + } + + ret = clk_prepare_enable(clk); + if (ret) { + pr_err("clock enable failed (%d)\n", ret); + goto err_clk_enable; + } + + base = of_iomap(np, 0); + if (!base) { + pr_err("unable to map registers\n"); + ret = -EADDRNOTAVAIL; + goto err_iomap; + } + + irq = irq_of_parse_and_map(np, 0); + if (!irq) { + pr_err("get irq failed\n"); + ret = -ENOENT; + goto err_irq; + } + + /* + * Disable timer and clear any pending interrupt (IR) on match + * channel 0 (MR0). Clear the prescaler as it's not used. + */ + writel_relaxed(0, base + LPC32XX_TIMER_TCR); + writel_relaxed(0, base + LPC32XX_TIMER_PR); + writel_relaxed(0, base + LPC32XX_TIMER_CTCR); + writel_relaxed(LPC32XX_TIMER_IR_MR0INT, base + LPC32XX_TIMER_IR); + + rate = clk_get_rate(clk); + lpc32xx_clk_event_ddata.base = base; + lpc32xx_clk_event_ddata.ticks_per_jiffy = DIV_ROUND_CLOSEST(rate, HZ); + clockevents_config_and_register(&lpc32xx_clk_event_ddata.evtdev, + rate, 1, -1); + + ret = request_irq(irq, lpc32xx_clock_event_handler, + IRQF_TIMER | IRQF_IRQPOLL, "lpc3220 clockevent", + &lpc32xx_clk_event_ddata); + if (ret) { + pr_err("request irq failed\n"); + goto err_irq; + } + + return 0; + +err_irq: + iounmap(base); +err_iomap: + clk_disable_unprepare(clk); +err_clk_enable: + clk_put(clk); + return ret; +} + +/* + * This function asserts that we have exactly one clocksource and one + * clock_event_device in the end. + */ +static int __init lpc32xx_timer_init(struct device_node *np) +{ + static int has_clocksource, has_clockevent; + int ret = 0; + + if (!has_clocksource) { + ret = lpc32xx_clocksource_init(np); + if (!ret) { + has_clocksource = 1; + return 0; + } + } + + if (!has_clockevent) { + ret = lpc32xx_clockevent_init(np); + if (!ret) { + has_clockevent = 1; + return 0; + } + } + + return ret; +} +TIMER_OF_DECLARE(lpc32xx_timer, "nxp,lpc3220-timer", lpc32xx_timer_init); diff --git a/drivers/clocksource/timer-orion.c b/drivers/clocksource/timer-orion.c new file mode 100644 index 0000000000000..12202067fe4b8 --- /dev/null +++ b/drivers/clocksource/timer-orion.c @@ -0,0 +1,192 @@ +/* + * Marvell Orion SoC timer handling. + * + * Sebastian Hesselbarth + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + * + * Timer 0 is used as free-running clocksource, while timer 1 is + * used as clock_event_device. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define TIMER_CTRL 0x00 +#define TIMER0_EN BIT(0) +#define TIMER0_RELOAD_EN BIT(1) +#define TIMER1_EN BIT(2) +#define TIMER1_RELOAD_EN BIT(3) +#define TIMER0_RELOAD 0x10 +#define TIMER0_VAL 0x14 +#define TIMER1_RELOAD 0x18 +#define TIMER1_VAL 0x1c + +#define ORION_ONESHOT_MIN 1 +#define ORION_ONESHOT_MAX 0xfffffffe + +static void __iomem *timer_base; + +static unsigned long notrace orion_read_timer(void) +{ + return ~readl(timer_base + TIMER0_VAL); +} + +static struct delay_timer orion_delay_timer = { + .read_current_timer = orion_read_timer, +}; + +static void orion_delay_timer_init(unsigned long rate) +{ + orion_delay_timer.freq = rate; + register_current_timer_delay(&orion_delay_timer); +} + +/* + * Free-running clocksource handling. + */ +static u64 notrace orion_read_sched_clock(void) +{ + return ~readl(timer_base + TIMER0_VAL); +} + +/* + * Clockevent handling. + */ +static u32 ticks_per_jiffy; + +static int orion_clkevt_next_event(unsigned long delta, + struct clock_event_device *dev) +{ + /* setup and enable one-shot timer */ + writel(delta, timer_base + TIMER1_VAL); + atomic_io_modify(timer_base + TIMER_CTRL, + TIMER1_RELOAD_EN | TIMER1_EN, TIMER1_EN); + + return 0; +} + +static int orion_clkevt_shutdown(struct clock_event_device *dev) +{ + /* disable timer */ + atomic_io_modify(timer_base + TIMER_CTRL, + TIMER1_RELOAD_EN | TIMER1_EN, 0); + return 0; +} + +static int orion_clkevt_set_periodic(struct clock_event_device *dev) +{ + /* setup and enable periodic timer at 1/HZ intervals */ + writel(ticks_per_jiffy - 1, timer_base + TIMER1_RELOAD); + writel(ticks_per_jiffy - 1, timer_base + TIMER1_VAL); + atomic_io_modify(timer_base + TIMER_CTRL, + TIMER1_RELOAD_EN | TIMER1_EN, + TIMER1_RELOAD_EN | TIMER1_EN); + return 0; +} + +static struct clock_event_device orion_clkevt = { + .name = "orion_event", + .features = CLOCK_EVT_FEAT_ONESHOT | + CLOCK_EVT_FEAT_PERIODIC, + .shift = 32, + .rating = 300, + .set_next_event = orion_clkevt_next_event, + .set_state_shutdown = orion_clkevt_shutdown, + .set_state_periodic = orion_clkevt_set_periodic, + .set_state_oneshot = orion_clkevt_shutdown, + .tick_resume = orion_clkevt_shutdown, +}; + +static irqreturn_t orion_clkevt_irq_handler(int irq, void *dev_id) +{ + orion_clkevt.event_handler(&orion_clkevt); + return IRQ_HANDLED; +} + +static struct irqaction orion_clkevt_irq = { + .name = "orion_event", + .flags = IRQF_TIMER, + .handler = orion_clkevt_irq_handler, +}; + +static int __init orion_timer_init(struct device_node *np) +{ + unsigned long rate; + struct clk *clk; + int irq, ret; + + /* timer registers are shared with watchdog timer */ + timer_base = of_iomap(np, 0); + if (!timer_base) { + pr_err("%s: unable to map resource\n", np->name); + return -ENXIO; + } + + clk = of_clk_get(np, 0); + if (IS_ERR(clk)) { + pr_err("%s: unable to get clk\n", np->name); + return PTR_ERR(clk); + } + + ret = clk_prepare_enable(clk); + if (ret) { + pr_err("Failed to prepare clock\n"); + return ret; + } + + /* we are only interested in timer1 irq */ + irq = irq_of_parse_and_map(np, 1); + if (irq <= 0) { + pr_err("%s: unable to parse timer1 irq\n", np->name); + return -EINVAL; + } + + rate = clk_get_rate(clk); + + /* setup timer0 as free-running clocksource */ + writel(~0, timer_base + TIMER0_VAL); + writel(~0, timer_base + TIMER0_RELOAD); + atomic_io_modify(timer_base + TIMER_CTRL, + TIMER0_RELOAD_EN | TIMER0_EN, + TIMER0_RELOAD_EN | TIMER0_EN); + + ret = clocksource_mmio_init(timer_base + TIMER0_VAL, + "orion_clocksource", rate, 300, 32, + clocksource_mmio_readl_down); + if (ret) { + pr_err("Failed to initialize mmio timer\n"); + return ret; + } + + sched_clock_register(orion_read_sched_clock, 32, rate); + + /* setup timer1 as clockevent timer */ + ret = setup_irq(irq, &orion_clkevt_irq); + if (ret) { + pr_err("%s: unable to setup irq\n", np->name); + return ret; + } + + ticks_per_jiffy = (clk_get_rate(clk) + HZ/2) / HZ; + orion_clkevt.cpumask = cpumask_of(0); + orion_clkevt.irq = irq; + clockevents_config_and_register(&orion_clkevt, rate, + ORION_ONESHOT_MIN, ORION_ONESHOT_MAX); + + + orion_delay_timer_init(rate); + + return 0; +} +TIMER_OF_DECLARE(orion_timer, "marvell,orion-timer", orion_timer_init); diff --git a/drivers/clocksource/timer-owl.c b/drivers/clocksource/timer-owl.c new file mode 100644 index 0000000000000..ea00a5e8f95d2 --- /dev/null +++ b/drivers/clocksource/timer-owl.c @@ -0,0 +1,173 @@ +/* + * Actions Semi Owl timer + * + * Copyright 2012 Actions Semi Inc. + * Author: Actions Semi, Inc. + * + * Copyright (c) 2017 SUSE Linux GmbH + * Author: Andreas Färber + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define OWL_Tx_CTL 0x0 +#define OWL_Tx_CMP 0x4 +#define OWL_Tx_VAL 0x8 + +#define OWL_Tx_CTL_PD BIT(0) +#define OWL_Tx_CTL_INTEN BIT(1) +#define OWL_Tx_CTL_EN BIT(2) + +static void __iomem *owl_timer_base; +static void __iomem *owl_clksrc_base; +static void __iomem *owl_clkevt_base; + +static inline void owl_timer_reset(void __iomem *base) +{ + writel(0, base + OWL_Tx_CTL); + writel(0, base + OWL_Tx_VAL); + writel(0, base + OWL_Tx_CMP); +} + +static inline void owl_timer_set_enabled(void __iomem *base, bool enabled) +{ + u32 ctl = readl(base + OWL_Tx_CTL); + + /* PD bit is cleared when set */ + ctl &= ~OWL_Tx_CTL_PD; + + if (enabled) + ctl |= OWL_Tx_CTL_EN; + else + ctl &= ~OWL_Tx_CTL_EN; + + writel(ctl, base + OWL_Tx_CTL); +} + +static u64 notrace owl_timer_sched_read(void) +{ + return (u64)readl(owl_clksrc_base + OWL_Tx_VAL); +} + +static int owl_timer_set_state_shutdown(struct clock_event_device *evt) +{ + owl_timer_set_enabled(owl_clkevt_base, false); + + return 0; +} + +static int owl_timer_set_state_oneshot(struct clock_event_device *evt) +{ + owl_timer_reset(owl_clkevt_base); + + return 0; +} + +static int owl_timer_tick_resume(struct clock_event_device *evt) +{ + return 0; +} + +static int owl_timer_set_next_event(unsigned long evt, + struct clock_event_device *ev) +{ + void __iomem *base = owl_clkevt_base; + + owl_timer_set_enabled(base, false); + writel(OWL_Tx_CTL_INTEN, base + OWL_Tx_CTL); + writel(0, base + OWL_Tx_VAL); + writel(evt, base + OWL_Tx_CMP); + owl_timer_set_enabled(base, true); + + return 0; +} + +static struct clock_event_device owl_clockevent = { + .name = "owl_tick", + .rating = 200, + .features = CLOCK_EVT_FEAT_ONESHOT | + CLOCK_EVT_FEAT_DYNIRQ, + .set_state_shutdown = owl_timer_set_state_shutdown, + .set_state_oneshot = owl_timer_set_state_oneshot, + .tick_resume = owl_timer_tick_resume, + .set_next_event = owl_timer_set_next_event, +}; + +static irqreturn_t owl_timer1_interrupt(int irq, void *dev_id) +{ + struct clock_event_device *evt = (struct clock_event_device *)dev_id; + + writel(OWL_Tx_CTL_PD, owl_clkevt_base + OWL_Tx_CTL); + + evt->event_handler(evt); + + return IRQ_HANDLED; +} + +static int __init owl_timer_init(struct device_node *node) +{ + struct clk *clk; + unsigned long rate; + int timer1_irq, ret; + + owl_timer_base = of_io_request_and_map(node, 0, "owl-timer"); + if (IS_ERR(owl_timer_base)) { + pr_err("Can't map timer registers\n"); + return PTR_ERR(owl_timer_base); + } + + owl_clksrc_base = owl_timer_base + 0x08; + owl_clkevt_base = owl_timer_base + 0x14; + + timer1_irq = of_irq_get_byname(node, "timer1"); + if (timer1_irq <= 0) { + pr_err("Can't parse timer1 IRQ\n"); + return -EINVAL; + } + + clk = of_clk_get(node, 0); + if (IS_ERR(clk)) + return PTR_ERR(clk); + + rate = clk_get_rate(clk); + + owl_timer_reset(owl_clksrc_base); + owl_timer_set_enabled(owl_clksrc_base, true); + + sched_clock_register(owl_timer_sched_read, 32, rate); + clocksource_mmio_init(owl_clksrc_base + OWL_Tx_VAL, node->name, + rate, 200, 32, clocksource_mmio_readl_up); + + owl_timer_reset(owl_clkevt_base); + + ret = request_irq(timer1_irq, owl_timer1_interrupt, IRQF_TIMER, + "owl-timer", &owl_clockevent); + if (ret) { + pr_err("failed to request irq %d\n", timer1_irq); + return ret; + } + + owl_clockevent.cpumask = cpumask_of(0); + owl_clockevent.irq = timer1_irq; + + clockevents_config_and_register(&owl_clockevent, rate, + 0xf, 0xffffffff); + + return 0; +} +TIMER_OF_DECLARE(owl_s500, "actions,s500-timer", owl_timer_init); +TIMER_OF_DECLARE(owl_s700, "actions,s700-timer", owl_timer_init); +TIMER_OF_DECLARE(owl_s900, "actions,s900-timer", owl_timer_init); diff --git a/drivers/clocksource/timer-pistachio.c b/drivers/clocksource/timer-pistachio.c new file mode 100644 index 0000000000000..a2dd85d0c1d75 --- /dev/null +++ b/drivers/clocksource/timer-pistachio.c @@ -0,0 +1,218 @@ +/* + * Pistachio clocksource based on general-purpose timers + * + * Copyright (C) 2015 Imagination Technologies + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + */ + +#define pr_fmt(fmt) "%s: " fmt, __func__ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* Top level reg */ +#define CR_TIMER_CTRL_CFG 0x00 +#define TIMER_ME_GLOBAL BIT(0) +#define CR_TIMER_REV 0x10 + +/* Timer specific registers */ +#define TIMER_CFG 0x20 +#define TIMER_ME_LOCAL BIT(0) +#define TIMER_RELOAD_VALUE 0x24 +#define TIMER_CURRENT_VALUE 0x28 +#define TIMER_CURRENT_OVERFLOW_VALUE 0x2C +#define TIMER_IRQ_STATUS 0x30 +#define TIMER_IRQ_CLEAR 0x34 +#define TIMER_IRQ_MASK 0x38 + +#define PERIP_TIMER_CONTROL 0x90 + +/* Timer specific configuration Values */ +#define RELOAD_VALUE 0xffffffff + +struct pistachio_clocksource { + void __iomem *base; + raw_spinlock_t lock; + struct clocksource cs; +}; + +static struct pistachio_clocksource pcs_gpt; + +#define to_pistachio_clocksource(cs) \ + container_of(cs, struct pistachio_clocksource, cs) + +static inline u32 gpt_readl(void __iomem *base, u32 offset, u32 gpt_id) +{ + return readl(base + 0x20 * gpt_id + offset); +} + +static inline void gpt_writel(void __iomem *base, u32 value, u32 offset, + u32 gpt_id) +{ + writel(value, base + 0x20 * gpt_id + offset); +} + +static u64 notrace +pistachio_clocksource_read_cycles(struct clocksource *cs) +{ + struct pistachio_clocksource *pcs = to_pistachio_clocksource(cs); + u32 counter, overflw; + unsigned long flags; + + /* + * The counter value is only refreshed after the overflow value is read. + * And they must be read in strict order, hence raw spin lock added. + */ + + raw_spin_lock_irqsave(&pcs->lock, flags); + overflw = gpt_readl(pcs->base, TIMER_CURRENT_OVERFLOW_VALUE, 0); + counter = gpt_readl(pcs->base, TIMER_CURRENT_VALUE, 0); + raw_spin_unlock_irqrestore(&pcs->lock, flags); + + return (u64)~counter; +} + +static u64 notrace pistachio_read_sched_clock(void) +{ + return pistachio_clocksource_read_cycles(&pcs_gpt.cs); +} + +static void pistachio_clksrc_set_mode(struct clocksource *cs, int timeridx, + int enable) +{ + struct pistachio_clocksource *pcs = to_pistachio_clocksource(cs); + u32 val; + + val = gpt_readl(pcs->base, TIMER_CFG, timeridx); + if (enable) + val |= TIMER_ME_LOCAL; + else + val &= ~TIMER_ME_LOCAL; + + gpt_writel(pcs->base, val, TIMER_CFG, timeridx); +} + +static void pistachio_clksrc_enable(struct clocksource *cs, int timeridx) +{ + struct pistachio_clocksource *pcs = to_pistachio_clocksource(cs); + + /* Disable GPT local before loading reload value */ + pistachio_clksrc_set_mode(cs, timeridx, false); + gpt_writel(pcs->base, RELOAD_VALUE, TIMER_RELOAD_VALUE, timeridx); + pistachio_clksrc_set_mode(cs, timeridx, true); +} + +static void pistachio_clksrc_disable(struct clocksource *cs, int timeridx) +{ + /* Disable GPT local */ + pistachio_clksrc_set_mode(cs, timeridx, false); +} + +static int pistachio_clocksource_enable(struct clocksource *cs) +{ + pistachio_clksrc_enable(cs, 0); + return 0; +} + +static void pistachio_clocksource_disable(struct clocksource *cs) +{ + pistachio_clksrc_disable(cs, 0); +} + +/* Desirable clock source for pistachio platform */ +static struct pistachio_clocksource pcs_gpt = { + .cs = { + .name = "gptimer", + .rating = 300, + .enable = pistachio_clocksource_enable, + .disable = pistachio_clocksource_disable, + .read = pistachio_clocksource_read_cycles, + .mask = CLOCKSOURCE_MASK(32), + .flags = CLOCK_SOURCE_IS_CONTINUOUS | + CLOCK_SOURCE_SUSPEND_NONSTOP, + }, +}; + +static int __init pistachio_clksrc_of_init(struct device_node *node) +{ + struct clk *sys_clk, *fast_clk; + struct regmap *periph_regs; + unsigned long rate; + int ret; + + pcs_gpt.base = of_iomap(node, 0); + if (!pcs_gpt.base) { + pr_err("cannot iomap\n"); + return -ENXIO; + } + + periph_regs = syscon_regmap_lookup_by_phandle(node, "img,cr-periph"); + if (IS_ERR(periph_regs)) { + pr_err("cannot get peripheral regmap (%ld)\n", + PTR_ERR(periph_regs)); + return PTR_ERR(periph_regs); + } + + /* Switch to using the fast counter clock */ + ret = regmap_update_bits(periph_regs, PERIP_TIMER_CONTROL, + 0xf, 0x0); + if (ret) + return ret; + + sys_clk = of_clk_get_by_name(node, "sys"); + if (IS_ERR(sys_clk)) { + pr_err("clock get failed (%ld)\n", PTR_ERR(sys_clk)); + return PTR_ERR(sys_clk); + } + + fast_clk = of_clk_get_by_name(node, "fast"); + if (IS_ERR(fast_clk)) { + pr_err("clock get failed (%lu)\n", PTR_ERR(fast_clk)); + return PTR_ERR(fast_clk); + } + + ret = clk_prepare_enable(sys_clk); + if (ret < 0) { + pr_err("failed to enable clock (%d)\n", ret); + return ret; + } + + ret = clk_prepare_enable(fast_clk); + if (ret < 0) { + pr_err("failed to enable clock (%d)\n", ret); + clk_disable_unprepare(sys_clk); + return ret; + } + + rate = clk_get_rate(fast_clk); + + /* Disable irq's for clocksource usage */ + gpt_writel(pcs_gpt.base, 0, TIMER_IRQ_MASK, 0); + gpt_writel(pcs_gpt.base, 0, TIMER_IRQ_MASK, 1); + gpt_writel(pcs_gpt.base, 0, TIMER_IRQ_MASK, 2); + gpt_writel(pcs_gpt.base, 0, TIMER_IRQ_MASK, 3); + + /* Enable timer block */ + writel(TIMER_ME_GLOBAL, pcs_gpt.base); + + raw_spin_lock_init(&pcs_gpt.lock); + sched_clock_register(pistachio_read_sched_clock, 32, rate); + return clocksource_register_hz(&pcs_gpt.cs, rate); +} +TIMER_OF_DECLARE(pistachio_gptimer, "img,pistachio-gptimer", + pistachio_clksrc_of_init); diff --git a/drivers/clocksource/timer-qcom.c b/drivers/clocksource/timer-qcom.c new file mode 100644 index 0000000000000..89816f89ff3f4 --- /dev/null +++ b/drivers/clocksource/timer-qcom.c @@ -0,0 +1,258 @@ +/* + * + * Copyright (C) 2007 Google, Inc. + * Copyright (c) 2009-2012,2014, The Linux Foundation. All rights reserved. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#define TIMER_MATCH_VAL 0x0000 +#define TIMER_COUNT_VAL 0x0004 +#define TIMER_ENABLE 0x0008 +#define TIMER_ENABLE_CLR_ON_MATCH_EN BIT(1) +#define TIMER_ENABLE_EN BIT(0) +#define TIMER_CLEAR 0x000C +#define DGT_CLK_CTL 0x10 +#define DGT_CLK_CTL_DIV_4 0x3 +#define TIMER_STS_GPT0_CLR_PEND BIT(10) + +#define GPT_HZ 32768 + +static void __iomem *event_base; +static void __iomem *sts_base; + +static irqreturn_t msm_timer_interrupt(int irq, void *dev_id) +{ + struct clock_event_device *evt = dev_id; + /* Stop the timer tick */ + if (clockevent_state_oneshot(evt)) { + u32 ctrl = readl_relaxed(event_base + TIMER_ENABLE); + ctrl &= ~TIMER_ENABLE_EN; + writel_relaxed(ctrl, event_base + TIMER_ENABLE); + } + evt->event_handler(evt); + return IRQ_HANDLED; +} + +static int msm_timer_set_next_event(unsigned long cycles, + struct clock_event_device *evt) +{ + u32 ctrl = readl_relaxed(event_base + TIMER_ENABLE); + + ctrl &= ~TIMER_ENABLE_EN; + writel_relaxed(ctrl, event_base + TIMER_ENABLE); + + writel_relaxed(ctrl, event_base + TIMER_CLEAR); + writel_relaxed(cycles, event_base + TIMER_MATCH_VAL); + + if (sts_base) + while (readl_relaxed(sts_base) & TIMER_STS_GPT0_CLR_PEND) + cpu_relax(); + + writel_relaxed(ctrl | TIMER_ENABLE_EN, event_base + TIMER_ENABLE); + return 0; +} + +static int msm_timer_shutdown(struct clock_event_device *evt) +{ + u32 ctrl; + + ctrl = readl_relaxed(event_base + TIMER_ENABLE); + ctrl &= ~(TIMER_ENABLE_EN | TIMER_ENABLE_CLR_ON_MATCH_EN); + writel_relaxed(ctrl, event_base + TIMER_ENABLE); + return 0; +} + +static struct clock_event_device __percpu *msm_evt; + +static void __iomem *source_base; + +static notrace u64 msm_read_timer_count(struct clocksource *cs) +{ + return readl_relaxed(source_base + TIMER_COUNT_VAL); +} + +static struct clocksource msm_clocksource = { + .name = "dg_timer", + .rating = 300, + .read = msm_read_timer_count, + .mask = CLOCKSOURCE_MASK(32), + .flags = CLOCK_SOURCE_IS_CONTINUOUS, +}; + +static int msm_timer_irq; +static int msm_timer_has_ppi; + +static int msm_local_timer_starting_cpu(unsigned int cpu) +{ + struct clock_event_device *evt = per_cpu_ptr(msm_evt, cpu); + int err; + + evt->irq = msm_timer_irq; + evt->name = "msm_timer"; + evt->features = CLOCK_EVT_FEAT_ONESHOT; + evt->rating = 200; + evt->set_state_shutdown = msm_timer_shutdown; + evt->set_state_oneshot = msm_timer_shutdown; + evt->tick_resume = msm_timer_shutdown; + evt->set_next_event = msm_timer_set_next_event; + evt->cpumask = cpumask_of(cpu); + + clockevents_config_and_register(evt, GPT_HZ, 4, 0xffffffff); + + if (msm_timer_has_ppi) { + enable_percpu_irq(evt->irq, IRQ_TYPE_EDGE_RISING); + } else { + err = request_irq(evt->irq, msm_timer_interrupt, + IRQF_TIMER | IRQF_NOBALANCING | + IRQF_TRIGGER_RISING, "gp_timer", evt); + if (err) + pr_err("request_irq failed\n"); + } + + return 0; +} + +static int msm_local_timer_dying_cpu(unsigned int cpu) +{ + struct clock_event_device *evt = per_cpu_ptr(msm_evt, cpu); + + evt->set_state_shutdown(evt); + disable_percpu_irq(evt->irq); + return 0; +} + +static u64 notrace msm_sched_clock_read(void) +{ + return msm_clocksource.read(&msm_clocksource); +} + +static unsigned long msm_read_current_timer(void) +{ + return msm_clocksource.read(&msm_clocksource); +} + +static struct delay_timer msm_delay_timer = { + .read_current_timer = msm_read_current_timer, +}; + +static int __init msm_timer_init(u32 dgt_hz, int sched_bits, int irq, + bool percpu) +{ + struct clocksource *cs = &msm_clocksource; + int res = 0; + + msm_timer_irq = irq; + msm_timer_has_ppi = percpu; + + msm_evt = alloc_percpu(struct clock_event_device); + if (!msm_evt) { + pr_err("memory allocation failed for clockevents\n"); + goto err; + } + + if (percpu) + res = request_percpu_irq(irq, msm_timer_interrupt, + "gp_timer", msm_evt); + + if (res) { + pr_err("request_percpu_irq failed\n"); + } else { + /* Install and invoke hotplug callbacks */ + res = cpuhp_setup_state(CPUHP_AP_QCOM_TIMER_STARTING, + "clockevents/qcom/timer:starting", + msm_local_timer_starting_cpu, + msm_local_timer_dying_cpu); + if (res) { + free_percpu_irq(irq, msm_evt); + goto err; + } + } + +err: + writel_relaxed(TIMER_ENABLE_EN, source_base + TIMER_ENABLE); + res = clocksource_register_hz(cs, dgt_hz); + if (res) + pr_err("clocksource_register failed\n"); + sched_clock_register(msm_sched_clock_read, sched_bits, dgt_hz); + msm_delay_timer.freq = dgt_hz; + register_current_timer_delay(&msm_delay_timer); + + return res; +} + +static int __init msm_dt_timer_init(struct device_node *np) +{ + u32 freq; + int irq, ret; + struct resource res; + u32 percpu_offset; + void __iomem *base; + void __iomem *cpu0_base; + + base = of_iomap(np, 0); + if (!base) { + pr_err("Failed to map event base\n"); + return -ENXIO; + } + + /* We use GPT0 for the clockevent */ + irq = irq_of_parse_and_map(np, 1); + if (irq <= 0) { + pr_err("Can't get irq\n"); + return -EINVAL; + } + + /* We use CPU0's DGT for the clocksource */ + if (of_property_read_u32(np, "cpu-offset", &percpu_offset)) + percpu_offset = 0; + + ret = of_address_to_resource(np, 0, &res); + if (ret) { + pr_err("Failed to parse DGT resource\n"); + return ret; + } + + cpu0_base = ioremap(res.start + percpu_offset, resource_size(&res)); + if (!cpu0_base) { + pr_err("Failed to map source base\n"); + return -EINVAL; + } + + if (of_property_read_u32(np, "clock-frequency", &freq)) { + pr_err("Unknown frequency\n"); + return -EINVAL; + } + + event_base = base + 0x4; + sts_base = base + 0x88; + source_base = cpu0_base + 0x24; + freq /= 4; + writel_relaxed(DGT_CLK_CTL_DIV_4, source_base + DGT_CLK_CTL); + + return msm_timer_init(freq, 32, irq, !!percpu_offset); +} +TIMER_OF_DECLARE(kpss_timer, "qcom,kpss-timer", msm_dt_timer_init); +TIMER_OF_DECLARE(scss_timer, "qcom,scss-timer", msm_dt_timer_init); diff --git a/drivers/clocksource/timer-versatile.c b/drivers/clocksource/timer-versatile.c new file mode 100644 index 0000000000000..39725d38aedee --- /dev/null +++ b/drivers/clocksource/timer-versatile.c @@ -0,0 +1,44 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * Copyright (C) 2014 ARM Limited + */ + +#include +#include +#include +#include + +#define SYS_24MHZ 0x05c + +static void __iomem *versatile_sys_24mhz; + +static u64 notrace versatile_sys_24mhz_read(void) +{ + return readl(versatile_sys_24mhz); +} + +static int __init versatile_sched_clock_init(struct device_node *node) +{ + void __iomem *base = of_iomap(node, 0); + + if (!base) + return -ENXIO; + + versatile_sys_24mhz = base + SYS_24MHZ; + + sched_clock_register(versatile_sys_24mhz_read, 32, 24000000); + + return 0; +} +TIMER_OF_DECLARE(vexpress, "arm,vexpress-sysreg", + versatile_sched_clock_init); +TIMER_OF_DECLARE(versatile, "arm,versatile-sysreg", + versatile_sched_clock_init); diff --git a/drivers/clocksource/timer-vf-pit.c b/drivers/clocksource/timer-vf-pit.c new file mode 100644 index 0000000000000..0f92089ec08c7 --- /dev/null +++ b/drivers/clocksource/timer-vf-pit.c @@ -0,0 +1,204 @@ +/* + * Copyright 2012-2013 Freescale Semiconductor, Inc. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + */ + +#include +#include +#include +#include +#include +#include + +/* + * Each pit takes 0x10 Bytes register space + */ +#define PITMCR 0x00 +#define PIT0_OFFSET 0x100 +#define PITn_OFFSET(n) (PIT0_OFFSET + 0x10 * (n)) +#define PITLDVAL 0x00 +#define PITCVAL 0x04 +#define PITTCTRL 0x08 +#define PITTFLG 0x0c + +#define PITMCR_MDIS (0x1 << 1) + +#define PITTCTRL_TEN (0x1 << 0) +#define PITTCTRL_TIE (0x1 << 1) +#define PITCTRL_CHN (0x1 << 2) + +#define PITTFLG_TIF 0x1 + +static void __iomem *clksrc_base; +static void __iomem *clkevt_base; +static unsigned long cycle_per_jiffy; + +static inline void pit_timer_enable(void) +{ + __raw_writel(PITTCTRL_TEN | PITTCTRL_TIE, clkevt_base + PITTCTRL); +} + +static inline void pit_timer_disable(void) +{ + __raw_writel(0, clkevt_base + PITTCTRL); +} + +static inline void pit_irq_acknowledge(void) +{ + __raw_writel(PITTFLG_TIF, clkevt_base + PITTFLG); +} + +static u64 notrace pit_read_sched_clock(void) +{ + return ~__raw_readl(clksrc_base + PITCVAL); +} + +static int __init pit_clocksource_init(unsigned long rate) +{ + /* set the max load value and start the clock source counter */ + __raw_writel(0, clksrc_base + PITTCTRL); + __raw_writel(~0UL, clksrc_base + PITLDVAL); + __raw_writel(PITTCTRL_TEN, clksrc_base + PITTCTRL); + + sched_clock_register(pit_read_sched_clock, 32, rate); + return clocksource_mmio_init(clksrc_base + PITCVAL, "vf-pit", rate, + 300, 32, clocksource_mmio_readl_down); +} + +static int pit_set_next_event(unsigned long delta, + struct clock_event_device *unused) +{ + /* + * set a new value to PITLDVAL register will not restart the timer, + * to abort the current cycle and start a timer period with the new + * value, the timer must be disabled and enabled again. + * and the PITLAVAL should be set to delta minus one according to pit + * hardware requirement. + */ + pit_timer_disable(); + __raw_writel(delta - 1, clkevt_base + PITLDVAL); + pit_timer_enable(); + + return 0; +} + +static int pit_shutdown(struct clock_event_device *evt) +{ + pit_timer_disable(); + return 0; +} + +static int pit_set_periodic(struct clock_event_device *evt) +{ + pit_set_next_event(cycle_per_jiffy, evt); + return 0; +} + +static irqreturn_t pit_timer_interrupt(int irq, void *dev_id) +{ + struct clock_event_device *evt = dev_id; + + pit_irq_acknowledge(); + + /* + * pit hardware doesn't support oneshot, it will generate an interrupt + * and reload the counter value from PITLDVAL when PITCVAL reach zero, + * and start the counter again. So software need to disable the timer + * to stop the counter loop in ONESHOT mode. + */ + if (likely(clockevent_state_oneshot(evt))) + pit_timer_disable(); + + evt->event_handler(evt); + + return IRQ_HANDLED; +} + +static struct clock_event_device clockevent_pit = { + .name = "VF pit timer", + .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT, + .set_state_shutdown = pit_shutdown, + .set_state_periodic = pit_set_periodic, + .set_next_event = pit_set_next_event, + .rating = 300, +}; + +static struct irqaction pit_timer_irq = { + .name = "VF pit timer", + .flags = IRQF_TIMER | IRQF_IRQPOLL, + .handler = pit_timer_interrupt, + .dev_id = &clockevent_pit, +}; + +static int __init pit_clockevent_init(unsigned long rate, int irq) +{ + __raw_writel(0, clkevt_base + PITTCTRL); + __raw_writel(PITTFLG_TIF, clkevt_base + PITTFLG); + + BUG_ON(setup_irq(irq, &pit_timer_irq)); + + clockevent_pit.cpumask = cpumask_of(0); + clockevent_pit.irq = irq; + /* + * The value for the LDVAL register trigger is calculated as: + * LDVAL trigger = (period / clock period) - 1 + * The pit is a 32-bit down count timer, when the conter value + * reaches 0, it will generate an interrupt, thus the minimal + * LDVAL trigger value is 1. And then the min_delta is + * minimal LDVAL trigger value + 1, and the max_delta is full 32-bit. + */ + clockevents_config_and_register(&clockevent_pit, rate, 2, 0xffffffff); + + return 0; +} + +static int __init pit_timer_init(struct device_node *np) +{ + struct clk *pit_clk; + void __iomem *timer_base; + unsigned long clk_rate; + int irq, ret; + + timer_base = of_iomap(np, 0); + if (!timer_base) { + pr_err("Failed to iomap\n"); + return -ENXIO; + } + + /* + * PIT0 and PIT1 can be chained to build a 64-bit timer, + * so choose PIT2 as clocksource, PIT3 as clockevent device, + * and leave PIT0 and PIT1 unused for anyone else who needs them. + */ + clksrc_base = timer_base + PITn_OFFSET(2); + clkevt_base = timer_base + PITn_OFFSET(3); + + irq = irq_of_parse_and_map(np, 0); + if (irq <= 0) + return -EINVAL; + + pit_clk = of_clk_get(np, 0); + if (IS_ERR(pit_clk)) + return PTR_ERR(pit_clk); + + ret = clk_prepare_enable(pit_clk); + if (ret) + return ret; + + clk_rate = clk_get_rate(pit_clk); + cycle_per_jiffy = clk_rate / (HZ); + + /* enable the pit module */ + __raw_writel(~PITMCR_MDIS, timer_base + PITMCR); + + ret = pit_clocksource_init(clk_rate); + if (ret) + return ret; + + return pit_clockevent_init(clk_rate, irq); +} +TIMER_OF_DECLARE(vf610, "fsl,vf610-pit", pit_timer_init); diff --git a/drivers/clocksource/timer-vt8500.c b/drivers/clocksource/timer-vt8500.c new file mode 100644 index 0000000000000..e0f7489cfc8e2 --- /dev/null +++ b/drivers/clocksource/timer-vt8500.c @@ -0,0 +1,168 @@ +/* + * arch/arm/mach-vt8500/timer.c + * + * Copyright (C) 2012 Tony Prisk + * Copyright (C) 2010 Alexey Charkov + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* + * This file is copied and modified from the original timer.c provided by + * Alexey Charkov. Minor changes have been made for Device Tree Support. + */ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#define VT8500_TIMER_OFFSET 0x0100 +#define VT8500_TIMER_HZ 3000000 +#define TIMER_MATCH_VAL 0x0000 +#define TIMER_COUNT_VAL 0x0010 +#define TIMER_STATUS_VAL 0x0014 +#define TIMER_IER_VAL 0x001c /* interrupt enable */ +#define TIMER_CTRL_VAL 0x0020 +#define TIMER_AS_VAL 0x0024 /* access status */ +#define TIMER_COUNT_R_ACTIVE (1 << 5) /* not ready for read */ +#define TIMER_COUNT_W_ACTIVE (1 << 4) /* not ready for write */ +#define TIMER_MATCH_W_ACTIVE (1 << 0) /* not ready for write */ + +#define msecs_to_loops(t) (loops_per_jiffy / 1000 * HZ * t) + +#define MIN_OSCR_DELTA 16 + +static void __iomem *regbase; + +static u64 vt8500_timer_read(struct clocksource *cs) +{ + int loops = msecs_to_loops(10); + writel(3, regbase + TIMER_CTRL_VAL); + while ((readl((regbase + TIMER_AS_VAL)) & TIMER_COUNT_R_ACTIVE) + && --loops) + cpu_relax(); + return readl(regbase + TIMER_COUNT_VAL); +} + +static struct clocksource clocksource = { + .name = "vt8500_timer", + .rating = 200, + .read = vt8500_timer_read, + .mask = CLOCKSOURCE_MASK(32), + .flags = CLOCK_SOURCE_IS_CONTINUOUS, +}; + +static int vt8500_timer_set_next_event(unsigned long cycles, + struct clock_event_device *evt) +{ + int loops = msecs_to_loops(10); + u64 alarm = clocksource.read(&clocksource) + cycles; + while ((readl(regbase + TIMER_AS_VAL) & TIMER_MATCH_W_ACTIVE) + && --loops) + cpu_relax(); + writel((unsigned long)alarm, regbase + TIMER_MATCH_VAL); + + if ((signed)(alarm - clocksource.read(&clocksource)) <= MIN_OSCR_DELTA) + return -ETIME; + + writel(1, regbase + TIMER_IER_VAL); + + return 0; +} + +static int vt8500_shutdown(struct clock_event_device *evt) +{ + writel(readl(regbase + TIMER_CTRL_VAL) | 1, regbase + TIMER_CTRL_VAL); + writel(0, regbase + TIMER_IER_VAL); + return 0; +} + +static struct clock_event_device clockevent = { + .name = "vt8500_timer", + .features = CLOCK_EVT_FEAT_ONESHOT, + .rating = 200, + .set_next_event = vt8500_timer_set_next_event, + .set_state_shutdown = vt8500_shutdown, + .set_state_oneshot = vt8500_shutdown, +}; + +static irqreturn_t vt8500_timer_interrupt(int irq, void *dev_id) +{ + struct clock_event_device *evt = dev_id; + writel(0xf, regbase + TIMER_STATUS_VAL); + evt->event_handler(evt); + + return IRQ_HANDLED; +} + +static struct irqaction irq = { + .name = "vt8500_timer", + .flags = IRQF_TIMER | IRQF_IRQPOLL, + .handler = vt8500_timer_interrupt, + .dev_id = &clockevent, +}; + +static int __init vt8500_timer_init(struct device_node *np) +{ + int timer_irq, ret; + + regbase = of_iomap(np, 0); + if (!regbase) { + pr_err("%s: Missing iobase description in Device Tree\n", + __func__); + return -ENXIO; + } + + timer_irq = irq_of_parse_and_map(np, 0); + if (!timer_irq) { + pr_err("%s: Missing irq description in Device Tree\n", + __func__); + return -EINVAL; + } + + writel(1, regbase + TIMER_CTRL_VAL); + writel(0xf, regbase + TIMER_STATUS_VAL); + writel(~0, regbase + TIMER_MATCH_VAL); + + ret = clocksource_register_hz(&clocksource, VT8500_TIMER_HZ); + if (ret) { + pr_err("%s: vt8500_timer_init: clocksource_register failed for %s\n", + __func__, clocksource.name); + return ret; + } + + clockevent.cpumask = cpumask_of(0); + + ret = setup_irq(timer_irq, &irq); + if (ret) { + pr_err("%s: setup_irq failed for %s\n", __func__, + clockevent.name); + return ret; + } + + clockevents_config_and_register(&clockevent, VT8500_TIMER_HZ, + MIN_OSCR_DELTA * 2, 0xf0000000); + + return 0; +} + +TIMER_OF_DECLARE(vt8500, "via,vt8500-timer", vt8500_timer_init); diff --git a/drivers/clocksource/timer-zevio.c b/drivers/clocksource/timer-zevio.c new file mode 100644 index 0000000000000..f74689334f7cb --- /dev/null +++ b/drivers/clocksource/timer-zevio.c @@ -0,0 +1,218 @@ +/* + * linux/drivers/clocksource/zevio-timer.c + * + * Copyright (C) 2013 Daniel Tang + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2, as + * published by the Free Software Foundation. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define IO_CURRENT_VAL 0x00 +#define IO_DIVIDER 0x04 +#define IO_CONTROL 0x08 + +#define IO_TIMER1 0x00 +#define IO_TIMER2 0x0C + +#define IO_MATCH_BEGIN 0x18 +#define IO_MATCH(x) (IO_MATCH_BEGIN + ((x) << 2)) + +#define IO_INTR_STS 0x00 +#define IO_INTR_ACK 0x00 +#define IO_INTR_MSK 0x04 + +#define CNTL_STOP_TIMER (1 << 4) +#define CNTL_RUN_TIMER (0 << 4) + +#define CNTL_INC (1 << 3) +#define CNTL_DEC (0 << 3) + +#define CNTL_TOZERO 0 +#define CNTL_MATCH(x) ((x) + 1) +#define CNTL_FOREVER 7 + +/* There are 6 match registers but we only use one. */ +#define TIMER_MATCH 0 + +#define TIMER_INTR_MSK (1 << (TIMER_MATCH)) +#define TIMER_INTR_ALL 0x3F + +struct zevio_timer { + void __iomem *base; + void __iomem *timer1, *timer2; + void __iomem *interrupt_regs; + + struct clk *clk; + struct clock_event_device clkevt; + struct irqaction clkevt_irq; + + char clocksource_name[64]; + char clockevent_name[64]; +}; + +static int zevio_timer_set_event(unsigned long delta, + struct clock_event_device *dev) +{ + struct zevio_timer *timer = container_of(dev, struct zevio_timer, + clkevt); + + writel(delta, timer->timer1 + IO_CURRENT_VAL); + writel(CNTL_RUN_TIMER | CNTL_DEC | CNTL_MATCH(TIMER_MATCH), + timer->timer1 + IO_CONTROL); + + return 0; +} + +static int zevio_timer_shutdown(struct clock_event_device *dev) +{ + struct zevio_timer *timer = container_of(dev, struct zevio_timer, + clkevt); + + /* Disable timer interrupts */ + writel(0, timer->interrupt_regs + IO_INTR_MSK); + writel(TIMER_INTR_ALL, timer->interrupt_regs + IO_INTR_ACK); + /* Stop timer */ + writel(CNTL_STOP_TIMER, timer->timer1 + IO_CONTROL); + return 0; +} + +static int zevio_timer_set_oneshot(struct clock_event_device *dev) +{ + struct zevio_timer *timer = container_of(dev, struct zevio_timer, + clkevt); + + /* Enable timer interrupts */ + writel(TIMER_INTR_MSK, timer->interrupt_regs + IO_INTR_MSK); + writel(TIMER_INTR_ALL, timer->interrupt_regs + IO_INTR_ACK); + return 0; +} + +static irqreturn_t zevio_timer_interrupt(int irq, void *dev_id) +{ + struct zevio_timer *timer = dev_id; + u32 intr; + + intr = readl(timer->interrupt_regs + IO_INTR_ACK); + if (!(intr & TIMER_INTR_MSK)) + return IRQ_NONE; + + writel(TIMER_INTR_MSK, timer->interrupt_regs + IO_INTR_ACK); + writel(CNTL_STOP_TIMER, timer->timer1 + IO_CONTROL); + + if (timer->clkevt.event_handler) + timer->clkevt.event_handler(&timer->clkevt); + + return IRQ_HANDLED; +} + +static int __init zevio_timer_add(struct device_node *node) +{ + struct zevio_timer *timer; + struct resource res; + int irqnr, ret; + + timer = kzalloc(sizeof(*timer), GFP_KERNEL); + if (!timer) + return -ENOMEM; + + timer->base = of_iomap(node, 0); + if (!timer->base) { + ret = -EINVAL; + goto error_free; + } + timer->timer1 = timer->base + IO_TIMER1; + timer->timer2 = timer->base + IO_TIMER2; + + timer->clk = of_clk_get(node, 0); + if (IS_ERR(timer->clk)) { + ret = PTR_ERR(timer->clk); + pr_err("Timer clock not found! (error %d)\n", ret); + goto error_unmap; + } + + timer->interrupt_regs = of_iomap(node, 1); + irqnr = irq_of_parse_and_map(node, 0); + + of_address_to_resource(node, 0, &res); + scnprintf(timer->clocksource_name, sizeof(timer->clocksource_name), + "%llx.%s_clocksource", + (unsigned long long)res.start, node->name); + + scnprintf(timer->clockevent_name, sizeof(timer->clockevent_name), + "%llx.%s_clockevent", + (unsigned long long)res.start, node->name); + + if (timer->interrupt_regs && irqnr) { + timer->clkevt.name = timer->clockevent_name; + timer->clkevt.set_next_event = zevio_timer_set_event; + timer->clkevt.set_state_shutdown = zevio_timer_shutdown; + timer->clkevt.set_state_oneshot = zevio_timer_set_oneshot; + timer->clkevt.tick_resume = zevio_timer_set_oneshot; + timer->clkevt.rating = 200; + timer->clkevt.cpumask = cpu_possible_mask; + timer->clkevt.features = CLOCK_EVT_FEAT_ONESHOT; + timer->clkevt.irq = irqnr; + + writel(CNTL_STOP_TIMER, timer->timer1 + IO_CONTROL); + writel(0, timer->timer1 + IO_DIVIDER); + + /* Start with timer interrupts disabled */ + writel(0, timer->interrupt_regs + IO_INTR_MSK); + writel(TIMER_INTR_ALL, timer->interrupt_regs + IO_INTR_ACK); + + /* Interrupt to occur when timer value matches 0 */ + writel(0, timer->base + IO_MATCH(TIMER_MATCH)); + + timer->clkevt_irq.name = timer->clockevent_name; + timer->clkevt_irq.handler = zevio_timer_interrupt; + timer->clkevt_irq.dev_id = timer; + timer->clkevt_irq.flags = IRQF_TIMER | IRQF_IRQPOLL; + + setup_irq(irqnr, &timer->clkevt_irq); + + clockevents_config_and_register(&timer->clkevt, + clk_get_rate(timer->clk), 0x0001, 0xffff); + pr_info("Added %s as clockevent\n", timer->clockevent_name); + } + + writel(CNTL_STOP_TIMER, timer->timer2 + IO_CONTROL); + writel(0, timer->timer2 + IO_CURRENT_VAL); + writel(0, timer->timer2 + IO_DIVIDER); + writel(CNTL_RUN_TIMER | CNTL_FOREVER | CNTL_INC, + timer->timer2 + IO_CONTROL); + + clocksource_mmio_init(timer->timer2 + IO_CURRENT_VAL, + timer->clocksource_name, + clk_get_rate(timer->clk), + 200, 16, + clocksource_mmio_readw_up); + + pr_info("Added %s as clocksource\n", timer->clocksource_name); + + return 0; +error_unmap: + iounmap(timer->base); +error_free: + kfree(timer); + return ret; +} + +static int __init zevio_timer_init(struct device_node *node) +{ + return zevio_timer_add(node); +} + +TIMER_OF_DECLARE(zevio_timer, "lsi,zevio-timer", zevio_timer_init); diff --git a/drivers/clocksource/versatile.c b/drivers/clocksource/versatile.c deleted file mode 100644 index 39725d38aedee..0000000000000 --- a/drivers/clocksource/versatile.c +++ /dev/null @@ -1,44 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * Copyright (C) 2014 ARM Limited - */ - -#include -#include -#include -#include - -#define SYS_24MHZ 0x05c - -static void __iomem *versatile_sys_24mhz; - -static u64 notrace versatile_sys_24mhz_read(void) -{ - return readl(versatile_sys_24mhz); -} - -static int __init versatile_sched_clock_init(struct device_node *node) -{ - void __iomem *base = of_iomap(node, 0); - - if (!base) - return -ENXIO; - - versatile_sys_24mhz = base + SYS_24MHZ; - - sched_clock_register(versatile_sys_24mhz_read, 32, 24000000); - - return 0; -} -TIMER_OF_DECLARE(vexpress, "arm,vexpress-sysreg", - versatile_sched_clock_init); -TIMER_OF_DECLARE(versatile, "arm,versatile-sysreg", - versatile_sched_clock_init); diff --git a/drivers/clocksource/vf_pit_timer.c b/drivers/clocksource/vf_pit_timer.c deleted file mode 100644 index 0f92089ec08c7..0000000000000 --- a/drivers/clocksource/vf_pit_timer.c +++ /dev/null @@ -1,204 +0,0 @@ -/* - * Copyright 2012-2013 Freescale Semiconductor, Inc. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - */ - -#include -#include -#include -#include -#include -#include - -/* - * Each pit takes 0x10 Bytes register space - */ -#define PITMCR 0x00 -#define PIT0_OFFSET 0x100 -#define PITn_OFFSET(n) (PIT0_OFFSET + 0x10 * (n)) -#define PITLDVAL 0x00 -#define PITCVAL 0x04 -#define PITTCTRL 0x08 -#define PITTFLG 0x0c - -#define PITMCR_MDIS (0x1 << 1) - -#define PITTCTRL_TEN (0x1 << 0) -#define PITTCTRL_TIE (0x1 << 1) -#define PITCTRL_CHN (0x1 << 2) - -#define PITTFLG_TIF 0x1 - -static void __iomem *clksrc_base; -static void __iomem *clkevt_base; -static unsigned long cycle_per_jiffy; - -static inline void pit_timer_enable(void) -{ - __raw_writel(PITTCTRL_TEN | PITTCTRL_TIE, clkevt_base + PITTCTRL); -} - -static inline void pit_timer_disable(void) -{ - __raw_writel(0, clkevt_base + PITTCTRL); -} - -static inline void pit_irq_acknowledge(void) -{ - __raw_writel(PITTFLG_TIF, clkevt_base + PITTFLG); -} - -static u64 notrace pit_read_sched_clock(void) -{ - return ~__raw_readl(clksrc_base + PITCVAL); -} - -static int __init pit_clocksource_init(unsigned long rate) -{ - /* set the max load value and start the clock source counter */ - __raw_writel(0, clksrc_base + PITTCTRL); - __raw_writel(~0UL, clksrc_base + PITLDVAL); - __raw_writel(PITTCTRL_TEN, clksrc_base + PITTCTRL); - - sched_clock_register(pit_read_sched_clock, 32, rate); - return clocksource_mmio_init(clksrc_base + PITCVAL, "vf-pit", rate, - 300, 32, clocksource_mmio_readl_down); -} - -static int pit_set_next_event(unsigned long delta, - struct clock_event_device *unused) -{ - /* - * set a new value to PITLDVAL register will not restart the timer, - * to abort the current cycle and start a timer period with the new - * value, the timer must be disabled and enabled again. - * and the PITLAVAL should be set to delta minus one according to pit - * hardware requirement. - */ - pit_timer_disable(); - __raw_writel(delta - 1, clkevt_base + PITLDVAL); - pit_timer_enable(); - - return 0; -} - -static int pit_shutdown(struct clock_event_device *evt) -{ - pit_timer_disable(); - return 0; -} - -static int pit_set_periodic(struct clock_event_device *evt) -{ - pit_set_next_event(cycle_per_jiffy, evt); - return 0; -} - -static irqreturn_t pit_timer_interrupt(int irq, void *dev_id) -{ - struct clock_event_device *evt = dev_id; - - pit_irq_acknowledge(); - - /* - * pit hardware doesn't support oneshot, it will generate an interrupt - * and reload the counter value from PITLDVAL when PITCVAL reach zero, - * and start the counter again. So software need to disable the timer - * to stop the counter loop in ONESHOT mode. - */ - if (likely(clockevent_state_oneshot(evt))) - pit_timer_disable(); - - evt->event_handler(evt); - - return IRQ_HANDLED; -} - -static struct clock_event_device clockevent_pit = { - .name = "VF pit timer", - .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT, - .set_state_shutdown = pit_shutdown, - .set_state_periodic = pit_set_periodic, - .set_next_event = pit_set_next_event, - .rating = 300, -}; - -static struct irqaction pit_timer_irq = { - .name = "VF pit timer", - .flags = IRQF_TIMER | IRQF_IRQPOLL, - .handler = pit_timer_interrupt, - .dev_id = &clockevent_pit, -}; - -static int __init pit_clockevent_init(unsigned long rate, int irq) -{ - __raw_writel(0, clkevt_base + PITTCTRL); - __raw_writel(PITTFLG_TIF, clkevt_base + PITTFLG); - - BUG_ON(setup_irq(irq, &pit_timer_irq)); - - clockevent_pit.cpumask = cpumask_of(0); - clockevent_pit.irq = irq; - /* - * The value for the LDVAL register trigger is calculated as: - * LDVAL trigger = (period / clock period) - 1 - * The pit is a 32-bit down count timer, when the conter value - * reaches 0, it will generate an interrupt, thus the minimal - * LDVAL trigger value is 1. And then the min_delta is - * minimal LDVAL trigger value + 1, and the max_delta is full 32-bit. - */ - clockevents_config_and_register(&clockevent_pit, rate, 2, 0xffffffff); - - return 0; -} - -static int __init pit_timer_init(struct device_node *np) -{ - struct clk *pit_clk; - void __iomem *timer_base; - unsigned long clk_rate; - int irq, ret; - - timer_base = of_iomap(np, 0); - if (!timer_base) { - pr_err("Failed to iomap\n"); - return -ENXIO; - } - - /* - * PIT0 and PIT1 can be chained to build a 64-bit timer, - * so choose PIT2 as clocksource, PIT3 as clockevent device, - * and leave PIT0 and PIT1 unused for anyone else who needs them. - */ - clksrc_base = timer_base + PITn_OFFSET(2); - clkevt_base = timer_base + PITn_OFFSET(3); - - irq = irq_of_parse_and_map(np, 0); - if (irq <= 0) - return -EINVAL; - - pit_clk = of_clk_get(np, 0); - if (IS_ERR(pit_clk)) - return PTR_ERR(pit_clk); - - ret = clk_prepare_enable(pit_clk); - if (ret) - return ret; - - clk_rate = clk_get_rate(pit_clk); - cycle_per_jiffy = clk_rate / (HZ); - - /* enable the pit module */ - __raw_writel(~PITMCR_MDIS, timer_base + PITMCR); - - ret = pit_clocksource_init(clk_rate); - if (ret) - return ret; - - return pit_clockevent_init(clk_rate, irq); -} -TIMER_OF_DECLARE(vf610, "fsl,vf610-pit", pit_timer_init); diff --git a/drivers/clocksource/vt8500_timer.c b/drivers/clocksource/vt8500_timer.c deleted file mode 100644 index e0f7489cfc8e2..0000000000000 --- a/drivers/clocksource/vt8500_timer.c +++ /dev/null @@ -1,168 +0,0 @@ -/* - * arch/arm/mach-vt8500/timer.c - * - * Copyright (C) 2012 Tony Prisk - * Copyright (C) 2010 Alexey Charkov - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* - * This file is copied and modified from the original timer.c provided by - * Alexey Charkov. Minor changes have been made for Device Tree Support. - */ - -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#define VT8500_TIMER_OFFSET 0x0100 -#define VT8500_TIMER_HZ 3000000 -#define TIMER_MATCH_VAL 0x0000 -#define TIMER_COUNT_VAL 0x0010 -#define TIMER_STATUS_VAL 0x0014 -#define TIMER_IER_VAL 0x001c /* interrupt enable */ -#define TIMER_CTRL_VAL 0x0020 -#define TIMER_AS_VAL 0x0024 /* access status */ -#define TIMER_COUNT_R_ACTIVE (1 << 5) /* not ready for read */ -#define TIMER_COUNT_W_ACTIVE (1 << 4) /* not ready for write */ -#define TIMER_MATCH_W_ACTIVE (1 << 0) /* not ready for write */ - -#define msecs_to_loops(t) (loops_per_jiffy / 1000 * HZ * t) - -#define MIN_OSCR_DELTA 16 - -static void __iomem *regbase; - -static u64 vt8500_timer_read(struct clocksource *cs) -{ - int loops = msecs_to_loops(10); - writel(3, regbase + TIMER_CTRL_VAL); - while ((readl((regbase + TIMER_AS_VAL)) & TIMER_COUNT_R_ACTIVE) - && --loops) - cpu_relax(); - return readl(regbase + TIMER_COUNT_VAL); -} - -static struct clocksource clocksource = { - .name = "vt8500_timer", - .rating = 200, - .read = vt8500_timer_read, - .mask = CLOCKSOURCE_MASK(32), - .flags = CLOCK_SOURCE_IS_CONTINUOUS, -}; - -static int vt8500_timer_set_next_event(unsigned long cycles, - struct clock_event_device *evt) -{ - int loops = msecs_to_loops(10); - u64 alarm = clocksource.read(&clocksource) + cycles; - while ((readl(regbase + TIMER_AS_VAL) & TIMER_MATCH_W_ACTIVE) - && --loops) - cpu_relax(); - writel((unsigned long)alarm, regbase + TIMER_MATCH_VAL); - - if ((signed)(alarm - clocksource.read(&clocksource)) <= MIN_OSCR_DELTA) - return -ETIME; - - writel(1, regbase + TIMER_IER_VAL); - - return 0; -} - -static int vt8500_shutdown(struct clock_event_device *evt) -{ - writel(readl(regbase + TIMER_CTRL_VAL) | 1, regbase + TIMER_CTRL_VAL); - writel(0, regbase + TIMER_IER_VAL); - return 0; -} - -static struct clock_event_device clockevent = { - .name = "vt8500_timer", - .features = CLOCK_EVT_FEAT_ONESHOT, - .rating = 200, - .set_next_event = vt8500_timer_set_next_event, - .set_state_shutdown = vt8500_shutdown, - .set_state_oneshot = vt8500_shutdown, -}; - -static irqreturn_t vt8500_timer_interrupt(int irq, void *dev_id) -{ - struct clock_event_device *evt = dev_id; - writel(0xf, regbase + TIMER_STATUS_VAL); - evt->event_handler(evt); - - return IRQ_HANDLED; -} - -static struct irqaction irq = { - .name = "vt8500_timer", - .flags = IRQF_TIMER | IRQF_IRQPOLL, - .handler = vt8500_timer_interrupt, - .dev_id = &clockevent, -}; - -static int __init vt8500_timer_init(struct device_node *np) -{ - int timer_irq, ret; - - regbase = of_iomap(np, 0); - if (!regbase) { - pr_err("%s: Missing iobase description in Device Tree\n", - __func__); - return -ENXIO; - } - - timer_irq = irq_of_parse_and_map(np, 0); - if (!timer_irq) { - pr_err("%s: Missing irq description in Device Tree\n", - __func__); - return -EINVAL; - } - - writel(1, regbase + TIMER_CTRL_VAL); - writel(0xf, regbase + TIMER_STATUS_VAL); - writel(~0, regbase + TIMER_MATCH_VAL); - - ret = clocksource_register_hz(&clocksource, VT8500_TIMER_HZ); - if (ret) { - pr_err("%s: vt8500_timer_init: clocksource_register failed for %s\n", - __func__, clocksource.name); - return ret; - } - - clockevent.cpumask = cpumask_of(0); - - ret = setup_irq(timer_irq, &irq); - if (ret) { - pr_err("%s: setup_irq failed for %s\n", __func__, - clockevent.name); - return ret; - } - - clockevents_config_and_register(&clockevent, VT8500_TIMER_HZ, - MIN_OSCR_DELTA * 2, 0xf0000000); - - return 0; -} - -TIMER_OF_DECLARE(vt8500, "via,vt8500-timer", vt8500_timer_init); diff --git a/drivers/clocksource/zevio-timer.c b/drivers/clocksource/zevio-timer.c deleted file mode 100644 index f74689334f7cb..0000000000000 --- a/drivers/clocksource/zevio-timer.c +++ /dev/null @@ -1,218 +0,0 @@ -/* - * linux/drivers/clocksource/zevio-timer.c - * - * Copyright (C) 2013 Daniel Tang - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2, as - * published by the Free Software Foundation. - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define IO_CURRENT_VAL 0x00 -#define IO_DIVIDER 0x04 -#define IO_CONTROL 0x08 - -#define IO_TIMER1 0x00 -#define IO_TIMER2 0x0C - -#define IO_MATCH_BEGIN 0x18 -#define IO_MATCH(x) (IO_MATCH_BEGIN + ((x) << 2)) - -#define IO_INTR_STS 0x00 -#define IO_INTR_ACK 0x00 -#define IO_INTR_MSK 0x04 - -#define CNTL_STOP_TIMER (1 << 4) -#define CNTL_RUN_TIMER (0 << 4) - -#define CNTL_INC (1 << 3) -#define CNTL_DEC (0 << 3) - -#define CNTL_TOZERO 0 -#define CNTL_MATCH(x) ((x) + 1) -#define CNTL_FOREVER 7 - -/* There are 6 match registers but we only use one. */ -#define TIMER_MATCH 0 - -#define TIMER_INTR_MSK (1 << (TIMER_MATCH)) -#define TIMER_INTR_ALL 0x3F - -struct zevio_timer { - void __iomem *base; - void __iomem *timer1, *timer2; - void __iomem *interrupt_regs; - - struct clk *clk; - struct clock_event_device clkevt; - struct irqaction clkevt_irq; - - char clocksource_name[64]; - char clockevent_name[64]; -}; - -static int zevio_timer_set_event(unsigned long delta, - struct clock_event_device *dev) -{ - struct zevio_timer *timer = container_of(dev, struct zevio_timer, - clkevt); - - writel(delta, timer->timer1 + IO_CURRENT_VAL); - writel(CNTL_RUN_TIMER | CNTL_DEC | CNTL_MATCH(TIMER_MATCH), - timer->timer1 + IO_CONTROL); - - return 0; -} - -static int zevio_timer_shutdown(struct clock_event_device *dev) -{ - struct zevio_timer *timer = container_of(dev, struct zevio_timer, - clkevt); - - /* Disable timer interrupts */ - writel(0, timer->interrupt_regs + IO_INTR_MSK); - writel(TIMER_INTR_ALL, timer->interrupt_regs + IO_INTR_ACK); - /* Stop timer */ - writel(CNTL_STOP_TIMER, timer->timer1 + IO_CONTROL); - return 0; -} - -static int zevio_timer_set_oneshot(struct clock_event_device *dev) -{ - struct zevio_timer *timer = container_of(dev, struct zevio_timer, - clkevt); - - /* Enable timer interrupts */ - writel(TIMER_INTR_MSK, timer->interrupt_regs + IO_INTR_MSK); - writel(TIMER_INTR_ALL, timer->interrupt_regs + IO_INTR_ACK); - return 0; -} - -static irqreturn_t zevio_timer_interrupt(int irq, void *dev_id) -{ - struct zevio_timer *timer = dev_id; - u32 intr; - - intr = readl(timer->interrupt_regs + IO_INTR_ACK); - if (!(intr & TIMER_INTR_MSK)) - return IRQ_NONE; - - writel(TIMER_INTR_MSK, timer->interrupt_regs + IO_INTR_ACK); - writel(CNTL_STOP_TIMER, timer->timer1 + IO_CONTROL); - - if (timer->clkevt.event_handler) - timer->clkevt.event_handler(&timer->clkevt); - - return IRQ_HANDLED; -} - -static int __init zevio_timer_add(struct device_node *node) -{ - struct zevio_timer *timer; - struct resource res; - int irqnr, ret; - - timer = kzalloc(sizeof(*timer), GFP_KERNEL); - if (!timer) - return -ENOMEM; - - timer->base = of_iomap(node, 0); - if (!timer->base) { - ret = -EINVAL; - goto error_free; - } - timer->timer1 = timer->base + IO_TIMER1; - timer->timer2 = timer->base + IO_TIMER2; - - timer->clk = of_clk_get(node, 0); - if (IS_ERR(timer->clk)) { - ret = PTR_ERR(timer->clk); - pr_err("Timer clock not found! (error %d)\n", ret); - goto error_unmap; - } - - timer->interrupt_regs = of_iomap(node, 1); - irqnr = irq_of_parse_and_map(node, 0); - - of_address_to_resource(node, 0, &res); - scnprintf(timer->clocksource_name, sizeof(timer->clocksource_name), - "%llx.%s_clocksource", - (unsigned long long)res.start, node->name); - - scnprintf(timer->clockevent_name, sizeof(timer->clockevent_name), - "%llx.%s_clockevent", - (unsigned long long)res.start, node->name); - - if (timer->interrupt_regs && irqnr) { - timer->clkevt.name = timer->clockevent_name; - timer->clkevt.set_next_event = zevio_timer_set_event; - timer->clkevt.set_state_shutdown = zevio_timer_shutdown; - timer->clkevt.set_state_oneshot = zevio_timer_set_oneshot; - timer->clkevt.tick_resume = zevio_timer_set_oneshot; - timer->clkevt.rating = 200; - timer->clkevt.cpumask = cpu_possible_mask; - timer->clkevt.features = CLOCK_EVT_FEAT_ONESHOT; - timer->clkevt.irq = irqnr; - - writel(CNTL_STOP_TIMER, timer->timer1 + IO_CONTROL); - writel(0, timer->timer1 + IO_DIVIDER); - - /* Start with timer interrupts disabled */ - writel(0, timer->interrupt_regs + IO_INTR_MSK); - writel(TIMER_INTR_ALL, timer->interrupt_regs + IO_INTR_ACK); - - /* Interrupt to occur when timer value matches 0 */ - writel(0, timer->base + IO_MATCH(TIMER_MATCH)); - - timer->clkevt_irq.name = timer->clockevent_name; - timer->clkevt_irq.handler = zevio_timer_interrupt; - timer->clkevt_irq.dev_id = timer; - timer->clkevt_irq.flags = IRQF_TIMER | IRQF_IRQPOLL; - - setup_irq(irqnr, &timer->clkevt_irq); - - clockevents_config_and_register(&timer->clkevt, - clk_get_rate(timer->clk), 0x0001, 0xffff); - pr_info("Added %s as clockevent\n", timer->clockevent_name); - } - - writel(CNTL_STOP_TIMER, timer->timer2 + IO_CONTROL); - writel(0, timer->timer2 + IO_CURRENT_VAL); - writel(0, timer->timer2 + IO_DIVIDER); - writel(CNTL_RUN_TIMER | CNTL_FOREVER | CNTL_INC, - timer->timer2 + IO_CONTROL); - - clocksource_mmio_init(timer->timer2 + IO_CURRENT_VAL, - timer->clocksource_name, - clk_get_rate(timer->clk), - 200, 16, - clocksource_mmio_readw_up); - - pr_info("Added %s as clocksource\n", timer->clocksource_name); - - return 0; -error_unmap: - iounmap(timer->base); -error_free: - kfree(timer); - return ret; -} - -static int __init zevio_timer_init(struct device_node *node) -{ - return zevio_timer_add(node); -} - -TIMER_OF_DECLARE(zevio_timer, "lsi,zevio-timer", zevio_timer_init); diff --git a/drivers/crypto/nx/Makefile b/drivers/crypto/nx/Makefile index 015155da59c29..76139865d7fa1 100644 --- a/drivers/crypto/nx/Makefile +++ b/drivers/crypto/nx/Makefile @@ -1,7 +1,6 @@ # SPDX-License-Identifier: GPL-2.0 obj-$(CONFIG_CRYPTO_DEV_NX_ENCRYPT) += nx-crypto.o nx-crypto-objs := nx.o \ - nx_debugfs.o \ nx-aes-cbc.o \ nx-aes-ecb.o \ nx-aes-gcm.o \ @@ -11,6 +10,7 @@ nx-crypto-objs := nx.o \ nx-sha256.o \ nx-sha512.o +nx-crypto-$(CONFIG_DEBUG_FS) += nx_debugfs.o obj-$(CONFIG_CRYPTO_DEV_NX_COMPRESS_PSERIES) += nx-compress-pseries.o nx-compress.o obj-$(CONFIG_CRYPTO_DEV_NX_COMPRESS_POWERNV) += nx-compress-powernv.o nx-compress.o nx-compress-objs := nx-842.o diff --git a/drivers/crypto/nx/nx.h b/drivers/crypto/nx/nx.h index c3e54af18645c..ebad937a9545c 100644 --- a/drivers/crypto/nx/nx.h +++ b/drivers/crypto/nx/nx.h @@ -180,8 +180,8 @@ struct nx_sg *nx_walk_and_build(struct nx_sg *, unsigned int, int nx_debugfs_init(struct nx_crypto_driver *); void nx_debugfs_fini(struct nx_crypto_driver *); #else -#define NX_DEBUGFS_INIT(drv) (0) -#define NX_DEBUGFS_FINI(drv) (0) +#define NX_DEBUGFS_INIT(drv) do {} while (0) +#define NX_DEBUGFS_FINI(drv) do {} while (0) #endif #define NX_PAGE_NUM(x) ((u64)(x) & 0xfffffffffffff000ULL) diff --git a/drivers/extcon/extcon.c b/drivers/extcon/extcon.c index 4c70136c7aa3c..84fc0e48bb0e8 100644 --- a/drivers/extcon/extcon.c +++ b/drivers/extcon/extcon.c @@ -204,6 +204,14 @@ static const struct __extcon_info { * @attr_name: "name" sysfs entry * @attr_state: "state" sysfs entry * @attrs: the array pointing to attr_name and attr_state for attr_g + * @usb_propval: the array of USB connector properties + * @chg_propval: the array of charger connector properties + * @jack_propval: the array of jack connector properties + * @disp_propval: the array of display connector properties + * @usb_bits: the bit array of the USB connector property capabilities + * @chg_bits: the bit array of the charger connector property capabilities + * @jack_bits: the bit array of the jack connector property capabilities + * @disp_bits: the bit array of the display connector property capabilities */ struct extcon_cable { struct extcon_dev *edev; diff --git a/drivers/firewire/ohci.c b/drivers/firewire/ohci.c index 45c048751f3bd..9e7abc86de8c2 100644 --- a/drivers/firewire/ohci.c +++ b/drivers/firewire/ohci.c @@ -1112,7 +1112,7 @@ static void context_tasklet(unsigned long data) static int context_add_buffer(struct context *ctx) { struct descriptor_buffer *desc; - dma_addr_t uninitialized_var(bus_addr); + dma_addr_t bus_addr; int offset; /* @@ -1302,7 +1302,7 @@ static int at_context_queue_packet(struct context *ctx, struct fw_packet *packet) { struct fw_ohci *ohci = ctx->ohci; - dma_addr_t d_bus, uninitialized_var(payload_bus); + dma_addr_t d_bus, payload_bus; struct driver_data *driver_data; struct descriptor *d, *last; __le32 *header; @@ -2458,7 +2458,7 @@ static int ohci_set_config_rom(struct fw_card *card, { struct fw_ohci *ohci; __be32 *next_config_rom; - dma_addr_t uninitialized_var(next_config_rom_bus); + dma_addr_t next_config_rom_bus; ohci = fw_ohci(card); @@ -2947,10 +2947,10 @@ static struct fw_iso_context *ohci_allocate_iso_context(struct fw_card *card, int type, int channel, size_t header_size) { struct fw_ohci *ohci = fw_ohci(card); - struct iso_context *uninitialized_var(ctx); - descriptor_callback_t uninitialized_var(callback); - u64 *uninitialized_var(channels); - u32 *uninitialized_var(mask), uninitialized_var(regs); + struct iso_context *ctx; + descriptor_callback_t callback; + u64 *channels; + u32 *mask, regs; int index, ret = -EBUSY; spin_lock_irq(&ohci->lock); diff --git a/drivers/gpio/gpio-tps68470.c b/drivers/gpio/gpio-tps68470.c index aff6e504c6668..9704cff9b4aa3 100644 --- a/drivers/gpio/gpio-tps68470.c +++ b/drivers/gpio/gpio-tps68470.c @@ -91,13 +91,13 @@ static int tps68470_gpio_output(struct gpio_chip *gc, unsigned int offset, struct tps68470_gpio_data *tps68470_gpio = gpiochip_get_data(gc); struct regmap *regmap = tps68470_gpio->tps68470_regmap; + /* Set the initial value */ + tps68470_gpio_set(gc, offset, value); + /* rest are always outputs */ if (offset >= TPS68470_N_REGULAR_GPIO) return 0; - /* Set the initial value */ - tps68470_gpio_set(gc, offset, value); - return regmap_update_bits(regmap, TPS68470_GPIO_CTL_REG_A(offset), TPS68470_GPIO_MODE_MASK, TPS68470_GPIO_MODE_OUT_CMOS); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c index 6a1f5df4bc07e..cdcf9e697c398 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c @@ -2989,6 +2989,10 @@ int amdgpu_vm_ioctl(struct drm_device *dev, void *data, struct drm_file *filp) struct amdgpu_fpriv *fpriv = filp->driver_priv; int r; + /* No valid flags defined yet */ + if (args->in.flags) + return -EINVAL; + switch (args->in.op) { case AMDGPU_VM_OP_RESERVE_VMID: /* current, we only have requirement to reserve vmid from gfxhub */ diff --git a/drivers/gpu/drm/bridge/sil-sii8620.c b/drivers/gpu/drm/bridge/sil-sii8620.c index c72092319a533..214cd2028cd57 100644 --- a/drivers/gpu/drm/bridge/sil-sii8620.c +++ b/drivers/gpu/drm/bridge/sil-sii8620.c @@ -988,7 +988,7 @@ static void sii8620_set_auto_zone(struct sii8620 *ctx) static void sii8620_stop_video(struct sii8620 *ctx) { - u8 uninitialized_var(val); + u8 val; sii8620_write_seq_static(ctx, REG_TPI_INTR_EN, 0, diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c index 281cf9cbb44c4..70b26487de79c 100644 --- a/drivers/gpu/drm/drm_atomic.c +++ b/drivers/gpu/drm/drm_atomic.c @@ -91,6 +91,12 @@ drm_atomic_state_init(struct drm_device *dev, struct drm_atomic_state *state) if (!state->planes) goto fail; + /* + * Because drm_atomic_state can be committed asynchronously we need our + * own reference and cannot rely on the on implied by drm_file in the + * ioctl call. + */ + drm_dev_get(dev); state->dev = dev; DRM_DEBUG_ATOMIC("Allocated atomic state %p\n", state); @@ -250,7 +256,8 @@ EXPORT_SYMBOL(drm_atomic_state_clear); void __drm_atomic_state_free(struct kref *ref) { struct drm_atomic_state *state = container_of(ref, typeof(*state), ref); - struct drm_mode_config *config = &state->dev->mode_config; + struct drm_device *dev = state->dev; + struct drm_mode_config *config = &dev->mode_config; drm_atomic_state_clear(state); @@ -262,6 +269,8 @@ void __drm_atomic_state_free(struct kref *ref) drm_atomic_state_default_release(state); kfree(state); } + + drm_dev_put(dev); } EXPORT_SYMBOL(__drm_atomic_state_free); diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c index 28ea3d260bea1..8b7b107cf2ce3 100644 --- a/drivers/gpu/drm/drm_edid.c +++ b/drivers/gpu/drm/drm_edid.c @@ -2778,7 +2778,7 @@ static int drm_cvt_modes(struct drm_connector *connector, const u8 empty[3] = { 0, 0, 0 }; for (i = 0; i < 4; i++) { - int uninitialized_var(width), height; + int width, height; cvt = &(timing->data.other_data.data.cvt[i]); if (!memcmp(cvt->code, empty, 3)) @@ -2786,6 +2786,8 @@ static int drm_cvt_modes(struct drm_connector *connector, height = (cvt->code[0] + ((cvt->code[1] & 0xf0) << 4) + 1) * 2; switch (cvt->code[1] & 0x0c) { + /* default - because compiler doesn't see that we've enumerated all cases */ + default: case 0x00: width = height * 4 / 3; break; diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c index fbe9156c9e7c1..ee6801fa36ad1 100644 --- a/drivers/gpu/drm/drm_fb_helper.c +++ b/drivers/gpu/drm/drm_fb_helper.c @@ -2233,6 +2233,9 @@ static bool drm_target_cloned(struct drm_fb_helper *fb_helper, can_clone = true; dmt_mode = drm_mode_find_dmt(fb_helper->dev, 1024, 768, 60, false); + if (!dmt_mode) + goto fail; + drm_fb_helper_for_each_connector(fb_helper, i) { if (!enabled[i]) continue; @@ -2249,11 +2252,13 @@ static bool drm_target_cloned(struct drm_fb_helper *fb_helper, if (!modes[i]) can_clone = false; } + kfree(dmt_mode); if (can_clone) { DRM_DEBUG_KMS("can clone using 1024x768\n"); return true; } +fail: DRM_INFO("kms: can't enable cloning when we probably wanted to.\n"); return false; } diff --git a/drivers/gpu/drm/exynos/exynos_drm_dsi.c b/drivers/gpu/drm/exynos/exynos_drm_dsi.c index 8d776070913da..8610589299fc6 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_dsi.c +++ b/drivers/gpu/drm/exynos/exynos_drm_dsi.c @@ -544,9 +544,9 @@ static unsigned long exynos_dsi_pll_find_pms(struct exynos_dsi *dsi, unsigned long best_freq = 0; u32 min_delta = 0xffffffff; u8 p_min, p_max; - u8 _p, uninitialized_var(best_p); - u16 _m, uninitialized_var(best_m); - u8 _s, uninitialized_var(best_s); + u8 _p, best_p; + u16 _m, best_m; + u8 _s, best_s; p_min = DIV_ROUND_UP(fin, (12 * MHZ)); p_max = fin / (6 * MHZ); diff --git a/drivers/gpu/drm/msm/adreno/a5xx_gpu.c b/drivers/gpu/drm/msm/adreno/a5xx_gpu.c index ba513018534e3..1bdba8cc25d3e 100644 --- a/drivers/gpu/drm/msm/adreno/a5xx_gpu.c +++ b/drivers/gpu/drm/msm/adreno/a5xx_gpu.c @@ -173,7 +173,7 @@ static void a5xx_submit_in_rb(struct msm_gpu *gpu, struct msm_gem_submit *submit * since we've already mapped it once in * submit_reloc() */ - if (WARN_ON(!ptr)) + if (WARN_ON(IS_ERR_OR_NULL(ptr))) return; for (i = 0; i < dwords; i++) { diff --git a/drivers/gpu/drm/panel/panel-simple.c b/drivers/gpu/drm/panel/panel-simple.c index a424afdcc77a1..35771e0e69fa6 100644 --- a/drivers/gpu/drm/panel/panel-simple.c +++ b/drivers/gpu/drm/panel/panel-simple.c @@ -405,8 +405,8 @@ static const struct panel_desc ampire_am_480272h3tmqw_t01h = { .num_modes = 1, .bpc = 8, .size = { - .width = 105, - .height = 67, + .width = 99, + .height = 58, }, .bus_format = MEDIA_BUS_FMT_RGB888_1X24, }; diff --git a/drivers/gpu/drm/radeon/ci_dpm.c b/drivers/gpu/drm/radeon/ci_dpm.c index 90c1afe498bea..ce8b14592b69b 100644 --- a/drivers/gpu/drm/radeon/ci_dpm.c +++ b/drivers/gpu/drm/radeon/ci_dpm.c @@ -5552,6 +5552,7 @@ static int ci_parse_power_table(struct radeon_device *rdev) u8 frev, crev; u8 *power_state_offset; struct ci_ps *ps; + int ret; if (!atom_parse_data_header(mode_info->atom_context, index, NULL, &frev, &crev, &data_offset)) @@ -5581,11 +5582,15 @@ static int ci_parse_power_table(struct radeon_device *rdev) non_clock_array_index = power_state->v2.nonClockInfoIndex; non_clock_info = (struct _ATOM_PPLIB_NONCLOCK_INFO *) &non_clock_info_array->nonClockInfo[non_clock_array_index]; - if (!rdev->pm.power_state[i].clock_info) - return -EINVAL; + if (!rdev->pm.power_state[i].clock_info) { + ret = -EINVAL; + goto err_free_ps; + } ps = kzalloc(sizeof(struct ci_ps), GFP_KERNEL); - if (ps == NULL) - return -ENOMEM; + if (ps == NULL) { + ret = -ENOMEM; + goto err_free_ps; + } rdev->pm.dpm.ps[i].ps_priv = ps; ci_parse_pplib_non_clock_info(rdev, &rdev->pm.dpm.ps[i], non_clock_info, @@ -5625,6 +5630,12 @@ static int ci_parse_power_table(struct radeon_device *rdev) } return 0; + +err_free_ps: + for (i = 0; i < rdev->pm.dpm.num_ps; i++) + kfree(rdev->pm.dpm.ps[i].ps_priv); + kfree(rdev->pm.dpm.ps); + return ret; } static int ci_get_vbios_boot_values(struct radeon_device *rdev, @@ -5713,25 +5724,26 @@ int ci_dpm_init(struct radeon_device *rdev) ret = ci_get_vbios_boot_values(rdev, &pi->vbios_boot_state); if (ret) { - ci_dpm_fini(rdev); + kfree(rdev->pm.dpm.priv); return ret; } ret = r600_get_platform_caps(rdev); if (ret) { - ci_dpm_fini(rdev); + kfree(rdev->pm.dpm.priv); return ret; } ret = r600_parse_extended_power_table(rdev); if (ret) { - ci_dpm_fini(rdev); + kfree(rdev->pm.dpm.priv); return ret; } ret = ci_parse_power_table(rdev); if (ret) { - ci_dpm_fini(rdev); + kfree(rdev->pm.dpm.priv); + r600_free_extended_power_table(rdev); return ret; } diff --git a/drivers/gpu/drm/radeon/cypress_dpm.c b/drivers/gpu/drm/radeon/cypress_dpm.c index 3eb7899a4035b..2c637e04dfebc 100644 --- a/drivers/gpu/drm/radeon/cypress_dpm.c +++ b/drivers/gpu/drm/radeon/cypress_dpm.c @@ -558,8 +558,12 @@ static int cypress_populate_mclk_value(struct radeon_device *rdev, ASIC_INTERNAL_MEMORY_SS, vco_freq)) { u32 reference_clock = rdev->clock.mpll.reference_freq; u32 decoded_ref = rv740_get_decoded_reference_divider(dividers.ref_div); - u32 clk_s = reference_clock * 5 / (decoded_ref * ss.rate); - u32 clk_v = ss.percentage * + u32 clk_s, clk_v; + + if (!decoded_ref) + return -EINVAL; + clk_s = reference_clock * 5 / (decoded_ref * ss.rate); + clk_v = ss.percentage * (0x4000 * dividers.whole_fb_div + 0x800 * dividers.frac_fb_div) / (clk_s * 625); mpll_ss1 &= ~CLKV_MASK; diff --git a/drivers/gpu/drm/radeon/ni_dpm.c b/drivers/gpu/drm/radeon/ni_dpm.c index a7273c01de34b..2a9d415400f79 100644 --- a/drivers/gpu/drm/radeon/ni_dpm.c +++ b/drivers/gpu/drm/radeon/ni_dpm.c @@ -2239,8 +2239,12 @@ static int ni_populate_mclk_value(struct radeon_device *rdev, ASIC_INTERNAL_MEMORY_SS, vco_freq)) { u32 reference_clock = rdev->clock.mpll.reference_freq; u32 decoded_ref = rv740_get_decoded_reference_divider(dividers.ref_div); - u32 clk_s = reference_clock * 5 / (decoded_ref * ss.rate); - u32 clk_v = ss.percentage * + u32 clk_s, clk_v; + + if (!decoded_ref) + return -EINVAL; + clk_s = reference_clock * 5 / (decoded_ref * ss.rate); + clk_v = ss.percentage * (0x4000 * dividers.whole_fb_div + 0x800 * dividers.frac_fb_div) / (clk_s * 625); mpll_ss1 &= ~CLKV_MASK; diff --git a/drivers/gpu/drm/radeon/rv740_dpm.c b/drivers/gpu/drm/radeon/rv740_dpm.c index afd597ec50858..50290e93c79dc 100644 --- a/drivers/gpu/drm/radeon/rv740_dpm.c +++ b/drivers/gpu/drm/radeon/rv740_dpm.c @@ -251,8 +251,12 @@ int rv740_populate_mclk_value(struct radeon_device *rdev, ASIC_INTERNAL_MEMORY_SS, vco_freq)) { u32 reference_clock = rdev->clock.mpll.reference_freq; u32 decoded_ref = rv740_get_decoded_reference_divider(dividers.ref_div); - u32 clk_s = reference_clock * 5 / (decoded_ref * ss.rate); - u32 clk_v = 0x40000 * ss.percentage * + u32 clk_s, clk_v; + + if (!decoded_ref) + return -EINVAL; + clk_s = reference_clock * 5 / (decoded_ref * ss.rate); + clk_v = 0x40000 * ss.percentage * (dividers.whole_fb_div + (dividers.frac_fb_div / 8)) / (clk_s * 10000); mpll_ss1 &= ~CLKV_MASK; diff --git a/drivers/hwmon/nct7802.c b/drivers/hwmon/nct7802.c index 779ec8fdfae08..56dd2d6ba9e49 100644 --- a/drivers/hwmon/nct7802.c +++ b/drivers/hwmon/nct7802.c @@ -698,7 +698,7 @@ static umode_t nct7802_temp_is_visible(struct kobject *kobj, if (index >= 38 && index < 46 && !(reg & 0x01)) /* PECI 0 */ return 0; - if (index >= 0x46 && (!(reg & 0x02))) /* PECI 1 */ + if (index >= 46 && !(reg & 0x02)) /* PECI 1 */ return 0; return attr->mode; diff --git a/drivers/i2c/busses/i2c-rk3x.c b/drivers/i2c/busses/i2c-rk3x.c index 61ab462fd94cf..fe7642b916cfc 100644 --- a/drivers/i2c/busses/i2c-rk3x.c +++ b/drivers/i2c/busses/i2c-rk3x.c @@ -421,7 +421,7 @@ static void rk3x_i2c_handle_read(struct rk3x_i2c *i2c, unsigned int ipd) { unsigned int i; unsigned int len = i2c->msg->len - i2c->processed; - u32 uninitialized_var(val); + u32 val; u8 byte; /* we only care for MBRF here. */ diff --git a/drivers/i2c/busses/i2c-xiic.c b/drivers/i2c/busses/i2c-xiic.c index 03ce9b7d6456a..c1f85114ab812 100644 --- a/drivers/i2c/busses/i2c-xiic.c +++ b/drivers/i2c/busses/i2c-xiic.c @@ -362,6 +362,9 @@ static irqreturn_t xiic_process(int irq, void *dev_id) struct xiic_i2c *i2c = dev_id; u32 pend, isr, ier; u32 clr = 0; + int xfer_more = 0; + int wakeup_req = 0; + int wakeup_code = 0; /* Get the interrupt Status from the IPIF. There is no clearing of * interrupts in the IPIF. Interrupts must be cleared at the source. @@ -398,10 +401,16 @@ static irqreturn_t xiic_process(int irq, void *dev_id) */ xiic_reinit(i2c); - if (i2c->rx_msg) - xiic_wakeup(i2c, STATE_ERROR); - if (i2c->tx_msg) - xiic_wakeup(i2c, STATE_ERROR); + if (i2c->rx_msg) { + wakeup_req = 1; + wakeup_code = STATE_ERROR; + } + if (i2c->tx_msg) { + wakeup_req = 1; + wakeup_code = STATE_ERROR; + } + /* don't try to handle other events */ + goto out; } if (pend & XIIC_INTR_RX_FULL_MASK) { /* Receive register/FIFO is full */ @@ -435,8 +444,7 @@ static irqreturn_t xiic_process(int irq, void *dev_id) i2c->tx_msg++; dev_dbg(i2c->adap.dev.parent, "%s will start next...\n", __func__); - - __xiic_start_xfer(i2c); + xfer_more = 1; } } } @@ -450,11 +458,13 @@ static irqreturn_t xiic_process(int irq, void *dev_id) if (!i2c->tx_msg) goto out; - if ((i2c->nmsgs == 1) && !i2c->rx_msg && - xiic_tx_space(i2c) == 0) - xiic_wakeup(i2c, STATE_DONE); + wakeup_req = 1; + + if (i2c->nmsgs == 1 && !i2c->rx_msg && + xiic_tx_space(i2c) == 0) + wakeup_code = STATE_DONE; else - xiic_wakeup(i2c, STATE_ERROR); + wakeup_code = STATE_ERROR; } if (pend & (XIIC_INTR_TX_EMPTY_MASK | XIIC_INTR_TX_HALF_MASK)) { /* Transmit register/FIFO is empty or ½ empty */ @@ -478,7 +488,7 @@ static irqreturn_t xiic_process(int irq, void *dev_id) if (i2c->nmsgs > 1) { i2c->nmsgs--; i2c->tx_msg++; - __xiic_start_xfer(i2c); + xfer_more = 1; } else { xiic_irq_dis(i2c, XIIC_INTR_TX_HALF_MASK); @@ -496,6 +506,13 @@ out: dev_dbg(i2c->adap.dev.parent, "%s clr: 0x%x\n", __func__, clr); xiic_setreg32(i2c, XIIC_IISR_OFFSET, clr); + if (xfer_more) + __xiic_start_xfer(i2c); + if (wakeup_req) + xiic_wakeup(i2c, wakeup_code); + + WARN_ON(xfer_more && wakeup_req); + mutex_unlock(&i2c->lock); return IRQ_HANDLED; } diff --git a/drivers/ide/ide-acpi.c b/drivers/ide/ide-acpi.c index 7d4e5c08f133e..05e18d6581416 100644 --- a/drivers/ide/ide-acpi.c +++ b/drivers/ide/ide-acpi.c @@ -180,7 +180,7 @@ err: static acpi_handle ide_acpi_hwif_get_handle(ide_hwif_t *hwif) { struct device *dev = hwif->gendev.parent; - acpi_handle uninitialized_var(dev_handle); + acpi_handle dev_handle; u64 pcidevfn; acpi_handle chan_handle; int err; diff --git a/drivers/ide/ide-atapi.c b/drivers/ide/ide-atapi.c index 4224c4dd89635..9a4c094c897c3 100644 --- a/drivers/ide/ide-atapi.c +++ b/drivers/ide/ide-atapi.c @@ -591,7 +591,7 @@ static int ide_delayed_transfer_pc(ide_drive_t *drive) static ide_startstop_t ide_transfer_pc(ide_drive_t *drive) { - struct ide_atapi_pc *uninitialized_var(pc); + struct ide_atapi_pc *pc; ide_hwif_t *hwif = drive->hwif; struct request *rq = hwif->rq; ide_expiry_t *expiry; diff --git a/drivers/ide/ide-io-std.c b/drivers/ide/ide-io-std.c index 19763977568c5..508f98ca3fe87 100644 --- a/drivers/ide/ide-io-std.c +++ b/drivers/ide/ide-io-std.c @@ -172,7 +172,7 @@ void ide_input_data(ide_drive_t *drive, struct ide_cmd *cmd, void *buf, u8 mmio = (hwif->host_flags & IDE_HFLAG_MMIO) ? 1 : 0; if (io_32bit) { - unsigned long uninitialized_var(flags); + unsigned long flags; if ((io_32bit & 2) && !mmio) { local_irq_save(flags); @@ -216,7 +216,7 @@ void ide_output_data(ide_drive_t *drive, struct ide_cmd *cmd, void *buf, u8 mmio = (hwif->host_flags & IDE_HFLAG_MMIO) ? 1 : 0; if (io_32bit) { - unsigned long uninitialized_var(flags); + unsigned long flags; if ((io_32bit & 2) && !mmio) { local_irq_save(flags); diff --git a/drivers/ide/ide-io.c b/drivers/ide/ide-io.c index 4381760846109..a01cc01244422 100644 --- a/drivers/ide/ide-io.c +++ b/drivers/ide/ide-io.c @@ -605,12 +605,12 @@ static int drive_is_ready(ide_drive_t *drive) void ide_timer_expiry (struct timer_list *t) { ide_hwif_t *hwif = from_timer(hwif, t, timer); - ide_drive_t *uninitialized_var(drive); + ide_drive_t *drive; ide_handler_t *handler; unsigned long flags; int wait = -1; int plug_device = 0; - struct request *uninitialized_var(rq_in_flight); + struct request *rq_in_flight; spin_lock_irqsave(&hwif->lock, flags); @@ -763,13 +763,13 @@ irqreturn_t ide_intr (int irq, void *dev_id) { ide_hwif_t *hwif = (ide_hwif_t *)dev_id; struct ide_host *host = hwif->host; - ide_drive_t *uninitialized_var(drive); + ide_drive_t *drive; ide_handler_t *handler; unsigned long flags; ide_startstop_t startstop; irqreturn_t irq_ret = IRQ_NONE; int plug_device = 0; - struct request *uninitialized_var(rq_in_flight); + struct request *rq_in_flight; if (host->host_flags & IDE_HFLAG_SERIALIZE) { if (hwif != host->cur_port) diff --git a/drivers/ide/ide-sysfs.c b/drivers/ide/ide-sysfs.c index b9dfeb2e8bd66..c08a8a0916e22 100644 --- a/drivers/ide/ide-sysfs.c +++ b/drivers/ide/ide-sysfs.c @@ -131,7 +131,7 @@ static struct device_attribute *ide_port_attrs[] = { int ide_sysfs_register_port(ide_hwif_t *hwif) { - int i, uninitialized_var(rc); + int i, rc; for (i = 0; ide_port_attrs[i]; i++) { rc = device_create_file(hwif->portdev, ide_port_attrs[i]); diff --git a/drivers/ide/umc8672.c b/drivers/ide/umc8672.c index 3aa0fea0f3d9c..1414caa97b401 100644 --- a/drivers/ide/umc8672.c +++ b/drivers/ide/umc8672.c @@ -107,7 +107,7 @@ static void umc_set_speeds(u8 speeds[]) static void umc_set_pio_mode(ide_hwif_t *hwif, ide_drive_t *drive) { ide_hwif_t *mate = hwif->mate; - unsigned long uninitialized_var(flags); + unsigned long flags; const u8 pio = drive->pio_mode - XFER_PIO_0; printk("%s: setting umc8672 to PIO mode%d (speed %d)\n", diff --git a/drivers/iio/adc/meson_saradc.c b/drivers/iio/adc/meson_saradc.c index 6e0ef9bb2497f..c448769357501 100644 --- a/drivers/iio/adc/meson_saradc.c +++ b/drivers/iio/adc/meson_saradc.c @@ -75,7 +75,7 @@ #define MESON_SAR_ADC_REG3_PANEL_DETECT_COUNT_MASK GENMASK(20, 18) #define MESON_SAR_ADC_REG3_PANEL_DETECT_FILTER_TB_MASK GENMASK(17, 16) #define MESON_SAR_ADC_REG3_ADC_CLK_DIV_SHIFT 10 - #define MESON_SAR_ADC_REG3_ADC_CLK_DIV_WIDTH 5 + #define MESON_SAR_ADC_REG3_ADC_CLK_DIV_WIDTH 6 #define MESON_SAR_ADC_REG3_BLOCK_DLY_SEL_MASK GENMASK(9, 8) #define MESON_SAR_ADC_REG3_BLOCK_DLY_MASK GENMASK(7, 0) diff --git a/drivers/infiniband/core/uverbs_cmd.c b/drivers/infiniband/core/uverbs_cmd.c index d28e6f6ad497c..3b287a51cd626 100644 --- a/drivers/infiniband/core/uverbs_cmd.c +++ b/drivers/infiniband/core/uverbs_cmd.c @@ -1726,7 +1726,7 @@ ssize_t ib_uverbs_open_qp(struct ib_uverbs_file *file, struct ib_udata udata; struct ib_uqp_object *obj; struct ib_xrcd *xrcd; - struct ib_uobject *uninitialized_var(xrcd_uobj); + struct ib_uobject *xrcd_uobj; struct ib_qp *qp; struct ib_qp_open_attr attr; int ret; @@ -3694,7 +3694,7 @@ static int __uverbs_create_xsrq(struct ib_uverbs_file *file, struct ib_usrq_object *obj; struct ib_pd *pd; struct ib_srq *srq; - struct ib_uobject *uninitialized_var(xrcd_uobj); + struct ib_uobject *xrcd_uobj; struct ib_srq_init_attr attr; int ret; struct ib_device *ib_dev; diff --git a/drivers/infiniband/hw/cxgb4/cm.c b/drivers/infiniband/hw/cxgb4/cm.c index 6c1a093b164e0..a252b13958b3b 100644 --- a/drivers/infiniband/hw/cxgb4/cm.c +++ b/drivers/infiniband/hw/cxgb4/cm.c @@ -3195,7 +3195,7 @@ static int get_lladdr(struct net_device *dev, struct in6_addr *addr, static int pick_local_ip6addrs(struct c4iw_dev *dev, struct iw_cm_id *cm_id) { - struct in6_addr uninitialized_var(addr); + struct in6_addr addr; struct sockaddr_in6 *la6 = (struct sockaddr_in6 *)&cm_id->m_local_addr; struct sockaddr_in6 *ra6 = (struct sockaddr_in6 *)&cm_id->m_remote_addr; diff --git a/drivers/infiniband/hw/cxgb4/cq.c b/drivers/infiniband/hw/cxgb4/cq.c index 43c611aa068c7..8f30d477ab769 100644 --- a/drivers/infiniband/hw/cxgb4/cq.c +++ b/drivers/infiniband/hw/cxgb4/cq.c @@ -755,7 +755,7 @@ skip_cqe: static int __c4iw_poll_cq_one(struct c4iw_cq *chp, struct c4iw_qp *qhp, struct ib_wc *wc, struct c4iw_srq *srq) { - struct t4_cqe uninitialized_var(cqe); + struct t4_cqe cqe; struct t4_wq *wq = qhp ? &qhp->wq : NULL; u32 credit = 0; u8 cqe_flushed; diff --git a/drivers/infiniband/hw/hfi1/sdma.c b/drivers/infiniband/hw/hfi1/sdma.c index 33ff9eca28f69..245f9505a9aca 100644 --- a/drivers/infiniband/hw/hfi1/sdma.c +++ b/drivers/infiniband/hw/hfi1/sdma.c @@ -3202,8 +3202,7 @@ int _pad_sdma_tx_descs(struct hfi1_devdata *dd, struct sdma_txreq *tx) { int rval = 0; - tx->num_desc++; - if ((unlikely(tx->num_desc == tx->desc_limit))) { + if ((unlikely(tx->num_desc + 1 == tx->desc_limit))) { rval = _extend_sdma_tx_descs(dd, tx); if (rval) { __sdma_txclean(dd, tx); @@ -3216,6 +3215,7 @@ int _pad_sdma_tx_descs(struct hfi1_devdata *dd, struct sdma_txreq *tx) SDMA_MAP_NONE, dd->sdma_pad_phys, sizeof(u32) - (tx->packet_len & (sizeof(u32) - 1))); + tx->num_desc++; _sdma_close_tx(dd, tx); return rval; } diff --git a/drivers/infiniband/hw/hfi1/sdma.h b/drivers/infiniband/hw/hfi1/sdma.h index 46c775f255d14..a3dd2f3d56cca 100644 --- a/drivers/infiniband/hw/hfi1/sdma.h +++ b/drivers/infiniband/hw/hfi1/sdma.h @@ -680,14 +680,13 @@ static inline void sdma_txclean(struct hfi1_devdata *dd, struct sdma_txreq *tx) static inline void _sdma_close_tx(struct hfi1_devdata *dd, struct sdma_txreq *tx) { - tx->descp[tx->num_desc].qw[0] |= - SDMA_DESC0_LAST_DESC_FLAG; - tx->descp[tx->num_desc].qw[1] |= - dd->default_desc1; + u16 last_desc = tx->num_desc - 1; + + tx->descp[last_desc].qw[0] |= SDMA_DESC0_LAST_DESC_FLAG; + tx->descp[last_desc].qw[1] |= dd->default_desc1; if (tx->flags & SDMA_TXREQ_F_URGENT) - tx->descp[tx->num_desc].qw[1] |= - (SDMA_DESC1_HEAD_TO_HOST_FLAG | - SDMA_DESC1_INT_REQ_FLAG); + tx->descp[last_desc].qw[1] |= (SDMA_DESC1_HEAD_TO_HOST_FLAG | + SDMA_DESC1_INT_REQ_FLAG); } static inline int _sdma_txadd_daddr( @@ -704,6 +703,7 @@ static inline int _sdma_txadd_daddr( type, addr, len); WARN_ON(len > tx->tlen); + tx->num_desc++; tx->tlen -= len; /* special cases for last */ if (!tx->tlen) { @@ -715,7 +715,6 @@ static inline int _sdma_txadd_daddr( _sdma_close_tx(dd, tx); } } - tx->num_desc++; return rval; } diff --git a/drivers/infiniband/hw/mlx4/qp.c b/drivers/infiniband/hw/mlx4/qp.c index 87358b8c45589..b48596e174d65 100644 --- a/drivers/infiniband/hw/mlx4/qp.c +++ b/drivers/infiniband/hw/mlx4/qp.c @@ -554,15 +554,15 @@ static int set_qp_rss(struct mlx4_ib_dev *dev, struct mlx4_ib_rss *rss_ctx, return (-EOPNOTSUPP); } - if (ucmd->rx_hash_fields_mask & ~(MLX4_IB_RX_HASH_SRC_IPV4 | - MLX4_IB_RX_HASH_DST_IPV4 | - MLX4_IB_RX_HASH_SRC_IPV6 | - MLX4_IB_RX_HASH_DST_IPV6 | - MLX4_IB_RX_HASH_SRC_PORT_TCP | - MLX4_IB_RX_HASH_DST_PORT_TCP | - MLX4_IB_RX_HASH_SRC_PORT_UDP | - MLX4_IB_RX_HASH_DST_PORT_UDP | - MLX4_IB_RX_HASH_INNER)) { + if (ucmd->rx_hash_fields_mask & ~(u64)(MLX4_IB_RX_HASH_SRC_IPV4 | + MLX4_IB_RX_HASH_DST_IPV4 | + MLX4_IB_RX_HASH_SRC_IPV6 | + MLX4_IB_RX_HASH_DST_IPV6 | + MLX4_IB_RX_HASH_SRC_PORT_TCP | + MLX4_IB_RX_HASH_DST_PORT_TCP | + MLX4_IB_RX_HASH_SRC_PORT_UDP | + MLX4_IB_RX_HASH_DST_PORT_UDP | + MLX4_IB_RX_HASH_INNER)) { pr_debug("RX Hash fields_mask has unsupported mask (0x%llx)\n", ucmd->rx_hash_fields_mask); return (-EOPNOTSUPP); @@ -3463,11 +3463,11 @@ static int _mlx4_ib_post_send(struct ib_qp *ibqp, const struct ib_send_wr *wr, int nreq; int err = 0; unsigned ind; - int uninitialized_var(size); - unsigned uninitialized_var(seglen); + int size; + unsigned seglen; __be32 dummy; __be32 *lso_wqe; - __be32 uninitialized_var(lso_hdr_sz); + __be32 lso_hdr_sz; __be32 blh; int i; struct mlx4_ib_dev *mdev = to_mdev(ibqp->device); diff --git a/drivers/infiniband/hw/mlx5/cq.c b/drivers/infiniband/hw/mlx5/cq.c index 872985e4eebec..c5d3fe256182f 100644 --- a/drivers/infiniband/hw/mlx5/cq.c +++ b/drivers/infiniband/hw/mlx5/cq.c @@ -1333,7 +1333,7 @@ int mlx5_ib_resize_cq(struct ib_cq *ibcq, int entries, struct ib_udata *udata) __be64 *pas; int page_shift; int inlen; - int uninitialized_var(cqe_size); + int cqe_size; unsigned long flags; if (!MLX5_CAP_GEN(dev->mdev, cq_resize)) { diff --git a/drivers/infiniband/hw/mthca/mthca_qp.c b/drivers/infiniband/hw/mthca/mthca_qp.c index 3d37f2373d63a..a336f69c2653a 100644 --- a/drivers/infiniband/hw/mthca/mthca_qp.c +++ b/drivers/infiniband/hw/mthca/mthca_qp.c @@ -1630,8 +1630,8 @@ int mthca_tavor_post_send(struct ib_qp *ibqp, const struct ib_send_wr *wr, * without initializing f0 and size0, and they are in fact * never used uninitialized. */ - int uninitialized_var(size0); - u32 uninitialized_var(f0); + int size0; + u32 f0; int ind; u8 op0 = 0; @@ -1831,7 +1831,7 @@ int mthca_tavor_post_receive(struct ib_qp *ibqp, const struct ib_recv_wr *wr, * without initializing size0, and it is in fact never used * uninitialized. */ - int uninitialized_var(size0); + int size0; int ind; void *wqe; void *prev_wqe; @@ -1945,8 +1945,8 @@ int mthca_arbel_post_send(struct ib_qp *ibqp, const struct ib_send_wr *wr, * without initializing f0 and size0, and they are in fact * never used uninitialized. */ - int uninitialized_var(size0); - u32 uninitialized_var(f0); + int size0; + u32 f0; int ind; u8 op0 = 0; diff --git a/drivers/input/misc/adxl34x.c b/drivers/input/misc/adxl34x.c index 3695dd7dbb9b4..ec0c91ec52277 100644 --- a/drivers/input/misc/adxl34x.c +++ b/drivers/input/misc/adxl34x.c @@ -811,8 +811,7 @@ struct adxl34x *adxl34x_probe(struct device *dev, int irq, AC_WRITE(ac, POWER_CTL, 0); err = request_threaded_irq(ac->irq, NULL, adxl34x_irq, - IRQF_TRIGGER_HIGH | IRQF_ONESHOT, - dev_name(dev), ac); + IRQF_ONESHOT, dev_name(dev), ac); if (err) { dev_err(dev, "irq %d busy?\n", ac->irq); goto err_free_mem; diff --git a/drivers/input/misc/drv260x.c b/drivers/input/misc/drv260x.c index 17eb84ab4c0b7..fe3fbde989be2 100644 --- a/drivers/input/misc/drv260x.c +++ b/drivers/input/misc/drv260x.c @@ -443,6 +443,7 @@ static int drv260x_init(struct drv260x_data *haptics) } do { + usleep_range(15000, 15500); error = regmap_read(haptics->regmap, DRV260X_GO, &cal_buf); if (error) { dev_err(&haptics->client->dev, diff --git a/drivers/input/serio/serio_raw.c b/drivers/input/serio/serio_raw.c index 17b7fbecd9fe7..d25059672323d 100644 --- a/drivers/input/serio/serio_raw.c +++ b/drivers/input/serio/serio_raw.c @@ -162,7 +162,7 @@ static ssize_t serio_raw_read(struct file *file, char __user *buffer, { struct serio_raw_client *client = file->private_data; struct serio_raw *serio_raw = client->serio_raw; - char uninitialized_var(c); + char c; ssize_t read = 0; int error; diff --git a/drivers/irqchip/irq-bcm6345-l1.c b/drivers/irqchip/irq-bcm6345-l1.c index 31ea6332ecb83..60dc64b4ac6d2 100644 --- a/drivers/irqchip/irq-bcm6345-l1.c +++ b/drivers/irqchip/irq-bcm6345-l1.c @@ -85,6 +85,7 @@ struct bcm6345_l1_chip { }; struct bcm6345_l1_cpu { + struct bcm6345_l1_chip *intc; void __iomem *map_base; unsigned int parent_irq; u32 enable_cache[]; @@ -118,17 +119,11 @@ static inline unsigned int cpu_for_irq(struct bcm6345_l1_chip *intc, static void bcm6345_l1_irq_handle(struct irq_desc *desc) { - struct bcm6345_l1_chip *intc = irq_desc_get_handler_data(desc); - struct bcm6345_l1_cpu *cpu; + struct bcm6345_l1_cpu *cpu = irq_desc_get_handler_data(desc); + struct bcm6345_l1_chip *intc = cpu->intc; struct irq_chip *chip = irq_desc_get_chip(desc); unsigned int idx; -#ifdef CONFIG_SMP - cpu = intc->cpus[cpu_logical_map(smp_processor_id())]; -#else - cpu = intc->cpus[0]; -#endif - chained_irq_enter(chip, desc); for (idx = 0; idx < intc->n_words; idx++) { @@ -260,6 +255,7 @@ static int __init bcm6345_l1_init_one(struct device_node *dn, if (!cpu) return -ENOMEM; + cpu->intc = intc; cpu->map_base = ioremap(res.start, sz); if (!cpu->map_base) return -ENOMEM; @@ -275,7 +271,7 @@ static int __init bcm6345_l1_init_one(struct device_node *dn, return -EINVAL; } irq_set_chained_handler_and_data(cpu->parent_irq, - bcm6345_l1_irq_handle, intc); + bcm6345_l1_irq_handle, cpu); return 0; } diff --git a/drivers/irqchip/irq-jcore-aic.c b/drivers/irqchip/irq-jcore-aic.c index 033bccb41455c..b9dcc8e78c750 100644 --- a/drivers/irqchip/irq-jcore-aic.c +++ b/drivers/irqchip/irq-jcore-aic.c @@ -68,6 +68,7 @@ static int __init aic_irq_of_init(struct device_node *node, unsigned min_irq = JCORE_AIC2_MIN_HWIRQ; unsigned dom_sz = JCORE_AIC_MAX_HWIRQ+1; struct irq_domain *domain; + int ret; pr_info("Initializing J-Core AIC\n"); @@ -100,11 +101,17 @@ static int __init aic_irq_of_init(struct device_node *node, jcore_aic.irq_unmask = noop; jcore_aic.name = "AIC"; - domain = irq_domain_add_linear(node, dom_sz, &jcore_aic_irqdomain_ops, + ret = irq_alloc_descs(-1, min_irq, dom_sz - min_irq, + of_node_to_nid(node)); + + if (ret < 0) + return ret; + + domain = irq_domain_add_legacy(node, dom_sz - min_irq, min_irq, min_irq, + &jcore_aic_irqdomain_ops, &jcore_aic); if (!domain) return -ENOMEM; - irq_create_strict_mappings(domain, min_irq, min_irq, dom_sz - min_irq); return 0; } diff --git a/drivers/mailbox/ti-msgmgr.c b/drivers/mailbox/ti-msgmgr.c index 01e9e462512b7..eb1e9771037f2 100644 --- a/drivers/mailbox/ti-msgmgr.c +++ b/drivers/mailbox/ti-msgmgr.c @@ -385,14 +385,20 @@ static int ti_msgmgr_send_data(struct mbox_chan *chan, void *data) /* Ensure all unused data is 0 */ data_trail &= 0xFFFFFFFF >> (8 * (sizeof(u32) - trail_bytes)); writel(data_trail, data_reg); - data_reg++; + data_reg += sizeof(u32); } + /* * 'data_reg' indicates next register to write. If we did not already * write on tx complete reg(last reg), we must do so for transmit + * In addition, we also need to make sure all intermediate data + * registers(if any required), are reset to 0 for TISCI backward + * compatibility to be maintained. */ - if (data_reg <= qinst->queue_buff_end) - writel(0, qinst->queue_buff_end); + while (data_reg <= qinst->queue_buff_end) { + writel(0, data_reg); + data_reg += sizeof(u32); + } return 0; } diff --git a/drivers/md/bcache/alloc.c b/drivers/md/bcache/alloc.c index 46794cac167e7..5310e1f4a2826 100644 --- a/drivers/md/bcache/alloc.c +++ b/drivers/md/bcache/alloc.c @@ -49,7 +49,7 @@ * * bch_bucket_alloc() allocates a single bucket from a specific cache. * - * bch_bucket_alloc_set() allocates one or more buckets from different caches + * bch_bucket_alloc_set() allocates one bucket from different caches * out of a cache set. * * free_some_buckets() drives all the processes described above. It's called @@ -488,34 +488,29 @@ void bch_bucket_free(struct cache_set *c, struct bkey *k) } int __bch_bucket_alloc_set(struct cache_set *c, unsigned int reserve, - struct bkey *k, int n, bool wait) + struct bkey *k, bool wait) { - int i; + struct cache *ca; + long b; /* No allocation if CACHE_SET_IO_DISABLE bit is set */ if (unlikely(test_bit(CACHE_SET_IO_DISABLE, &c->flags))) return -1; lockdep_assert_held(&c->bucket_lock); - BUG_ON(!n || n > c->caches_loaded || n > 8); bkey_init(k); - /* sort by free space/prio of oldest data in caches */ - - for (i = 0; i < n; i++) { - struct cache *ca = c->cache_by_alloc[i]; - long b = bch_bucket_alloc(ca, reserve, wait); + ca = c->cache_by_alloc[0]; + b = bch_bucket_alloc(ca, reserve, wait); + if (b == -1) + goto err; - if (b == -1) - goto err; + k->ptr[0] = MAKE_PTR(ca->buckets[b].gen, + bucket_to_sector(c, b), + ca->sb.nr_this_dev); - k->ptr[i] = MAKE_PTR(ca->buckets[b].gen, - bucket_to_sector(c, b), - ca->sb.nr_this_dev); - - SET_KEY_PTRS(k, i + 1); - } + SET_KEY_PTRS(k, 1); return 0; err: @@ -525,12 +520,12 @@ err: } int bch_bucket_alloc_set(struct cache_set *c, unsigned int reserve, - struct bkey *k, int n, bool wait) + struct bkey *k, bool wait) { int ret; mutex_lock(&c->bucket_lock); - ret = __bch_bucket_alloc_set(c, reserve, k, n, wait); + ret = __bch_bucket_alloc_set(c, reserve, k, wait); mutex_unlock(&c->bucket_lock); return ret; } @@ -638,7 +633,7 @@ bool bch_alloc_sectors(struct cache_set *c, spin_unlock(&c->data_bucket_lock); - if (bch_bucket_alloc_set(c, watermark, &alloc.key, 1, wait)) + if (bch_bucket_alloc_set(c, watermark, &alloc.key, wait)) return false; spin_lock(&c->data_bucket_lock); diff --git a/drivers/md/bcache/bcache.h b/drivers/md/bcache/bcache.h index 6a380ed4919a0..e81d783109847 100644 --- a/drivers/md/bcache/bcache.h +++ b/drivers/md/bcache/bcache.h @@ -952,9 +952,9 @@ void bch_bucket_free(struct cache_set *c, struct bkey *k); long bch_bucket_alloc(struct cache *ca, unsigned int reserve, bool wait); int __bch_bucket_alloc_set(struct cache_set *c, unsigned int reserve, - struct bkey *k, int n, bool wait); + struct bkey *k, bool wait); int bch_bucket_alloc_set(struct cache_set *c, unsigned int reserve, - struct bkey *k, int n, bool wait); + struct bkey *k, bool wait); bool bch_alloc_sectors(struct cache_set *c, struct bkey *k, unsigned int sectors, unsigned int write_point, unsigned int write_prio, bool wait); diff --git a/drivers/md/bcache/btree.c b/drivers/md/bcache/btree.c index e388e7bb7b5db..71d670934a07e 100644 --- a/drivers/md/bcache/btree.c +++ b/drivers/md/bcache/btree.c @@ -1125,11 +1125,13 @@ struct btree *__bch_btree_node_alloc(struct cache_set *c, struct btree_op *op, struct btree *parent) { BKEY_PADDED(key) k; - struct btree *b = ERR_PTR(-EAGAIN); + struct btree *b; mutex_lock(&c->bucket_lock); retry: - if (__bch_bucket_alloc_set(c, RESERVE_BTREE, &k.key, 1, wait)) + /* return ERR_PTR(-EAGAIN) when it fails */ + b = ERR_PTR(-EAGAIN); + if (__bch_bucket_alloc_set(c, RESERVE_BTREE, &k.key, wait)) goto err; bkey_put(c, &k.key); @@ -1174,7 +1176,7 @@ static struct btree *btree_node_alloc_replacement(struct btree *b, { struct btree *n = bch_btree_node_alloc(b->c, op, b->level, b->parent); - if (!IS_ERR_OR_NULL(n)) { + if (!IS_ERR(n)) { mutex_lock(&n->write_lock); bch_btree_sort_into(&b->keys, &n->keys, &b->c->sort); bkey_copy_key(&n->key, &b->key); @@ -1377,7 +1379,7 @@ static int btree_gc_coalesce(struct btree *b, struct btree_op *op, memset(new_nodes, 0, sizeof(new_nodes)); closure_init_stack(&cl); - while (nodes < GC_MERGE_NODES && !IS_ERR_OR_NULL(r[nodes].b)) + while (nodes < GC_MERGE_NODES && !IS_ERR(r[nodes].b)) keys += r[nodes++].keys; blocks = btree_default_blocks(b->c) * 2 / 3; @@ -1389,7 +1391,7 @@ static int btree_gc_coalesce(struct btree *b, struct btree_op *op, for (i = 0; i < nodes; i++) { new_nodes[i] = btree_node_alloc_replacement(r[i].b, NULL); - if (IS_ERR_OR_NULL(new_nodes[i])) + if (IS_ERR(new_nodes[i])) goto out_nocoalesce; } @@ -1524,7 +1526,7 @@ out_nocoalesce: atomic_dec(&b->c->prio_blocked); for (i = 0; i < nodes; i++) - if (!IS_ERR_OR_NULL(new_nodes[i])) { + if (!IS_ERR(new_nodes[i])) { btree_node_free(new_nodes[i]); rw_unlock(true, new_nodes[i]); } @@ -1706,7 +1708,7 @@ static int bch_btree_gc_root(struct btree *b, struct btree_op *op, if (should_rewrite) { n = btree_node_alloc_replacement(b, NULL); - if (!IS_ERR_OR_NULL(n)) { + if (!IS_ERR(n)) { bch_btree_node_write_sync(n); bch_btree_set_root(n); diff --git a/drivers/md/bcache/super.c b/drivers/md/bcache/super.c index 2df75db52e917..4b076f7f184be 100644 --- a/drivers/md/bcache/super.c +++ b/drivers/md/bcache/super.c @@ -423,7 +423,7 @@ static int __uuid_write(struct cache_set *c) closure_init_stack(&cl); lockdep_assert_held(&bch_register_lock); - if (bch_bucket_alloc_set(c, RESERVE_BTREE, &k.key, 1, true)) + if (bch_bucket_alloc_set(c, RESERVE_BTREE, &k.key, true)) return 1; SET_KEY_SIZE(&k.key, c->sb.bucket_size); @@ -1576,7 +1576,7 @@ static void cache_set_flush(struct closure *cl) if (!IS_ERR_OR_NULL(c->gc_thread)) kthread_stop(c->gc_thread); - if (!IS_ERR_OR_NULL(c->root)) + if (!IS_ERR(c->root)) list_add(&c->root->list, &c->btree_cache); /* Should skip this if we're unregistering because of an error */ @@ -1921,7 +1921,7 @@ static int run_cache_set(struct cache_set *c) err = "cannot allocate new btree root"; c->root = __bch_btree_node_alloc(c, NULL, 0, true, NULL); - if (IS_ERR_OR_NULL(c->root)) + if (IS_ERR(c->root)) goto err; mutex_lock(&c->root->write_lock); diff --git a/drivers/md/dm-cache-policy-smq.c b/drivers/md/dm-cache-policy-smq.c index 1b5b9ad9e492f..6030193b216eb 100644 --- a/drivers/md/dm-cache-policy-smq.c +++ b/drivers/md/dm-cache-policy-smq.c @@ -854,7 +854,13 @@ struct smq_policy { struct background_tracker *bg_work; - bool migrations_allowed; + bool migrations_allowed:1; + + /* + * If this is set the policy will try and clean the whole cache + * even if the device is not idle. + */ + bool cleaner:1; }; /*----------------------------------------------------------------*/ @@ -1133,7 +1139,7 @@ static bool clean_target_met(struct smq_policy *mq, bool idle) * Cache entries may not be populated. So we cannot rely on the * size of the clean queue. */ - if (idle) { + if (idle || mq->cleaner) { /* * We'd like to clean everything. */ @@ -1716,11 +1722,9 @@ static void calc_hotspot_params(sector_t origin_size, *hotspot_block_size /= 2u; } -static struct dm_cache_policy *__smq_create(dm_cblock_t cache_size, - sector_t origin_size, - sector_t cache_block_size, - bool mimic_mq, - bool migrations_allowed) +static struct dm_cache_policy * +__smq_create(dm_cblock_t cache_size, sector_t origin_size, sector_t cache_block_size, + bool mimic_mq, bool migrations_allowed, bool cleaner) { unsigned i; unsigned nr_sentinels_per_queue = 2u * NR_CACHE_LEVELS; @@ -1807,6 +1811,7 @@ static struct dm_cache_policy *__smq_create(dm_cblock_t cache_size, goto bad_btracker; mq->migrations_allowed = migrations_allowed; + mq->cleaner = cleaner; return &mq->policy; @@ -1830,21 +1835,24 @@ static struct dm_cache_policy *smq_create(dm_cblock_t cache_size, sector_t origin_size, sector_t cache_block_size) { - return __smq_create(cache_size, origin_size, cache_block_size, false, true); + return __smq_create(cache_size, origin_size, cache_block_size, + false, true, false); } static struct dm_cache_policy *mq_create(dm_cblock_t cache_size, sector_t origin_size, sector_t cache_block_size) { - return __smq_create(cache_size, origin_size, cache_block_size, true, true); + return __smq_create(cache_size, origin_size, cache_block_size, + true, true, false); } static struct dm_cache_policy *cleaner_create(dm_cblock_t cache_size, sector_t origin_size, sector_t cache_block_size) { - return __smq_create(cache_size, origin_size, cache_block_size, false, false); + return __smq_create(cache_size, origin_size, cache_block_size, + false, false, true); } /*----------------------------------------------------------------*/ diff --git a/drivers/md/dm-io.c b/drivers/md/dm-io.c index 81ffc59d05c90..4312007d2d34b 100644 --- a/drivers/md/dm-io.c +++ b/drivers/md/dm-io.c @@ -306,7 +306,7 @@ static void do_region(int op, int op_flags, unsigned region, struct request_queue *q = bdev_get_queue(where->bdev); unsigned short logical_block_size = queue_logical_block_size(q); sector_t num_sectors; - unsigned int uninitialized_var(special_cmd_max_sectors); + unsigned int special_cmd_max_sectors; /* * Reject unsupported discard and write same requests. diff --git a/drivers/md/dm-ioctl.c b/drivers/md/dm-ioctl.c index e1603c17e346f..88e89796ccbff 100644 --- a/drivers/md/dm-ioctl.c +++ b/drivers/md/dm-ioctl.c @@ -1822,7 +1822,7 @@ static int ctl_ioctl(struct file *file, uint command, struct dm_ioctl __user *us int ioctl_flags; int param_flags; unsigned int cmd; - struct dm_ioctl *uninitialized_var(param); + struct dm_ioctl *param; ioctl_fn fn = NULL; size_t input_param_size; struct dm_ioctl param_kernel; diff --git a/drivers/md/dm-raid.c b/drivers/md/dm-raid.c index 5c45100f6d53e..72aa5097b68ff 100644 --- a/drivers/md/dm-raid.c +++ b/drivers/md/dm-raid.c @@ -3289,15 +3289,19 @@ static int raid_ctr(struct dm_target *ti, unsigned int argc, char **argv) /* Try to adjust the raid4/5/6 stripe cache size to the stripe size */ if (rs_is_raid456(rs)) { r = rs_set_raid456_stripe_cache(rs); - if (r) + if (r) { + mddev_unlock(&rs->md); goto bad_stripe_cache; + } } /* Now do an early reshape check */ if (test_bit(RT_FLAG_RESHAPE_RS, &rs->runtime_flags)) { r = rs_check_reshape(rs); - if (r) + if (r) { + mddev_unlock(&rs->md); goto bad_check_reshape; + } /* Restore new, ctr requested layout to perform check */ rs_config_restore(rs, &rs_layout); @@ -3306,6 +3310,7 @@ static int raid_ctr(struct dm_target *ti, unsigned int argc, char **argv) r = rs->md.pers->check_reshape(&rs->md); if (r) { ti->error = "Reshape check failed"; + mddev_unlock(&rs->md); goto bad_check_reshape; } } diff --git a/drivers/md/dm-snap-persistent.c b/drivers/md/dm-snap-persistent.c index 963d3774c93e2..247089c2be256 100644 --- a/drivers/md/dm-snap-persistent.c +++ b/drivers/md/dm-snap-persistent.c @@ -613,7 +613,7 @@ static int persistent_read_metadata(struct dm_exception_store *store, chunk_t old, chunk_t new), void *callback_context) { - int r, uninitialized_var(new_snapshot); + int r, new_snapshot; struct pstore *ps = get_info(store); /* diff --git a/drivers/md/dm-table.c b/drivers/md/dm-table.c index 71d3fdbce50a3..3faaf21be5b65 100644 --- a/drivers/md/dm-table.c +++ b/drivers/md/dm-table.c @@ -671,7 +671,7 @@ static int validate_hardware_logical_block_alignment(struct dm_table *table, */ unsigned short remaining = 0; - struct dm_target *uninitialized_var(ti); + struct dm_target *ti; struct queue_limits ti_limits; unsigned i; diff --git a/drivers/md/md-bitmap.c b/drivers/md/md-bitmap.c index 1c4c462787198..7ca81e917aef4 100644 --- a/drivers/md/md-bitmap.c +++ b/drivers/md/md-bitmap.c @@ -53,14 +53,7 @@ __acquires(bitmap->lock) { unsigned char *mappage; - if (page >= bitmap->pages) { - /* This can happen if bitmap_start_sync goes beyond - * End-of-device while looking for a whole page. - * It is harmless. - */ - return -EINVAL; - } - + WARN_ON_ONCE(page >= bitmap->pages); if (bitmap->bp[page].hijacked) /* it's hijacked, don't try to alloc */ return 0; @@ -1368,6 +1361,14 @@ __acquires(bitmap->lock) sector_t csize; int err; + if (page >= bitmap->pages) { + /* + * This can happen if bitmap_start_sync goes beyond + * End-of-device while looking for a whole page or + * user set a huge number to sysfs bitmap_set_bits. + */ + return NULL; + } err = md_bitmap_checkpage(bitmap, page, create, 0); if (bitmap->bp[page].hijacked || diff --git a/drivers/md/md.c b/drivers/md/md.c index f8c111b369928..6b074c2202d5a 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -3671,8 +3671,9 @@ int strict_strtoul_scaled(const char *cp, unsigned long *res, int scale) static ssize_t safe_delay_show(struct mddev *mddev, char *page) { - int msec = (mddev->safemode_delay*1000)/HZ; - return sprintf(page, "%d.%03d\n", msec/1000, msec%1000); + unsigned int msec = ((unsigned long)mddev->safemode_delay*1000)/HZ; + + return sprintf(page, "%u.%03u\n", msec/1000, msec%1000); } static ssize_t safe_delay_store(struct mddev *mddev, const char *cbuf, size_t len) @@ -3684,7 +3685,7 @@ safe_delay_store(struct mddev *mddev, const char *cbuf, size_t len) return -EINVAL; } - if (strict_strtoul_scaled(cbuf, &msec, 3) < 0) + if (strict_strtoul_scaled(cbuf, &msec, 3) < 0 || msec > UINT_MAX / HZ) return -EINVAL; if (msec == 0) mddev->safemode_delay = 0; @@ -4336,6 +4337,8 @@ max_corrected_read_errors_store(struct mddev *mddev, const char *buf, size_t len rv = kstrtouint(buf, 10, &n); if (rv < 0) return rv; + if (n > INT_MAX) + return -EINVAL; atomic_set(&mddev->max_corr_read_errors, n); return len; } @@ -4636,11 +4639,21 @@ action_store(struct mddev *mddev, const char *page, size_t len) return -EINVAL; err = mddev_lock(mddev); if (!err) { - if (test_bit(MD_RECOVERY_RUNNING, &mddev->recovery)) + if (test_bit(MD_RECOVERY_RUNNING, &mddev->recovery)) { err = -EBUSY; - else { + } else if (mddev->reshape_position == MaxSector || + mddev->pers->check_reshape == NULL || + mddev->pers->check_reshape(mddev)) { clear_bit(MD_RECOVERY_FROZEN, &mddev->recovery); err = mddev->pers->start_reshape(mddev); + } else { + /* + * If reshape is still in progress, and + * md_check_recovery() can continue to reshape, + * don't restart reshape because data can be + * corrupted for raid456. + */ + clear_bit(MD_RECOVERY_FROZEN, &mddev->recovery); } mddev_unlock(mddev); } diff --git a/drivers/md/raid0.c b/drivers/md/raid0.c index 252ef0eab41cb..6f5710e833c1b 100644 --- a/drivers/md/raid0.c +++ b/drivers/md/raid0.c @@ -296,6 +296,18 @@ static int create_strip_zones(struct mddev *mddev, struct r0conf **private_conf) goto abort; } + if (conf->layout == RAID0_ORIG_LAYOUT) { + for (i = 1; i < conf->nr_strip_zones; i++) { + sector_t first_sector = conf->strip_zone[i-1].zone_end; + + sector_div(first_sector, mddev->chunk_sectors); + zone = conf->strip_zone + i; + /* disk_shift is first disk index used in the zone */ + zone->disk_shift = sector_div(first_sector, + zone->nb_dev); + } + } + pr_debug("md/raid0:%s: done.\n", mdname(mddev)); *private_conf = conf; @@ -482,6 +494,20 @@ static inline int is_io_in_chunk_boundary(struct mddev *mddev, } } +/* + * Convert disk_index to the disk order in which it is read/written. + * For example, if we have 4 disks, they are numbered 0,1,2,3. If we + * write the disks starting at disk 3, then the read/write order would + * be disk 3, then 0, then 1, and then disk 2 and we want map_disk_shift() + * to map the disks as follows 0,1,2,3 => 1,2,3,0. So disk 0 would map + * to 1, 1 to 2, 2 to 3, and 3 to 0. That way we can compare disks in + * that 'output' space to understand the read/write disk ordering. + */ +static int map_disk_shift(int disk_index, int num_disks, int disk_shift) +{ + return ((disk_index + num_disks - disk_shift) % num_disks); +} + static void raid0_handle_discard(struct mddev *mddev, struct bio *bio) { struct r0conf *conf = mddev->private; @@ -495,7 +521,9 @@ static void raid0_handle_discard(struct mddev *mddev, struct bio *bio) sector_t end_disk_offset; unsigned int end_disk_index; unsigned int disk; + sector_t orig_start, orig_end; + orig_start = start; zone = find_zone(conf, &start); if (bio_end_sector(bio) > zone->zone_end) { @@ -509,6 +537,7 @@ static void raid0_handle_discard(struct mddev *mddev, struct bio *bio) } else end = bio_end_sector(bio); + orig_end = end; if (zone != conf->strip_zone) end = end - zone[-1].zone_end; @@ -520,13 +549,26 @@ static void raid0_handle_discard(struct mddev *mddev, struct bio *bio) last_stripe_index = end; sector_div(last_stripe_index, stripe_size); - start_disk_index = (int)(start - first_stripe_index * stripe_size) / - mddev->chunk_sectors; + /* In the first zone the original and alternate layouts are the same */ + if ((conf->layout == RAID0_ORIG_LAYOUT) && (zone != conf->strip_zone)) { + sector_div(orig_start, mddev->chunk_sectors); + start_disk_index = sector_div(orig_start, zone->nb_dev); + start_disk_index = map_disk_shift(start_disk_index, + zone->nb_dev, + zone->disk_shift); + sector_div(orig_end, mddev->chunk_sectors); + end_disk_index = sector_div(orig_end, zone->nb_dev); + end_disk_index = map_disk_shift(end_disk_index, + zone->nb_dev, zone->disk_shift); + } else { + start_disk_index = (int)(start - first_stripe_index * stripe_size) / + mddev->chunk_sectors; + end_disk_index = (int)(end - last_stripe_index * stripe_size) / + mddev->chunk_sectors; + } start_disk_offset = ((int)(start - first_stripe_index * stripe_size) % mddev->chunk_sectors) + first_stripe_index * mddev->chunk_sectors; - end_disk_index = (int)(end - last_stripe_index * stripe_size) / - mddev->chunk_sectors; end_disk_offset = ((int)(end - last_stripe_index * stripe_size) % mddev->chunk_sectors) + last_stripe_index * mddev->chunk_sectors; @@ -535,18 +577,22 @@ static void raid0_handle_discard(struct mddev *mddev, struct bio *bio) sector_t dev_start, dev_end; struct bio *discard_bio = NULL; struct md_rdev *rdev; + int compare_disk; + + compare_disk = map_disk_shift(disk, zone->nb_dev, + zone->disk_shift); - if (disk < start_disk_index) + if (compare_disk < start_disk_index) dev_start = (first_stripe_index + 1) * mddev->chunk_sectors; - else if (disk > start_disk_index) + else if (compare_disk > start_disk_index) dev_start = first_stripe_index * mddev->chunk_sectors; else dev_start = start_disk_offset; - if (disk < end_disk_index) + if (compare_disk < end_disk_index) dev_end = (last_stripe_index + 1) * mddev->chunk_sectors; - else if (disk > end_disk_index) + else if (compare_disk > end_disk_index) dev_end = last_stripe_index * mddev->chunk_sectors; else dev_end = end_disk_offset; diff --git a/drivers/md/raid0.h b/drivers/md/raid0.h index 3816e5477db1e..8cc761ca74230 100644 --- a/drivers/md/raid0.h +++ b/drivers/md/raid0.h @@ -6,6 +6,7 @@ struct strip_zone { sector_t zone_end; /* Start of the next zone (in sectors) */ sector_t dev_start; /* Zone offset in real dev (in sectors) */ int nb_dev; /* # of devices attached to the zone */ + int disk_shift; /* start disk for the original layout */ }; /* Linux 3.14 (20d0189b101) made an unintended change to diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c index f6d2be1d23864..bee694be20132 100644 --- a/drivers/md/raid10.c +++ b/drivers/md/raid10.c @@ -781,8 +781,16 @@ static struct md_rdev *read_balance(struct r10conf *conf, disk = r10_bio->devs[slot].devnum; rdev = rcu_dereference(conf->mirrors[disk].replacement); if (rdev == NULL || test_bit(Faulty, &rdev->flags) || - r10_bio->devs[slot].addr + sectors > rdev->recovery_offset) + r10_bio->devs[slot].addr + sectors > + rdev->recovery_offset) { + /* + * Read replacement first to prevent reading both rdev + * and replacement as NULL during replacement replace + * rdev. + */ + smp_mb(); rdev = rcu_dereference(conf->mirrors[disk].rdev); + } if (rdev == NULL || test_bit(Faulty, &rdev->flags)) continue; @@ -934,6 +942,7 @@ static void flush_pending_writes(struct r10conf *conf) else generic_make_request(bio); bio = next; + cond_resched(); } blk_finish_plug(&plug); } else @@ -1119,6 +1128,7 @@ static void raid10_unplug(struct blk_plug_cb *cb, bool from_schedule) else generic_make_request(bio); bio = next; + cond_resched(); } kfree(plug); } @@ -1400,9 +1410,15 @@ retry_write: for (i = 0; i < conf->copies; i++) { int d = r10_bio->devs[i].devnum; - struct md_rdev *rdev = rcu_dereference(conf->mirrors[d].rdev); - struct md_rdev *rrdev = rcu_dereference( - conf->mirrors[d].replacement); + struct md_rdev *rdev, *rrdev; + + rrdev = rcu_dereference(conf->mirrors[d].replacement); + /* + * Read replacement first to prevent reading both rdev and + * replacement as NULL during replacement replace rdev. + */ + smp_mb(); + rdev = rcu_dereference(conf->mirrors[d].rdev); if (rdev == rrdev) rrdev = NULL; if (rdev && unlikely(test_bit(Blocked, &rdev->flags))) { diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c index 7eeae0301ccc6..b98abe927d06b 100644 --- a/drivers/md/raid5.c +++ b/drivers/md/raid5.c @@ -2603,7 +2603,7 @@ static void raid5_end_write_request(struct bio *bi) struct stripe_head *sh = bi->bi_private; struct r5conf *conf = sh->raid_conf; int disks = sh->disks, i; - struct md_rdev *uninitialized_var(rdev); + struct md_rdev *rdev; sector_t first_bad; int bad_sectors; int replacement = 0; diff --git a/drivers/media/dvb-frontends/rtl2832.c b/drivers/media/dvb-frontends/rtl2832.c index 2f1f5cbaf03c4..7cad4e985315a 100644 --- a/drivers/media/dvb-frontends/rtl2832.c +++ b/drivers/media/dvb-frontends/rtl2832.c @@ -653,7 +653,7 @@ static int rtl2832_read_status(struct dvb_frontend *fe, enum fe_status *status) struct i2c_client *client = dev->client; struct dtv_frontend_properties *c = &fe->dtv_property_cache; int ret; - u32 uninitialized_var(tmp); + u32 tmp; u8 u8tmp, buf[2]; u16 u16tmp; diff --git a/drivers/media/tuners/qt1010.c b/drivers/media/tuners/qt1010.c index 4565c06b16176..6d397cc85428d 100644 --- a/drivers/media/tuners/qt1010.c +++ b/drivers/media/tuners/qt1010.c @@ -224,7 +224,7 @@ static int qt1010_set_params(struct dvb_frontend *fe) static int qt1010_init_meas1(struct qt1010_priv *priv, u8 oper, u8 reg, u8 reg_init_val, u8 *retval) { - u8 i, val1, uninitialized_var(val2); + u8 i, val1, val2; int err; qt1010_i2c_oper_t i2c_data[] = { @@ -259,7 +259,7 @@ static int qt1010_init_meas1(struct qt1010_priv *priv, static int qt1010_init_meas2(struct qt1010_priv *priv, u8 reg_init_val, u8 *retval) { - u8 i, uninitialized_var(val); + u8 i, val; int err; qt1010_i2c_oper_t i2c_data[] = { { QT1010_WR, 0x07, reg_init_val }, diff --git a/drivers/media/usb/dvb-usb-v2/az6007.c b/drivers/media/usb/dvb-usb-v2/az6007.c index 746926364535d..8e914be5b7c5e 100644 --- a/drivers/media/usb/dvb-usb-v2/az6007.c +++ b/drivers/media/usb/dvb-usb-v2/az6007.c @@ -210,7 +210,8 @@ static int az6007_rc_query(struct dvb_usb_device *d) unsigned code; enum rc_proto proto; - az6007_read(d, AZ6007_READ_IR, 0, 0, st->data, 10); + if (az6007_read(d, AZ6007_READ_IR, 0, 0, st->data, 10) < 0) + return -EIO; if (st->data[1] == 0x44) return 0; diff --git a/drivers/media/usb/gspca/vicam.c b/drivers/media/usb/gspca/vicam.c index 8562bda0ef886..624fdcfdc85a6 100644 --- a/drivers/media/usb/gspca/vicam.c +++ b/drivers/media/usb/gspca/vicam.c @@ -234,7 +234,7 @@ static int sd_init(struct gspca_dev *gspca_dev) { int ret; const struct ihex_binrec *rec; - const struct firmware *uninitialized_var(fw); + const struct firmware *fw; u8 *firmware_buf; ret = request_ihex_firmware(&fw, VICAM_FIRMWARE, diff --git a/drivers/media/usb/siano/smsusb.c b/drivers/media/usb/siano/smsusb.c index 2df3d730ea768..cd706874899c3 100644 --- a/drivers/media/usb/siano/smsusb.c +++ b/drivers/media/usb/siano/smsusb.c @@ -190,7 +190,8 @@ static void smsusb_stop_streaming(struct smsusb_device_t *dev) for (i = 0; i < MAX_URBS; i++) { usb_kill_urb(&dev->surbs[i].urb); - cancel_work_sync(&dev->surbs[i].wq); + if (dev->surbs[i].wq.func) + cancel_work_sync(&dev->surbs[i].wq); if (dev->surbs[i].cb) { smscore_putbuffer(dev->coredev, dev->surbs[i].cb); diff --git a/drivers/media/usb/uvc/uvc_video.c b/drivers/media/usb/uvc/uvc_video.c index 1c0249df52566..c57bc62251bb8 100644 --- a/drivers/media/usb/uvc/uvc_video.c +++ b/drivers/media/usb/uvc/uvc_video.c @@ -802,9 +802,9 @@ static void uvc_video_stats_decode(struct uvc_streaming *stream, unsigned int header_size; bool has_pts = false; bool has_scr = false; - u16 uninitialized_var(scr_sof); - u32 uninitialized_var(scr_stc); - u32 uninitialized_var(pts); + u16 scr_sof; + u32 scr_stc; + u32 pts; if (stream->stats.stream.nb_frames == 0 && stream->stats.frame.nb_packets == 0) @@ -1801,7 +1801,7 @@ static int uvc_init_video(struct uvc_streaming *stream, gfp_t gfp_flags) struct usb_host_endpoint *best_ep = NULL; unsigned int best_psize = UINT_MAX; unsigned int bandwidth; - unsigned int uninitialized_var(altsetting); + unsigned int altsetting; int intfnum = stream->intfnum; /* Isochronous endpoint, select the alternate setting. */ diff --git a/drivers/memstick/host/jmb38x_ms.c b/drivers/memstick/host/jmb38x_ms.c index 0610d3c9f1318..9f65db9a69b3d 100644 --- a/drivers/memstick/host/jmb38x_ms.c +++ b/drivers/memstick/host/jmb38x_ms.c @@ -316,7 +316,7 @@ static int jmb38x_ms_transfer_data(struct jmb38x_ms_host *host) } while (length) { - unsigned int uninitialized_var(p_off); + unsigned int p_off; if (host->req->long_data) { pg = nth_page(sg_page(&host->req->sg), diff --git a/drivers/memstick/host/r592.c b/drivers/memstick/host/r592.c index edb1b5588b7a0..6360f5c6d3958 100644 --- a/drivers/memstick/host/r592.c +++ b/drivers/memstick/host/r592.c @@ -47,12 +47,10 @@ static const char *tpc_names[] = { * memstick_debug_get_tpc_name - debug helper that returns string for * a TPC number */ -const char *memstick_debug_get_tpc_name(int tpc) +static __maybe_unused const char *memstick_debug_get_tpc_name(int tpc) { return tpc_names[tpc-1]; } -EXPORT_SYMBOL(memstick_debug_get_tpc_name); - /* Read a register*/ static inline u32 r592_read_reg(struct r592_device *dev, int address) diff --git a/drivers/memstick/host/tifm_ms.c b/drivers/memstick/host/tifm_ms.c index bed205849d027..ecd8d71f8a398 100644 --- a/drivers/memstick/host/tifm_ms.c +++ b/drivers/memstick/host/tifm_ms.c @@ -200,7 +200,7 @@ static unsigned int tifm_ms_transfer_data(struct tifm_ms *host) host->block_pos); while (length) { - unsigned int uninitialized_var(p_off); + unsigned int p_off; if (host->req->long_data) { pg = nth_page(sg_page(&host->req->sg), diff --git a/drivers/mfd/intel-lpss-acpi.c b/drivers/mfd/intel-lpss-acpi.c index fc44fb7c595bc..281ef5f52eb55 100644 --- a/drivers/mfd/intel-lpss-acpi.c +++ b/drivers/mfd/intel-lpss-acpi.c @@ -92,6 +92,9 @@ static int intel_lpss_acpi_probe(struct platform_device *pdev) return -ENOMEM; info->mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!info->mem) + return -ENODEV; + info->irq = platform_get_irq(pdev, 0); ret = intel_lpss_probe(&pdev->dev, info); diff --git a/drivers/mfd/rt5033.c b/drivers/mfd/rt5033.c index 9bd089c563753..94cdad91c0657 100644 --- a/drivers/mfd/rt5033.c +++ b/drivers/mfd/rt5033.c @@ -44,9 +44,6 @@ static const struct mfd_cell rt5033_devs[] = { { .name = "rt5033-charger", .of_compatible = "richtek,rt5033-charger", - }, { - .name = "rt5033-battery", - .of_compatible = "richtek,rt5033-battery", }, { .name = "rt5033-led", .of_compatible = "richtek,rt5033-led", diff --git a/drivers/mfd/stmpe.c b/drivers/mfd/stmpe.c index 722ad2c368a56..d752c56d60e42 100644 --- a/drivers/mfd/stmpe.c +++ b/drivers/mfd/stmpe.c @@ -1428,9 +1428,9 @@ int stmpe_probe(struct stmpe_client_info *ci, enum stmpe_partnum partnum) int stmpe_remove(struct stmpe *stmpe) { - if (!IS_ERR(stmpe->vio)) + if (!IS_ERR(stmpe->vio) && regulator_is_enabled(stmpe->vio)) regulator_disable(stmpe->vio); - if (!IS_ERR(stmpe->vcc)) + if (!IS_ERR(stmpe->vcc) && regulator_is_enabled(stmpe->vcc)) regulator_disable(stmpe->vcc); mfd_remove_devices(stmpe->dev); diff --git a/drivers/misc/pci_endpoint_test.c b/drivers/misc/pci_endpoint_test.c index 7d166f57f6242..e5b05e11675b4 100644 --- a/drivers/misc/pci_endpoint_test.c +++ b/drivers/misc/pci_endpoint_test.c @@ -601,6 +601,10 @@ static long pci_endpoint_test_ioctl(struct file *file, unsigned int cmd, struct pci_dev *pdev = test->pdev; mutex_lock(&test->mutex); + + reinit_completion(&test->irq_raised); + test->last_irq = -ENODATA; + switch (cmd) { case PCITEST_BAR: bar = arg; @@ -785,6 +789,9 @@ static void pci_endpoint_test_remove(struct pci_dev *pdev) if (id < 0) return; + pci_endpoint_test_release_irq(test); + pci_endpoint_test_free_irq_vectors(test); + misc_deregister(&test->miscdev); kfree(misc_device->name); ida_simple_remove(&pci_endpoint_test_ida, id); @@ -793,9 +800,6 @@ static void pci_endpoint_test_remove(struct pci_dev *pdev) pci_iounmap(pdev, test->bar[bar]); } - pci_endpoint_test_release_irq(test); - pci_endpoint_test_free_irq_vectors(test); - pci_release_regions(pdev); pci_disable_device(pdev); } diff --git a/drivers/mmc/core/quirks.h b/drivers/mmc/core/quirks.h index d5bbe8e544de7..e35c204cdac11 100644 --- a/drivers/mmc/core/quirks.h +++ b/drivers/mmc/core/quirks.h @@ -90,6 +90,20 @@ static const struct mmc_fixup mmc_blk_fixups[] = { MMC_FIXUP("VZL00M", CID_MANFID_SAMSUNG, CID_OEMID_ANY, add_quirk_mmc, MMC_QUIRK_SEC_ERASE_TRIM_BROKEN), + /* + * Kingston EMMC04G-M627 advertises TRIM but it does not seems to + * support being used to offload WRITE_ZEROES. + */ + MMC_FIXUP("M62704", CID_MANFID_KINGSTON, 0x0100, add_quirk_mmc, + MMC_QUIRK_TRIM_BROKEN), + + /* + * Micron MTFC4GACAJCN-1M advertises TRIM but it does not seems to + * support being used to offload WRITE_ZEROES. + */ + MMC_FIXUP("Q2J54A", CID_MANFID_MICRON, 0x014e, add_quirk_mmc, + MMC_QUIRK_TRIM_BROKEN), + /* * On Some Kingston eMMCs, performing trim can result in * unrecoverable data conrruption occasionally due to a firmware bug. diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c index 57be129fe4f33..b7afbeeca08a3 100644 --- a/drivers/mmc/host/sdhci.c +++ b/drivers/mmc/host/sdhci.c @@ -374,7 +374,7 @@ static void sdhci_read_block_pio(struct sdhci_host *host) { unsigned long flags; size_t blksize, len, chunk; - u32 uninitialized_var(scratch); + u32 scratch; u8 *buf; DBG("PIO reading\n"); diff --git a/drivers/mtd/nand/raw/nand_ecc.c b/drivers/mtd/nand/raw/nand_ecc.c index 8e132edbc5ce9..d1066f635e4c8 100644 --- a/drivers/mtd/nand/raw/nand_ecc.c +++ b/drivers/mtd/nand/raw/nand_ecc.c @@ -144,7 +144,7 @@ void __nand_calculate_ecc(const unsigned char *buf, unsigned int eccsize, /* rp0..rp15..rp17 are the various accumulated parities (per byte) */ uint32_t rp0, rp1, rp2, rp3, rp4, rp5, rp6, rp7; uint32_t rp8, rp9, rp10, rp11, rp12, rp13, rp14, rp15, rp16; - uint32_t uninitialized_var(rp17); /* to make compiler happy */ + uint32_t rp17; uint32_t par; /* the cumulative parity for all data */ uint32_t tmppar; /* the cumulative parity for this iteration; for rp12, rp14 and rp16 at the end of the diff --git a/drivers/mtd/nand/raw/omap_elm.c b/drivers/mtd/nand/raw/omap_elm.c index 6736777a41567..02d1740383120 100644 --- a/drivers/mtd/nand/raw/omap_elm.c +++ b/drivers/mtd/nand/raw/omap_elm.c @@ -184,17 +184,17 @@ static void elm_load_syndrome(struct elm_info *info, switch (info->bch_type) { case BCH8_ECC: /* syndrome fragment 0 = ecc[9-12B] */ - val = cpu_to_be32(*(u32 *) &ecc[9]); + val = (__force u32)cpu_to_be32(*(u32 *)&ecc[9]); elm_write_reg(info, offset, val); /* syndrome fragment 1 = ecc[5-8B] */ offset += 4; - val = cpu_to_be32(*(u32 *) &ecc[5]); + val = (__force u32)cpu_to_be32(*(u32 *)&ecc[5]); elm_write_reg(info, offset, val); /* syndrome fragment 2 = ecc[1-4B] */ offset += 4; - val = cpu_to_be32(*(u32 *) &ecc[1]); + val = (__force u32)cpu_to_be32(*(u32 *)&ecc[1]); elm_write_reg(info, offset, val); /* syndrome fragment 3 = ecc[0B] */ @@ -204,35 +204,35 @@ static void elm_load_syndrome(struct elm_info *info, break; case BCH4_ECC: /* syndrome fragment 0 = ecc[20-52b] bits */ - val = (cpu_to_be32(*(u32 *) &ecc[3]) >> 4) | + val = ((__force u32)cpu_to_be32(*(u32 *)&ecc[3]) >> 4) | ((ecc[2] & 0xf) << 28); elm_write_reg(info, offset, val); /* syndrome fragment 1 = ecc[0-20b] bits */ offset += 4; - val = cpu_to_be32(*(u32 *) &ecc[0]) >> 12; + val = (__force u32)cpu_to_be32(*(u32 *)&ecc[0]) >> 12; elm_write_reg(info, offset, val); break; case BCH16_ECC: - val = cpu_to_be32(*(u32 *) &ecc[22]); + val = (__force u32)cpu_to_be32(*(u32 *)&ecc[22]); elm_write_reg(info, offset, val); offset += 4; - val = cpu_to_be32(*(u32 *) &ecc[18]); + val = (__force u32)cpu_to_be32(*(u32 *)&ecc[18]); elm_write_reg(info, offset, val); offset += 4; - val = cpu_to_be32(*(u32 *) &ecc[14]); + val = (__force u32)cpu_to_be32(*(u32 *)&ecc[14]); elm_write_reg(info, offset, val); offset += 4; - val = cpu_to_be32(*(u32 *) &ecc[10]); + val = (__force u32)cpu_to_be32(*(u32 *)&ecc[10]); elm_write_reg(info, offset, val); offset += 4; - val = cpu_to_be32(*(u32 *) &ecc[6]); + val = (__force u32)cpu_to_be32(*(u32 *)&ecc[6]); elm_write_reg(info, offset, val); offset += 4; - val = cpu_to_be32(*(u32 *) &ecc[2]); + val = (__force u32)cpu_to_be32(*(u32 *)&ecc[2]); elm_write_reg(info, offset, val); offset += 4; - val = cpu_to_be32(*(u32 *) &ecc[0]) >> 16; + val = (__force u32)cpu_to_be32(*(u32 *)&ecc[0]) >> 16; elm_write_reg(info, offset, val); break; default: diff --git a/drivers/mtd/nand/raw/s3c2410.c b/drivers/mtd/nand/raw/s3c2410.c index cf045813c160a..83d3e3cb77ded 100644 --- a/drivers/mtd/nand/raw/s3c2410.c +++ b/drivers/mtd/nand/raw/s3c2410.c @@ -304,7 +304,7 @@ static int s3c2410_nand_setrate(struct s3c2410_nand_info *info) int tacls_max = (info->cpu_type == TYPE_S3C2412) ? 8 : 4; int tacls, twrph0, twrph1; unsigned long clkrate = clk_get_rate(info->clk); - unsigned long uninitialized_var(set), cfg, uninitialized_var(mask); + unsigned long set, cfg, mask; unsigned long flags; /* calculate the timing information for the controller */ diff --git a/drivers/mtd/ubi/eba.c b/drivers/mtd/ubi/eba.c index 3e25421f22a27..fa6ff75459c6e 100644 --- a/drivers/mtd/ubi/eba.c +++ b/drivers/mtd/ubi/eba.c @@ -612,7 +612,7 @@ int ubi_eba_read_leb(struct ubi_device *ubi, struct ubi_volume *vol, int lnum, int err, pnum, scrub = 0, vol_id = vol->vol_id; struct ubi_vid_io_buf *vidb; struct ubi_vid_hdr *vid_hdr; - uint32_t uninitialized_var(crc); + uint32_t crc; err = leb_read_lock(ubi, vol_id, lnum); if (err) diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index 4e4adacb5c2c1..47e02c5342b28 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c @@ -1128,6 +1128,11 @@ static void bond_setup_by_slave(struct net_device *bond_dev, memcpy(bond_dev->broadcast, slave_dev->broadcast, slave_dev->addr_len); + + if (slave_dev->flags & IFF_POINTOPOINT) { + bond_dev->flags &= ~(IFF_BROADCAST | IFF_MULTICAST); + bond_dev->flags |= (IFF_POINTOPOINT | IFF_NOARP); + } } /* On bonding slaves other than the currently active slave, suppress diff --git a/drivers/net/can/janz-ican3.c b/drivers/net/can/janz-ican3.c index 02042cb09bd29..0e939a4cd9998 100644 --- a/drivers/net/can/janz-ican3.c +++ b/drivers/net/can/janz-ican3.c @@ -1455,7 +1455,7 @@ static int ican3_napi(struct napi_struct *napi, int budget) /* process all communication messages */ while (true) { - struct ican3_msg uninitialized_var(msg); + struct ican3_msg msg; ret = ican3_recv_msg(mod, &msg); if (ret) break; diff --git a/drivers/net/can/usb/gs_usb.c b/drivers/net/can/usb/gs_usb.c index 62ca4964a863a..b2e48c8595f0f 100644 --- a/drivers/net/can/usb/gs_usb.c +++ b/drivers/net/can/usb/gs_usb.c @@ -740,6 +740,8 @@ static int gs_can_close(struct net_device *netdev) usb_kill_anchored_urbs(&dev->tx_submitted); atomic_set(&dev->active_tx_urbs, 0); + dev->can.state = CAN_STATE_STOPPED; + /* reset the device */ rc = gs_cmd_reset(dev); if (rc < 0) diff --git a/drivers/net/ethernet/atheros/atl1e/atl1e_main.c b/drivers/net/ethernet/atheros/atl1e/atl1e_main.c index 3164aad29bcf8..e4d58c7aeaf82 100644 --- a/drivers/net/ethernet/atheros/atl1e/atl1e_main.c +++ b/drivers/net/ethernet/atheros/atl1e/atl1e_main.c @@ -1651,8 +1651,11 @@ static int atl1e_tso_csum(struct atl1e_adapter *adapter, real_len = (((unsigned char *)ip_hdr(skb) - skb->data) + ntohs(ip_hdr(skb)->tot_len)); - if (real_len < skb->len) - pskb_trim(skb, real_len); + if (real_len < skb->len) { + err = pskb_trim(skb, real_len); + if (err) + return err; + } hdr_len = (skb_transport_offset(skb) + tcp_hdrlen(skb)); if (unlikely(skb->len == hdr_len)) { diff --git a/drivers/net/ethernet/broadcom/bnx2.c b/drivers/net/ethernet/broadcom/bnx2.c index 9993f1162ac68..c69700088082d 100644 --- a/drivers/net/ethernet/broadcom/bnx2.c +++ b/drivers/net/ethernet/broadcom/bnx2.c @@ -1461,7 +1461,7 @@ bnx2_test_and_disable_2g5(struct bnx2 *bp) static void bnx2_enable_forced_2g5(struct bnx2 *bp) { - u32 uninitialized_var(bmcr); + u32 bmcr; int err; if (!(bp->phy_flags & BNX2_PHY_FLAG_2_5G_CAPABLE)) @@ -1505,7 +1505,7 @@ bnx2_enable_forced_2g5(struct bnx2 *bp) static void bnx2_disable_forced_2g5(struct bnx2 *bp) { - u32 uninitialized_var(bmcr); + u32 bmcr; int err; if (!(bp->phy_flags & BNX2_PHY_FLAG_2_5G_CAPABLE)) diff --git a/drivers/net/ethernet/broadcom/genet/bcmmii.c b/drivers/net/ethernet/broadcom/genet/bcmmii.c index 494601c39b847..9041a422dd15a 100644 --- a/drivers/net/ethernet/broadcom/genet/bcmmii.c +++ b/drivers/net/ethernet/broadcom/genet/bcmmii.c @@ -620,5 +620,7 @@ void bcmgenet_mii_exit(struct net_device *dev) if (of_phy_is_fixed_link(dn)) of_phy_deregister_fixed_link(dn); of_node_put(priv->phy_dn); + clk_prepare_enable(priv->clk); platform_device_unregister(priv->mii_pdev); + clk_disable_unprepare(priv->clk); } diff --git a/drivers/net/ethernet/broadcom/tg3.c b/drivers/net/ethernet/broadcom/tg3.c index 2cf144bbef3ee..43b83a3a28049 100644 --- a/drivers/net/ethernet/broadcom/tg3.c +++ b/drivers/net/ethernet/broadcom/tg3.c @@ -235,6 +235,7 @@ MODULE_DESCRIPTION("Broadcom Tigon3 ethernet driver"); MODULE_LICENSE("GPL"); MODULE_VERSION(DRV_MODULE_VERSION); MODULE_FIRMWARE(FIRMWARE_TG3); +MODULE_FIRMWARE(FIRMWARE_TG357766); MODULE_FIRMWARE(FIRMWARE_TG3TSO); MODULE_FIRMWARE(FIRMWARE_TG3TSO5); diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c index 8603df2ae1736..d0d9a420f557e 100644 --- a/drivers/net/ethernet/emulex/benet/be_main.c +++ b/drivers/net/ethernet/emulex/benet/be_main.c @@ -1139,7 +1139,8 @@ static struct sk_buff *be_lancer_xmit_workarounds(struct be_adapter *adapter, (lancer_chip(adapter) || BE3_chip(adapter) || skb_vlan_tag_present(skb)) && is_ipv4_pkt(skb)) { ip = (struct iphdr *)ip_hdr(skb); - pskb_trim(skb, eth_hdr_len + ntohs(ip->tot_len)); + if (unlikely(pskb_trim(skb, eth_hdr_len + ntohs(ip->tot_len)))) + goto tx_drop; } /* If vlan tag is already inlined in the packet, skip HW VLAN diff --git a/drivers/net/ethernet/intel/i40e/i40e_debugfs.c b/drivers/net/ethernet/intel/i40e/i40e_debugfs.c index a66492b9403c4..5b82c89330e30 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_debugfs.c +++ b/drivers/net/ethernet/intel/i40e/i40e_debugfs.c @@ -1798,7 +1798,7 @@ void i40e_dbg_pf_exit(struct i40e_pf *pf) void i40e_dbg_init(void) { i40e_dbg_root = debugfs_create_dir(i40e_driver_name, NULL); - if (!i40e_dbg_root) + if (IS_ERR(i40e_dbg_root)) pr_info("init of debugfs failed\n"); } diff --git a/drivers/net/ethernet/intel/igb/igb_main.c b/drivers/net/ethernet/intel/igb/igb_main.c index 6f9d563deb6ba..be51179089852 100644 --- a/drivers/net/ethernet/intel/igb/igb_main.c +++ b/drivers/net/ethernet/intel/igb/igb_main.c @@ -9059,6 +9059,11 @@ static pci_ers_result_t igb_io_error_detected(struct pci_dev *pdev, struct net_device *netdev = pci_get_drvdata(pdev); struct igb_adapter *adapter = netdev_priv(netdev); + if (state == pci_channel_io_normal) { + dev_warn(&pdev->dev, "Non-correctable non-fatal error reported.\n"); + return PCI_ERS_RESULT_CAN_RECOVER; + } + netif_device_detach(netdev); if (state == pci_channel_io_perm_failure) diff --git a/drivers/net/ethernet/marvell/mvneta.c b/drivers/net/ethernet/marvell/mvneta.c index f1a4b11ce0d19..512f9cd68070a 100644 --- a/drivers/net/ethernet/marvell/mvneta.c +++ b/drivers/net/ethernet/marvell/mvneta.c @@ -1415,7 +1415,7 @@ static void mvneta_defaults_set(struct mvneta_port *pp) */ if (txq_number == 1) txq_map = (cpu == pp->rxq_def) ? - MVNETA_CPU_TXQ_ACCESS(1) : 0; + MVNETA_CPU_TXQ_ACCESS(0) : 0; } else { txq_map = MVNETA_CPU_TXQ_ACCESS_ALL_MASK; @@ -3665,7 +3665,7 @@ static void mvneta_percpu_elect(struct mvneta_port *pp) */ if (txq_number == 1) txq_map = (cpu == elected_cpu) ? - MVNETA_CPU_TXQ_ACCESS(1) : 0; + MVNETA_CPU_TXQ_ACCESS(0) : 0; else txq_map = mvreg_read(pp, MVNETA_CPU_MAP(cpu)) & MVNETA_CPU_TXQ_ACCESS_ALL_MASK; diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_rxtx.c b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_rxtx.c index 128a82b1dbfc6..ad9db70eb879e 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_rxtx.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_rxtx.c @@ -121,7 +121,9 @@ static int mlx5e_ipsec_remove_trailer(struct sk_buff *skb, struct xfrm_state *x) trailer_len = alen + plen + 2; - pskb_trim(skb, skb->len - trailer_len); + ret = pskb_trim(skb, skb->len - trailer_len); + if (unlikely(ret)) + return ret; if (skb->protocol == htons(ETH_P_IP)) { ipv4hdr->tot_len = htons(ntohs(ipv4hdr->tot_len) - trailer_len); ip_send_check(ipv4hdr); diff --git a/drivers/net/ethernet/mellanox/mlx5/core/pagealloc.c b/drivers/net/ethernet/mellanox/mlx5/core/pagealloc.c index fc880c02459db..c9ba97b400fa1 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/pagealloc.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/pagealloc.c @@ -471,8 +471,8 @@ void mlx5_core_req_pages_handler(struct mlx5_core_dev *dev, u16 func_id, int mlx5_satisfy_startup_pages(struct mlx5_core_dev *dev, int boot) { - u16 uninitialized_var(func_id); - s32 uninitialized_var(npages); + u16 func_id; + s32 npages; int err; err = mlx5_cmd_query_pages(dev, &func_id, &npages, boot); diff --git a/drivers/net/ethernet/microchip/lan743x_main.c b/drivers/net/ethernet/microchip/lan743x_main.c index e734bc5e3ceb4..112d374e71663 100644 --- a/drivers/net/ethernet/microchip/lan743x_main.c +++ b/drivers/net/ethernet/microchip/lan743x_main.c @@ -80,6 +80,18 @@ static int lan743x_csr_light_reset(struct lan743x_adapter *adapter) !(data & HW_CFG_LRST_), 100000, 10000000); } +static int lan743x_csr_wait_for_bit_atomic(struct lan743x_adapter *adapter, + int offset, u32 bit_mask, + int target_value, int udelay_min, + int udelay_max, int count) +{ + u32 data; + + return readx_poll_timeout_atomic(LAN743X_CSR_READ_OP, offset, data, + target_value == !!(data & bit_mask), + udelay_max, udelay_min * count); +} + static int lan743x_csr_wait_for_bit(struct lan743x_adapter *adapter, int offset, u32 bit_mask, int target_value, int usleep_min, @@ -675,8 +687,8 @@ static int lan743x_dp_write(struct lan743x_adapter *adapter, u32 dp_sel; int i; - if (lan743x_csr_wait_for_bit(adapter, DP_SEL, DP_SEL_DPRDY_, - 1, 40, 100, 100)) + if (lan743x_csr_wait_for_bit_atomic(adapter, DP_SEL, DP_SEL_DPRDY_, + 1, 40, 100, 100)) return -EIO; dp_sel = lan743x_csr_read(adapter, DP_SEL); dp_sel &= ~DP_SEL_MASK_; @@ -687,8 +699,9 @@ static int lan743x_dp_write(struct lan743x_adapter *adapter, lan743x_csr_write(adapter, DP_ADDR, addr + i); lan743x_csr_write(adapter, DP_DATA_0, buf[i]); lan743x_csr_write(adapter, DP_CMD, DP_CMD_WRITE_); - if (lan743x_csr_wait_for_bit(adapter, DP_SEL, DP_SEL_DPRDY_, - 1, 40, 100, 100)) + if (lan743x_csr_wait_for_bit_atomic(adapter, DP_SEL, + DP_SEL_DPRDY_, + 1, 40, 100, 100)) return -EIO; } diff --git a/drivers/net/ethernet/neterion/s2io.c b/drivers/net/ethernet/neterion/s2io.c index b42f81d0c6f05..f5272d2fcc7e4 100644 --- a/drivers/net/ethernet/neterion/s2io.c +++ b/drivers/net/ethernet/neterion/s2io.c @@ -7291,7 +7291,7 @@ static int rx_osm_handler(struct ring_info *ring_data, struct RxD_t * rxdp) int ring_no = ring_data->ring_no; u16 l3_csum, l4_csum; unsigned long long err = rxdp->Control_1 & RXD_T_CODE; - struct lro *uninitialized_var(lro); + struct lro *lro; u8 err_mask; struct swStat *swstats = &sp->mac_control.stats_info->sw_stat; diff --git a/drivers/net/ethernet/qlogic/qla3xxx.c b/drivers/net/ethernet/qlogic/qla3xxx.c index 7a65a1534e41a..d545593354c63 100644 --- a/drivers/net/ethernet/qlogic/qla3xxx.c +++ b/drivers/net/ethernet/qlogic/qla3xxx.c @@ -3771,7 +3771,7 @@ static int ql3xxx_probe(struct pci_dev *pdev, struct net_device *ndev = NULL; struct ql3_adapter *qdev = NULL; static int cards_found; - int uninitialized_var(pci_using_dac), err; + int pci_using_dac, err; err = pci_enable_device(pdev); if (err) { diff --git a/drivers/net/ethernet/sun/cassini.c b/drivers/net/ethernet/sun/cassini.c index 909f6d1605f7a..861d1f6d7508f 100644 --- a/drivers/net/ethernet/sun/cassini.c +++ b/drivers/net/ethernet/sun/cassini.c @@ -2291,7 +2291,7 @@ static int cas_rx_ringN(struct cas *cp, int ring, int budget) drops = 0; while (1) { struct cas_rx_comp *rxc = rxcs + entry; - struct sk_buff *uninitialized_var(skb); + struct sk_buff *skb; int type, len; u64 words[4]; int i, dring; diff --git a/drivers/net/ethernet/sun/niu.c b/drivers/net/ethernet/sun/niu.c index 1693a70325c50..1c13c08c4f965 100644 --- a/drivers/net/ethernet/sun/niu.c +++ b/drivers/net/ethernet/sun/niu.c @@ -429,7 +429,7 @@ static int serdes_init_niu_1g_serdes(struct niu *np) struct niu_link_config *lp = &np->link_config; u16 pll_cfg, pll_sts; int max_retry = 100; - u64 uninitialized_var(sig), mask, val; + u64 sig, mask, val; u32 tx_cfg, rx_cfg; unsigned long i; int err; @@ -526,7 +526,7 @@ static int serdes_init_niu_10g_serdes(struct niu *np) struct niu_link_config *lp = &np->link_config; u32 tx_cfg, rx_cfg, pll_cfg, pll_sts; int max_retry = 100; - u64 uninitialized_var(sig), mask, val; + u64 sig, mask, val; unsigned long i; int err; @@ -714,7 +714,7 @@ static int esr_write_glue0(struct niu *np, unsigned long chan, u32 val) static int esr_reset(struct niu *np) { - u32 uninitialized_var(reset); + u32 reset; int err; err = mdio_write(np, np->port, NIU_ESR_DEV_ADDR, diff --git a/drivers/net/ethernet/ti/cpsw_ale.c b/drivers/net/ethernet/ti/cpsw_ale.c index c245629a38c76..6cb98760bc84e 100644 --- a/drivers/net/ethernet/ti/cpsw_ale.c +++ b/drivers/net/ethernet/ti/cpsw_ale.c @@ -67,23 +67,37 @@ static inline int cpsw_ale_get_field(u32 *ale_entry, u32 start, u32 bits) { - int idx; + int idx, idx2; + u32 hi_val = 0; idx = start / 32; + idx2 = (start + bits - 1) / 32; + /* Check if bits to be fetched exceed a word */ + if (idx != idx2) { + idx2 = 2 - idx2; /* flip */ + hi_val = ale_entry[idx2] << ((idx2 * 32) - start); + } start -= idx * 32; idx = 2 - idx; /* flip */ - return (ale_entry[idx] >> start) & BITMASK(bits); + return (hi_val + (ale_entry[idx] >> start)) & BITMASK(bits); } static inline void cpsw_ale_set_field(u32 *ale_entry, u32 start, u32 bits, u32 value) { - int idx; + int idx, idx2; value &= BITMASK(bits); - idx = start / 32; + idx = start / 32; + idx2 = (start + bits - 1) / 32; + /* Check if bits to be set exceed a word */ + if (idx != idx2) { + idx2 = 2 - idx2; /* flip */ + ale_entry[idx2] &= ~(BITMASK(bits + start - (idx2 * 32))); + ale_entry[idx2] |= (value >> ((idx2 * 32) - start)); + } start -= idx * 32; - idx = 2 - idx; /* flip */ + idx = 2 - idx; /* flip */ ale_entry[idx] &= ~(BITMASK(bits) << start); ale_entry[idx] |= (value << start); } diff --git a/drivers/net/gtp.c b/drivers/net/gtp.c index e18d06cb2173c..2718b0507f713 100644 --- a/drivers/net/gtp.c +++ b/drivers/net/gtp.c @@ -301,7 +301,9 @@ static void __gtp_encap_destroy(struct sock *sk) gtp->sk1u = NULL; udp_sk(sk)->encap_type = 0; rcu_assign_sk_user_data(sk, NULL); + release_sock(sk); sock_put(sk); + return; } release_sock(sk); } diff --git a/drivers/net/ipvlan/ipvlan_core.c b/drivers/net/ipvlan/ipvlan_core.c index eb80d277b56f5..6b6c5a7250a65 100644 --- a/drivers/net/ipvlan/ipvlan_core.c +++ b/drivers/net/ipvlan/ipvlan_core.c @@ -592,7 +592,8 @@ static int ipvlan_xmit_mode_l3(struct sk_buff *skb, struct net_device *dev) consume_skb(skb); return NET_XMIT_DROP; } - return ipvlan_rcv_frame(addr, &skb, true); + ipvlan_rcv_frame(addr, &skb, true); + return NET_XMIT_SUCCESS; } } out: @@ -618,7 +619,8 @@ static int ipvlan_xmit_mode_l2(struct sk_buff *skb, struct net_device *dev) consume_skb(skb); return NET_XMIT_DROP; } - return ipvlan_rcv_frame(addr, &skb, true); + ipvlan_rcv_frame(addr, &skb, true); + return NET_XMIT_SUCCESS; } } skb = skb_share_check(skb, GFP_ATOMIC); @@ -630,7 +632,8 @@ static int ipvlan_xmit_mode_l2(struct sk_buff *skb, struct net_device *dev) * the skb for the main-dev. At the RX side we just return * RX_PASS for it to be processed further on the stack. */ - return dev_forward_skb(ipvlan->phy_dev, skb); + dev_forward_skb(ipvlan->phy_dev, skb); + return NET_XMIT_SUCCESS; } else if (is_multicast_ether_addr(eth->h_dest)) { skb_reset_mac_header(skb); diff --git a/drivers/net/team/team.c b/drivers/net/team/team.c index 2410f08e2bb5c..d80bc5f59b3fc 100644 --- a/drivers/net/team/team.c +++ b/drivers/net/team/team.c @@ -2103,6 +2103,15 @@ static void team_setup_by_port(struct net_device *dev, dev->mtu = port_dev->mtu; memcpy(dev->broadcast, port_dev->broadcast, port_dev->addr_len); eth_hw_addr_inherit(dev, port_dev); + + if (port_dev->flags & IFF_POINTOPOINT) { + dev->flags &= ~(IFF_BROADCAST | IFF_MULTICAST); + dev->flags |= (IFF_POINTOPOINT | IFF_NOARP); + } else if ((port_dev->flags & (IFF_BROADCAST | IFF_MULTICAST)) == + (IFF_BROADCAST | IFF_MULTICAST)) { + dev->flags |= (IFF_BROADCAST | IFF_MULTICAST); + dev->flags &= ~(IFF_POINTOPOINT | IFF_NOARP); + } } static int team_dev_type_check_change(struct net_device *dev, diff --git a/drivers/net/usb/cdc_ether.c b/drivers/net/usb/cdc_ether.c index 17b932505be0c..e2ce3c5541baa 100644 --- a/drivers/net/usb/cdc_ether.c +++ b/drivers/net/usb/cdc_ether.c @@ -618,9 +618,23 @@ static const struct usb_device_id products[] = { .match_flags = USB_DEVICE_ID_MATCH_INT_INFO | USB_DEVICE_ID_MATCH_DEVICE, .idVendor = 0x04DD, + .idProduct = 0x8005, /* A-300 */ + ZAURUS_FAKE_INTERFACE, + .driver_info = 0, +}, { + .match_flags = USB_DEVICE_ID_MATCH_INT_INFO + | USB_DEVICE_ID_MATCH_DEVICE, + .idVendor = 0x04DD, .idProduct = 0x8006, /* B-500/SL-5600 */ ZAURUS_MASTER_INTERFACE, .driver_info = 0, +}, { + .match_flags = USB_DEVICE_ID_MATCH_INT_INFO + | USB_DEVICE_ID_MATCH_DEVICE, + .idVendor = 0x04DD, + .idProduct = 0x8006, /* B-500/SL-5600 */ + ZAURUS_FAKE_INTERFACE, + .driver_info = 0, }, { .match_flags = USB_DEVICE_ID_MATCH_INT_INFO | USB_DEVICE_ID_MATCH_DEVICE, @@ -628,6 +642,13 @@ static const struct usb_device_id products[] = { .idProduct = 0x8007, /* C-700 */ ZAURUS_MASTER_INTERFACE, .driver_info = 0, +}, { + .match_flags = USB_DEVICE_ID_MATCH_INT_INFO + | USB_DEVICE_ID_MATCH_DEVICE, + .idVendor = 0x04DD, + .idProduct = 0x8007, /* C-700 */ + ZAURUS_FAKE_INTERFACE, + .driver_info = 0, }, { .match_flags = USB_DEVICE_ID_MATCH_INT_INFO | USB_DEVICE_ID_MATCH_DEVICE, diff --git a/drivers/net/usb/usbnet.c b/drivers/net/usb/usbnet.c index 2263a66f6314e..f7f037b399a75 100644 --- a/drivers/net/usb/usbnet.c +++ b/drivers/net/usb/usbnet.c @@ -1767,6 +1767,10 @@ usbnet_probe (struct usb_interface *udev, const struct usb_device_id *prod) } else if (!info->in || !info->out) status = usbnet_get_endpoints (dev, udev); else { + u8 ep_addrs[3] = { + info->in + USB_DIR_IN, info->out + USB_DIR_OUT, 0 + }; + dev->in = usb_rcvbulkpipe (xdev, info->in); dev->out = usb_sndbulkpipe (xdev, info->out); if (!(info->flags & FLAG_NO_SETINT)) @@ -1776,6 +1780,8 @@ usbnet_probe (struct usb_interface *udev, const struct usb_device_id *prod) else status = 0; + if (status == 0 && !usb_check_bulk_endpoints(udev, ep_addrs)) + status = -EINVAL; } if (status >= 0 && dev->status) status = init_status (dev, udev); diff --git a/drivers/net/usb/zaurus.c b/drivers/net/usb/zaurus.c index 1f19fc5e6117e..9a6ab75752e16 100644 --- a/drivers/net/usb/zaurus.c +++ b/drivers/net/usb/zaurus.c @@ -301,9 +301,23 @@ static const struct usb_device_id products [] = { .match_flags = USB_DEVICE_ID_MATCH_INT_INFO | USB_DEVICE_ID_MATCH_DEVICE, .idVendor = 0x04DD, + .idProduct = 0x8005, /* A-300 */ + ZAURUS_FAKE_INTERFACE, + .driver_info = (unsigned long)&bogus_mdlm_info, +}, { + .match_flags = USB_DEVICE_ID_MATCH_INT_INFO + | USB_DEVICE_ID_MATCH_DEVICE, + .idVendor = 0x04DD, .idProduct = 0x8006, /* B-500/SL-5600 */ ZAURUS_MASTER_INTERFACE, .driver_info = ZAURUS_PXA_INFO, +}, { + .match_flags = USB_DEVICE_ID_MATCH_INT_INFO + | USB_DEVICE_ID_MATCH_DEVICE, + .idVendor = 0x04DD, + .idProduct = 0x8006, /* B-500/SL-5600 */ + ZAURUS_FAKE_INTERFACE, + .driver_info = (unsigned long)&bogus_mdlm_info, }, { .match_flags = USB_DEVICE_ID_MATCH_INT_INFO | USB_DEVICE_ID_MATCH_DEVICE, @@ -311,6 +325,13 @@ static const struct usb_device_id products [] = { .idProduct = 0x8007, /* C-700 */ ZAURUS_MASTER_INTERFACE, .driver_info = ZAURUS_PXA_INFO, +}, { + .match_flags = USB_DEVICE_ID_MATCH_INT_INFO + | USB_DEVICE_ID_MATCH_DEVICE, + .idVendor = 0x04DD, + .idProduct = 0x8007, /* C-700 */ + ZAURUS_FAKE_INTERFACE, + .driver_info = (unsigned long)&bogus_mdlm_info, }, { .match_flags = USB_DEVICE_ID_MATCH_INT_INFO | USB_DEVICE_ID_MATCH_DEVICE, diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c index d45e8de79f286..03e0f8060cc2e 100644 --- a/drivers/net/virtio_net.c +++ b/drivers/net/virtio_net.c @@ -3120,6 +3120,8 @@ static int virtnet_probe(struct virtio_device *vdev) } } + _virtnet_set_queues(vi, vi->curr_queue_pairs); + /* serialize netdev register + virtio_device_ready() with ndo_open() */ rtnl_lock(); @@ -3140,8 +3142,6 @@ static int virtnet_probe(struct virtio_device *vdev) goto free_unregister_netdev; } - virtnet_set_queues(vi, vi->curr_queue_pairs); - /* Assume link up if device can't report link status, otherwise get link status from config. */ netif_carrier_off(dev); diff --git a/drivers/net/wan/z85230.c b/drivers/net/wan/z85230.c index deea41e96f018..96025d42b0eea 100644 --- a/drivers/net/wan/z85230.c +++ b/drivers/net/wan/z85230.c @@ -705,7 +705,7 @@ EXPORT_SYMBOL(z8530_nop); irqreturn_t z8530_interrupt(int irq, void *dev_id) { struct z8530_dev *dev=dev_id; - u8 uninitialized_var(intr); + u8 intr; static volatile int locker=0; int work=0; struct z8530_irqhandler *irqs; diff --git a/drivers/net/wireless/ath/ath10k/core.c b/drivers/net/wireless/ath/ath10k/core.c index 436eac342b622..7e43d449131dd 100644 --- a/drivers/net/wireless/ath/ath10k/core.c +++ b/drivers/net/wireless/ath/ath10k/core.c @@ -1891,7 +1891,7 @@ static int ath10k_init_uart(struct ath10k *ar) static int ath10k_init_hw_params(struct ath10k *ar) { - const struct ath10k_hw_params *uninitialized_var(hw_params); + const struct ath10k_hw_params *hw_params; int i; for (i = 0; i < ARRAY_SIZE(ath10k_hw_params_list); i++) { diff --git a/drivers/net/wireless/ath/ath6kl/init.c b/drivers/net/wireless/ath/ath6kl/init.c index 58fb227a849f6..49b93a5b7a72a 100644 --- a/drivers/net/wireless/ath/ath6kl/init.c +++ b/drivers/net/wireless/ath/ath6kl/init.c @@ -1575,7 +1575,7 @@ static int ath6kl_init_upload(struct ath6kl *ar) int ath6kl_init_hw_params(struct ath6kl *ar) { - const struct ath6kl_hw *uninitialized_var(hw); + const struct ath6kl_hw *hw; int i; for (i = 0; i < ARRAY_SIZE(hw_list); i++) { diff --git a/drivers/net/wireless/ath/ath9k/ar9003_hw.c b/drivers/net/wireless/ath/ath9k/ar9003_hw.c index 2fe12b0de5b4f..dea8a998fb622 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_hw.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_hw.c @@ -1099,17 +1099,22 @@ static bool ath9k_hw_verify_hang(struct ath_hw *ah, unsigned int queue) { u32 dma_dbg_chain, dma_dbg_complete; u8 dcu_chain_state, dcu_complete_state; + unsigned int dbg_reg, reg_offset; int i; - for (i = 0; i < NUM_STATUS_READS; i++) { - if (queue < 6) - dma_dbg_chain = REG_READ(ah, AR_DMADBG_4); - else - dma_dbg_chain = REG_READ(ah, AR_DMADBG_5); + if (queue < 6) { + dbg_reg = AR_DMADBG_4; + reg_offset = queue * 5; + } else { + dbg_reg = AR_DMADBG_5; + reg_offset = (queue - 6) * 5; + } + for (i = 0; i < NUM_STATUS_READS; i++) { + dma_dbg_chain = REG_READ(ah, dbg_reg); dma_dbg_complete = REG_READ(ah, AR_DMADBG_6); - dcu_chain_state = (dma_dbg_chain >> (5 * queue)) & 0x1f; + dcu_chain_state = (dma_dbg_chain >> reg_offset) & 0x1f; dcu_complete_state = dma_dbg_complete & 0x3; if ((dcu_chain_state != 0x6) || (dcu_complete_state != 0x1)) @@ -1128,6 +1133,7 @@ static bool ar9003_hw_detect_mac_hang(struct ath_hw *ah) u8 dcu_chain_state, dcu_complete_state; bool dcu_wait_frdone = false; unsigned long chk_dcu = 0; + unsigned int reg_offset; unsigned int i = 0; dma_dbg_4 = REG_READ(ah, AR_DMADBG_4); @@ -1139,12 +1145,15 @@ static bool ar9003_hw_detect_mac_hang(struct ath_hw *ah) goto exit; for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) { - if (i < 6) + if (i < 6) { chk_dbg = dma_dbg_4; - else + reg_offset = i * 5; + } else { chk_dbg = dma_dbg_5; + reg_offset = (i - 6) * 5; + } - dcu_chain_state = (chk_dbg >> (5 * i)) & 0x1f; + dcu_chain_state = (chk_dbg >> reg_offset) & 0x1f; if (dcu_chain_state == 0x6) { dcu_wait_frdone = true; chk_dcu |= BIT(i); diff --git a/drivers/net/wireless/ath/ath9k/htc_hst.c b/drivers/net/wireless/ath/ath9k/htc_hst.c index 6331c98088e03..d5e5f9cf4ca86 100644 --- a/drivers/net/wireless/ath/ath9k/htc_hst.c +++ b/drivers/net/wireless/ath/ath9k/htc_hst.c @@ -114,7 +114,13 @@ static void htc_process_conn_rsp(struct htc_target *target, if (svc_rspmsg->status == HTC_SERVICE_SUCCESS) { epid = svc_rspmsg->endpoint_id; - if (epid < 0 || epid >= ENDPOINT_MAX) + + /* Check that the received epid for the endpoint to attach + * a new service is valid. ENDPOINT0 can't be used here as it + * is already reserved for HTC_CTRL_RSVD_SVC service and thus + * should not be modified. + */ + if (epid <= ENDPOINT0 || epid >= ENDPOINT_MAX) return; service_id = be16_to_cpu(svc_rspmsg->service_id); diff --git a/drivers/net/wireless/ath/ath9k/init.c b/drivers/net/wireless/ath/ath9k/init.c index fae572b384169..922a3f208837e 100644 --- a/drivers/net/wireless/ath/ath9k/init.c +++ b/drivers/net/wireless/ath/ath9k/init.c @@ -230,7 +230,7 @@ static unsigned int ath9k_reg_rmw(void *hw_priv, u32 reg_offset, u32 set, u32 cl struct ath_hw *ah = hw_priv; struct ath_common *common = ath9k_hw_common(ah); struct ath_softc *sc = (struct ath_softc *) common->priv; - unsigned long uninitialized_var(flags); + unsigned long flags; u32 val; if (NR_CPUS > 1 && ah->config.serialize_regmode == SER_REG_MODE_ON) { diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index ee1b9c39bad7a..2fdf9858a73d9 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c @@ -200,7 +200,7 @@ void ath_cancel_work(struct ath_softc *sc) void ath_restart_work(struct ath_softc *sc) { ieee80211_queue_delayed_work(sc->hw, &sc->hw_check_work, - ATH_HW_CHECK_POLL_INT); + msecs_to_jiffies(ATH_HW_CHECK_POLL_INT)); if (AR_SREV_9340(sc->sc_ah) || AR_SREV_9330(sc->sc_ah)) ieee80211_queue_delayed_work(sc->hw, &sc->hw_pll_work, @@ -847,7 +847,7 @@ static bool ath9k_txq_list_has_key(struct list_head *txq_list, u32 keyix) static bool ath9k_txq_has_key(struct ath_softc *sc, u32 keyix) { struct ath_hw *ah = sc->sc_ah; - int i; + int i, j; struct ath_txq *txq; bool key_in_use = false; @@ -865,8 +865,9 @@ static bool ath9k_txq_has_key(struct ath_softc *sc, u32 keyix) if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) { int idx = txq->txq_tailidx; - while (!key_in_use && - !list_empty(&txq->txq_fifo[idx])) { + for (j = 0; !key_in_use && + !list_empty(&txq->txq_fifo[idx]) && + j < ATH_TXFIFO_DEPTH; j++) { key_in_use = ath9k_txq_list_has_key( &txq->txq_fifo[idx], keyix); INCR(idx, ATH_TXFIFO_DEPTH); @@ -2227,7 +2228,7 @@ void __ath9k_flush(struct ieee80211_hw *hw, u32 queues, bool drop, } ieee80211_queue_delayed_work(hw, &sc->hw_check_work, - ATH_HW_CHECK_POLL_INT); + msecs_to_jiffies(ATH_HW_CHECK_POLL_INT)); } static bool ath9k_tx_frames_pending(struct ieee80211_hw *hw) diff --git a/drivers/net/wireless/ath/ath9k/wmi.c b/drivers/net/wireless/ath/ath9k/wmi.c index e4ea6f5cc78ab..5e2a610df61cf 100644 --- a/drivers/net/wireless/ath/ath9k/wmi.c +++ b/drivers/net/wireless/ath/ath9k/wmi.c @@ -218,6 +218,10 @@ static void ath9k_wmi_ctrl_rx(void *priv, struct sk_buff *skb, if (unlikely(wmi->stopped)) goto free_skb; + /* Validate the obtained SKB. */ + if (unlikely(skb->len < sizeof(struct wmi_cmd_hdr))) + goto free_skb; + hdr = (struct wmi_cmd_hdr *) skb->data; cmd_id = be16_to_cpu(hdr->command_id); diff --git a/drivers/net/wireless/atmel/atmel_cs.c b/drivers/net/wireless/atmel/atmel_cs.c index 7afc9c5329fb1..f5fa1a95b0c15 100644 --- a/drivers/net/wireless/atmel/atmel_cs.c +++ b/drivers/net/wireless/atmel/atmel_cs.c @@ -73,6 +73,7 @@ struct local_info { static int atmel_probe(struct pcmcia_device *p_dev) { struct local_info *local; + int ret; dev_dbg(&p_dev->dev, "atmel_attach()\n"); @@ -83,8 +84,16 @@ static int atmel_probe(struct pcmcia_device *p_dev) p_dev->priv = local; - return atmel_config(p_dev); -} /* atmel_attach */ + ret = atmel_config(p_dev); + if (ret) + goto err_free_priv; + + return 0; + +err_free_priv: + kfree(p_dev->priv); + return ret; +} static void atmel_detach(struct pcmcia_device *link) { diff --git a/drivers/net/wireless/broadcom/b43/debugfs.c b/drivers/net/wireless/broadcom/b43/debugfs.c index 77046384dd800..70b02d6641709 100644 --- a/drivers/net/wireless/broadcom/b43/debugfs.c +++ b/drivers/net/wireless/broadcom/b43/debugfs.c @@ -506,7 +506,7 @@ static ssize_t b43_debugfs_read(struct file *file, char __user *userbuf, struct b43_wldev *dev; struct b43_debugfs_fops *dfops; struct b43_dfs_file *dfile; - ssize_t uninitialized_var(ret); + ssize_t ret; char *buf; const size_t bufsize = 1024 * 16; /* 16 kiB buffer */ const size_t buforder = get_order(bufsize); diff --git a/drivers/net/wireless/broadcom/b43/dma.c b/drivers/net/wireless/broadcom/b43/dma.c index d46d57b989aec..06139835055fa 100644 --- a/drivers/net/wireless/broadcom/b43/dma.c +++ b/drivers/net/wireless/broadcom/b43/dma.c @@ -50,7 +50,7 @@ static u32 b43_dma_address(struct b43_dma *dma, dma_addr_t dmaaddr, enum b43_addrtype addrtype) { - u32 uninitialized_var(addr); + u32 addr; switch (addrtype) { case B43_DMA_ADDR_LOW: diff --git a/drivers/net/wireless/broadcom/b43/lo.c b/drivers/net/wireless/broadcom/b43/lo.c index a335f94c72ff7..10cc0c0d70c3a 100644 --- a/drivers/net/wireless/broadcom/b43/lo.c +++ b/drivers/net/wireless/broadcom/b43/lo.c @@ -742,7 +742,7 @@ struct b43_lo_calib *b43_calibrate_lo_setting(struct b43_wldev *dev, }; int max_rx_gain; struct b43_lo_calib *cal; - struct lo_g_saved_values uninitialized_var(saved_regs); + struct lo_g_saved_values saved_regs; /* Values from the "TXCTL Register and Value Table" */ u16 txctl_reg; u16 txctl_value; diff --git a/drivers/net/wireless/broadcom/b43/phy_n.c b/drivers/net/wireless/broadcom/b43/phy_n.c index 3508a78226193..3a74e82c9fb68 100644 --- a/drivers/net/wireless/broadcom/b43/phy_n.c +++ b/drivers/net/wireless/broadcom/b43/phy_n.c @@ -5655,7 +5655,7 @@ static int b43_nphy_rev2_cal_rx_iq(struct b43_wldev *dev, u8 rfctl[2]; u8 afectl_core; u16 tmp[6]; - u16 uninitialized_var(cur_hpf1), uninitialized_var(cur_hpf2), cur_lna; + u16 cur_hpf1, cur_hpf2, cur_lna; u32 real, imag; enum nl80211_band band; diff --git a/drivers/net/wireless/broadcom/b43/xmit.c b/drivers/net/wireless/broadcom/b43/xmit.c index 1b9c191e2a229..c123e22046637 100644 --- a/drivers/net/wireless/broadcom/b43/xmit.c +++ b/drivers/net/wireless/broadcom/b43/xmit.c @@ -435,10 +435,10 @@ int b43_generate_txhdr(struct b43_wldev *dev, if ((rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS) || (rates[0].flags & IEEE80211_TX_RC_USE_CTS_PROTECT)) { unsigned int len; - struct ieee80211_hdr *uninitialized_var(hdr); + struct ieee80211_hdr *hdr; int rts_rate, rts_rate_fb; int rts_rate_ofdm, rts_rate_fb_ofdm; - struct b43_plcp_hdr6 *uninitialized_var(plcp); + struct b43_plcp_hdr6 *plcp; struct ieee80211_rate *rts_cts_rate; rts_cts_rate = ieee80211_get_rts_cts_rate(dev->wl->hw, info); @@ -449,7 +449,7 @@ int b43_generate_txhdr(struct b43_wldev *dev, rts_rate_fb_ofdm = b43_is_ofdm_rate(rts_rate_fb); if (rates[0].flags & IEEE80211_TX_RC_USE_CTS_PROTECT) { - struct ieee80211_cts *uninitialized_var(cts); + struct ieee80211_cts *cts; switch (dev->fw.hdr_format) { case B43_FW_HDR_598: @@ -471,7 +471,7 @@ int b43_generate_txhdr(struct b43_wldev *dev, mac_ctl |= B43_TXH_MAC_SENDCTS; len = sizeof(struct ieee80211_cts); } else { - struct ieee80211_rts *uninitialized_var(rts); + struct ieee80211_rts *rts; switch (dev->fw.hdr_format) { case B43_FW_HDR_598: @@ -663,8 +663,8 @@ void b43_rx(struct b43_wldev *dev, struct sk_buff *skb, const void *_rxhdr) const struct b43_rxhdr_fw4 *rxhdr = _rxhdr; __le16 fctl; u16 phystat0, phystat3; - u16 uninitialized_var(chanstat), uninitialized_var(mactime); - u32 uninitialized_var(macstat); + u16 chanstat, mactime; + u32 macstat; u16 chanid; int padding, rate_idx; diff --git a/drivers/net/wireless/broadcom/b43legacy/debugfs.c b/drivers/net/wireless/broadcom/b43legacy/debugfs.c index 82ef56ed7ca1b..d3c9a916b44c5 100644 --- a/drivers/net/wireless/broadcom/b43legacy/debugfs.c +++ b/drivers/net/wireless/broadcom/b43legacy/debugfs.c @@ -203,7 +203,7 @@ static ssize_t b43legacy_debugfs_read(struct file *file, char __user *userbuf, struct b43legacy_wldev *dev; struct b43legacy_debugfs_fops *dfops; struct b43legacy_dfs_file *dfile; - ssize_t uninitialized_var(ret); + ssize_t ret; char *buf; const size_t bufsize = 1024 * 16; /* 16 KiB buffer */ const size_t buforder = get_order(bufsize); diff --git a/drivers/net/wireless/broadcom/b43legacy/main.c b/drivers/net/wireless/broadcom/b43legacy/main.c index ef1f1b5d63b10..a147c93583b26 100644 --- a/drivers/net/wireless/broadcom/b43legacy/main.c +++ b/drivers/net/wireless/broadcom/b43legacy/main.c @@ -2612,7 +2612,7 @@ static void b43legacy_put_phy_into_reset(struct b43legacy_wldev *dev) static int b43legacy_switch_phymode(struct b43legacy_wl *wl, unsigned int new_mode) { - struct b43legacy_wldev *uninitialized_var(up_dev); + struct b43legacy_wldev *up_dev; struct b43legacy_wldev *down_dev; int err; bool gmode = false; diff --git a/drivers/net/wireless/cisco/airo.c b/drivers/net/wireless/cisco/airo.c index 5a6ee0b014da0..a01b42c7c07ac 100644 --- a/drivers/net/wireless/cisco/airo.c +++ b/drivers/net/wireless/cisco/airo.c @@ -6100,8 +6100,11 @@ static int airo_get_rate(struct net_device *dev, { struct airo_info *local = dev->ml_priv; StatusRid status_rid; /* Card status info */ + int ret; - readStatusRid(local, &status_rid, 1); + ret = readStatusRid(local, &status_rid, 1); + if (ret) + return -EBUSY; vwrq->value = le16_to_cpu(status_rid.currentXmitRate) * 500000; /* If more than one rate, set auto */ diff --git a/drivers/net/wireless/intel/iwlegacy/3945.c b/drivers/net/wireless/intel/iwlegacy/3945.c index 3e568ce2fb208..6703ce95e640e 100644 --- a/drivers/net/wireless/intel/iwlegacy/3945.c +++ b/drivers/net/wireless/intel/iwlegacy/3945.c @@ -2115,7 +2115,7 @@ il3945_txpower_set_from_eeprom(struct il_priv *il) /* set tx power value for all OFDM rates */ for (rate_idx = 0; rate_idx < IL_OFDM_RATES; rate_idx++) { - s32 uninitialized_var(power_idx); + s32 power_idx; int rc; /* use channel group's clip-power table, diff --git a/drivers/net/wireless/intel/iwlegacy/4965-mac.c b/drivers/net/wireless/intel/iwlegacy/4965-mac.c index 4970c19df582e..2b60473e7bf9c 100644 --- a/drivers/net/wireless/intel/iwlegacy/4965-mac.c +++ b/drivers/net/wireless/intel/iwlegacy/4965-mac.c @@ -2784,7 +2784,7 @@ il4965_hdl_tx(struct il_priv *il, struct il_rx_buf *rxb) struct ieee80211_tx_info *info; struct il4965_tx_resp *tx_resp = (void *)&pkt->u.raw[0]; u32 status = le32_to_cpu(tx_resp->u.status); - int uninitialized_var(tid); + int tid; int sta_id; int freed; u8 *qc = NULL; diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/sta.c b/drivers/net/wireless/intel/iwlwifi/mvm/sta.c index 373ace38edab7..83883ce7f55dc 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/sta.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/sta.c @@ -2237,7 +2237,7 @@ int iwl_mvm_sta_rx_agg(struct iwl_mvm *mvm, struct ieee80211_sta *sta, } if (iwl_mvm_has_new_rx_api(mvm) && start) { - u16 reorder_buf_size = buf_size * sizeof(baid_data->entries[0]); + u32 reorder_buf_size = buf_size * sizeof(baid_data->entries[0]); /* sparse doesn't like the __align() so don't check */ #ifndef __CHECKER__ diff --git a/drivers/net/wireless/intersil/orinoco/orinoco_cs.c b/drivers/net/wireless/intersil/orinoco/orinoco_cs.c index a956f965a1e5e..03bfd2482656c 100644 --- a/drivers/net/wireless/intersil/orinoco/orinoco_cs.c +++ b/drivers/net/wireless/intersil/orinoco/orinoco_cs.c @@ -96,6 +96,7 @@ orinoco_cs_probe(struct pcmcia_device *link) { struct orinoco_private *priv; struct orinoco_pccard *card; + int ret; priv = alloc_orinocodev(sizeof(*card), &link->dev, orinoco_cs_hard_reset, NULL); @@ -107,8 +108,16 @@ orinoco_cs_probe(struct pcmcia_device *link) card->p_dev = link; link->priv = priv; - return orinoco_cs_config(link); -} /* orinoco_cs_attach */ + ret = orinoco_cs_config(link); + if (ret) + goto err_free_orinocodev; + + return 0; + +err_free_orinocodev: + free_orinocodev(priv); + return ret; +} static void orinoco_cs_detach(struct pcmcia_device *link) { diff --git a/drivers/net/wireless/intersil/orinoco/spectrum_cs.c b/drivers/net/wireless/intersil/orinoco/spectrum_cs.c index b60048c95e0a8..011c86e55923e 100644 --- a/drivers/net/wireless/intersil/orinoco/spectrum_cs.c +++ b/drivers/net/wireless/intersil/orinoco/spectrum_cs.c @@ -157,6 +157,7 @@ spectrum_cs_probe(struct pcmcia_device *link) { struct orinoco_private *priv; struct orinoco_pccard *card; + int ret; priv = alloc_orinocodev(sizeof(*card), &link->dev, spectrum_cs_hard_reset, @@ -169,8 +170,16 @@ spectrum_cs_probe(struct pcmcia_device *link) card->p_dev = link; link->priv = priv; - return spectrum_cs_config(link); -} /* spectrum_cs_attach */ + ret = spectrum_cs_config(link); + if (ret) + goto err_free_orinocodev; + + return 0; + +err_free_orinocodev: + free_orinocodev(priv); + return ret; +} static void spectrum_cs_detach(struct pcmcia_device *link) { diff --git a/drivers/net/wireless/marvell/mwifiex/scan.c b/drivers/net/wireless/marvell/mwifiex/scan.c index c9f6cd2919699..4f0e78ae3dbd0 100644 --- a/drivers/net/wireless/marvell/mwifiex/scan.c +++ b/drivers/net/wireless/marvell/mwifiex/scan.c @@ -2208,9 +2208,9 @@ int mwifiex_ret_802_11_scan(struct mwifiex_private *priv, if (nd_config) { adapter->nd_info = - kzalloc(sizeof(struct cfg80211_wowlan_nd_match) + - sizeof(struct cfg80211_wowlan_nd_match *) * - scan_rsp->number_of_sets, GFP_ATOMIC); + kzalloc(struct_size(adapter->nd_info, matches, + scan_rsp->number_of_sets), + GFP_ATOMIC); if (adapter->nd_info) adapter->nd_info->n_matches = scan_rsp->number_of_sets; diff --git a/drivers/net/wireless/ray_cs.c b/drivers/net/wireless/ray_cs.c index 8704bae39e1bf..edc990d099789 100644 --- a/drivers/net/wireless/ray_cs.c +++ b/drivers/net/wireless/ray_cs.c @@ -282,13 +282,14 @@ static int ray_probe(struct pcmcia_device *p_dev) { ray_dev_t *local; struct net_device *dev; + int ret; dev_dbg(&p_dev->dev, "ray_attach()\n"); /* Allocate space for private device-specific data */ dev = alloc_etherdev(sizeof(ray_dev_t)); if (!dev) - goto fail_alloc_dev; + return -ENOMEM; local = netdev_priv(dev); local->finder = p_dev; @@ -325,11 +326,16 @@ static int ray_probe(struct pcmcia_device *p_dev) timer_setup(&local->timer, NULL, 0); this_device = p_dev; - return ray_config(p_dev); + ret = ray_config(p_dev); + if (ret) + goto err_free_dev; + + return 0; -fail_alloc_dev: - return -ENOMEM; -} /* ray_attach */ +err_free_dev: + free_netdev(dev); + return ret; +} static void ray_detach(struct pcmcia_device *link) { @@ -1651,38 +1657,34 @@ static void authenticate_timeout(struct timer_list *t) /*===========================================================================*/ static int parse_addr(char *in_str, UCHAR *out) { + int i, k; int len; - int i, j, k; - int status; if (in_str == NULL) return 0; - if ((len = strlen(in_str)) < 2) + len = strnlen(in_str, ADDRLEN * 2 + 1) - 1; + if (len < 1) return 0; memset(out, 0, ADDRLEN); - status = 1; - j = len - 1; - if (j > 12) - j = 12; i = 5; - while (j > 0) { - if ((k = hex_to_bin(in_str[j--])) != -1) + while (len > 0) { + if ((k = hex_to_bin(in_str[len--])) != -1) out[i] = k; else return 0; - if (j == 0) + if (len == 0) break; - if ((k = hex_to_bin(in_str[j--])) != -1) + if ((k = hex_to_bin(in_str[len--])) != -1) out[i] += k << 4; else return 0; if (!i--) break; } - return status; + return 1; } /*===========================================================================*/ diff --git a/drivers/net/wireless/rsi/rsi_91x_sdio.c b/drivers/net/wireless/rsi/rsi_91x_sdio.c index 48efe83c58d89..409a3e8305763 100644 --- a/drivers/net/wireless/rsi/rsi_91x_sdio.c +++ b/drivers/net/wireless/rsi/rsi_91x_sdio.c @@ -1368,9 +1368,6 @@ static void rsi_shutdown(struct device *dev) if (sdev->write_fail) rsi_dbg(INFO_ZONE, "###### Device is not ready #######\n"); - if (rsi_set_sdio_pm_caps(adapter)) - rsi_dbg(INFO_ZONE, "Setting power management caps failed\n"); - rsi_dbg(INFO_ZONE, "***** RSI module shut down *****\n"); } diff --git a/drivers/net/wireless/wl3501_cs.c b/drivers/net/wireless/wl3501_cs.c index cfde9b94b4b60..4380c5d8fdd27 100644 --- a/drivers/net/wireless/wl3501_cs.c +++ b/drivers/net/wireless/wl3501_cs.c @@ -133,8 +133,8 @@ static const struct { /** * iw_valid_channel - validate channel in regulatory domain - * @reg_comain - regulatory domain - * @channel - channel to validate + * @reg_domain: regulatory domain + * @channel: channel to validate * * Returns 0 if invalid in the specified regulatory domain, non-zero if valid. */ @@ -153,7 +153,7 @@ static int iw_valid_channel(int reg_domain, int channel) /** * iw_default_channel - get default channel for a regulatory domain - * @reg_comain - regulatory domain + * @reg_domain: regulatory domain * * Returns the default channel for a regulatory domain */ @@ -236,6 +236,7 @@ static int wl3501_get_flash_mac_addr(struct wl3501_card *this) /** * wl3501_set_to_wla - Move 'size' bytes from PC to card + * @this: Card * @dest: Card addressing space * @src: PC addressing space * @size: Bytes to move @@ -258,6 +259,7 @@ static void wl3501_set_to_wla(struct wl3501_card *this, u16 dest, void *src, /** * wl3501_get_from_wla - Move 'size' bytes from card to PC + * @this: Card * @src: Card addressing space * @dest: PC addressing space * @size: Bytes to move @@ -454,12 +456,10 @@ out: /** * wl3501_send_pkt - Send a packet. - * @this - card - * - * Send a packet. - * - * data = Ethernet raw frame. (e.g. data[0] - data[5] is Dest MAC Addr, + * @this: Card + * @data: Ethernet raw frame. (e.g. data[0] - data[5] is Dest MAC Addr, * data[6] - data[11] is Src MAC Addr) + * @len: Packet length * Ref: IEEE 802.11 */ static int wl3501_send_pkt(struct wl3501_card *this, u8 *data, u16 len) @@ -722,7 +722,7 @@ static void wl3501_mgmt_scan_confirm(struct wl3501_card *this, u16 addr) /** * wl3501_block_interrupt - Mask interrupt from SUTRO - * @this - card + * @this: Card * * Mask interrupt from SUTRO. (i.e. SUTRO cannot interrupt the HOST) * Return: 1 if interrupt is originally enabled @@ -739,7 +739,7 @@ static int wl3501_block_interrupt(struct wl3501_card *this) /** * wl3501_unblock_interrupt - Enable interrupt from SUTRO - * @this - card + * @this: Card * * Enable interrupt from SUTRO. (i.e. SUTRO can interrupt the HOST) * Return: 1 if interrupt is originally enabled @@ -1113,8 +1113,8 @@ static inline void wl3501_ack_interrupt(struct wl3501_card *this) /** * wl3501_interrupt - Hardware interrupt from card. - * @irq - Interrupt number - * @dev_id - net_device + * @irq: Interrupt number + * @dev_id: net_device * * We must acknowledge the interrupt as soon as possible, and block the * interrupt from the same card immediately to prevent re-entry. @@ -1252,7 +1252,7 @@ static int wl3501_close(struct net_device *dev) /** * wl3501_reset - Reset the SUTRO. - * @dev - network device + * @dev: network device * * It is almost the same as wl3501_open(). In fact, we may just wl3501_close() * and wl3501_open() again, but I wouldn't like to free_irq() when the driver @@ -1415,7 +1415,7 @@ static struct iw_statistics *wl3501_get_wireless_stats(struct net_device *dev) /** * wl3501_detach - deletes a driver "instance" - * @link - FILL_IN + * @link: FILL_IN * * This deletes a driver "instance". The device is de-registered with Card * Services. If it has been released, all local data structures are freed. @@ -1436,9 +1436,7 @@ static void wl3501_detach(struct pcmcia_device *link) wl3501_release(link); unregister_netdev(dev); - - if (link->priv) - free_netdev(link->priv); + free_netdev(dev); } static int wl3501_get_name(struct net_device *dev, struct iw_request_info *info, @@ -1865,6 +1863,7 @@ static int wl3501_probe(struct pcmcia_device *p_dev) { struct net_device *dev; struct wl3501_card *this; + int ret; /* The io structure describes IO port mapping */ p_dev->resource[0]->end = 16; @@ -1876,8 +1875,7 @@ static int wl3501_probe(struct pcmcia_device *p_dev) dev = alloc_etherdev(sizeof(struct wl3501_card)); if (!dev) - goto out_link; - + return -ENOMEM; dev->netdev_ops = &wl3501_netdev_ops; dev->watchdog_timeo = 5 * HZ; @@ -1890,9 +1888,15 @@ static int wl3501_probe(struct pcmcia_device *p_dev) netif_stop_queue(dev); p_dev->priv = dev; - return wl3501_config(p_dev); -out_link: - return -ENOMEM; + ret = wl3501_config(p_dev); + if (ret) + goto out_free_etherdev; + + return 0; + +out_free_etherdev: + free_netdev(dev); + return ret; } static int wl3501_config(struct pcmcia_device *link) @@ -1948,8 +1952,7 @@ static int wl3501_config(struct pcmcia_device *link) goto failed; } - for (i = 0; i < 6; i++) - dev->dev_addr[i] = ((char *)&this->mac_addr)[i]; + eth_hw_addr_set(dev, this->mac_addr); /* print probe information */ printk(KERN_INFO "%s: wl3501 @ 0x%3.3x, IRQ %d, " diff --git a/drivers/ntb/hw/amd/ntb_hw_amd.c b/drivers/ntb/hw/amd/ntb_hw_amd.c index 0b1fbb5dba9b6..7de7616803935 100644 --- a/drivers/ntb/hw/amd/ntb_hw_amd.c +++ b/drivers/ntb/hw/amd/ntb_hw_amd.c @@ -1139,12 +1139,17 @@ static struct pci_driver amd_ntb_pci_driver = { static int __init amd_ntb_pci_driver_init(void) { + int ret; pr_info("%s %s\n", NTB_DESC, NTB_VER); if (debugfs_initialized()) debugfs_dir = debugfs_create_dir(KBUILD_MODNAME, NULL); - return pci_register_driver(&amd_ntb_pci_driver); + ret = pci_register_driver(&amd_ntb_pci_driver); + if (ret) + debugfs_remove_recursive(debugfs_dir); + + return ret; } module_init(amd_ntb_pci_driver_init); diff --git a/drivers/ntb/hw/idt/ntb_hw_idt.c b/drivers/ntb/hw/idt/ntb_hw_idt.c index a67ef23e81bca..82e08f583980b 100644 --- a/drivers/ntb/hw/idt/ntb_hw_idt.c +++ b/drivers/ntb/hw/idt/ntb_hw_idt.c @@ -2692,6 +2692,7 @@ static struct pci_driver idt_pci_driver = { static int __init idt_pci_driver_init(void) { + int ret; pr_info("%s %s\n", NTB_DESC, NTB_VER); /* Create the top DebugFS directory if the FS is initialized */ @@ -2699,7 +2700,11 @@ static int __init idt_pci_driver_init(void) dbgfs_topdir = debugfs_create_dir(KBUILD_MODNAME, NULL); /* Register the NTB hardware driver to handle the PCI device */ - return pci_register_driver(&idt_pci_driver); + ret = pci_register_driver(&idt_pci_driver); + if (ret) + debugfs_remove_recursive(dbgfs_topdir); + + return ret; } module_init(idt_pci_driver_init); diff --git a/drivers/ntb/hw/intel/ntb_hw_gen1.c b/drivers/ntb/hw/intel/ntb_hw_gen1.c index 2ad263f708da7..084bd1d1ac1dc 100644 --- a/drivers/ntb/hw/intel/ntb_hw_gen1.c +++ b/drivers/ntb/hw/intel/ntb_hw_gen1.c @@ -2052,12 +2052,17 @@ static struct pci_driver intel_ntb_pci_driver = { static int __init intel_ntb_pci_driver_init(void) { + int ret; pr_info("%s %s\n", NTB_DESC, NTB_VER); if (debugfs_initialized()) debugfs_dir = debugfs_create_dir(KBUILD_MODNAME, NULL); - return pci_register_driver(&intel_ntb_pci_driver); + ret = pci_register_driver(&intel_ntb_pci_driver); + if (ret) + debugfs_remove_recursive(debugfs_dir); + + return ret; } module_init(intel_ntb_pci_driver_init); diff --git a/drivers/ntb/ntb_transport.c b/drivers/ntb/ntb_transport.c index 9398959664769..2d647a1cd0ee5 100644 --- a/drivers/ntb/ntb_transport.c +++ b/drivers/ntb/ntb_transport.c @@ -393,7 +393,7 @@ int ntb_transport_register_client_dev(char *device_name) rc = device_register(dev); if (rc) { - kfree(client_dev); + put_device(dev); goto err; } diff --git a/drivers/ntb/test/ntb_tool.c b/drivers/ntb/test/ntb_tool.c index 6301aa413c3b8..1f64146546221 100644 --- a/drivers/ntb/test/ntb_tool.c +++ b/drivers/ntb/test/ntb_tool.c @@ -998,6 +998,8 @@ static int tool_init_mws(struct tool_ctx *tc) tc->peers[pidx].outmws = devm_kcalloc(&tc->ntb->dev, tc->peers[pidx].outmw_cnt, sizeof(*tc->peers[pidx].outmws), GFP_KERNEL); + if (tc->peers[pidx].outmws == NULL) + return -ENOMEM; for (widx = 0; widx < tc->peers[pidx].outmw_cnt; widx++) { tc->peers[pidx].outmws[widx].pidx = pidx; diff --git a/drivers/pci/controller/dwc/pcie-qcom.c b/drivers/pci/controller/dwc/pcie-qcom.c index 133fad284c9fa..ea0cd2401d6b7 100644 --- a/drivers/pci/controller/dwc/pcie-qcom.c +++ b/drivers/pci/controller/dwc/pcie-qcom.c @@ -758,6 +758,8 @@ static int qcom_pcie_get_resources_2_4_0(struct qcom_pcie *pcie) if (IS_ERR(res->phy_ahb_reset)) return PTR_ERR(res->phy_ahb_reset); + dw_pcie_dbi_ro_wr_dis(pci); + return 0; } diff --git a/drivers/pci/controller/pcie-rockchip-ep.c b/drivers/pci/controller/pcie-rockchip-ep.c index 06dd2ab73b6ee..4d3a589af1296 100644 --- a/drivers/pci/controller/pcie-rockchip-ep.c +++ b/drivers/pci/controller/pcie-rockchip-ep.c @@ -124,6 +124,7 @@ static void rockchip_pcie_prog_ep_ob_atu(struct rockchip_pcie *rockchip, u8 fn, static int rockchip_pcie_ep_write_header(struct pci_epc *epc, u8 fn, struct pci_epf_header *hdr) { + u32 reg; struct rockchip_pcie_ep *ep = epc_get_drvdata(epc); struct rockchip_pcie *rockchip = &ep->rockchip; @@ -136,8 +137,9 @@ static int rockchip_pcie_ep_write_header(struct pci_epc *epc, u8 fn, PCIE_CORE_CONFIG_VENDOR); } - rockchip_pcie_write(rockchip, hdr->deviceid << 16, - ROCKCHIP_PCIE_EP_FUNC_BASE(fn) + PCI_VENDOR_ID); + reg = rockchip_pcie_read(rockchip, PCIE_EP_CONFIG_DID_VID); + reg = (reg & 0xFFFF) | (hdr->deviceid << 16); + rockchip_pcie_write(rockchip, reg, PCIE_EP_CONFIG_DID_VID); rockchip_pcie_write(rockchip, hdr->revid | @@ -311,15 +313,15 @@ static int rockchip_pcie_ep_set_msi(struct pci_epc *epc, u8 fn, { struct rockchip_pcie_ep *ep = epc_get_drvdata(epc); struct rockchip_pcie *rockchip = &ep->rockchip; - u16 flags; + u32 flags; flags = rockchip_pcie_read(rockchip, ROCKCHIP_PCIE_EP_FUNC_BASE(fn) + ROCKCHIP_PCIE_EP_MSI_CTRL_REG); flags &= ~ROCKCHIP_PCIE_EP_MSI_CTRL_MMC_MASK; flags |= - ((multi_msg_cap << 1) << ROCKCHIP_PCIE_EP_MSI_CTRL_MMC_OFFSET) | - PCI_MSI_FLAGS_64BIT; + (multi_msg_cap << ROCKCHIP_PCIE_EP_MSI_CTRL_MMC_OFFSET) | + (PCI_MSI_FLAGS_64BIT << ROCKCHIP_PCIE_EP_MSI_FLAGS_OFFSET); flags &= ~ROCKCHIP_PCIE_EP_MSI_CTRL_MASK_MSI_CAP; rockchip_pcie_write(rockchip, flags, ROCKCHIP_PCIE_EP_FUNC_BASE(fn) + @@ -331,7 +333,7 @@ static int rockchip_pcie_ep_get_msi(struct pci_epc *epc, u8 fn) { struct rockchip_pcie_ep *ep = epc_get_drvdata(epc); struct rockchip_pcie *rockchip = &ep->rockchip; - u16 flags; + u32 flags; flags = rockchip_pcie_read(rockchip, ROCKCHIP_PCIE_EP_FUNC_BASE(fn) + @@ -344,48 +346,25 @@ static int rockchip_pcie_ep_get_msi(struct pci_epc *epc, u8 fn) } static void rockchip_pcie_ep_assert_intx(struct rockchip_pcie_ep *ep, u8 fn, - u8 intx, bool is_asserted) + u8 intx, bool do_assert) { struct rockchip_pcie *rockchip = &ep->rockchip; - u32 r = ep->max_regions - 1; - u32 offset; - u32 status; - u8 msg_code; - - if (unlikely(ep->irq_pci_addr != ROCKCHIP_PCIE_EP_PCI_LEGACY_IRQ_ADDR || - ep->irq_pci_fn != fn)) { - rockchip_pcie_prog_ep_ob_atu(rockchip, fn, r, - AXI_WRAPPER_NOR_MSG, - ep->irq_phys_addr, 0, 0); - ep->irq_pci_addr = ROCKCHIP_PCIE_EP_PCI_LEGACY_IRQ_ADDR; - ep->irq_pci_fn = fn; - } intx &= 3; - if (is_asserted) { + + if (do_assert) { ep->irq_pending |= BIT(intx); - msg_code = ROCKCHIP_PCIE_MSG_CODE_ASSERT_INTA + intx; + rockchip_pcie_write(rockchip, + PCIE_CLIENT_INT_IN_ASSERT | + PCIE_CLIENT_INT_PEND_ST_PEND, + PCIE_CLIENT_LEGACY_INT_CTRL); } else { ep->irq_pending &= ~BIT(intx); - msg_code = ROCKCHIP_PCIE_MSG_CODE_DEASSERT_INTA + intx; + rockchip_pcie_write(rockchip, + PCIE_CLIENT_INT_IN_DEASSERT | + PCIE_CLIENT_INT_PEND_ST_NORMAL, + PCIE_CLIENT_LEGACY_INT_CTRL); } - - status = rockchip_pcie_read(rockchip, - ROCKCHIP_PCIE_EP_FUNC_BASE(fn) + - ROCKCHIP_PCIE_EP_CMD_STATUS); - status &= ROCKCHIP_PCIE_EP_CMD_STATUS_IS; - - if ((status != 0) ^ (ep->irq_pending != 0)) { - status ^= ROCKCHIP_PCIE_EP_CMD_STATUS_IS; - rockchip_pcie_write(rockchip, status, - ROCKCHIP_PCIE_EP_FUNC_BASE(fn) + - ROCKCHIP_PCIE_EP_CMD_STATUS); - } - - offset = - ROCKCHIP_PCIE_MSG_ROUTING(ROCKCHIP_PCIE_MSG_ROUTING_LOCAL_INTX) | - ROCKCHIP_PCIE_MSG_CODE(msg_code) | ROCKCHIP_PCIE_MSG_NO_DATA; - writel(0, ep->irq_cpu_addr + offset); } static int rockchip_pcie_ep_send_legacy_irq(struct rockchip_pcie_ep *ep, u8 fn, @@ -415,7 +394,7 @@ static int rockchip_pcie_ep_send_msi_irq(struct rockchip_pcie_ep *ep, u8 fn, u8 interrupt_num) { struct rockchip_pcie *rockchip = &ep->rockchip; - u16 flags, mme, data, data_mask; + u32 flags, mme, data, data_mask; u8 msi_count; u64 pci_addr, pci_addr_mask = 0xff; @@ -620,6 +599,9 @@ static int rockchip_pcie_ep_probe(struct platform_device *pdev) ep->irq_pci_addr = ROCKCHIP_PCIE_EP_DUMMY_IRQ_ADDR; + rockchip_pcie_write(rockchip, PCIE_CLIENT_CONF_ENABLE, + PCIE_CLIENT_CONFIG); + return 0; err_epc_mem_exit: pci_epc_mem_exit(epc); diff --git a/drivers/pci/controller/pcie-rockchip.c b/drivers/pci/controller/pcie-rockchip.c index c53d1322a3d6c..b047437605cb2 100644 --- a/drivers/pci/controller/pcie-rockchip.c +++ b/drivers/pci/controller/pcie-rockchip.c @@ -14,6 +14,7 @@ #include #include #include +#include #include #include #include @@ -154,6 +155,12 @@ int rockchip_pcie_parse_dt(struct rockchip_pcie *rockchip) } EXPORT_SYMBOL_GPL(rockchip_pcie_parse_dt); +#define rockchip_pcie_read_addr(addr) rockchip_pcie_read(rockchip, addr) +/* 100 ms max wait time for PHY PLLs to lock */ +#define RK_PHY_PLL_LOCK_TIMEOUT_US 100000 +/* Sleep should be less than 20ms */ +#define RK_PHY_PLL_LOCK_SLEEP_US 1000 + int rockchip_pcie_init_port(struct rockchip_pcie *rockchip) { struct device *dev = rockchip->dev; @@ -255,6 +262,16 @@ int rockchip_pcie_init_port(struct rockchip_pcie *rockchip) } } + err = readx_poll_timeout(rockchip_pcie_read_addr, + PCIE_CLIENT_SIDE_BAND_STATUS, + regs, !(regs & PCIE_CLIENT_PHY_ST), + RK_PHY_PLL_LOCK_SLEEP_US, + RK_PHY_PLL_LOCK_TIMEOUT_US); + if (err) { + dev_err(dev, "PHY PLLs could not lock, %d\n", err); + goto err_power_off_phy; + } + /* * Please don't reorder the deassert sequence of the following * four reset pins. diff --git a/drivers/pci/controller/pcie-rockchip.h b/drivers/pci/controller/pcie-rockchip.h index 8e87a059ce73d..1c45b3c32151c 100644 --- a/drivers/pci/controller/pcie-rockchip.h +++ b/drivers/pci/controller/pcie-rockchip.h @@ -37,6 +37,13 @@ #define PCIE_CLIENT_MODE_EP HIWORD_UPDATE(0x0040, 0) #define PCIE_CLIENT_GEN_SEL_1 HIWORD_UPDATE(0x0080, 0) #define PCIE_CLIENT_GEN_SEL_2 HIWORD_UPDATE_BIT(0x0080) +#define PCIE_CLIENT_LEGACY_INT_CTRL (PCIE_CLIENT_BASE + 0x0c) +#define PCIE_CLIENT_INT_IN_ASSERT HIWORD_UPDATE_BIT(0x0002) +#define PCIE_CLIENT_INT_IN_DEASSERT HIWORD_UPDATE(0x0002, 0) +#define PCIE_CLIENT_INT_PEND_ST_PEND HIWORD_UPDATE_BIT(0x0001) +#define PCIE_CLIENT_INT_PEND_ST_NORMAL HIWORD_UPDATE(0x0001, 0) +#define PCIE_CLIENT_SIDE_BAND_STATUS (PCIE_CLIENT_BASE + 0x20) +#define PCIE_CLIENT_PHY_ST BIT(12) #define PCIE_CLIENT_DEBUG_OUT_0 (PCIE_CLIENT_BASE + 0x3c) #define PCIE_CLIENT_DEBUG_LTSSM_MASK GENMASK(5, 0) #define PCIE_CLIENT_DEBUG_LTSSM_L1 0x18 @@ -132,6 +139,8 @@ #define PCIE_RC_RP_ATS_BASE 0x400000 #define PCIE_RC_CONFIG_NORMAL_BASE 0x800000 #define PCIE_RC_CONFIG_BASE 0xa00000 +#define PCIE_EP_CONFIG_BASE 0xa00000 +#define PCIE_EP_CONFIG_DID_VID (PCIE_EP_CONFIG_BASE + 0x00) #define PCIE_RC_CONFIG_RID_CCR (PCIE_RC_CONFIG_BASE + 0x08) #define PCIE_RC_CONFIG_SCC_SHIFT 16 #define PCIE_RC_CONFIG_DCR (PCIE_RC_CONFIG_BASE + 0xc4) @@ -223,6 +232,7 @@ #define ROCKCHIP_PCIE_EP_CMD_STATUS 0x4 #define ROCKCHIP_PCIE_EP_CMD_STATUS_IS BIT(19) #define ROCKCHIP_PCIE_EP_MSI_CTRL_REG 0x90 +#define ROCKCHIP_PCIE_EP_MSI_FLAGS_OFFSET 16 #define ROCKCHIP_PCIE_EP_MSI_CTRL_MMC_OFFSET 17 #define ROCKCHIP_PCIE_EP_MSI_CTRL_MMC_MASK GENMASK(19, 17) #define ROCKCHIP_PCIE_EP_MSI_CTRL_MME_OFFSET 20 @@ -230,7 +240,6 @@ #define ROCKCHIP_PCIE_EP_MSI_CTRL_ME BIT(16) #define ROCKCHIP_PCIE_EP_MSI_CTRL_MASK_MSI_CAP BIT(24) #define ROCKCHIP_PCIE_EP_DUMMY_IRQ_ADDR 0x1 -#define ROCKCHIP_PCIE_EP_PCI_LEGACY_IRQ_ADDR 0x3 #define ROCKCHIP_PCIE_EP_FUNC_BASE(fn) (((fn) << 12) & GENMASK(19, 12)) #define ROCKCHIP_PCIE_AT_IB_EP_FUNC_BAR_ADDR0(fn, bar) \ (PCIE_RC_RP_ATS_BASE + 0x0840 + (fn) * 0x0040 + (bar) * 0x0008) diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index 7ac6f4710908b..c8326c7b468fa 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -2521,13 +2521,13 @@ static const struct dmi_system_id bridge_d3_blacklist[] = { { /* * Downstream device is not accessible after putting a root port - * into D3cold and back into D0 on Elo i2. + * into D3cold and back into D0 on Elo Continental Z2 board */ - .ident = "Elo i2", + .ident = "Elo Continental Z2", .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "Elo Touch Solutions"), - DMI_MATCH(DMI_PRODUCT_NAME, "Elo i2"), - DMI_MATCH(DMI_PRODUCT_VERSION, "RevB"), + DMI_MATCH(DMI_BOARD_VENDOR, "Elo Touch Solutions"), + DMI_MATCH(DMI_BOARD_NAME, "Geminilake"), + DMI_MATCH(DMI_BOARD_VERSION, "Continental Z2"), }, }, #endif diff --git a/drivers/pci/pcie/aspm.c b/drivers/pci/pcie/aspm.c index 279f9f0197b01..eec62f7377f48 100644 --- a/drivers/pci/pcie/aspm.c +++ b/drivers/pci/pcie/aspm.c @@ -203,12 +203,39 @@ static void pcie_clkpm_cap_init(struct pcie_link_state *link, int blacklist) link->clkpm_disable = blacklist ? 1 : 0; } -static bool pcie_retrain_link(struct pcie_link_state *link) +static int pcie_wait_for_retrain(struct pci_dev *pdev) +{ + unsigned long end_jiffies; + u16 reg16; + + /* Wait for Link Training to be cleared by hardware */ + end_jiffies = jiffies + LINK_RETRAIN_TIMEOUT; + do { + pcie_capability_read_word(pdev, PCI_EXP_LNKSTA, ®16); + if (!(reg16 & PCI_EXP_LNKSTA_LT)) + return 0; + msleep(1); + } while (time_before(jiffies, end_jiffies)); + + return -ETIMEDOUT; +} + +static int pcie_retrain_link(struct pcie_link_state *link) { struct pci_dev *parent = link->pdev; - unsigned long start_jiffies; + int rc; u16 reg16; + /* + * Ensure the updated LNKCTL parameters are used during link + * training by checking that there is no ongoing link training to + * avoid LTSSM race as recommended in Implementation Note at the + * end of PCIe r6.0.1 sec 7.5.3.7. + */ + rc = pcie_wait_for_retrain(parent); + if (rc) + return rc; + pcie_capability_read_word(parent, PCI_EXP_LNKCTL, ®16); reg16 |= PCI_EXP_LNKCTL_RL; pcie_capability_write_word(parent, PCI_EXP_LNKCTL, reg16); @@ -222,17 +249,7 @@ static bool pcie_retrain_link(struct pcie_link_state *link) pcie_capability_write_word(parent, PCI_EXP_LNKCTL, reg16); } - /* Wait for link training end. Break out after waiting for timeout */ - start_jiffies = jiffies; - for (;;) { - pcie_capability_read_word(parent, PCI_EXP_LNKSTA, ®16); - if (!(reg16 & PCI_EXP_LNKSTA_LT)) - break; - if (time_after(jiffies, start_jiffies + LINK_RETRAIN_TIMEOUT)) - break; - msleep(1); - } - return !(reg16 & PCI_EXP_LNKSTA_LT); + return pcie_wait_for_retrain(parent); } /* @@ -301,15 +318,15 @@ static void pcie_aspm_configure_common_clock(struct pcie_link_state *link) reg16 &= ~PCI_EXP_LNKCTL_CCC; pcie_capability_write_word(parent, PCI_EXP_LNKCTL, reg16); - if (pcie_retrain_link(link)) - return; + if (pcie_retrain_link(link)) { - /* Training failed. Restore common clock configurations */ - pci_err(parent, "ASPM: Could not configure common clock\n"); - list_for_each_entry(child, &linkbus->devices, bus_list) - pcie_capability_write_word(child, PCI_EXP_LNKCTL, + /* Training failed. Restore common clock configurations */ + pci_err(parent, "ASPM: Could not configure common clock\n"); + list_for_each_entry(child, &linkbus->devices, bus_list) + pcie_capability_write_word(child, PCI_EXP_LNKCTL, child_reg[PCI_FUNC(child->devfn)]); - pcie_capability_write_word(parent, PCI_EXP_LNKCTL, parent_reg); + pcie_capability_write_word(parent, PCI_EXP_LNKCTL, parent_reg); + } } /* Convert L0s latency encoding to ns */ diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index afa6acb58eec8..fa9d6c8f1cf89 100644 --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c @@ -4074,6 +4074,8 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_MARVELL_EXT, 0x9220, /* https://bugzilla.kernel.org/show_bug.cgi?id=42679#c49 */ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_MARVELL_EXT, 0x9230, quirk_dma_func1_alias); +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_MARVELL_EXT, 0x9235, + quirk_dma_func1_alias); DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_TTI, 0x0642, quirk_dma_func1_alias); DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_TTI, 0x0645, diff --git a/drivers/phy/hisilicon/phy-hisi-inno-usb2.c b/drivers/phy/hisilicon/phy-hisi-inno-usb2.c index 524381249a2b8..b51e19402ab0c 100644 --- a/drivers/phy/hisilicon/phy-hisi-inno-usb2.c +++ b/drivers/phy/hisilicon/phy-hisi-inno-usb2.c @@ -167,7 +167,7 @@ static int hisi_inno_phy_probe(struct platform_device *pdev) phy_set_drvdata(phy, &priv->ports[i]); i++; - if (i > INNO_PHY_PORT_NUM) { + if (i >= INNO_PHY_PORT_NUM) { dev_warn(dev, "Support %d ports in maximum\n", i); break; } diff --git a/drivers/pinctrl/intel/pinctrl-cherryview.c b/drivers/pinctrl/intel/pinctrl-cherryview.c index 25932d2a71547..ef8eb42e4d383 100644 --- a/drivers/pinctrl/intel/pinctrl-cherryview.c +++ b/drivers/pinctrl/intel/pinctrl-cherryview.c @@ -1032,11 +1032,6 @@ static int chv_config_get(struct pinctrl_dev *pctldev, unsigned pin, break; - case PIN_CONFIG_DRIVE_OPEN_DRAIN: - if (!(ctrl1 & CHV_PADCTRL1_ODEN)) - return -EINVAL; - break; - case PIN_CONFIG_BIAS_HIGH_IMPEDANCE: { u32 cfg; @@ -1046,6 +1041,16 @@ static int chv_config_get(struct pinctrl_dev *pctldev, unsigned pin, return -EINVAL; break; + + case PIN_CONFIG_DRIVE_PUSH_PULL: + if (ctrl1 & CHV_PADCTRL1_ODEN) + return -EINVAL; + break; + + case PIN_CONFIG_DRIVE_OPEN_DRAIN: + if (!(ctrl1 & CHV_PADCTRL1_ODEN)) + return -EINVAL; + break; } default: diff --git a/drivers/pinctrl/pinctrl-amd.c b/drivers/pinctrl/pinctrl-amd.c index a44902b140879..c140ee16fe7c8 100644 --- a/drivers/pinctrl/pinctrl-amd.c +++ b/drivers/pinctrl/pinctrl-amd.c @@ -127,6 +127,14 @@ static int amd_gpio_set_debounce(struct gpio_chip *gc, unsigned offset, struct amd_gpio *gpio_dev = gpiochip_get_data(gc); raw_spin_lock_irqsave(&gpio_dev->lock, flags); + + /* Use special handling for Pin0 debounce */ + if (offset == 0) { + pin_reg = readl(gpio_dev->base + WAKE_INT_MASTER_REG); + if (pin_reg & INTERNAL_GPIO0_DEBOUNCE) + debounce = 0; + } + pin_reg = readl(gpio_dev->base + offset * 4); if (debounce) { @@ -182,18 +190,6 @@ static int amd_gpio_set_debounce(struct gpio_chip *gc, unsigned offset, return ret; } -static int amd_gpio_set_config(struct gpio_chip *gc, unsigned offset, - unsigned long config) -{ - u32 debounce; - - if (pinconf_to_config_param(config) != PIN_CONFIG_INPUT_DEBOUNCE) - return -ENOTSUPP; - - debounce = pinconf_to_config_argument(config); - return amd_gpio_set_debounce(gc, offset, debounce); -} - #ifdef CONFIG_DEBUG_FS static void amd_gpio_dbg_show(struct seq_file *s, struct gpio_chip *gc) { @@ -216,6 +212,7 @@ static void amd_gpio_dbg_show(struct seq_file *s, struct gpio_chip *gc) char *output_value; char *output_enable; + seq_printf(s, "WAKE_INT_MASTER_REG: 0x%08x\n", readl(gpio_dev->base + WAKE_INT_MASTER_REG)); for (bank = 0; bank < gpio_dev->hwbank_num; bank++) { seq_printf(s, "GPIO bank%d\t", bank); @@ -677,7 +674,7 @@ static int amd_pinconf_get(struct pinctrl_dev *pctldev, } static int amd_pinconf_set(struct pinctrl_dev *pctldev, unsigned int pin, - unsigned long *configs, unsigned num_configs) + unsigned long *configs, unsigned int num_configs) { int i; u32 arg; @@ -767,6 +764,20 @@ static int amd_pinconf_group_set(struct pinctrl_dev *pctldev, return 0; } +static int amd_gpio_set_config(struct gpio_chip *gc, unsigned int pin, + unsigned long config) +{ + struct amd_gpio *gpio_dev = gpiochip_get_data(gc); + + if (pinconf_to_config_param(config) == PIN_CONFIG_INPUT_DEBOUNCE) { + u32 debounce = pinconf_to_config_argument(config); + + return amd_gpio_set_debounce(gc, pin, debounce); + } + + return amd_pinconf_set(gpio_dev->pctrl, pin, &config, 1); +} + static const struct pinconf_ops amd_pinconf_ops = { .pin_config_get = amd_pinconf_get, .pin_config_set = amd_pinconf_set, @@ -794,9 +805,9 @@ static void amd_gpio_irq_init(struct amd_gpio *gpio_dev) raw_spin_lock_irqsave(&gpio_dev->lock, flags); - pin_reg = readl(gpio_dev->base + i * 4); + pin_reg = readl(gpio_dev->base + pin * 4); pin_reg &= ~mask; - writel(pin_reg, gpio_dev->base + i * 4); + writel(pin_reg, gpio_dev->base + pin * 4); raw_spin_unlock_irqrestore(&gpio_dev->lock, flags); } diff --git a/drivers/pinctrl/pinctrl-amd.h b/drivers/pinctrl/pinctrl-amd.h index 91da7527f0020..0f7c02bc9044a 100644 --- a/drivers/pinctrl/pinctrl-amd.h +++ b/drivers/pinctrl/pinctrl-amd.h @@ -21,6 +21,7 @@ #define AMD_GPIO_PINS_BANK3 32 #define WAKE_INT_MASTER_REG 0xfc +#define INTERNAL_GPIO0_DEBOUNCE (1 << 15) #define EOI_MASK (1 << 29) #define WAKE_INT_STATUS_REG0 0x2f8 diff --git a/drivers/pinctrl/pinctrl-at91-pio4.c b/drivers/pinctrl/pinctrl-at91-pio4.c index 5b883eb49ce92..cbbda24bf6a80 100644 --- a/drivers/pinctrl/pinctrl-at91-pio4.c +++ b/drivers/pinctrl/pinctrl-at91-pio4.c @@ -1024,6 +1024,8 @@ static int atmel_pinctrl_probe(struct platform_device *pdev) /* Pin naming convention: P(bank_name)(bank_pin_number). */ pin_desc[i].name = devm_kasprintf(&pdev->dev, GFP_KERNEL, "P%c%d", bank + 'A', line); + if (!pin_desc[i].name) + return -ENOMEM; group->name = group_names[i] = pin_desc[i].name; group->pin = pin_desc[i].number; diff --git a/drivers/platform/x86/hdaps.c b/drivers/platform/x86/hdaps.c index c26baf77938ea..96cc87d123292 100644 --- a/drivers/platform/x86/hdaps.c +++ b/drivers/platform/x86/hdaps.c @@ -378,7 +378,7 @@ static ssize_t hdaps_variance_show(struct device *dev, static ssize_t hdaps_temp1_show(struct device *dev, struct device_attribute *attr, char *buf) { - u8 uninitialized_var(temp); + u8 temp; int ret; ret = hdaps_readb_one(HDAPS_PORT_TEMP1, &temp); @@ -391,7 +391,7 @@ static ssize_t hdaps_temp1_show(struct device *dev, static ssize_t hdaps_temp2_show(struct device *dev, struct device_attribute *attr, char *buf) { - u8 uninitialized_var(temp); + u8 temp; int ret; ret = hdaps_readb_one(HDAPS_PORT_TEMP2, &temp); diff --git a/drivers/platform/x86/msi-laptop.c b/drivers/platform/x86/msi-laptop.c index 42b31c549db00..1781e67781a55 100644 --- a/drivers/platform/x86/msi-laptop.c +++ b/drivers/platform/x86/msi-laptop.c @@ -223,7 +223,7 @@ static ssize_t set_device_state(const char *buf, size_t count, u8 mask) return -EINVAL; if (quirks->ec_read_only) - return -EOPNOTSUPP; + return 0; /* read current device state */ result = ec_read(MSI_STANDARD_EC_COMMAND_ADDRESS, &rdata); @@ -854,15 +854,15 @@ static bool msi_laptop_i8042_filter(unsigned char data, unsigned char str, static void msi_init_rfkill(struct work_struct *ignored) { if (rfk_wlan) { - rfkill_set_sw_state(rfk_wlan, !wlan_s); + msi_rfkill_set_state(rfk_wlan, !wlan_s); rfkill_wlan_set(NULL, !wlan_s); } if (rfk_bluetooth) { - rfkill_set_sw_state(rfk_bluetooth, !bluetooth_s); + msi_rfkill_set_state(rfk_bluetooth, !bluetooth_s); rfkill_bluetooth_set(NULL, !bluetooth_s); } if (rfk_threeg) { - rfkill_set_sw_state(rfk_threeg, !threeg_s); + msi_rfkill_set_state(rfk_threeg, !threeg_s); rfkill_threeg_set(NULL, !threeg_s); } } diff --git a/drivers/rtc/rtc-st-lpc.c b/drivers/rtc/rtc-st-lpc.c index e66439b6247a4..e8a8ca3545f00 100644 --- a/drivers/rtc/rtc-st-lpc.c +++ b/drivers/rtc/rtc-st-lpc.c @@ -239,7 +239,7 @@ static int st_rtc_probe(struct platform_device *pdev) enable_irq_wake(rtc->irq); disable_irq(rtc->irq); - rtc->clk = clk_get(&pdev->dev, NULL); + rtc->clk = devm_clk_get(&pdev->dev, NULL); if (IS_ERR(rtc->clk)) { dev_err(&pdev->dev, "Unable to request clock\n"); return PTR_ERR(rtc->clk); diff --git a/drivers/s390/block/dasd_ioctl.c b/drivers/s390/block/dasd_ioctl.c index 2016e0ed58657..9f3f483137598 100644 --- a/drivers/s390/block/dasd_ioctl.c +++ b/drivers/s390/block/dasd_ioctl.c @@ -137,6 +137,7 @@ static int dasd_ioctl_resume(struct dasd_block *block) spin_unlock_irqrestore(get_ccwdev_lock(base->cdev), flags); dasd_schedule_block_bh(block); + dasd_schedule_device_bh(base); return 0; } diff --git a/drivers/s390/scsi/zfcp_fc.c b/drivers/s390/scsi/zfcp_fc.c index dc87a6b84d739..72e9e2945ee09 100644 --- a/drivers/s390/scsi/zfcp_fc.c +++ b/drivers/s390/scsi/zfcp_fc.c @@ -534,8 +534,7 @@ static void zfcp_fc_adisc_handler(void *data) /* re-init to undo drop from zfcp_fc_adisc() */ port->d_id = ntoh24(adisc_resp->adisc_port_id); - /* port is good, unblock rport without going through erp */ - zfcp_scsi_schedule_rport_register(port); + /* port is still good, nothing to do */ out: atomic_andnot(ZFCP_STATUS_PORT_LINK_TEST, &port->status); put_device(&port->dev); @@ -595,9 +594,6 @@ void zfcp_fc_link_test_work(struct work_struct *work) int retval; set_worker_desc("zadisc%16llx", port->wwpn); /* < WORKER_DESC_LEN=24 */ - get_device(&port->dev); - port->rport_task = RPORT_DEL; - zfcp_scsi_rport_work(&port->rport_work); /* only issue one test command at one time per port */ if (atomic_read(&port->status) & ZFCP_STATUS_PORT_LINK_TEST) diff --git a/drivers/scsi/3w-xxxx.c b/drivers/scsi/3w-xxxx.c index 471366945bd4f..8a61e832607eb 100644 --- a/drivers/scsi/3w-xxxx.c +++ b/drivers/scsi/3w-xxxx.c @@ -2303,8 +2303,10 @@ static int tw_probe(struct pci_dev *pdev, const struct pci_device_id *dev_id) TW_DISABLE_INTERRUPTS(tw_dev); /* Initialize the card */ - if (tw_reset_sequence(tw_dev)) + if (tw_reset_sequence(tw_dev)) { + retval = -EINVAL; goto out_release_mem_region; + } /* Set host specific parameters */ host->max_id = TW_MAX_UNITS; diff --git a/drivers/scsi/dc395x.c b/drivers/scsi/dc395x.c index 8b5a07503d5f0..fdfa88e0d1d07 100644 --- a/drivers/scsi/dc395x.c +++ b/drivers/scsi/dc395x.c @@ -4275,7 +4275,7 @@ static int adapter_sg_tables_alloc(struct AdapterCtlBlk *acb) const unsigned srbs_per_page = PAGE_SIZE/SEGMENTX_LEN; int srb_idx = 0; unsigned i = 0; - struct SGentry *uninitialized_var(ptr); + struct SGentry *ptr; for (i = 0; i < DC395x_MAX_SRB_CNT; i++) acb->srb_array[i].segment_x = NULL; diff --git a/drivers/scsi/pm8001/pm8001_hwi.c b/drivers/scsi/pm8001/pm8001_hwi.c index d532230c62f3e..69695bb99925b 100644 --- a/drivers/scsi/pm8001/pm8001_hwi.c +++ b/drivers/scsi/pm8001/pm8001_hwi.c @@ -4174,7 +4174,7 @@ static int process_oq(struct pm8001_hba_info *pm8001_ha, u8 vec) { struct outbound_queue_table *circularQ; void *pMsg1 = NULL; - u8 uninitialized_var(bc); + u8 bc; u32 ret = MPI_IO_STATUS_FAIL; unsigned long flags; diff --git a/drivers/scsi/pm8001/pm80xx_hwi.c b/drivers/scsi/pm8001/pm80xx_hwi.c index d655f72db51d5..067be417e251b 100644 --- a/drivers/scsi/pm8001/pm80xx_hwi.c +++ b/drivers/scsi/pm8001/pm80xx_hwi.c @@ -3811,7 +3811,7 @@ static int process_oq(struct pm8001_hba_info *pm8001_ha, u8 vec) { struct outbound_queue_table *circularQ; void *pMsg1 = NULL; - u8 uninitialized_var(bc); + u8 bc; u32 ret = MPI_IO_STATUS_FAIL; unsigned long flags; u32 regval; diff --git a/drivers/scsi/qla2xxx/qla_attr.c b/drivers/scsi/qla2xxx/qla_attr.c index d46a10d24ed4b..6c9095d0aa0f4 100644 --- a/drivers/scsi/qla2xxx/qla_attr.c +++ b/drivers/scsi/qla2xxx/qla_attr.c @@ -1800,6 +1800,7 @@ static void qla2x00_terminate_rport_io(struct fc_rport *rport) { fc_port_t *fcport = *(fc_port_t **)rport->dd_data; + scsi_qla_host_t *vha; if (!fcport) return; @@ -1809,9 +1810,12 @@ qla2x00_terminate_rport_io(struct fc_rport *rport) if (test_bit(ABORT_ISP_ACTIVE, &fcport->vha->dpc_flags)) return; + vha = fcport->vha; if (unlikely(pci_channel_offline(fcport->vha->hw->pdev))) { qla2x00_abort_all_cmds(fcport->vha, DID_NO_CONNECT << 16); + qla2x00_eh_wait_for_pending_commands(fcport->vha, fcport->d_id.b24, + 0, WAIT_TARGET); return; } /* @@ -1826,6 +1830,15 @@ qla2x00_terminate_rport_io(struct fc_rport *rport) else qla2x00_port_logout(fcport->vha, fcport); } + + /* check for any straggling io left behind */ + if (qla2x00_eh_wait_for_pending_commands(fcport->vha, fcport->d_id.b24, 0, WAIT_TARGET)) { + ql_log(ql_log_warn, vha, 0x300b, + "IO not return. Resetting. \n"); + set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags); + qla2xxx_wake_dpc(vha); + qla2x00_wait_for_chip_reset(vha); + } } static int diff --git a/drivers/scsi/qla2xxx/qla_bsg.c b/drivers/scsi/qla2xxx/qla_bsg.c index eae1665729643..430dfe3d5416a 100644 --- a/drivers/scsi/qla2xxx/qla_bsg.c +++ b/drivers/scsi/qla2xxx/qla_bsg.c @@ -264,6 +264,10 @@ qla2x00_process_els(struct bsg_job *bsg_job) if (bsg_request->msgcode == FC_BSG_RPT_ELS) { rport = fc_bsg_to_rport(bsg_job); + if (!rport) { + rval = -ENOMEM; + goto done; + } fcport = *(fc_port_t **) rport->dd_data; host = rport_to_shost(rport); vha = shost_priv(host); @@ -2484,6 +2488,8 @@ qla24xx_bsg_request(struct bsg_job *bsg_job) if (bsg_request->msgcode == FC_BSG_RPT_ELS) { rport = fc_bsg_to_rport(bsg_job); + if (!rport) + return ret; host = rport_to_shost(rport); vha = shost_priv(host); } else { diff --git a/drivers/scsi/qla2xxx/qla_iocb.c b/drivers/scsi/qla2xxx/qla_iocb.c index 7e47321e003c8..23cd9ff824789 100644 --- a/drivers/scsi/qla2xxx/qla_iocb.c +++ b/drivers/scsi/qla2xxx/qla_iocb.c @@ -603,7 +603,8 @@ qla24xx_build_scsi_type_6_iocbs(srb_t *sp, struct cmd_type_6 *cmd_pkt, *((uint32_t *)(&cmd_pkt->entry_type)) = cpu_to_le32(COMMAND_TYPE_6); /* No data transfer */ - if (!scsi_bufflen(cmd) || cmd->sc_data_direction == DMA_NONE) { + if (!scsi_bufflen(cmd) || cmd->sc_data_direction == DMA_NONE || + tot_dsds == 0) { cmd_pkt->byte_count = cpu_to_le32(0); return 0; } diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index 7863ad1390f8a..4580774b2c3e7 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c @@ -4604,7 +4604,8 @@ struct scsi_qla_host *qla2x00_create_host(struct scsi_host_template *sht, } INIT_DELAYED_WORK(&vha->scan.scan_work, qla_scan_work_fn); - sprintf(vha->host_str, "%s_%ld", QLA2XXX_DRIVER_NAME, vha->host_no); + snprintf(vha->host_str, sizeof(vha->host_str), "%s_%lu", + QLA2XXX_DRIVER_NAME, vha->host_no); ql_dbg(ql_dbg_init, vha, 0x0041, "Allocated the host=%p hw=%p vha=%p dev_name=%s", vha->host, vha->hw, vha, @@ -4735,7 +4736,7 @@ qla2x00_uevent_emit(struct scsi_qla_host *vha, u32 code) switch (code) { case QLA_UEVENT_CODE_FW_DUMP: - snprintf(event_string, sizeof(event_string), "FW_DUMP=%ld", + snprintf(event_string, sizeof(event_string), "FW_DUMP=%lu", vha->host_no); break; default: diff --git a/drivers/soc/fsl/qe/Kconfig b/drivers/soc/fsl/qe/Kconfig index fabba17e9d65b..7ec158e2acf91 100644 --- a/drivers/soc/fsl/qe/Kconfig +++ b/drivers/soc/fsl/qe/Kconfig @@ -37,6 +37,7 @@ config QE_TDM config QE_USB bool + depends on QUICC_ENGINE default y if USB_FSL_QE help QE USB Controller support diff --git a/drivers/spi/spi-bcm-qspi.c b/drivers/spi/spi-bcm-qspi.c index 3f291db7b39a0..e3c69b6237708 100644 --- a/drivers/spi/spi-bcm-qspi.c +++ b/drivers/spi/spi-bcm-qspi.c @@ -1255,13 +1255,9 @@ int bcm_qspi_probe(struct platform_device *pdev, res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "mspi"); - if (res) { - qspi->base[MSPI] = devm_ioremap_resource(dev, res); - if (IS_ERR(qspi->base[MSPI])) - return PTR_ERR(qspi->base[MSPI]); - } else { - return 0; - } + qspi->base[MSPI] = devm_ioremap_resource(dev, res); + if (IS_ERR(qspi->base[MSPI])) + return PTR_ERR(qspi->base[MSPI]); res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "bspi"); if (res) { diff --git a/drivers/spi/spi-bcm63xx.c b/drivers/spi/spi-bcm63xx.c index bfe5754768f97..cc6ec3fb5bfdf 100644 --- a/drivers/spi/spi-bcm63xx.c +++ b/drivers/spi/spi-bcm63xx.c @@ -134,7 +134,7 @@ enum bcm63xx_regs_spi { SPI_MSG_DATA_SIZE, }; -#define BCM63XX_SPI_MAX_PREPEND 15 +#define BCM63XX_SPI_MAX_PREPEND 7 #define BCM63XX_SPI_MAX_CS 8 #define BCM63XX_SPI_BUS_NUM 0 diff --git a/drivers/spi/spi-fsl-spi.c b/drivers/spi/spi-fsl-spi.c index 5e49fed487f8a..fd15b030b3815 100644 --- a/drivers/spi/spi-fsl-spi.c +++ b/drivers/spi/spi-fsl-spi.c @@ -339,7 +339,7 @@ static int fsl_spi_do_one_msg(struct spi_master *master, struct spi_transfer *t, *first; unsigned int cs_change; const int nsecs = 50; - int status; + int status, last_bpw; /* * In CPU mode, optimize large byte transfers to use larger @@ -373,26 +373,27 @@ static int fsl_spi_do_one_msg(struct spi_master *master, } /* Don't allow changes if CS is active */ - first = list_first_entry(&m->transfers, struct spi_transfer, - transfer_list); + cs_change = 1; list_for_each_entry(t, &m->transfers, transfer_list) { - if ((first->bits_per_word != t->bits_per_word) || - (first->speed_hz != t->speed_hz)) { + if (cs_change) + first = t; + cs_change = t->cs_change; + if (first->speed_hz != t->speed_hz) { dev_err(&spi->dev, - "bits_per_word/speed_hz should be same for the same SPI transfer\n"); + "speed_hz cannot change while CS is active\n"); return -EINVAL; } } + last_bpw = -1; cs_change = 1; status = -EINVAL; list_for_each_entry(t, &m->transfers, transfer_list) { - if (t->bits_per_word || t->speed_hz) { - if (cs_change) - status = fsl_spi_setup_transfer(spi, t); - if (status < 0) - break; - } + if (cs_change || last_bpw != t->bits_per_word) + status = fsl_spi_setup_transfer(spi, t); + if (status < 0) + break; + last_bpw = t->bits_per_word; if (cs_change) { fsl_spi_chipselect(spi, BITBANG_CS_ACTIVE); diff --git a/drivers/ssb/driver_chipcommon.c b/drivers/ssb/driver_chipcommon.c index 99a4656d113d5..832ee69f45f52 100644 --- a/drivers/ssb/driver_chipcommon.c +++ b/drivers/ssb/driver_chipcommon.c @@ -119,7 +119,7 @@ void ssb_chipco_set_clockmode(struct ssb_chipcommon *cc, static enum ssb_clksrc chipco_pctl_get_slowclksrc(struct ssb_chipcommon *cc) { struct ssb_bus *bus = cc->dev->bus; - u32 uninitialized_var(tmp); + u32 tmp; if (cc->dev->id.revision < 6) { if (bus->bustype == SSB_BUSTYPE_SSB || @@ -149,7 +149,7 @@ static enum ssb_clksrc chipco_pctl_get_slowclksrc(struct ssb_chipcommon *cc) /* Get maximum or minimum (depending on get_max flag) slowclock frequency. */ static int chipco_pctl_clockfreqlimit(struct ssb_chipcommon *cc, int get_max) { - int uninitialized_var(limit); + int limit; enum ssb_clksrc clocksrc; int divisor = 1; u32 tmp; diff --git a/drivers/staging/ks7010/ks_wlan_net.c b/drivers/staging/ks7010/ks_wlan_net.c index f624d0d53a8f2..1b6226efe15eb 100644 --- a/drivers/staging/ks7010/ks_wlan_net.c +++ b/drivers/staging/ks7010/ks_wlan_net.c @@ -1584,8 +1584,10 @@ static int ks_wlan_set_encode_ext(struct net_device *dev, commit |= SME_WEP_FLAG; } if (enc->key_len) { - memcpy(&key->key_val[0], &enc->key[0], enc->key_len); - key->key_len = enc->key_len; + int key_len = clamp_val(enc->key_len, 0, IW_ENCODING_TOKEN_MAX); + + memcpy(&key->key_val[0], &enc->key[0], key_len); + key->key_len = key_len; commit |= (SME_WEP_VAL1 << index); } break; diff --git a/drivers/tty/cyclades.c b/drivers/tty/cyclades.c index db048dbe9f785..6fec20c01ef15 100644 --- a/drivers/tty/cyclades.c +++ b/drivers/tty/cyclades.c @@ -3648,7 +3648,7 @@ static int cy_pci_probe(struct pci_dev *pdev, struct cyclades_card *card; void __iomem *addr0 = NULL, *addr2 = NULL; char *card_name = NULL; - u32 uninitialized_var(mailbox); + u32 mailbox; unsigned int device_id, nchan = 0, card_no, i, j; unsigned char plx_ver; int retval, irq; diff --git a/drivers/tty/isicom.c b/drivers/tty/isicom.c index 8d96e86966f1b..274480a3c4b97 100644 --- a/drivers/tty/isicom.c +++ b/drivers/tty/isicom.c @@ -1537,7 +1537,7 @@ static unsigned int card_count; static int isicom_probe(struct pci_dev *pdev, const struct pci_device_id *ent) { - unsigned int uninitialized_var(signature), index; + unsigned int signature, index; int retval = -EPERM; struct isi_board *board = NULL; diff --git a/drivers/tty/serial/8250/8250.h b/drivers/tty/serial/8250/8250.h index 8c8aa3b9c2989..b0c5f0dba6fcc 100644 --- a/drivers/tty/serial/8250/8250.h +++ b/drivers/tty/serial/8250/8250.h @@ -85,7 +85,6 @@ struct serial8250_config { #define UART_BUG_TXEN (1 << 1) /* UART has buggy TX IIR status */ #define UART_BUG_NOMSR (1 << 2) /* UART has buggy MSR status bits (Au1x00) */ #define UART_BUG_THRE (1 << 3) /* UART has buggy THRE reassertion */ -#define UART_BUG_PARITY (1 << 4) /* UART mishandles parity if FIFO enabled */ #ifdef CONFIG_SERIAL_8250_SHARE_IRQ diff --git a/drivers/tty/serial/8250/8250_dwlib.c b/drivers/tty/serial/8250/8250_dwlib.c new file mode 100644 index 0000000000000..1cf229cca5928 --- /dev/null +++ b/drivers/tty/serial/8250/8250_dwlib.c @@ -0,0 +1,128 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* Synopsys DesignWare 8250 library. */ + +#include +#include +#include +#include +#include +#include + +#include "8250_dwlib.h" + +/* Offsets for the DesignWare specific registers */ +#define DW_UART_DLF 0xc0 /* Divisor Latch Fraction Register */ +#define DW_UART_CPR 0xf4 /* Component Parameter Register */ +#define DW_UART_UCV 0xf8 /* UART Component Version */ + +/* Component Parameter Register bits */ +#define DW_UART_CPR_ABP_DATA_WIDTH (3 << 0) +#define DW_UART_CPR_AFCE_MODE (1 << 4) +#define DW_UART_CPR_THRE_MODE (1 << 5) +#define DW_UART_CPR_SIR_MODE (1 << 6) +#define DW_UART_CPR_SIR_LP_MODE (1 << 7) +#define DW_UART_CPR_ADDITIONAL_FEATURES (1 << 8) +#define DW_UART_CPR_FIFO_ACCESS (1 << 9) +#define DW_UART_CPR_FIFO_STAT (1 << 10) +#define DW_UART_CPR_SHADOW (1 << 11) +#define DW_UART_CPR_ENCODED_PARMS (1 << 12) +#define DW_UART_CPR_DMA_EXTRA (1 << 13) +#define DW_UART_CPR_FIFO_MODE (0xff << 16) + +/* Helper for FIFO size calculation */ +#define DW_UART_CPR_FIFO_SIZE(a) (((a >> 16) & 0xff) * 16) + +static inline u32 dw8250_readl_ext(struct uart_port *p, int offset) +{ + if (p->iotype == UPIO_MEM32BE) + return ioread32be(p->membase + offset); + return readl(p->membase + offset); +} + +static inline void dw8250_writel_ext(struct uart_port *p, int offset, u32 reg) +{ + if (p->iotype == UPIO_MEM32BE) + iowrite32be(reg, p->membase + offset); + else + writel(reg, p->membase + offset); +} + +/* + * divisor = div(I) + div(F) + * "I" means integer, "F" means fractional + * quot = div(I) = clk / (16 * baud) + * frac = div(F) * 2^dlf_size + * + * let rem = clk % (16 * baud) + * we have: div(F) * (16 * baud) = rem + * so frac = 2^dlf_size * rem / (16 * baud) = (rem << dlf_size) / (16 * baud) + */ +static unsigned int dw8250_get_divisor(struct uart_port *p, unsigned int baud, + unsigned int *frac) +{ + unsigned int quot, rem, base_baud = baud * 16; + struct dw8250_port_data *d = p->private_data; + + quot = p->uartclk / base_baud; + rem = p->uartclk % base_baud; + *frac = DIV_ROUND_CLOSEST(rem << d->dlf_size, base_baud); + + return quot; +} + +static void dw8250_set_divisor(struct uart_port *p, unsigned int baud, + unsigned int quot, unsigned int quot_frac) +{ + dw8250_writel_ext(p, DW_UART_DLF, quot_frac); + serial8250_do_set_divisor(p, baud, quot, quot_frac); +} + +void dw8250_setup_port(struct uart_port *p) +{ + struct uart_8250_port *up = up_to_u8250p(p); + u32 reg, old_dlf; + + /* + * If the Component Version Register returns zero, we know that + * ADDITIONAL_FEATURES are not enabled. No need to go any further. + */ + reg = dw8250_readl_ext(p, DW_UART_UCV); + if (!reg) + return; + + dev_dbg(p->dev, "Designware UART version %c.%c%c\n", + (reg >> 24) & 0xff, (reg >> 16) & 0xff, (reg >> 8) & 0xff); + + /* Preserve value written by firmware or bootloader */ + old_dlf = dw8250_readl_ext(p, DW_UART_DLF); + dw8250_writel_ext(p, DW_UART_DLF, ~0U); + reg = dw8250_readl_ext(p, DW_UART_DLF); + dw8250_writel_ext(p, DW_UART_DLF, old_dlf); + + if (reg) { + struct dw8250_port_data *d = p->private_data; + + d->dlf_size = fls(reg); + p->get_divisor = dw8250_get_divisor; + p->set_divisor = dw8250_set_divisor; + } + + reg = dw8250_readl_ext(p, DW_UART_CPR); + if (!reg) + return; + + /* Select the type based on FIFO */ + if (reg & DW_UART_CPR_FIFO_MODE) { + p->type = PORT_16550A; + p->flags |= UPF_FIXED_TYPE; + p->fifosize = DW_UART_CPR_FIFO_SIZE(reg); + up->capabilities = UART_CAP_FIFO; + } + + if (reg & DW_UART_CPR_AFCE_MODE) + up->capabilities |= UART_CAP_AFE; + + if (reg & DW_UART_CPR_SIR_MODE) + up->capabilities |= UART_CAP_IRDA; +} +EXPORT_SYMBOL_GPL(dw8250_setup_port); diff --git a/drivers/tty/serial/8250/8250_dwlib.h b/drivers/tty/serial/8250/8250_dwlib.h new file mode 100644 index 0000000000000..87a4db2a8aba6 --- /dev/null +++ b/drivers/tty/serial/8250/8250_dwlib.h @@ -0,0 +1,19 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* Synopsys DesignWare 8250 library header file. */ + +#include + +#include "8250.h" + +struct dw8250_port_data { + /* Port properties */ + int line; + + /* DMA operations */ + struct uart_8250_dma dma; + + /* Hardware configuration */ + u8 dlf_size; +}; + +void dw8250_setup_port(struct uart_port *p); diff --git a/drivers/tty/serial/8250/8250_pci.c b/drivers/tty/serial/8250/8250_pci.c index 274e644f34f27..2c224bf70cfd0 100644 --- a/drivers/tty/serial/8250/8250_pci.c +++ b/drivers/tty/serial/8250/8250_pci.c @@ -1049,14 +1049,6 @@ static int pci_oxsemi_tornado_init(struct pci_dev *dev) return number_uarts; } -static int pci_asix_setup(struct serial_private *priv, - const struct pciserial_board *board, - struct uart_8250_port *port, int idx) -{ - port->bugs |= UART_BUG_PARITY; - return pci_default_setup(priv, board, port, idx); -} - /* Quatech devices have their own extra interface features */ struct quatech_feature { @@ -1683,7 +1675,6 @@ pci_wch_ch38x_setup(struct serial_private *priv, #define PCI_DEVICE_ID_WCH_CH355_4S 0x7173 #define PCI_VENDOR_ID_AGESTAR 0x5372 #define PCI_DEVICE_ID_AGESTAR_9375 0x6872 -#define PCI_VENDOR_ID_ASIX 0x9710 #define PCI_DEVICE_ID_BROADCOM_TRUMANAGE 0x160a #define PCI_DEVICE_ID_AMCC_ADDIDATA_APCI7800 0x818e @@ -2454,16 +2445,6 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = { .subdevice = PCI_ANY_ID, .setup = pci_wch_ch38x_setup, }, - /* - * ASIX devices with FIFO bug - */ - { - .vendor = PCI_VENDOR_ID_ASIX, - .device = PCI_ANY_ID, - .subvendor = PCI_ANY_ID, - .subdevice = PCI_ANY_ID, - .setup = pci_asix_setup, - }, /* * Broadcom TruManage (NetXtreme) */ diff --git a/drivers/tty/serial/8250/8250_port.c b/drivers/tty/serial/8250/8250_port.c index cba4888bc4824..66de3a59f5779 100644 --- a/drivers/tty/serial/8250/8250_port.c +++ b/drivers/tty/serial/8250/8250_port.c @@ -2617,11 +2617,8 @@ static unsigned char serial8250_compute_lcr(struct uart_8250_port *up, if (c_cflag & CSTOPB) cval |= UART_LCR_STOP; - if (c_cflag & PARENB) { + if (c_cflag & PARENB) cval |= UART_LCR_PARITY; - if (up->bugs & UART_BUG_PARITY) - up->fifo_bug = true; - } if (!(c_cflag & PARODD)) cval |= UART_LCR_EPAR; #ifdef CMSPAR @@ -2735,8 +2732,7 @@ serial8250_do_set_termios(struct uart_port *port, struct ktermios *termios, up->lcr = cval; /* Save computed LCR */ if (up->capabilities & UART_CAP_FIFO && port->fifosize > 1) { - /* NOTE: If fifo_bug is not set, a user can set RX_trigger. */ - if ((baud < 2400 && !up->dma) || up->fifo_bug) { + if (baud < 2400 && !up->dma) { up->fcr &= ~UART_FCR_TRIGGER_MASK; up->fcr |= UART_FCR_TRIGGER_1; } @@ -3072,8 +3068,7 @@ static int do_set_rxtrig(struct tty_port *port, unsigned char bytes) struct uart_8250_port *up = up_to_u8250p(uport); int rxtrig; - if (!(up->capabilities & UART_CAP_FIFO) || uport->fifosize <= 1 || - up->fifo_bug) + if (!(up->capabilities & UART_CAP_FIFO) || uport->fifosize <= 1) return -EINVAL; rxtrig = bytes_to_fcr_rxtrig(up, bytes); diff --git a/drivers/tty/serial/8250/Kconfig b/drivers/tty/serial/8250/Kconfig index a9ddd76d41701..733ac320938c1 100644 --- a/drivers/tty/serial/8250/Kconfig +++ b/drivers/tty/serial/8250/Kconfig @@ -312,6 +312,9 @@ config SERIAL_8250_RSA If you don't have such card, or if unsure, say N. +config SERIAL_8250_DWLIB + bool + config SERIAL_8250_ACORN tristate "Acorn expansion card serial port support" depends on ARCH_ACORN && SERIAL_8250 diff --git a/drivers/tty/serial/8250/Makefile b/drivers/tty/serial/8250/Makefile index 18751bc63a848..9b451d81588b2 100644 --- a/drivers/tty/serial/8250/Makefile +++ b/drivers/tty/serial/8250/Makefile @@ -8,6 +8,7 @@ obj-$(CONFIG_SERIAL_8250) += 8250.o 8250_base.o 8250-$(CONFIG_SERIAL_8250_PNP) += 8250_pnp.o 8250_base-y := 8250_port.o 8250_base-$(CONFIG_SERIAL_8250_DMA) += 8250_dma.o +8250_base-$(CONFIG_SERIAL_8250_DWLIB) += 8250_dwlib.o 8250_base-$(CONFIG_SERIAL_8250_FINTEK) += 8250_fintek.o obj-$(CONFIG_SERIAL_8250_GSC) += 8250_gsc.o obj-$(CONFIG_SERIAL_8250_PCI) += 8250_pci.o diff --git a/drivers/tty/serial/atmel_serial.c b/drivers/tty/serial/atmel_serial.c index 50c4058a00e6a..1688c190fc7d8 100644 --- a/drivers/tty/serial/atmel_serial.c +++ b/drivers/tty/serial/atmel_serial.c @@ -791,11 +791,11 @@ static void atmel_complete_tx_dma(void *arg) port->icount.tx += atmel_port->tx_len; - spin_lock_irq(&atmel_port->lock_tx); + spin_lock(&atmel_port->lock_tx); async_tx_ack(atmel_port->desc_tx); atmel_port->cookie_tx = -EINVAL; atmel_port->desc_tx = NULL; - spin_unlock_irq(&atmel_port->lock_tx); + spin_unlock(&atmel_port->lock_tx); if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) uart_write_wakeup(port); diff --git a/drivers/tty/serial/samsung.c b/drivers/tty/serial/samsung.c index 964d6d33b6097..5f1f52cc63951 100644 --- a/drivers/tty/serial/samsung.c +++ b/drivers/tty/serial/samsung.c @@ -1199,8 +1199,12 @@ static unsigned int s3c24xx_serial_getclk(struct s3c24xx_uart_port *ourport, continue; rate = clk_get_rate(clk); - if (!rate) + if (!rate) { + dev_err(ourport->port.dev, + "Failed to get clock rate for %s.\n", clkname); + clk_put(clk); continue; + } if (ourport->info->has_divslot) { unsigned long div = rate / req_baud; @@ -1226,10 +1230,18 @@ static unsigned int s3c24xx_serial_getclk(struct s3c24xx_uart_port *ourport, calc_deviation = -calc_deviation; if (calc_deviation < deviation) { + /* + * If we find a better clk, release the previous one, if + * any. + */ + if (!IS_ERR(*best_clk)) + clk_put(*best_clk); *best_clk = clk; best_quot = quot; *clk_num = cnt; deviation = calc_deviation; + } else { + clk_put(clk); } } diff --git a/drivers/usb/core/quirks.c b/drivers/usb/core/quirks.c index 1346c600ebedf..48cda9b7a8f24 100644 --- a/drivers/usb/core/quirks.c +++ b/drivers/usb/core/quirks.c @@ -437,6 +437,10 @@ static const struct usb_device_id usb_quirk_list[] = { /* novation SoundControl XL */ { USB_DEVICE(0x1235, 0x0061), .driver_info = USB_QUIRK_RESET_RESUME }, + /* Focusrite Scarlett Solo USB */ + { USB_DEVICE(0x1235, 0x8211), .driver_info = + USB_QUIRK_DISCONNECT_SUSPEND }, + /* Huawei 4G LTE module */ { USB_DEVICE(0x12d1, 0x15bb), .driver_info = USB_QUIRK_DISCONNECT_SUSPEND }, diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c index 81a5ca15b9c7a..d31cc8d75595d 100644 --- a/drivers/usb/dwc3/core.c +++ b/drivers/usb/dwc3/core.c @@ -242,9 +242,9 @@ static int dwc3_core_soft_reset(struct dwc3 *dwc) /* * We're resetting only the device side because, if we're in host mode, * XHCI driver will reset the host block. If dwc3 was configured for - * host-only mode, then we can return early. + * host-only mode or current role is host, then we can return early. */ - if (dwc->current_dr_role == DWC3_GCTL_PRTCAP_HOST) + if (dwc->dr_mode == USB_DR_MODE_HOST || dwc->current_dr_role == DWC3_GCTL_PRTCAP_HOST) return 0; reg = dwc3_readl(dwc->regs, DWC3_DCTL); @@ -993,22 +993,6 @@ static int dwc3_core_init(struct dwc3 *dwc) dwc3_writel(dwc->regs, DWC3_GUCTL1, reg); } - if (dwc->dr_mode == USB_DR_MODE_HOST || - dwc->dr_mode == USB_DR_MODE_OTG) { - reg = dwc3_readl(dwc->regs, DWC3_GUCTL); - - /* - * Enable Auto retry Feature to make the controller operating in - * Host mode on seeing transaction errors(CRC errors or internal - * overrun scenerios) on IN transfers to reply to the device - * with a non-terminating retry ACK (i.e, an ACK transcation - * packet with Retry=1 & Nump != 0) - */ - reg |= DWC3_GUCTL_HSTINAUTORETRY; - - dwc3_writel(dwc->regs, DWC3_GUCTL, reg); - } - /* * Must config both number of packets and max burst settings to enable * RX and/or TX threshold. diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h index 55ee41283f395..a1d65e36a4d41 100644 --- a/drivers/usb/dwc3/core.h +++ b/drivers/usb/dwc3/core.h @@ -238,9 +238,6 @@ #define DWC3_GCTL_GBLHIBERNATIONEN BIT(1) #define DWC3_GCTL_DSBLCLKGTNG BIT(0) -/* Global User Control Register */ -#define DWC3_GUCTL_HSTINAUTORETRY BIT(14) - /* Global User Control 1 Register */ #define DWC3_GUCTL1_PARKMODE_DISABLE_SS BIT(17) #define DWC3_GUCTL1_TX_IPGAP_LINECHECK_DIS BIT(28) diff --git a/drivers/usb/dwc3/dwc3-pci.c b/drivers/usb/dwc3/dwc3-pci.c index 955bf820f4102..8d4f1b13f4157 100644 --- a/drivers/usb/dwc3/dwc3-pci.c +++ b/drivers/usb/dwc3/dwc3-pci.c @@ -171,10 +171,12 @@ static int dwc3_pci_quirks(struct dwc3_pci *dwc) /* * A lot of BYT devices lack ACPI resource entries for - * the GPIOs, add a fallback mapping to the reference + * the GPIOs. If the ACPI entry for the GPIO controller + * is present add a fallback mapping to the reference * design GPIOs which all boards seem to use. */ - gpiod_add_lookup_table(&platform_bytcr_gpios); + if (acpi_dev_present("INT33FC", NULL, -1)) + gpiod_add_lookup_table(&platform_bytcr_gpios); /* * These GPIOs will turn on the USB2 PHY. Note that we have to diff --git a/drivers/usb/host/ohci-at91.c b/drivers/usb/host/ohci-at91.c index ec6739ef3129e..687aeab64e4db 100644 --- a/drivers/usb/host/ohci-at91.c +++ b/drivers/usb/host/ohci-at91.c @@ -642,7 +642,13 @@ ohci_hcd_at91_drv_resume(struct device *dev) at91_start_clock(ohci_at91); - ohci_resume(hcd, false); + /* + * According to the comment in ohci_hcd_at91_drv_suspend() + * we need to do a reset if the 48Mhz clock was stopped, + * that is, if ohci_at91->wakeup is clear. Tell ohci_resume() + * to reset in this case by setting its "hibernated" flag. + */ + ohci_resume(hcd, !ohci_at91->wakeup); ohci_at91_port_suspend(ohci_at91->sfr_regmap, 0); diff --git a/drivers/usb/host/xhci-mtk.c b/drivers/usb/host/xhci-mtk.c index f4b2e766f195b..cb22beb55f7e0 100644 --- a/drivers/usb/host/xhci-mtk.c +++ b/drivers/usb/host/xhci-mtk.c @@ -538,6 +538,7 @@ static int xhci_mtk_probe(struct platform_device *pdev) } device_init_wakeup(dev, true); + dma_set_max_seg_size(dev, UINT_MAX); xhci = hcd_to_xhci(hcd); xhci->main_hcd = hcd; diff --git a/drivers/usb/musb/cppi_dma.c b/drivers/usb/musb/cppi_dma.c index b4d6d9bb32395..c545b27ea5681 100644 --- a/drivers/usb/musb/cppi_dma.c +++ b/drivers/usb/musb/cppi_dma.c @@ -1146,7 +1146,7 @@ irqreturn_t cppi_interrupt(int irq, void *dev_id) struct musb_hw_ep *hw_ep = NULL; u32 rx, tx; int i, index; - unsigned long uninitialized_var(flags); + unsigned long flags; cppi = container_of(musb->dma_controller, struct cppi, controller); if (cppi->irq) diff --git a/drivers/usb/phy/phy-tahvo.c b/drivers/usb/phy/phy-tahvo.c index 60d390e28289f..2923a7f6952dc 100644 --- a/drivers/usb/phy/phy-tahvo.c +++ b/drivers/usb/phy/phy-tahvo.c @@ -398,7 +398,7 @@ static int tahvo_usb_probe(struct platform_device *pdev) tu->irq = ret = platform_get_irq(pdev, 0); if (ret < 0) - return ret; + goto err_remove_phy; ret = request_threaded_irq(tu->irq, NULL, tahvo_usb_vbus_interrupt, IRQF_ONESHOT, "tahvo-vbus", tu); diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c index 126e276edd2ed..cf68a422e75e4 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c @@ -251,6 +251,7 @@ static void option_instat_callback(struct urb *urb); #define QUECTEL_PRODUCT_EM061K_LTA 0x0123 #define QUECTEL_PRODUCT_EM061K_LMS 0x0124 #define QUECTEL_PRODUCT_EC25 0x0125 +#define QUECTEL_PRODUCT_EM060K_128 0x0128 #define QUECTEL_PRODUCT_EG91 0x0191 #define QUECTEL_PRODUCT_EG95 0x0195 #define QUECTEL_PRODUCT_BG96 0x0296 @@ -268,6 +269,7 @@ static void option_instat_callback(struct urb *urb); #define QUECTEL_PRODUCT_RM520N 0x0801 #define QUECTEL_PRODUCT_EC200U 0x0901 #define QUECTEL_PRODUCT_EC200S_CN 0x6002 +#define QUECTEL_PRODUCT_EC200A 0x6005 #define QUECTEL_PRODUCT_EM061K_LWW 0x6008 #define QUECTEL_PRODUCT_EM061K_LCN 0x6009 #define QUECTEL_PRODUCT_EC200T 0x6026 @@ -1151,6 +1153,10 @@ static const struct usb_device_id option_ids[] = { { USB_DEVICE(QUALCOMM_VENDOR_ID, 0x90fa), .driver_info = RSVD(3) }, /* u-blox products */ + { USB_DEVICE(UBLOX_VENDOR_ID, 0x1311) }, /* u-blox LARA-R6 01B */ + { USB_DEVICE(UBLOX_VENDOR_ID, 0x1312), /* u-blox LARA-R6 01B (RMNET) */ + .driver_info = RSVD(4) }, + { USB_DEVICE_INTERFACE_CLASS(UBLOX_VENDOR_ID, 0x1313, 0xff) }, /* u-blox LARA-R6 01B (ECM) */ { USB_DEVICE(UBLOX_VENDOR_ID, 0x1341) }, /* u-blox LARA-L6 */ { USB_DEVICE(UBLOX_VENDOR_ID, 0x1342), /* u-blox LARA-L6 (RMNET) */ .driver_info = RSVD(4) }, @@ -1193,6 +1199,9 @@ static const struct usb_device_id option_ids[] = { { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EM060K, 0xff, 0x00, 0x40) }, { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EM060K, 0xff, 0xff, 0x30) }, { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EM060K, 0xff, 0xff, 0x40) }, + { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EM060K_128, 0xff, 0xff, 0x30) }, + { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EM060K_128, 0xff, 0x00, 0x40) }, + { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EM060K_128, 0xff, 0xff, 0x40) }, { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EM061K_LCN, 0xff, 0xff, 0x30) }, { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EM061K_LCN, 0xff, 0x00, 0x40) }, { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EM061K_LCN, 0xff, 0xff, 0x40) }, @@ -1221,6 +1230,7 @@ static const struct usb_device_id option_ids[] = { { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_RM520N, 0xff, 0, 0) }, { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, 0x0900, 0xff, 0, 0), /* RM500U-CN */ .driver_info = ZLP }, + { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EC200A, 0xff, 0, 0) }, { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EC200U, 0xff, 0, 0) }, { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EC200S_CN, 0xff, 0, 0) }, { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EC200T, 0xff, 0, 0) }, diff --git a/drivers/usb/serial/usb-serial-simple.c b/drivers/usb/serial/usb-serial-simple.c index 4c6747889a194..24b8772a345e2 100644 --- a/drivers/usb/serial/usb-serial-simple.c +++ b/drivers/usb/serial/usb-serial-simple.c @@ -38,16 +38,6 @@ static struct usb_serial_driver vendor##_device = { \ { USB_DEVICE(0x0a21, 0x8001) } /* MMT-7305WW */ DEVICE(carelink, CARELINK_IDS); -/* ZIO Motherboard USB driver */ -#define ZIO_IDS() \ - { USB_DEVICE(0x1CBE, 0x0103) } -DEVICE(zio, ZIO_IDS); - -/* Funsoft Serial USB driver */ -#define FUNSOFT_IDS() \ - { USB_DEVICE(0x1404, 0xcddc) } -DEVICE(funsoft, FUNSOFT_IDS); - /* Infineon Flashloader driver */ #define FLASHLOADER_IDS() \ { USB_DEVICE_INTERFACE_CLASS(0x058b, 0x0041, USB_CLASS_CDC_DATA) }, \ @@ -55,6 +45,11 @@ DEVICE(funsoft, FUNSOFT_IDS); { USB_DEVICE(0x8087, 0x0801) } DEVICE(flashloader, FLASHLOADER_IDS); +/* Funsoft Serial USB driver */ +#define FUNSOFT_IDS() \ + { USB_DEVICE(0x1404, 0xcddc) } +DEVICE(funsoft, FUNSOFT_IDS); + /* Google Serial USB SubClass */ #define GOOGLE_IDS() \ { USB_VENDOR_AND_INTERFACE_INFO(0x18d1, \ @@ -63,16 +58,21 @@ DEVICE(flashloader, FLASHLOADER_IDS); 0x01) } DEVICE(google, GOOGLE_IDS); +/* HP4x (48/49) Generic Serial driver */ +#define HP4X_IDS() \ + { USB_DEVICE(0x03f0, 0x0121) } +DEVICE(hp4x, HP4X_IDS); + +/* KAUFMANN RKS+CAN VCP */ +#define KAUFMANN_IDS() \ + { USB_DEVICE(0x16d0, 0x0870) } +DEVICE(kaufmann, KAUFMANN_IDS); + /* Libtransistor USB console */ #define LIBTRANSISTOR_IDS() \ { USB_DEVICE(0x1209, 0x8b00) } DEVICE(libtransistor, LIBTRANSISTOR_IDS); -/* ViVOpay USB Serial Driver */ -#define VIVOPAY_IDS() \ - { USB_DEVICE(0x1d5f, 0x1004) } /* ViVOpay 8800 */ -DEVICE(vivopay, VIVOPAY_IDS); - /* Motorola USB Phone driver */ #define MOTO_IDS() \ { USB_DEVICE(0x05c6, 0x3197) }, /* unknown Motorola phone */ \ @@ -101,10 +101,10 @@ DEVICE(nokia, NOKIA_IDS); { USB_DEVICE(0x09d7, 0x0100) } /* NovAtel FlexPack GPS */ DEVICE_N(novatel_gps, NOVATEL_IDS, 3); -/* HP4x (48/49) Generic Serial driver */ -#define HP4X_IDS() \ - { USB_DEVICE(0x03f0, 0x0121) } -DEVICE(hp4x, HP4X_IDS); +/* Siemens USB/MPI adapter */ +#define SIEMENS_IDS() \ + { USB_DEVICE(0x908, 0x0004) } +DEVICE(siemens_mpi, SIEMENS_IDS); /* Suunto ANT+ USB Driver */ #define SUUNTO_IDS() \ @@ -112,45 +112,52 @@ DEVICE(hp4x, HP4X_IDS); { USB_DEVICE(0x0fcf, 0x1009) } /* Dynastream ANT USB-m Stick */ DEVICE(suunto, SUUNTO_IDS); -/* Siemens USB/MPI adapter */ -#define SIEMENS_IDS() \ - { USB_DEVICE(0x908, 0x0004) } -DEVICE(siemens_mpi, SIEMENS_IDS); +/* ViVOpay USB Serial Driver */ +#define VIVOPAY_IDS() \ + { USB_DEVICE(0x1d5f, 0x1004) } /* ViVOpay 8800 */ +DEVICE(vivopay, VIVOPAY_IDS); + +/* ZIO Motherboard USB driver */ +#define ZIO_IDS() \ + { USB_DEVICE(0x1CBE, 0x0103) } +DEVICE(zio, ZIO_IDS); /* All of the above structures mushed into two lists */ static struct usb_serial_driver * const serial_drivers[] = { &carelink_device, - &zio_device, - &funsoft_device, &flashloader_device, + &funsoft_device, &google_device, + &hp4x_device, + &kaufmann_device, &libtransistor_device, - &vivopay_device, &moto_modem_device, &motorola_tetra_device, &nokia_device, &novatel_gps_device, - &hp4x_device, - &suunto_device, &siemens_mpi_device, + &suunto_device, + &vivopay_device, + &zio_device, NULL }; static const struct usb_device_id id_table[] = { CARELINK_IDS(), - ZIO_IDS(), - FUNSOFT_IDS(), FLASHLOADER_IDS(), + FUNSOFT_IDS(), GOOGLE_IDS(), + HP4X_IDS(), + KAUFMANN_IDS(), LIBTRANSISTOR_IDS(), - VIVOPAY_IDS(), MOTO_IDS(), MOTOROLA_TETRA_IDS(), NOKIA_IDS(), NOVATEL_IDS(), - HP4X_IDS(), - SUUNTO_IDS(), SIEMENS_IDS(), + SUUNTO_IDS(), + VIVOPAY_IDS(), + ZIO_IDS(), { }, }; MODULE_DEVICE_TABLE(usb, id_table); diff --git a/drivers/usb/storage/sddr55.c b/drivers/usb/storage/sddr55.c index b8527c55335b6..35306c0559622 100644 --- a/drivers/usb/storage/sddr55.c +++ b/drivers/usb/storage/sddr55.c @@ -553,8 +553,8 @@ static int sddr55_reset(struct us_data *us) static unsigned long sddr55_get_capacity(struct us_data *us) { - unsigned char uninitialized_var(manufacturerID); - unsigned char uninitialized_var(deviceID); + unsigned char manufacturerID; + unsigned char deviceID; int result; struct sddr55_card_info *info = (struct sddr55_card_info *)us->extra; diff --git a/drivers/vhost/net.c b/drivers/vhost/net.c index 5ea7b0a94fe38..4dc1842e3e8e1 100644 --- a/drivers/vhost/net.c +++ b/drivers/vhost/net.c @@ -828,7 +828,7 @@ static int get_rx_bufs(struct vhost_virtqueue *vq, /* len is always initialized before use since we are always called with * datalen > 0. */ - u32 uninitialized_var(len); + u32 len; while (datalen > 0 && headcount < quota) { if (unlikely(seg >= UIO_MAXIOV)) { @@ -885,7 +885,7 @@ static void handle_rx(struct vhost_net *net) { struct vhost_net_virtqueue *nvq = &net->vqs[VHOST_NET_VQ_RX]; struct vhost_virtqueue *vq = &nvq->vq; - unsigned uninitialized_var(in), log; + unsigned in, log; struct vhost_log *vq_log; struct msghdr msg = { .msg_name = NULL, diff --git a/drivers/video/fbdev/au1200fb.c b/drivers/video/fbdev/au1200fb.c index f8e83a9519189..593c390e98629 100644 --- a/drivers/video/fbdev/au1200fb.c +++ b/drivers/video/fbdev/au1200fb.c @@ -1744,6 +1744,9 @@ static int au1200fb_drv_probe(struct platform_device *dev) /* Now hook interrupt too */ irq = platform_get_irq(dev, 0); + if (irq < 0) + return irq; + ret = request_irq(irq, au1200fb_handle_irq, IRQF_SHARED, "lcd", (void *)dev); if (ret) { diff --git a/drivers/video/fbdev/imsttfb.c b/drivers/video/fbdev/imsttfb.c index ecdcf358ad5ea..4a3f89b223600 100644 --- a/drivers/video/fbdev/imsttfb.c +++ b/drivers/video/fbdev/imsttfb.c @@ -1348,7 +1348,7 @@ static struct fb_ops imsttfb_ops = { .fb_ioctl = imsttfb_ioctl, }; -static void init_imstt(struct fb_info *info) +static int init_imstt(struct fb_info *info) { struct imstt_par *par = info->par; __u32 i, tmp, *ip, *end; @@ -1420,7 +1420,7 @@ static void init_imstt(struct fb_info *info) || !(compute_imstt_regvals(par, info->var.xres, info->var.yres))) { printk("imsttfb: %ux%ux%u not supported\n", info->var.xres, info->var.yres, info->var.bits_per_pixel); framebuffer_release(info); - return; + return -ENODEV; } sprintf(info->fix.id, "IMS TT (%s)", par->ramdac == IBM ? "IBM" : "TVP"); @@ -1456,12 +1456,13 @@ static void init_imstt(struct fb_info *info) if (register_framebuffer(info) < 0) { framebuffer_release(info); - return; + return -ENODEV; } tmp = (read_reg_le32(par->dc_regs, SSTATUS) & 0x0f00) >> 8; fb_info(info, "%s frame buffer; %uMB vram; chip version %u\n", info->fix.id, info->fix.smem_len >> 20, tmp); + return 0; } static int imsttfb_probe(struct pci_dev *pdev, const struct pci_device_id *ent) @@ -1470,6 +1471,7 @@ static int imsttfb_probe(struct pci_dev *pdev, const struct pci_device_id *ent) struct imstt_par *par; struct fb_info *info; struct device_node *dp; + int ret = -ENOMEM; dp = pci_device_to_OF_node(pdev); if(dp) @@ -1508,23 +1510,37 @@ static int imsttfb_probe(struct pci_dev *pdev, const struct pci_device_id *ent) default: printk(KERN_INFO "imsttfb: Device 0x%x unknown, " "contact maintainer.\n", pdev->device); - release_mem_region(addr, size); - framebuffer_release(info); - return -ENODEV; + ret = -ENODEV; + goto error; } info->fix.smem_start = addr; info->screen_base = (__u8 *)ioremap(addr, par->ramdac == IBM ? 0x400000 : 0x800000); + if (!info->screen_base) + goto error; info->fix.mmio_start = addr + 0x800000; par->dc_regs = ioremap(addr + 0x800000, 0x1000); + if (!par->dc_regs) + goto error; par->cmap_regs_phys = addr + 0x840000; par->cmap_regs = (__u8 *)ioremap(addr + 0x840000, 0x1000); + if (!par->cmap_regs) + goto error; info->pseudo_palette = par->palette; - init_imstt(info); - - pci_set_drvdata(pdev, info); - return 0; + ret = init_imstt(info); + if (!ret) + pci_set_drvdata(pdev, info); + return ret; + +error: + if (par->dc_regs) + iounmap(par->dc_regs); + if (info->screen_base) + iounmap(info->screen_base); + release_mem_region(addr, size); + framebuffer_release(info); + return ret; } static void imsttfb_remove(struct pci_dev *pdev) diff --git a/drivers/video/fbdev/imxfb.c b/drivers/video/fbdev/imxfb.c index c4eb8661f7516..8ec260ed9a6f6 100644 --- a/drivers/video/fbdev/imxfb.c +++ b/drivers/video/fbdev/imxfb.c @@ -601,10 +601,10 @@ static int imxfb_activate_var(struct fb_var_screeninfo *var, struct fb_info *inf if (var->hsync_len < 1 || var->hsync_len > 64) printk(KERN_ERR "%s: invalid hsync_len %d\n", info->fix.id, var->hsync_len); - if (var->left_margin > 255) + if (var->left_margin < 3 || var->left_margin > 255) printk(KERN_ERR "%s: invalid left_margin %d\n", info->fix.id, var->left_margin); - if (var->right_margin > 255) + if (var->right_margin < 1 || var->right_margin > 255) printk(KERN_ERR "%s: invalid right_margin %d\n", info->fix.id, var->right_margin); if (var->yres < 1 || var->yres > ymax_mask) diff --git a/drivers/video/fbdev/matrox/matroxfb_maven.c b/drivers/video/fbdev/matrox/matroxfb_maven.c index bf5ce04f9aea5..267b31ddb02d3 100644 --- a/drivers/video/fbdev/matrox/matroxfb_maven.c +++ b/drivers/video/fbdev/matrox/matroxfb_maven.c @@ -299,7 +299,7 @@ static int matroxfb_mavenclock(const struct matrox_pll_ctl *ctl, unsigned int* in, unsigned int* feed, unsigned int* post, unsigned int* htotal2) { unsigned int fvco; - unsigned int uninitialized_var(p); + unsigned int p; fvco = matroxfb_PLL_mavenclock(&maven1000_pll, ctl, htotal, vtotal, in, feed, &p, htotal2); if (!fvco) @@ -731,8 +731,8 @@ static int maven_find_exact_clocks(unsigned int ht, unsigned int vt, for (x = 0; x < 8; x++) { unsigned int c; - unsigned int uninitialized_var(a), uninitialized_var(b), - uninitialized_var(h2); + unsigned int a, b, + h2; unsigned int h = ht + 2 + x; if (!matroxfb_mavenclock((m->mode == MATROXFB_OUTPUT_MODE_PAL) ? &maven_PAL : &maven_NTSC, h, vt, &a, &b, &c, &h2)) { diff --git a/drivers/video/fbdev/omap/lcd_mipid.c b/drivers/video/fbdev/omap/lcd_mipid.c index e3a85432f9266..5730355ee5986 100644 --- a/drivers/video/fbdev/omap/lcd_mipid.c +++ b/drivers/video/fbdev/omap/lcd_mipid.c @@ -576,11 +576,15 @@ static int mipid_spi_probe(struct spi_device *spi) r = mipid_detect(md); if (r < 0) - return r; + goto free_md; omapfb_register_panel(&md->panel); return 0; + +free_md: + kfree(md); + return r; } static int mipid_spi_remove(struct spi_device *spi) diff --git a/drivers/video/fbdev/pm3fb.c b/drivers/video/fbdev/pm3fb.c index 6130aa56a1e93..7bd45334dcac4 100644 --- a/drivers/video/fbdev/pm3fb.c +++ b/drivers/video/fbdev/pm3fb.c @@ -821,9 +821,9 @@ static void pm3fb_write_mode(struct fb_info *info) wmb(); { - unsigned char uninitialized_var(m); /* ClkPreScale */ - unsigned char uninitialized_var(n); /* ClkFeedBackScale */ - unsigned char uninitialized_var(p); /* ClkPostScale */ + unsigned char m; /* ClkPreScale */ + unsigned char n; /* ClkFeedBackScale */ + unsigned char p; /* ClkPostScale */ unsigned long pixclock = PICOS2KHZ(info->var.pixclock); (void)pm3fb_calculate_clock(pixclock, &m, &n, &p); diff --git a/drivers/video/fbdev/riva/riva_hw.c b/drivers/video/fbdev/riva/riva_hw.c index 0601c13f21050..f90b9327bae73 100644 --- a/drivers/video/fbdev/riva/riva_hw.c +++ b/drivers/video/fbdev/riva/riva_hw.c @@ -1245,8 +1245,7 @@ int CalcStateExt ) { int pixelDepth; - int uninitialized_var(VClk),uninitialized_var(m), - uninitialized_var(n), uninitialized_var(p); + int VClk, m, n, p; /* * Save mode parameters. diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c index 0cc0cfd3a3cb7..8acfbe420b5a0 100644 --- a/drivers/virtio/virtio_ring.c +++ b/drivers/virtio/virtio_ring.c @@ -268,7 +268,7 @@ static inline int virtqueue_add(struct virtqueue *_vq, struct vring_virtqueue *vq = to_vvq(_vq); struct scatterlist *sg; struct vring_desc *desc; - unsigned int i, n, avail, descs_used, uninitialized_var(prev), err_idx; + unsigned int i, n, avail, descs_used, prev, err_idx; int head; bool indirect; diff --git a/drivers/w1/w1.c b/drivers/w1/w1.c index cb3650efc29cd..8db9ca241d99c 100644 --- a/drivers/w1/w1.c +++ b/drivers/w1/w1.c @@ -1237,10 +1237,10 @@ err_out_exit_init: static void __exit w1_fini(void) { - struct w1_master *dev; + struct w1_master *dev, *n; /* Set netlink removal messages and some cleanup */ - list_for_each_entry(dev, &w1_masters, w1_master_entry) + list_for_each_entry_safe(dev, n, &w1_masters, w1_master_entry) __w1_remove_master_device(dev); w1_fini_netlink(); diff --git a/fs/afs/dir.c b/fs/afs/dir.c index 59eb924840518..31055d71b7882 100644 --- a/fs/afs/dir.c +++ b/fs/afs/dir.c @@ -887,7 +887,7 @@ static struct dentry *afs_lookup(struct inode *dir, struct dentry *dentry, static int afs_d_revalidate(struct dentry *dentry, unsigned int flags) { struct afs_vnode *vnode, *dir; - struct afs_fid uninitialized_var(fid); + struct afs_fid fid; struct dentry *parent; struct inode *inode; struct key *key; diff --git a/fs/afs/security.c b/fs/afs/security.c index 66042b432baa8..e12e532069eef 100644 --- a/fs/afs/security.c +++ b/fs/afs/security.c @@ -340,7 +340,7 @@ int afs_check_permit(struct afs_vnode *vnode, struct key *key, int afs_permission(struct inode *inode, int mask) { struct afs_vnode *vnode = AFS_FS_I(inode); - afs_access_t uninitialized_var(access); + afs_access_t access; struct key *key; int ret; diff --git a/fs/btrfs/ctree.c b/fs/btrfs/ctree.c index 34d56f0fa7501..e48c6d7a860f4 100644 --- a/fs/btrfs/ctree.c +++ b/fs/btrfs/ctree.c @@ -3590,6 +3590,8 @@ static noinline int split_node(struct btrfs_trans_handle *trans, ret = tree_mod_log_eb_copy(fs_info, split, c, 0, mid, c_nritems - mid); if (ret) { + btrfs_tree_unlock(split); + free_extent_buffer(split); btrfs_abort_transaction(trans, ret); return ret; } diff --git a/fs/btrfs/qgroup.c b/fs/btrfs/qgroup.c index 69b43df186a89..ef95525fa6cdf 100644 --- a/fs/btrfs/qgroup.c +++ b/fs/btrfs/qgroup.c @@ -1115,7 +1115,9 @@ int btrfs_quota_disable(struct btrfs_fs_info *fs_info) goto end_trans; } + spin_lock(&fs_info->trans_lock); list_del("a_root->dirty_list); + spin_unlock(&fs_info->trans_lock); btrfs_tree_lock(quota_root->node); clean_tree_block(fs_info, quota_root->node); diff --git a/fs/btrfs/transaction.c b/fs/btrfs/transaction.c index 049535115c9dc..1f31861453d9f 100644 --- a/fs/btrfs/transaction.c +++ b/fs/btrfs/transaction.c @@ -703,8 +703,13 @@ btrfs_attach_transaction_barrier(struct btrfs_root *root) trans = start_transaction(root, 0, TRANS_ATTACH, BTRFS_RESERVE_NO_FLUSH, true); - if (trans == ERR_PTR(-ENOENT)) - btrfs_wait_for_commit(root->fs_info, 0); + if (trans == ERR_PTR(-ENOENT)) { + int ret; + + ret = btrfs_wait_for_commit(root->fs_info, 0); + if (ret) + return ERR_PTR(ret); + } return trans; } diff --git a/fs/ceph/caps.c b/fs/ceph/caps.c index ba65b4bd7c0ac..fcfba2af5f98a 100644 --- a/fs/ceph/caps.c +++ b/fs/ceph/caps.c @@ -3285,6 +3285,15 @@ static void handle_cap_grant(struct inode *inode, } BUG_ON(cap->issued & ~cap->implemented); + /* don't let check_caps skip sending a response to MDS for revoke msgs */ + if (le32_to_cpu(grant->op) == CEPH_CAP_OP_REVOKE) { + cap->mds_wanted = 0; + if (cap == ci->i_auth_cap) + check_caps = 1; /* check auth cap only */ + else + check_caps = 2; /* check all caps */ + } + if (extra_info->inline_version > 0 && extra_info->inline_version >= ci->i_inline_version) { ci->i_inline_version = extra_info->inline_version; diff --git a/fs/dlm/netlink.c b/fs/dlm/netlink.c index 43a96c330570d..ea50f59610e52 100644 --- a/fs/dlm/netlink.c +++ b/fs/dlm/netlink.c @@ -115,7 +115,7 @@ static void fill_data(struct dlm_lock_data *data, struct dlm_lkb *lkb) void dlm_timeout_warn(struct dlm_lkb *lkb) { - struct sk_buff *uninitialized_var(send_skb); + struct sk_buff *send_skb; struct dlm_lock_data *data; size_t size; int rv; diff --git a/fs/dlm/plock.c b/fs/dlm/plock.c index e0c05e08d8bfe..9fef426ce6f41 100644 --- a/fs/dlm/plock.c +++ b/fs/dlm/plock.c @@ -22,20 +22,20 @@ static struct list_head recv_list; static wait_queue_head_t send_wq; static wait_queue_head_t recv_wq; -struct plock_op { - struct list_head list; - int done; - struct dlm_plock_info info; - int (*callback)(struct file_lock *fl, int result); -}; - -struct plock_xop { - struct plock_op xop; +struct plock_async_data { void *fl; void *file; struct file_lock flc; + int (*callback)(struct file_lock *fl, int result); }; +struct plock_op { + struct list_head list; + int done; + struct dlm_plock_info info; + /* if set indicates async handling */ + struct plock_async_data *data; +}; static inline void set_version(struct dlm_plock_info *info) { @@ -61,6 +61,12 @@ static int check_version(struct dlm_plock_info *info) return 0; } +static void dlm_release_plock_op(struct plock_op *op) +{ + kfree(op->data); + kfree(op); +} + static void send_op(struct plock_op *op) { set_version(&op->info); @@ -104,22 +110,21 @@ static void do_unlock_close(struct dlm_ls *ls, u64 number, int dlm_posix_lock(dlm_lockspace_t *lockspace, u64 number, struct file *file, int cmd, struct file_lock *fl) { + struct plock_async_data *op_data; struct dlm_ls *ls; struct plock_op *op; - struct plock_xop *xop; int rv; ls = dlm_find_lockspace_local(lockspace); if (!ls) return -EINVAL; - xop = kzalloc(sizeof(*xop), GFP_NOFS); - if (!xop) { + op = kzalloc(sizeof(*op), GFP_NOFS); + if (!op) { rv = -ENOMEM; goto out; } - op = &xop->xop; op->info.optype = DLM_PLOCK_OP_LOCK; op->info.pid = fl->fl_pid; op->info.ex = (fl->fl_type == F_WRLCK); @@ -128,35 +133,44 @@ int dlm_posix_lock(dlm_lockspace_t *lockspace, u64 number, struct file *file, op->info.number = number; op->info.start = fl->fl_start; op->info.end = fl->fl_end; + /* async handling */ if (fl->fl_lmops && fl->fl_lmops->lm_grant) { + op_data = kzalloc(sizeof(*op_data), GFP_NOFS); + if (!op_data) { + dlm_release_plock_op(op); + rv = -ENOMEM; + goto out; + } + /* fl_owner is lockd which doesn't distinguish processes on the nfs client */ op->info.owner = (__u64) fl->fl_pid; - op->callback = fl->fl_lmops->lm_grant; - locks_init_lock(&xop->flc); - locks_copy_lock(&xop->flc, fl); - xop->fl = fl; - xop->file = file; + op_data->callback = fl->fl_lmops->lm_grant; + locks_init_lock(&op_data->flc); + locks_copy_lock(&op_data->flc, fl); + op_data->fl = fl; + op_data->file = file; + + op->data = op_data; + + send_op(op); + rv = FILE_LOCK_DEFERRED; + goto out; } else { op->info.owner = (__u64)(long) fl->fl_owner; } send_op(op); - if (!op->callback) { - rv = wait_event_interruptible(recv_wq, (op->done != 0)); - if (rv == -ERESTARTSYS) { - log_debug(ls, "dlm_posix_lock: wait killed %llx", - (unsigned long long)number); - spin_lock(&ops_lock); - list_del(&op->list); - spin_unlock(&ops_lock); - kfree(xop); - do_unlock_close(ls, number, file, fl); - goto out; - } - } else { - rv = FILE_LOCK_DEFERRED; + rv = wait_event_killable(recv_wq, (op->done != 0)); + if (rv == -ERESTARTSYS) { + log_debug(ls, "%s: wait killed %llx", __func__, + (unsigned long long)number); + spin_lock(&ops_lock); + list_del(&op->list); + spin_unlock(&ops_lock); + dlm_release_plock_op(op); + do_unlock_close(ls, number, file, fl); goto out; } @@ -176,7 +190,7 @@ int dlm_posix_lock(dlm_lockspace_t *lockspace, u64 number, struct file *file, (unsigned long long)number); } - kfree(xop); + dlm_release_plock_op(op); out: dlm_put_lockspace(ls); return rv; @@ -186,11 +200,11 @@ EXPORT_SYMBOL_GPL(dlm_posix_lock); /* Returns failure iff a successful lock operation should be canceled */ static int dlm_plock_callback(struct plock_op *op) { + struct plock_async_data *op_data = op->data; struct file *file; struct file_lock *fl; struct file_lock *flc; int (*notify)(struct file_lock *fl, int result) = NULL; - struct plock_xop *xop = (struct plock_xop *)op; int rv = 0; spin_lock(&ops_lock); @@ -202,10 +216,10 @@ static int dlm_plock_callback(struct plock_op *op) spin_unlock(&ops_lock); /* check if the following 2 are still valid or make a copy */ - file = xop->file; - flc = &xop->flc; - fl = xop->fl; - notify = op->callback; + file = op_data->file; + flc = &op_data->flc; + fl = op_data->fl; + notify = op_data->callback; if (op->info.rv) { notify(fl, op->info.rv); @@ -236,7 +250,7 @@ static int dlm_plock_callback(struct plock_op *op) } out: - kfree(xop); + dlm_release_plock_op(op); return rv; } @@ -306,7 +320,7 @@ int dlm_posix_unlock(dlm_lockspace_t *lockspace, u64 number, struct file *file, rv = 0; out_free: - kfree(op); + dlm_release_plock_op(op); out: dlm_put_lockspace(ls); fl->fl_flags = fl_flags; @@ -366,13 +380,15 @@ int dlm_posix_get(dlm_lockspace_t *lockspace, u64 number, struct file *file, locks_init_lock(fl); fl->fl_type = (op->info.ex) ? F_WRLCK : F_RDLCK; fl->fl_flags = FL_POSIX; - fl->fl_pid = -op->info.pid; + fl->fl_pid = op->info.pid; + if (op->info.nodeid != dlm_our_nodeid()) + fl->fl_pid = -fl->fl_pid; fl->fl_start = op->info.start; fl->fl_end = op->info.end; rv = 0; } - kfree(op); + dlm_release_plock_op(op); out: dlm_put_lockspace(ls); return rv; @@ -408,7 +424,7 @@ static ssize_t dev_read(struct file *file, char __user *u, size_t count, (the process did not make an unlock call). */ if (op->info.flags & DLM_PLOCK_FL_CLOSE) - kfree(op); + dlm_release_plock_op(op); if (copy_to_user(u, &info, sizeof(info))) return -EFAULT; @@ -440,7 +456,7 @@ static ssize_t dev_write(struct file *file, const char __user *u, size_t count, op->info.owner == info.owner) { list_del_init(&op->list); memcpy(&op->info, &info, sizeof(info)); - if (op->callback) + if (op->data) do_callback = 1; else op->done = 1; diff --git a/fs/ext2/ext2.h b/fs/ext2/ext2.h index a203a5723e2c0..598dc28748086 100644 --- a/fs/ext2/ext2.h +++ b/fs/ext2/ext2.h @@ -68,10 +68,7 @@ struct mb_cache; * second extended-fs super-block data in memory */ struct ext2_sb_info { - unsigned long s_frag_size; /* Size of a fragment in bytes */ - unsigned long s_frags_per_block;/* Number of fragments per block */ unsigned long s_inodes_per_block;/* Number of inodes per block */ - unsigned long s_frags_per_group;/* Number of fragments in a group */ unsigned long s_blocks_per_group;/* Number of blocks in a group */ unsigned long s_inodes_per_group;/* Number of inodes in a group */ unsigned long s_itb_per_group; /* Number of inode table blocks per group */ @@ -185,15 +182,6 @@ static inline struct ext2_sb_info *EXT2_SB(struct super_block *sb) #define EXT2_INODE_SIZE(s) (EXT2_SB(s)->s_inode_size) #define EXT2_FIRST_INO(s) (EXT2_SB(s)->s_first_ino) -/* - * Macro-instructions used to manage fragments - */ -#define EXT2_MIN_FRAG_SIZE 1024 -#define EXT2_MAX_FRAG_SIZE 4096 -#define EXT2_MIN_FRAG_LOG_SIZE 10 -#define EXT2_FRAG_SIZE(s) (EXT2_SB(s)->s_frag_size) -#define EXT2_FRAGS_PER_BLOCK(s) (EXT2_SB(s)->s_frags_per_block) - /* * Structure of a blocks group descriptor */ diff --git a/fs/ext2/super.c b/fs/ext2/super.c index 3349ce85d27cb..5c0af53f2e8fc 100644 --- a/fs/ext2/super.c +++ b/fs/ext2/super.c @@ -691,10 +691,9 @@ static int ext2_setup_super (struct super_block * sb, es->s_max_mnt_count = cpu_to_le16(EXT2_DFL_MAX_MNT_COUNT); le16_add_cpu(&es->s_mnt_count, 1); if (test_opt (sb, DEBUG)) - ext2_msg(sb, KERN_INFO, "%s, %s, bs=%lu, fs=%lu, gc=%lu, " + ext2_msg(sb, KERN_INFO, "%s, %s, bs=%lu, gc=%lu, " "bpg=%lu, ipg=%lu, mo=%04lx]", EXT2FS_VERSION, EXT2FS_DATE, sb->s_blocksize, - sbi->s_frag_size, sbi->s_groups_count, EXT2_BLOCKS_PER_GROUP(sb), EXT2_INODES_PER_GROUP(sb), @@ -1040,14 +1039,7 @@ static int ext2_fill_super(struct super_block *sb, void *data, int silent) } } - sbi->s_frag_size = EXT2_MIN_FRAG_SIZE << - le32_to_cpu(es->s_log_frag_size); - if (sbi->s_frag_size == 0) - goto cantfind_ext2; - sbi->s_frags_per_block = sb->s_blocksize / sbi->s_frag_size; - sbi->s_blocks_per_group = le32_to_cpu(es->s_blocks_per_group); - sbi->s_frags_per_group = le32_to_cpu(es->s_frags_per_group); sbi->s_inodes_per_group = le32_to_cpu(es->s_inodes_per_group); if (EXT2_INODE_SIZE(sb) == 0) @@ -1075,11 +1067,10 @@ static int ext2_fill_super(struct super_block *sb, void *data, int silent) goto failed_mount; } - if (sb->s_blocksize != sbi->s_frag_size) { + if (es->s_log_frag_size != es->s_log_block_size) { ext2_msg(sb, KERN_ERR, - "error: fragsize %lu != blocksize %lu" - "(not supported yet)", - sbi->s_frag_size, sb->s_blocksize); + "error: fragsize log %u != blocksize log %u", + le32_to_cpu(es->s_log_frag_size), sb->s_blocksize_bits); goto failed_mount; } @@ -1089,12 +1080,6 @@ static int ext2_fill_super(struct super_block *sb, void *data, int silent) sbi->s_blocks_per_group); goto failed_mount; } - if (sbi->s_frags_per_group > sb->s_blocksize * 8) { - ext2_msg(sb, KERN_ERR, - "error: #fragments per group too big: %lu", - sbi->s_frags_per_group); - goto failed_mount; - } if (sbi->s_inodes_per_group < sbi->s_inodes_per_block || sbi->s_inodes_per_group > sb->s_blocksize * 8) { ext2_msg(sb, KERN_ERR, diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h index 19e2a52d1e5a1..909f231a387d7 100644 --- a/fs/ext4/ext4.h +++ b/fs/ext4/ext4.h @@ -1412,7 +1412,7 @@ struct ext4_sb_info { unsigned long s_commit_interval; u32 s_max_batch_time; u32 s_min_batch_time; - struct block_device *journal_bdev; + struct block_device *s_journal_bdev; #ifdef CONFIG_QUOTA /* Names of quota files with journalled quota */ char __rcu *s_qf_names[EXT4_MAXQUOTAS]; diff --git a/fs/ext4/fsmap.c b/fs/ext4/fsmap.c index 6b52ace1463c2..69c76327792e0 100644 --- a/fs/ext4/fsmap.c +++ b/fs/ext4/fsmap.c @@ -576,8 +576,8 @@ static bool ext4_getfsmap_is_valid_device(struct super_block *sb, if (fm->fmr_device == 0 || fm->fmr_device == UINT_MAX || fm->fmr_device == new_encode_dev(sb->s_bdev->bd_dev)) return true; - if (EXT4_SB(sb)->journal_bdev && - fm->fmr_device == new_encode_dev(EXT4_SB(sb)->journal_bdev->bd_dev)) + if (EXT4_SB(sb)->s_journal_bdev && + fm->fmr_device == new_encode_dev(EXT4_SB(sb)->s_journal_bdev->bd_dev)) return true; return false; } @@ -647,9 +647,9 @@ int ext4_getfsmap(struct super_block *sb, struct ext4_fsmap_head *head, memset(handlers, 0, sizeof(handlers)); handlers[0].gfd_dev = new_encode_dev(sb->s_bdev->bd_dev); handlers[0].gfd_fn = ext4_getfsmap_datadev; - if (EXT4_SB(sb)->journal_bdev) { + if (EXT4_SB(sb)->s_journal_bdev) { handlers[1].gfd_dev = new_encode_dev( - EXT4_SB(sb)->journal_bdev->bd_dev); + EXT4_SB(sb)->s_journal_bdev->bd_dev); handlers[1].gfd_fn = ext4_getfsmap_logdev; } diff --git a/fs/ext4/indirect.c b/fs/ext4/indirect.c index 0cc0d22c08569..9bf711d63368c 100644 --- a/fs/ext4/indirect.c +++ b/fs/ext4/indirect.c @@ -642,6 +642,14 @@ int ext4_ind_map_blocks(handle_t *handle, struct inode *inode, ext4_update_inode_fsync_trans(handle, inode, 1); count = ar.len; + + /* + * Update reserved blocks/metadata blocks after successful block + * allocation which had been deferred till now. + */ + if (flags & EXT4_GET_BLOCKS_DELALLOC_RESERVE) + ext4_da_update_reserve_space(inode, count, 1); + got_it: map->m_flags |= EXT4_MAP_MAPPED; map->m_pblk = le32_to_cpu(chain[depth-1].key); diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index 7aaf4dafd3e78..646285fbc9fc0 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c @@ -668,16 +668,6 @@ found: */ ext4_clear_inode_state(inode, EXT4_STATE_EXT_MIGRATE); } - - /* - * Update reserved blocks/metadata blocks after successful - * block allocation which had been deferred till now. We don't - * support fallocate for non extent files. So we can update - * reserve space here. - */ - if ((retval > 0) && - (flags & EXT4_GET_BLOCKS_DELALLOC_RESERVE)) - ext4_da_update_reserve_space(inode, retval, 1); } if (retval > 0) { diff --git a/fs/ext4/ioctl.c b/fs/ext4/ioctl.c index b930e8d559d41..43e036f0b661d 100644 --- a/fs/ext4/ioctl.c +++ b/fs/ext4/ioctl.c @@ -561,6 +561,7 @@ static int ext4_shutdown(struct super_block *sb, unsigned long arg) { struct ext4_sb_info *sbi = EXT4_SB(sb); __u32 flags; + struct super_block *ret; if (!capable(CAP_SYS_ADMIN)) return -EPERM; @@ -579,7 +580,9 @@ static int ext4_shutdown(struct super_block *sb, unsigned long arg) switch (flags) { case EXT4_GOING_FLAGS_DEFAULT: - freeze_bdev(sb->s_bdev); + ret = freeze_bdev(sb->s_bdev); + if (IS_ERR(ret)) + return PTR_ERR(ret); set_bit(EXT4_FLAGS_SHUTDOWN, &sbi->s_ext4_flags); thaw_bdev(sb->s_bdev, sb); break; diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c index 23e56c1ffc1bf..7692c12b85285 100644 --- a/fs/ext4/mballoc.c +++ b/fs/ext4/mballoc.c @@ -4948,8 +4948,8 @@ do_more: * them with group lock_held */ if (test_opt(sb, DISCARD)) { - err = ext4_issue_discard(sb, block_group, bit, count, - NULL); + err = ext4_issue_discard(sb, block_group, bit, + count_clusters, NULL); if (err && err != -EOPNOTSUPP) ext4_msg(sb, KERN_WARNING, "discard request in" " group:%d block:%d count:%lu failed" diff --git a/fs/ext4/super.c b/fs/ext4/super.c index ce5abd25eb99c..926063a6d2321 100644 --- a/fs/ext4/super.c +++ b/fs/ext4/super.c @@ -905,10 +905,16 @@ static void ext4_blkdev_put(struct block_device *bdev) static void ext4_blkdev_remove(struct ext4_sb_info *sbi) { struct block_device *bdev; - bdev = sbi->journal_bdev; + bdev = sbi->s_journal_bdev; if (bdev) { + /* + * Invalidate the journal device's buffers. We don't want them + * floating about in memory - the physical journal device may + * hotswapped, and it breaks the `ro-after' testing code. + */ + invalidate_bdev(bdev); ext4_blkdev_put(bdev); - sbi->journal_bdev = NULL; + sbi->s_journal_bdev = NULL; } } @@ -1032,14 +1038,8 @@ static void ext4_put_super(struct super_block *sb) sync_blockdev(sb->s_bdev); invalidate_bdev(sb->s_bdev); - if (sbi->journal_bdev && sbi->journal_bdev != sb->s_bdev) { - /* - * Invalidate the journal device's buffers. We don't want them - * floating about in memory - the physical journal device may - * hotswapped, and it breaks the `ro-after' testing code. - */ - sync_blockdev(sbi->journal_bdev); - invalidate_bdev(sbi->journal_bdev); + if (sbi->s_journal_bdev && sbi->s_journal_bdev != sb->s_bdev) { + sync_blockdev(sbi->s_journal_bdev); ext4_blkdev_remove(sbi); } if (sbi->s_ea_inode_cache) { @@ -3537,7 +3537,7 @@ int ext4_calculate_overhead(struct super_block *sb) * Add the internal journal blocks whether the journal has been * loaded or not */ - if (sbi->s_journal && !sbi->journal_bdev) + if (sbi->s_journal && !sbi->s_journal_bdev) overhead += EXT4_NUM_B2C(sbi, sbi->s_journal->j_maxlen); else if (ext4_has_feature_journal(sb) && !sbi->s_journal && j_inum) { /* j_inum for internal journal is non-zero */ @@ -4673,6 +4673,7 @@ failed_mount: ext4_blkdev_remove(sbi); brelse(bh); out_fail: + invalidate_bdev(sb->s_bdev); sb->s_fs_info = NULL; kfree(sbi->s_blockgroup_lock); out_free_base: @@ -4848,7 +4849,7 @@ static journal_t *ext4_get_dev_journal(struct super_block *sb, be32_to_cpu(journal->j_superblock->s_nr_users)); goto out_journal; } - EXT4_SB(sb)->journal_bdev = bdev; + EXT4_SB(sb)->s_journal_bdev = bdev; ext4_init_journal_params(sb, journal); return journal; diff --git a/fs/ext4/xattr.c b/fs/ext4/xattr.c index f8a8807c20977..88bdb2714e519 100644 --- a/fs/ext4/xattr.c +++ b/fs/ext4/xattr.c @@ -1767,6 +1767,20 @@ static int ext4_xattr_set_entry(struct ext4_xattr_info *i, memmove(here, (void *)here + size, (void *)last - (void *)here + sizeof(__u32)); memset(last, 0, size); + + /* + * Update i_inline_off - moved ibody region might contain + * system.data attribute. Handling a failure here won't + * cause other complications for setting an xattr. + */ + if (!is_block && ext4_has_inline_data(inode)) { + ret = ext4_find_inline_data_nolock(inode); + if (ret) { + ext4_warning_inode(inode, + "unable to update i_inline_off"); + goto out; + } + } } else if (s->not_found) { /* Insert new name. */ size_t size = EXT4_XATTR_LEN(name_len); diff --git a/fs/f2fs/node.c b/fs/f2fs/node.c index 2c28f488ac2f0..9911f780e0136 100644 --- a/fs/f2fs/node.c +++ b/fs/f2fs/node.c @@ -879,8 +879,10 @@ static int truncate_dnode(struct dnode_of_data *dn) dn->ofs_in_node = 0; f2fs_truncate_data_blocks(dn); err = truncate_node(dn); - if (err) + if (err) { + f2fs_put_page(page, 1); return err; + } return 1; } diff --git a/fs/fat/dir.c b/fs/fat/dir.c index de60c05c0ca1d..10769b2e4d468 100644 --- a/fs/fat/dir.c +++ b/fs/fat/dir.c @@ -1287,7 +1287,7 @@ int fat_add_entries(struct inode *dir, void *slots, int nr_slots, struct super_block *sb = dir->i_sb; struct msdos_sb_info *sbi = MSDOS_SB(sb); struct buffer_head *bh, *prev, *bhs[3]; /* 32*slots (672bytes) */ - struct msdos_dir_entry *uninitialized_var(de); + struct msdos_dir_entry *de; int err, free_slots, i, nr_bhs; loff_t pos, i_pos; diff --git a/fs/fuse/control.c b/fs/fuse/control.c index acc35819aae64..af253127b309a 100644 --- a/fs/fuse/control.c +++ b/fs/fuse/control.c @@ -117,7 +117,7 @@ static ssize_t fuse_conn_max_background_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos) { - unsigned uninitialized_var(val); + unsigned val; ssize_t ret; ret = fuse_conn_limit_write(file, buf, count, ppos, &val, diff --git a/fs/fuse/cuse.c b/fs/fuse/cuse.c index e10e2b62ccf45..acd985aa2cbab 100644 --- a/fs/fuse/cuse.c +++ b/fs/fuse/cuse.c @@ -269,7 +269,7 @@ static int cuse_parse_one(char **pp, char *end, char **keyp, char **valp) static int cuse_parse_devinfo(char *p, size_t len, struct cuse_devinfo *devinfo) { char *end = p + len; - char *uninitialized_var(key), *uninitialized_var(val); + char *key, *val; int rc; while (true) { diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c index 6098e0c7f87b3..0e03adbcf9423 100644 --- a/fs/fuse/dir.c +++ b/fs/fuse/dir.c @@ -232,7 +232,7 @@ static int fuse_dentry_revalidate(struct dentry *entry, unsigned int flags) spin_unlock(&fc->lock); } kfree(forget); - if (ret == -ENOMEM) + if (ret == -ENOMEM || ret == -EINTR) goto out; if (ret || fuse_invalid_attr(&outarg.attr) || (outarg.attr.mode ^ inode->i_mode) & S_IFMT) diff --git a/fs/fuse/file.c b/fs/fuse/file.c index 599a6eeed02e0..c629ccafb2b0e 100644 --- a/fs/fuse/file.c +++ b/fs/fuse/file.c @@ -2774,7 +2774,7 @@ static void fuse_register_polled_file(struct fuse_conn *fc, { spin_lock(&fc->lock); if (RB_EMPTY_NODE(&ff->polled_node)) { - struct rb_node **link, *uninitialized_var(parent); + struct rb_node **link, *parent; link = fuse_find_polled_node(fc, ff->kh, &parent); BUG_ON(*link); diff --git a/fs/gfs2/aops.c b/fs/gfs2/aops.c index d9866d89f2fb9..910bfc39dc4b4 100644 --- a/fs/gfs2/aops.c +++ b/fs/gfs2/aops.c @@ -359,7 +359,7 @@ static int gfs2_write_cache_jdata(struct address_space *mapping, int done = 0; struct pagevec pvec; int nr_pages; - pgoff_t uninitialized_var(writeback_index); + pgoff_t writeback_index; pgoff_t index; pgoff_t end; pgoff_t done_index; diff --git a/fs/gfs2/bmap.c b/fs/gfs2/bmap.c index ccafd45b63f69..729f36fdced1f 100644 --- a/fs/gfs2/bmap.c +++ b/fs/gfs2/bmap.c @@ -1754,7 +1754,7 @@ static int punch_hole(struct gfs2_inode *ip, u64 offset, u64 length) u64 lblock = (offset + (1 << bsize_shift) - 1) >> bsize_shift; __u16 start_list[GFS2_MAX_META_HEIGHT]; __u16 __end_list[GFS2_MAX_META_HEIGHT], *end_list = NULL; - unsigned int start_aligned, uninitialized_var(end_aligned); + unsigned int start_aligned, end_aligned; unsigned int strip_h = ip->i_height - 1; u32 btotal = 0; int ret, state; diff --git a/fs/gfs2/super.c b/fs/gfs2/super.c index 3cc2237e58967..bb0eaa4638e3c 100644 --- a/fs/gfs2/super.c +++ b/fs/gfs2/super.c @@ -1586,6 +1586,14 @@ static void gfs2_evict_inode(struct inode *inode) if (inode->i_nlink || sb_rdonly(sb)) goto out; + /* + * In case of an incomplete mount, gfs2_evict_inode() may be called for + * system files without having an active journal to write to. In that + * case, skip the filesystem evict. + */ + if (!sdp->sd_jdesc) + goto out; + if (test_bit(GIF_ALLOC_FAILED, &ip->i_flags)) { BUG_ON(!gfs2_glock_is_locked_by_me(ip->i_gl)); gfs2_holder_mark_uninitialized(&gh); diff --git a/fs/hfsplus/unicode.c b/fs/hfsplus/unicode.c index c8d1b2be7854e..73342c925a4b6 100644 --- a/fs/hfsplus/unicode.c +++ b/fs/hfsplus/unicode.c @@ -398,7 +398,7 @@ int hfsplus_hash_dentry(const struct dentry *dentry, struct qstr *str) astr = str->name; len = str->len; while (len > 0) { - int uninitialized_var(dsize); + int dsize; size = asc2unichar(sb, astr, len, &c); astr += size; len -= size; diff --git a/fs/isofs/namei.c b/fs/isofs/namei.c index 558e7c51ce0d4..58f80e1b3ac0d 100644 --- a/fs/isofs/namei.c +++ b/fs/isofs/namei.c @@ -153,8 +153,8 @@ isofs_find_entry(struct inode *dir, struct dentry *dentry, struct dentry *isofs_lookup(struct inode *dir, struct dentry *dentry, unsigned int flags) { int found; - unsigned long uninitialized_var(block); - unsigned long uninitialized_var(offset); + unsigned long block; + unsigned long offset; struct inode *inode; struct page *page; diff --git a/fs/jffs2/build.c b/fs/jffs2/build.c index 837cd55fd4c5e..6ae9d6fefb861 100644 --- a/fs/jffs2/build.c +++ b/fs/jffs2/build.c @@ -211,7 +211,10 @@ static int jffs2_build_filesystem(struct jffs2_sb_info *c) ic->scan_dents = NULL; cond_resched(); } - jffs2_build_xattr_subsystem(c); + ret = jffs2_build_xattr_subsystem(c); + if (ret) + goto exit; + c->flags &= ~JFFS2_SB_FLAG_BUILDING; dbg_fsbuild("FS build complete\n"); diff --git a/fs/jffs2/erase.c b/fs/jffs2/erase.c index 83b8f06b4a642..7e9abdb897122 100644 --- a/fs/jffs2/erase.c +++ b/fs/jffs2/erase.c @@ -401,7 +401,7 @@ static void jffs2_mark_erased_block(struct jffs2_sb_info *c, struct jffs2_eraseb { size_t retlen; int ret; - uint32_t uninitialized_var(bad_offset); + uint32_t bad_offset; switch (jffs2_block_check_erase(c, jeb, &bad_offset)) { case -EAGAIN: goto refile; diff --git a/fs/jffs2/xattr.c b/fs/jffs2/xattr.c index da3e18503c658..acb4492f5970c 100644 --- a/fs/jffs2/xattr.c +++ b/fs/jffs2/xattr.c @@ -772,10 +772,10 @@ void jffs2_clear_xattr_subsystem(struct jffs2_sb_info *c) } #define XREF_TMPHASH_SIZE (128) -void jffs2_build_xattr_subsystem(struct jffs2_sb_info *c) +int jffs2_build_xattr_subsystem(struct jffs2_sb_info *c) { struct jffs2_xattr_ref *ref, *_ref; - struct jffs2_xattr_ref *xref_tmphash[XREF_TMPHASH_SIZE]; + struct jffs2_xattr_ref **xref_tmphash; struct jffs2_xattr_datum *xd, *_xd; struct jffs2_inode_cache *ic; struct jffs2_raw_node_ref *raw; @@ -784,9 +784,12 @@ void jffs2_build_xattr_subsystem(struct jffs2_sb_info *c) BUG_ON(!(c->flags & JFFS2_SB_FLAG_BUILDING)); + xref_tmphash = kcalloc(XREF_TMPHASH_SIZE, + sizeof(struct jffs2_xattr_ref *), GFP_KERNEL); + if (!xref_tmphash) + return -ENOMEM; + /* Phase.1 : Merge same xref */ - for (i=0; i < XREF_TMPHASH_SIZE; i++) - xref_tmphash[i] = NULL; for (ref=c->xref_temp; ref; ref=_ref) { struct jffs2_xattr_ref *tmp; @@ -884,6 +887,8 @@ void jffs2_build_xattr_subsystem(struct jffs2_sb_info *c) "%u of xref (%u dead, %u orphan) found.\n", xdatum_count, xdatum_unchecked_count, xdatum_orphan_count, xref_count, xref_dead_count, xref_orphan_count); + kfree(xref_tmphash); + return 0; } struct jffs2_xattr_datum *jffs2_setup_xattr_datum(struct jffs2_sb_info *c, diff --git a/fs/jffs2/xattr.h b/fs/jffs2/xattr.h index 720007b2fd65d..1b5030a3349db 100644 --- a/fs/jffs2/xattr.h +++ b/fs/jffs2/xattr.h @@ -71,7 +71,7 @@ static inline int is_xattr_ref_dead(struct jffs2_xattr_ref *ref) #ifdef CONFIG_JFFS2_FS_XATTR extern void jffs2_init_xattr_subsystem(struct jffs2_sb_info *c); -extern void jffs2_build_xattr_subsystem(struct jffs2_sb_info *c); +extern int jffs2_build_xattr_subsystem(struct jffs2_sb_info *c); extern void jffs2_clear_xattr_subsystem(struct jffs2_sb_info *c); extern struct jffs2_xattr_datum *jffs2_setup_xattr_datum(struct jffs2_sb_info *c, @@ -103,7 +103,7 @@ extern ssize_t jffs2_listxattr(struct dentry *, char *, size_t); #else #define jffs2_init_xattr_subsystem(c) -#define jffs2_build_xattr_subsystem(c) +#define jffs2_build_xattr_subsystem(c) (0) #define jffs2_clear_xattr_subsystem(c) #define jffs2_xattr_do_crccheck_inode(c, ic) diff --git a/fs/jfs/jfs_dmap.c b/fs/jfs/jfs_dmap.c index 3ad0a33e0443b..07b9df8938f29 100644 --- a/fs/jfs/jfs_dmap.c +++ b/fs/jfs/jfs_dmap.c @@ -191,7 +191,13 @@ int dbMount(struct inode *ipbmap) dbmp_le = (struct dbmap_disk *) mp->data; bmp->db_mapsize = le64_to_cpu(dbmp_le->dn_mapsize); bmp->db_nfree = le64_to_cpu(dbmp_le->dn_nfree); + bmp->db_l2nbperpage = le32_to_cpu(dbmp_le->dn_l2nbperpage); + if (bmp->db_l2nbperpage > L2PSIZE - L2MINBLOCKSIZE) { + err = -EINVAL; + goto err_release_metapage; + } + bmp->db_numag = le32_to_cpu(dbmp_le->dn_numag); if (!bmp->db_numag) { err = -EINVAL; diff --git a/fs/jfs/jfs_filsys.h b/fs/jfs/jfs_filsys.h index 415bfa90607a2..0c36ce6318d53 100644 --- a/fs/jfs/jfs_filsys.h +++ b/fs/jfs/jfs_filsys.h @@ -135,7 +135,9 @@ #define NUM_INODE_PER_IAG INOSPERIAG #define MINBLOCKSIZE 512 +#define L2MINBLOCKSIZE 9 #define MAXBLOCKSIZE 4096 +#define L2MAXBLOCKSIZE 12 #define MAXFILESIZE ((s64)1 << 52) #define JFS_LINK_MAX 0xffffffff diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c index c82f898325c1c..74ab20c89e752 100644 --- a/fs/nfsd/nfs4xdr.c +++ b/fs/nfsd/nfs4xdr.c @@ -3403,7 +3403,7 @@ nfsd4_encode_open(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_op p = xdr_reserve_space(xdr, 32); if (!p) return nfserr_resource; - *p++ = cpu_to_be32(0); + *p++ = cpu_to_be32(open->op_recall); /* * TODO: space_limit's in delegations diff --git a/fs/nfsd/nfsctl.c b/fs/nfsd/nfsctl.c index ff9899cc9913f..7af48d306f20c 100644 --- a/fs/nfsd/nfsctl.c +++ b/fs/nfsd/nfsctl.c @@ -347,7 +347,7 @@ static ssize_t write_unlock_fs(struct file *file, char *buf, size_t size) static ssize_t write_filehandle(struct file *file, char *buf, size_t size) { char *dname, *path; - int uninitialized_var(maxsize); + int maxsize; char *mesg = buf; int len; struct auth_domain *dom; diff --git a/fs/ocfs2/alloc.c b/fs/ocfs2/alloc.c index 046f5e3c9622d..c7cf0913229cb 100644 --- a/fs/ocfs2/alloc.c +++ b/fs/ocfs2/alloc.c @@ -4722,7 +4722,7 @@ int ocfs2_insert_extent(handle_t *handle, struct ocfs2_alloc_context *meta_ac) { int status; - int uninitialized_var(free_records); + int free_records; struct buffer_head *last_eb_bh = NULL; struct ocfs2_insert_type insert = {0, }; struct ocfs2_extent_rec rec; @@ -7052,7 +7052,7 @@ int ocfs2_convert_inline_data_to_extents(struct inode *inode, int need_free = 0; u32 bit_off, num; handle_t *handle; - u64 uninitialized_var(block); + u64 block; struct ocfs2_inode_info *oi = OCFS2_I(inode); struct ocfs2_super *osb = OCFS2_SB(inode->i_sb); struct ocfs2_dinode *di = (struct ocfs2_dinode *)di_bh->b_data; diff --git a/fs/ocfs2/dir.c b/fs/ocfs2/dir.c index c121abbdfc7db..13f4bb4e174c4 100644 --- a/fs/ocfs2/dir.c +++ b/fs/ocfs2/dir.c @@ -866,9 +866,9 @@ static int ocfs2_dx_dir_lookup(struct inode *inode, u64 *ret_phys_blkno) { int ret = 0; - unsigned int cend, uninitialized_var(clen); - u32 uninitialized_var(cpos); - u64 uninitialized_var(blkno); + unsigned int cend, clen; + u32 cpos; + u64 blkno; u32 name_hash = hinfo->major_hash; ret = ocfs2_dx_dir_lookup_rec(inode, el, name_hash, &cpos, &blkno, @@ -912,7 +912,7 @@ static int ocfs2_dx_dir_search(const char *name, int namelen, struct ocfs2_dir_lookup_result *res) { int ret, i, found; - u64 uninitialized_var(phys); + u64 phys; struct buffer_head *dx_leaf_bh = NULL; struct ocfs2_dx_leaf *dx_leaf; struct ocfs2_dx_entry *dx_entry = NULL; @@ -4420,9 +4420,9 @@ out: int ocfs2_dx_dir_truncate(struct inode *dir, struct buffer_head *di_bh) { int ret; - unsigned int uninitialized_var(clen); - u32 major_hash = UINT_MAX, p_cpos, uninitialized_var(cpos); - u64 uninitialized_var(blkno); + unsigned int clen; + u32 major_hash = UINT_MAX, p_cpos, cpos; + u64 blkno; struct ocfs2_super *osb = OCFS2_SB(dir->i_sb); struct buffer_head *dx_root_bh = NULL; struct ocfs2_dx_root_block *dx_root; diff --git a/fs/ocfs2/extent_map.c b/fs/ocfs2/extent_map.c index 06cb96462bf99..1f41171c14687 100644 --- a/fs/ocfs2/extent_map.c +++ b/fs/ocfs2/extent_map.c @@ -416,7 +416,7 @@ static int ocfs2_get_clusters_nocache(struct inode *inode, { int i, ret, tree_height, len; struct ocfs2_dinode *di; - struct ocfs2_extent_block *uninitialized_var(eb); + struct ocfs2_extent_block *eb; struct ocfs2_extent_list *el; struct ocfs2_extent_rec *rec; struct buffer_head *eb_bh = NULL; @@ -613,7 +613,7 @@ int ocfs2_get_clusters(struct inode *inode, u32 v_cluster, unsigned int *extent_flags) { int ret; - unsigned int uninitialized_var(hole_len), flags = 0; + unsigned int hole_len, flags = 0; struct buffer_head *di_bh = NULL; struct ocfs2_extent_rec rec; diff --git a/fs/ocfs2/namei.c b/fs/ocfs2/namei.c index d437b21925228..bd8d742adf65a 100644 --- a/fs/ocfs2/namei.c +++ b/fs/ocfs2/namei.c @@ -2506,7 +2506,7 @@ int ocfs2_create_inode_in_orphan(struct inode *dir, struct buffer_head *new_di_bh = NULL; struct ocfs2_alloc_context *inode_ac = NULL; struct ocfs2_dir_lookup_result orphan_insert = { NULL, }; - u64 uninitialized_var(di_blkno), suballoc_loc; + u64 di_blkno, suballoc_loc; u16 suballoc_bit; status = ocfs2_inode_lock(dir, &parent_di_bh, 1); diff --git a/fs/ocfs2/refcounttree.c b/fs/ocfs2/refcounttree.c index fc197e599e8ce..e184b36f8dd33 100644 --- a/fs/ocfs2/refcounttree.c +++ b/fs/ocfs2/refcounttree.c @@ -1069,7 +1069,7 @@ static int ocfs2_get_refcount_rec(struct ocfs2_caching_info *ci, struct buffer_head **ret_bh) { int ret = 0, i, found; - u32 low_cpos, uninitialized_var(cpos_end); + u32 low_cpos, cpos_end; struct ocfs2_extent_list *el; struct ocfs2_extent_rec *rec = NULL; struct ocfs2_extent_block *eb = NULL; diff --git a/fs/ocfs2/xattr.c b/fs/ocfs2/xattr.c index c146e12a8601f..54d881c9ac81e 100644 --- a/fs/ocfs2/xattr.c +++ b/fs/ocfs2/xattr.c @@ -1219,7 +1219,7 @@ static int ocfs2_xattr_block_get(struct inode *inode, struct ocfs2_xattr_value_root *xv; size_t size; int ret = -ENODATA, name_offset, name_len, i; - int uninitialized_var(block_off); + int block_off; xs->bucket = ocfs2_xattr_bucket_new(inode); if (!xs->bucket) { diff --git a/fs/omfs/file.c b/fs/omfs/file.c index bf83e6644333f..ce59b2fb50c74 100644 --- a/fs/omfs/file.c +++ b/fs/omfs/file.c @@ -220,7 +220,7 @@ static int omfs_get_block(struct inode *inode, sector_t block, struct buffer_head *bh; sector_t next, offset; int ret; - u64 uninitialized_var(new_block); + u64 new_block; u32 max_extents; int extent_count; struct omfs_extent *oe; diff --git a/fs/overlayfs/copy_up.c b/fs/overlayfs/copy_up.c index 30abafcd4ecce..3d7a700350c1d 100644 --- a/fs/overlayfs/copy_up.c +++ b/fs/overlayfs/copy_up.c @@ -713,7 +713,7 @@ static int ovl_copy_up_meta_inode_data(struct ovl_copy_up_ctx *c) struct path upperpath, datapath; int err; char *capability = NULL; - ssize_t uninitialized_var(cap_size); + ssize_t cap_size; ovl_path_upper(c->dentry, &upperpath); if (WARN_ON(upperpath.dentry == NULL)) diff --git a/fs/sysv/itree.c b/fs/sysv/itree.c index 31f66053e2393..e3d1673b8ec97 100644 --- a/fs/sysv/itree.c +++ b/fs/sysv/itree.c @@ -145,6 +145,10 @@ static int alloc_branch(struct inode *inode, */ parent = block_to_cpu(SYSV_SB(inode->i_sb), branch[n-1].key); bh = sb_getblk(inode->i_sb, parent); + if (!bh) { + sysv_free_block(inode->i_sb, branch[n].key); + break; + } lock_buffer(bh); memset(bh->b_data, 0, blocksize); branch[n].bh = bh; diff --git a/fs/ubifs/commit.c b/fs/ubifs/commit.c index 591f2c7a48f07..583e20787689b 100644 --- a/fs/ubifs/commit.c +++ b/fs/ubifs/commit.c @@ -564,11 +564,11 @@ out: */ int dbg_check_old_index(struct ubifs_info *c, struct ubifs_zbranch *zroot) { - int lnum, offs, len, err = 0, uninitialized_var(last_level), child_cnt; + int lnum, offs, len, err = 0, last_level, child_cnt; int first = 1, iip; struct ubifs_debug_info *d = c->dbg; - union ubifs_key uninitialized_var(lower_key), upper_key, l_key, u_key; - unsigned long long uninitialized_var(last_sqnum); + union ubifs_key lower_key, upper_key, l_key, u_key; + unsigned long long last_sqnum; struct ubifs_idx_node *idx; struct list_head list; struct idx_node *i; diff --git a/fs/ubifs/dir.c b/fs/ubifs/dir.c index cb52aa9ea276c..39296e8012421 100644 --- a/fs/ubifs/dir.c +++ b/fs/ubifs/dir.c @@ -1294,7 +1294,7 @@ static int do_rename(struct inode *old_dir, struct dentry *old_dentry, struct ubifs_budget_req ino_req = { .dirtied_ino = 1, .dirtied_ino_d = ALIGN(old_inode_ui->data_len, 8) }; struct timespec64 time; - unsigned int uninitialized_var(saved_nlink); + unsigned int saved_nlink; struct fscrypt_name old_nm, new_nm; /* diff --git a/fs/ubifs/file.c b/fs/ubifs/file.c index ae836e8bb2933..fca3b7f483c79 100644 --- a/fs/ubifs/file.c +++ b/fs/ubifs/file.c @@ -234,7 +234,7 @@ static int write_begin_slow(struct address_space *mapping, struct ubifs_info *c = inode->i_sb->s_fs_info; pgoff_t index = pos >> PAGE_SHIFT; struct ubifs_budget_req req = { .new_page = 1 }; - int uninitialized_var(err), appending = !!(pos + len > inode->i_size); + int err, appending = !!(pos + len > inode->i_size); struct page *page; dbg_gen("ino %lu, pos %llu, len %u, i_size %lld", @@ -438,7 +438,7 @@ static int ubifs_write_begin(struct file *file, struct address_space *mapping, struct ubifs_info *c = inode->i_sb->s_fs_info; struct ubifs_inode *ui = ubifs_inode(inode); pgoff_t index = pos >> PAGE_SHIFT; - int uninitialized_var(err), appending = !!(pos + len > inode->i_size); + int err, appending = !!(pos + len > inode->i_size); int skipped_read = 0; struct page *page; diff --git a/fs/ubifs/journal.c b/fs/ubifs/journal.c index 802565a17733c..0a60a065c7e8b 100644 --- a/fs/ubifs/journal.c +++ b/fs/ubifs/journal.c @@ -1355,7 +1355,7 @@ int ubifs_jnl_truncate(struct ubifs_info *c, const struct inode *inode, union ubifs_key key, to_key; struct ubifs_ino_node *ino; struct ubifs_trun_node *trun; - struct ubifs_data_node *uninitialized_var(dn); + struct ubifs_data_node *dn; int err, dlen, len, lnum, offs, bit, sz, sync = IS_SYNC(inode); struct ubifs_inode *ui = ubifs_inode(inode); ino_t inum = inode->i_ino; diff --git a/fs/ubifs/lpt.c b/fs/ubifs/lpt.c index 31393370e3348..433bfcddc497c 100644 --- a/fs/ubifs/lpt.c +++ b/fs/ubifs/lpt.c @@ -287,7 +287,7 @@ uint32_t ubifs_unpack_bits(const struct ubifs_info *c, uint8_t **addr, int *pos, const int k = 32 - nrbits; uint8_t *p = *addr; int b = *pos; - uint32_t uninitialized_var(val); + uint32_t val; const int bytes = (nrbits + b + 7) >> 3; ubifs_assert(c, nrbits > 0); diff --git a/fs/ubifs/tnc.c b/fs/ubifs/tnc.c index 08ed942b76271..330ccf72745bb 100644 --- a/fs/ubifs/tnc.c +++ b/fs/ubifs/tnc.c @@ -936,7 +936,7 @@ static int fallible_resolve_collision(struct ubifs_info *c, int adding) { struct ubifs_znode *o_znode = NULL, *znode = *zn; - int uninitialized_var(o_n), err, cmp, unsure = 0, nn = *n; + int o_n, err, cmp, unsure = 0, nn = *n; cmp = fallible_matches_name(c, &znode->zbranch[nn], nm); if (unlikely(cmp < 0)) @@ -1558,8 +1558,8 @@ out: */ int ubifs_tnc_get_bu_keys(struct ubifs_info *c, struct bu_info *bu) { - int n, err = 0, lnum = -1, uninitialized_var(offs); - int uninitialized_var(len); + int n, err = 0, lnum = -1, offs; + int len; unsigned int block = key_block(c, &bu->key); struct ubifs_znode *znode; diff --git a/fs/ubifs/tnc_misc.c b/fs/ubifs/tnc_misc.c index d90ee01076a9e..fe3b52d2749b4 100644 --- a/fs/ubifs/tnc_misc.c +++ b/fs/ubifs/tnc_misc.c @@ -138,8 +138,8 @@ int ubifs_search_zbranch(const struct ubifs_info *c, const struct ubifs_znode *znode, const union ubifs_key *key, int *n) { - int beg = 0, end = znode->child_cnt, uninitialized_var(mid); - int uninitialized_var(cmp); + int beg = 0, end = znode->child_cnt, mid; + int cmp; const struct ubifs_zbranch *zbr = &znode->zbranch[0]; ubifs_assert(c, end > beg); diff --git a/fs/udf/balloc.c b/fs/udf/balloc.c index fcda0fc97b90a..4c0307f378d72 100644 --- a/fs/udf/balloc.c +++ b/fs/udf/balloc.c @@ -555,7 +555,7 @@ static udf_pblk_t udf_table_new_block(struct super_block *sb, udf_pblk_t newblock = 0; uint32_t adsize; uint32_t elen, goal_elen = 0; - struct kernel_lb_addr eloc, uninitialized_var(goal_eloc); + struct kernel_lb_addr eloc, goal_eloc; struct extent_position epos, goal_epos; int8_t etype; struct udf_inode_info *iinfo = UDF_I(table); diff --git a/fs/xfs/xfs_bmap_util.c b/fs/xfs/xfs_bmap_util.c index 3e1dd66bd6769..734b80a4220c1 100644 --- a/fs/xfs/xfs_bmap_util.c +++ b/fs/xfs/xfs_bmap_util.c @@ -130,7 +130,7 @@ xfs_bmap_rtalloc( * pick an extent that will space things out in the rt area. */ if (ap->eof && ap->offset == 0) { - xfs_rtblock_t uninitialized_var(rtx); /* realtime extent no */ + xfs_rtblock_t rtx; /* realtime extent no */ error = xfs_rtpick_extent(mp, ap->tp, ralen, &rtx); if (error) diff --git a/include/asm-generic/word-at-a-time.h b/include/asm-generic/word-at-a-time.h index 20c93f08c9933..95a1d214108a5 100644 --- a/include/asm-generic/word-at-a-time.h +++ b/include/asm-generic/word-at-a-time.h @@ -38,7 +38,7 @@ static inline long find_zero(unsigned long mask) return (mask >> 8) ? byte : byte + 1; } -static inline bool has_zero(unsigned long val, unsigned long *data, const struct word_at_a_time *c) +static inline unsigned long has_zero(unsigned long val, unsigned long *data, const struct word_at_a_time *c) { unsigned long rhs = val | c->low_bits; *data = rhs; diff --git a/include/linux/etherdevice.h b/include/linux/etherdevice.h index e1e9eff096d05..2932a40060c1d 100644 --- a/include/linux/etherdevice.h +++ b/include/linux/etherdevice.h @@ -291,6 +291,18 @@ static inline void ether_addr_copy(u8 *dst, const u8 *src) #endif } +/** + * eth_hw_addr_set - Assign Ethernet address to a net_device + * @dev: pointer to net_device structure + * @addr: address to assign + * + * Assign given address to the net_device, addr_assign_type is not changed. + */ +static inline void eth_hw_addr_set(struct net_device *dev, const u8 *addr) +{ + ether_addr_copy(dev->dev_addr, addr); +} + /** * eth_hw_addr_inherit - Copy dev_addr from another net_device * @dst: pointer to net_device to copy dev_addr to diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index 90827d85265b0..7e9df3854420a 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -4079,6 +4079,24 @@ void __hw_addr_unsync_dev(struct netdev_hw_addr_list *list, void __hw_addr_init(struct netdev_hw_addr_list *list); /* Functions used for device addresses handling */ +static inline void +__dev_addr_set(struct net_device *dev, const u8 *addr, size_t len) +{ + memcpy(dev->dev_addr, addr, len); +} + +static inline void dev_addr_set(struct net_device *dev, const u8 *addr) +{ + __dev_addr_set(dev, addr, dev->addr_len); +} + +static inline void +dev_addr_mod(struct net_device *dev, unsigned int offset, + const u8 *addr, size_t len) +{ + memcpy(&dev->dev_addr[offset], addr, len); +} + int dev_addr_add(struct net_device *dev, const unsigned char *addr, unsigned char addr_type); int dev_addr_del(struct net_device *dev, const unsigned char *addr, diff --git a/include/linux/netfilter/nfnetlink.h b/include/linux/netfilter/nfnetlink.h index a806803fbe37a..de206e410ee23 100644 --- a/include/linux/netfilter/nfnetlink.h +++ b/include/linux/netfilter/nfnetlink.h @@ -49,6 +49,33 @@ static inline u16 nfnl_msg_type(u8 subsys, u8 msg_type) return subsys << 8 | msg_type; } +static inline void nfnl_fill_hdr(struct nlmsghdr *nlh, u8 family, u8 version, + __be16 res_id) +{ + struct nfgenmsg *nfmsg; + + nfmsg = nlmsg_data(nlh); + nfmsg->nfgen_family = family; + nfmsg->version = version; + nfmsg->res_id = res_id; +} + +static inline struct nlmsghdr *nfnl_msg_put(struct sk_buff *skb, u32 portid, + u32 seq, int type, int flags, + u8 family, u8 version, + __be16 res_id) +{ + struct nlmsghdr *nlh; + + nlh = nlmsg_put(skb, portid, seq, type, sizeof(struct nfgenmsg), flags); + if (!nlh) + return NULL; + + nfnl_fill_hdr(nlh, family, version, res_id); + + return nlh; +} + void nfnl_lock(__u8 subsys_id); void nfnl_unlock(__u8 subsys_id); #ifdef CONFIG_PROVE_LOCKING diff --git a/include/linux/nmi.h b/include/linux/nmi.h index e972d1ae1ee63..6cb593d9ed08a 100644 --- a/include/linux/nmi.h +++ b/include/linux/nmi.h @@ -197,7 +197,7 @@ u64 hw_nmi_get_sample_period(int watchdog_thresh); #endif #if defined(CONFIG_HARDLOCKUP_CHECK_TIMESTAMP) && \ - defined(CONFIG_HARDLOCKUP_DETECTOR) + defined(CONFIG_HARDLOCKUP_DETECTOR_PERF) void watchdog_update_hrtimer_threshold(u64 period); #else static inline void watchdog_update_hrtimer_threshold(u64 period) { } diff --git a/include/linux/pci.h b/include/linux/pci.h index 3e06e9790c255..1d1b0bfd51968 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -1643,6 +1643,7 @@ static inline struct pci_dev *pci_get_class(unsigned int class, #define pci_dev_put(dev) do { } while (0) static inline void pci_set_master(struct pci_dev *dev) { } +static inline void pci_clear_master(struct pci_dev *dev) { } static inline int pci_enable_device(struct pci_dev *dev) { return -EIO; } static inline void pci_disable_device(struct pci_dev *dev) { } static inline int pci_assign_resource(struct pci_dev *dev, int i) diff --git a/include/linux/pm_wakeirq.h b/include/linux/pm_wakeirq.h index cd5b62db90845..e63a63aa47a37 100644 --- a/include/linux/pm_wakeirq.h +++ b/include/linux/pm_wakeirq.h @@ -17,8 +17,8 @@ #ifdef CONFIG_PM extern int dev_pm_set_wake_irq(struct device *dev, int irq); -extern int dev_pm_set_dedicated_wake_irq(struct device *dev, - int irq); +extern int dev_pm_set_dedicated_wake_irq(struct device *dev, int irq); +extern int dev_pm_set_dedicated_wake_irq_reverse(struct device *dev, int irq); extern void dev_pm_clear_wake_irq(struct device *dev); extern void dev_pm_enable_wake_irq(struct device *dev); extern void dev_pm_disable_wake_irq(struct device *dev); @@ -35,6 +35,11 @@ static inline int dev_pm_set_dedicated_wake_irq(struct device *dev, int irq) return 0; } +static inline int dev_pm_set_dedicated_wake_irq_reverse(struct device *dev, int irq) +{ + return 0; +} + static inline void dev_pm_clear_wake_irq(struct device *dev) { } diff --git a/include/linux/sched/signal.h b/include/linux/sched/signal.h index 660d78c9af6c8..6a55b30ae742b 100644 --- a/include/linux/sched/signal.h +++ b/include/linux/sched/signal.h @@ -127,7 +127,7 @@ struct signal_struct { #ifdef CONFIG_POSIX_TIMERS /* POSIX.1b Interval Timers */ - int posix_timer_id; + unsigned int next_posix_timer_id; struct list_head posix_timers; /* ITIMER_REAL timer for the process */ diff --git a/include/linux/serial_8250.h b/include/linux/serial_8250.h index 5a655ba8d2730..bfde7f1a7674d 100644 --- a/include/linux/serial_8250.h +++ b/include/linux/serial_8250.h @@ -99,7 +99,6 @@ struct uart_8250_port { struct list_head list; /* ports on this IRQ */ u32 capabilities; /* port capabilities */ unsigned short bugs; /* port bugs */ - bool fifo_bug; /* min RX trigger if enabled */ unsigned int tx_loadsz; /* transmit fifo load size */ unsigned char acr; unsigned char fcr; diff --git a/include/linux/tcp.h b/include/linux/tcp.h index 621ab5a7fb8fa..0d63a428e6f9c 100644 --- a/include/linux/tcp.h +++ b/include/linux/tcp.h @@ -460,7 +460,7 @@ static inline void fastopen_queue_tune(struct sock *sk, int backlog) struct request_sock_queue *queue = &inet_csk(sk)->icsk_accept_queue; int somaxconn = READ_ONCE(sock_net(sk)->core.sysctl_somaxconn); - queue->fastopenq.max_qlen = min_t(unsigned int, backlog, somaxconn); + WRITE_ONCE(queue->fastopenq.max_qlen, min_t(unsigned int, backlog, somaxconn)); } static inline void tcp_move_syn(struct tcp_sock *tp, diff --git a/include/linux/workqueue.h b/include/linux/workqueue.h index 60d673e156321..a7224fec99a7a 100644 --- a/include/linux/workqueue.h +++ b/include/linux/workqueue.h @@ -73,7 +73,6 @@ enum { WORK_OFFQ_FLAG_BASE = WORK_STRUCT_COLOR_SHIFT, __WORK_OFFQ_CANCELING = WORK_OFFQ_FLAG_BASE, - WORK_OFFQ_CANCELING = (1 << __WORK_OFFQ_CANCELING), /* * When a work item is off queue, its high bits point to the last @@ -84,12 +83,6 @@ enum { WORK_OFFQ_POOL_SHIFT = WORK_OFFQ_FLAG_BASE + WORK_OFFQ_FLAG_BITS, WORK_OFFQ_LEFT = BITS_PER_LONG - WORK_OFFQ_POOL_SHIFT, WORK_OFFQ_POOL_BITS = WORK_OFFQ_LEFT <= 31 ? WORK_OFFQ_LEFT : 31, - WORK_OFFQ_POOL_NONE = (1LU << WORK_OFFQ_POOL_BITS) - 1, - - /* convenience constants */ - WORK_STRUCT_FLAG_MASK = (1UL << WORK_STRUCT_FLAG_BITS) - 1, - WORK_STRUCT_WQ_DATA_MASK = ~WORK_STRUCT_FLAG_MASK, - WORK_STRUCT_NO_POOL = (unsigned long)WORK_OFFQ_POOL_NONE << WORK_OFFQ_POOL_SHIFT, /* bit mask for work_busy() return values */ WORK_BUSY_PENDING = 1 << 0, @@ -99,6 +92,14 @@ enum { WORKER_DESC_LEN = 24, }; +/* Convenience constants - of type 'unsigned long', not 'enum'! */ +#define WORK_OFFQ_CANCELING (1ul << __WORK_OFFQ_CANCELING) +#define WORK_OFFQ_POOL_NONE ((1ul << WORK_OFFQ_POOL_BITS) - 1) +#define WORK_STRUCT_NO_POOL (WORK_OFFQ_POOL_NONE << WORK_OFFQ_POOL_SHIFT) + +#define WORK_STRUCT_FLAG_MASK ((1ul << WORK_STRUCT_FLAG_BITS) - 1) +#define WORK_STRUCT_WQ_DATA_MASK (~WORK_STRUCT_FLAG_MASK) + struct work_struct { atomic_long_t data; struct list_head entry; diff --git a/include/net/addrconf.h b/include/net/addrconf.h index db2a87981dd46..9583d3bbab039 100644 --- a/include/net/addrconf.h +++ b/include/net/addrconf.h @@ -340,6 +340,22 @@ static inline struct inet6_dev *__in6_dev_get(const struct net_device *dev) return rcu_dereference_rtnl(dev->ip6_ptr); } +/** + * __in6_dev_stats_get - get inet6_dev pointer for stats + * @dev: network device + * @skb: skb for original incoming interface if neeeded + * + * Caller must hold rcu_read_lock or RTNL, because this function + * does not take a reference on the inet6_dev. + */ +static inline struct inet6_dev *__in6_dev_stats_get(const struct net_device *dev, + const struct sk_buff *skb) +{ + if (netif_is_l3_master(dev)) + dev = dev_get_by_index_rcu(dev_net(dev), inet6_iif(skb)); + return __in6_dev_get(dev); +} + /** * __in6_dev_get_safely - get inet6_dev pointer from netdevice * @dev: network device diff --git a/include/net/ipv6.h b/include/net/ipv6.h index 0c883249814cc..3a55a0931ed86 100644 --- a/include/net/ipv6.h +++ b/include/net/ipv6.h @@ -602,12 +602,8 @@ static inline u32 ipv6_addr_hash(const struct in6_addr *a) /* more secured version of ipv6_addr_hash() */ static inline u32 __ipv6_addr_jhash(const struct in6_addr *a, const u32 initval) { - u32 v = (__force u32)a->s6_addr32[0] ^ (__force u32)a->s6_addr32[1]; - - return jhash_3words(v, - (__force u32)a->s6_addr32[2], - (__force u32)a->s6_addr32[3], - initval); + return jhash2((__force const u32 *)a->s6_addr32, + ARRAY_SIZE(a->s6_addr32), initval); } static inline bool ipv6_addr_loopback(const struct in6_addr *a) diff --git a/include/net/netfilter/nf_tables.h b/include/net/netfilter/nf_tables.h index 1b4f47a878060..4719440873723 100644 --- a/include/net/netfilter/nf_tables.h +++ b/include/net/netfilter/nf_tables.h @@ -736,6 +736,7 @@ struct nft_expr_type { enum nft_trans_phase { NFT_TRANS_PREPARE, + NFT_TRANS_PREPARE_ERROR, NFT_TRANS_ABORT, NFT_TRANS_COMMIT, NFT_TRANS_RELEASE @@ -1319,12 +1320,14 @@ static inline void nft_set_elem_clear_busy(struct nft_set_ext *ext) * struct nft_trans - nf_tables object update in transaction * * @list: used internally + * @binding_list: list of objects with possible bindings * @msg_type: message type * @ctx: transaction context * @data: internal information related to the transaction */ struct nft_trans { struct list_head list; + struct list_head binding_list; int msg_type; struct nft_ctx ctx; char data[0]; @@ -1409,4 +1412,15 @@ struct nft_trans_flowtable { int __init nft_chain_filter_init(void); void nft_chain_filter_fini(void); +struct nftables_pernet { + struct list_head tables; + struct list_head commit_list; + struct list_head binding_list; + struct list_head module_list; + struct list_head notify_list; + struct mutex commit_mutex; + unsigned int base_seq; + u8 validate_state; +}; + #endif /* _NET_NF_TABLES_H */ diff --git a/include/net/netns/nftables.h b/include/net/netns/nftables.h index 286fd960896fd..8c77832d02404 100644 --- a/include/net/netns/nftables.h +++ b/include/net/netns/nftables.h @@ -5,12 +5,7 @@ #include struct netns_nftables { - struct list_head tables; - struct list_head commit_list; - struct mutex commit_mutex; - unsigned int base_seq; u8 gencursor; - u8 validate_state; }; #endif diff --git a/include/net/nfc/nfc.h b/include/net/nfc/nfc.h index bbdc73a3239df..8b86560b5cfb1 100644 --- a/include/net/nfc/nfc.h +++ b/include/net/nfc/nfc.h @@ -278,7 +278,7 @@ struct sk_buff *nfc_alloc_send_skb(struct nfc_dev *dev, struct sock *sk, struct sk_buff *nfc_alloc_recv_skb(unsigned int size, gfp_t gfp); int nfc_set_remote_general_bytes(struct nfc_dev *dev, - u8 *gt, u8 gt_len); + const u8 *gt, u8 gt_len); u8 *nfc_get_local_general_bytes(struct nfc_dev *dev, size_t *gb_len); int nfc_fw_download_done(struct nfc_dev *dev, const char *firmware_name, @@ -292,7 +292,7 @@ int nfc_dep_link_is_up(struct nfc_dev *dev, u32 target_idx, u8 comm_mode, u8 rf_mode); int nfc_tm_activated(struct nfc_dev *dev, u32 protocol, u8 comm_mode, - u8 *gb, size_t gb_len); + const u8 *gb, size_t gb_len); int nfc_tm_deactivated(struct nfc_dev *dev); int nfc_tm_data_received(struct nfc_dev *dev, struct sk_buff *skb); diff --git a/include/net/pkt_sched.h b/include/net/pkt_sched.h index e09ea6917c061..83a16f3bd6e6a 100644 --- a/include/net/pkt_sched.h +++ b/include/net/pkt_sched.h @@ -131,7 +131,7 @@ extern const struct nla_policy rtm_tca_policy[TCA_MAX + 1]; */ static inline unsigned int psched_mtu(const struct net_device *dev) { - return dev->mtu + dev->hard_header_len; + return READ_ONCE(dev->mtu) + dev->hard_header_len; } static inline struct net *qdisc_net(struct Qdisc *q) diff --git a/include/net/sock.h b/include/net/sock.h index 616e84d1670df..72739f72e4b90 100644 --- a/include/net/sock.h +++ b/include/net/sock.h @@ -1840,6 +1840,7 @@ static inline void sock_graft(struct sock *sk, struct socket *parent) } kuid_t sock_i_uid(struct sock *sk); +unsigned long __sock_i_ino(struct sock *sk); unsigned long sock_i_ino(struct sock *sk); static inline kuid_t sock_net_uid(const struct net *net, const struct sock *sk) diff --git a/include/net/tcp.h b/include/net/tcp.h index 81300a04b5808..c6c48409e7b42 100644 --- a/include/net/tcp.h +++ b/include/net/tcp.h @@ -128,6 +128,7 @@ void tcp_time_wait(struct sock *sk, int state, int timeo); * to combine FIN-WAIT-2 timeout with * TIME-WAIT timer. */ +#define TCP_FIN_TIMEOUT_MAX (120 * HZ) /* max TCP_LINGER2 value (two minutes) */ #define TCP_DELACK_MAX ((unsigned)(HZ/5)) /* maximal time to delay before sending an ACK */ #if HZ >= 100 @@ -1882,7 +1883,11 @@ void __tcp_v4_send_check(struct sk_buff *skb, __be32 saddr, __be32 daddr); static inline u32 tcp_notsent_lowat(const struct tcp_sock *tp) { struct net *net = sock_net((struct sock *)tp); - return tp->notsent_lowat ?: READ_ONCE(net->ipv4.sysctl_tcp_notsent_lowat); + u32 val; + + val = READ_ONCE(tp->notsent_lowat); + + return val ?: READ_ONCE(net->ipv4.sysctl_tcp_notsent_lowat); } /* @wake is one when sk_stream_write_space() calls us. diff --git a/include/uapi/linux/affs_hardblocks.h b/include/uapi/linux/affs_hardblocks.h index 5e2fb8481252a..a5aff2eb5f708 100644 --- a/include/uapi/linux/affs_hardblocks.h +++ b/include/uapi/linux/affs_hardblocks.h @@ -7,42 +7,42 @@ /* Just the needed definitions for the RDB of an Amiga HD. */ struct RigidDiskBlock { - __u32 rdb_ID; + __be32 rdb_ID; __be32 rdb_SummedLongs; - __s32 rdb_ChkSum; - __u32 rdb_HostID; + __be32 rdb_ChkSum; + __be32 rdb_HostID; __be32 rdb_BlockBytes; - __u32 rdb_Flags; - __u32 rdb_BadBlockList; + __be32 rdb_Flags; + __be32 rdb_BadBlockList; __be32 rdb_PartitionList; - __u32 rdb_FileSysHeaderList; - __u32 rdb_DriveInit; - __u32 rdb_Reserved1[6]; - __u32 rdb_Cylinders; - __u32 rdb_Sectors; - __u32 rdb_Heads; - __u32 rdb_Interleave; - __u32 rdb_Park; - __u32 rdb_Reserved2[3]; - __u32 rdb_WritePreComp; - __u32 rdb_ReducedWrite; - __u32 rdb_StepRate; - __u32 rdb_Reserved3[5]; - __u32 rdb_RDBBlocksLo; - __u32 rdb_RDBBlocksHi; - __u32 rdb_LoCylinder; - __u32 rdb_HiCylinder; - __u32 rdb_CylBlocks; - __u32 rdb_AutoParkSeconds; - __u32 rdb_HighRDSKBlock; - __u32 rdb_Reserved4; + __be32 rdb_FileSysHeaderList; + __be32 rdb_DriveInit; + __be32 rdb_Reserved1[6]; + __be32 rdb_Cylinders; + __be32 rdb_Sectors; + __be32 rdb_Heads; + __be32 rdb_Interleave; + __be32 rdb_Park; + __be32 rdb_Reserved2[3]; + __be32 rdb_WritePreComp; + __be32 rdb_ReducedWrite; + __be32 rdb_StepRate; + __be32 rdb_Reserved3[5]; + __be32 rdb_RDBBlocksLo; + __be32 rdb_RDBBlocksHi; + __be32 rdb_LoCylinder; + __be32 rdb_HiCylinder; + __be32 rdb_CylBlocks; + __be32 rdb_AutoParkSeconds; + __be32 rdb_HighRDSKBlock; + __be32 rdb_Reserved4; char rdb_DiskVendor[8]; char rdb_DiskProduct[16]; char rdb_DiskRevision[4]; char rdb_ControllerVendor[8]; char rdb_ControllerProduct[16]; char rdb_ControllerRevision[4]; - __u32 rdb_Reserved5[10]; + __be32 rdb_Reserved5[10]; }; #define IDNAME_RIGIDDISK 0x5244534B /* "RDSK" */ @@ -50,16 +50,16 @@ struct RigidDiskBlock { struct PartitionBlock { __be32 pb_ID; __be32 pb_SummedLongs; - __s32 pb_ChkSum; - __u32 pb_HostID; + __be32 pb_ChkSum; + __be32 pb_HostID; __be32 pb_Next; - __u32 pb_Flags; - __u32 pb_Reserved1[2]; - __u32 pb_DevFlags; + __be32 pb_Flags; + __be32 pb_Reserved1[2]; + __be32 pb_DevFlags; __u8 pb_DriveName[32]; - __u32 pb_Reserved2[15]; + __be32 pb_Reserved2[15]; __be32 pb_Environment[17]; - __u32 pb_EReserved[15]; + __be32 pb_EReserved[15]; }; #define IDNAME_PARTITION 0x50415254 /* "PART" */ diff --git a/include/uapi/linux/blkzoned.h b/include/uapi/linux/blkzoned.h index ff5a5db8906a7..2f3a0cca4b78b 100644 --- a/include/uapi/linux/blkzoned.h +++ b/include/uapi/linux/blkzoned.h @@ -51,13 +51,13 @@ enum blk_zone_type { * * The Zone Condition state machine in the ZBC/ZAC standards maps the above * deinitions as: - * - ZC1: Empty | BLK_ZONE_EMPTY + * - ZC1: Empty | BLK_ZONE_COND_EMPTY * - ZC2: Implicit Open | BLK_ZONE_COND_IMP_OPEN * - ZC3: Explicit Open | BLK_ZONE_COND_EXP_OPEN - * - ZC4: Closed | BLK_ZONE_CLOSED - * - ZC5: Full | BLK_ZONE_FULL - * - ZC6: Read Only | BLK_ZONE_READONLY - * - ZC7: Offline | BLK_ZONE_OFFLINE + * - ZC4: Closed | BLK_ZONE_COND_CLOSED + * - ZC5: Full | BLK_ZONE_COND_FULL + * - ZC6: Read Only | BLK_ZONE_COND_READONLY + * - ZC7: Offline | BLK_ZONE_COND_OFFLINE * * Conditions 0x5 to 0xC are reserved by the current ZBC/ZAC spec and should * be considered invalid. diff --git a/include/uapi/linux/videodev2.h b/include/uapi/linux/videodev2.h index ad6a633f5848a..ac22e7f062399 100644 --- a/include/uapi/linux/videodev2.h +++ b/include/uapi/linux/videodev2.h @@ -1510,7 +1510,7 @@ struct v4l2_input { __u8 name[32]; /* Label */ __u32 type; /* Type of input */ __u32 audioset; /* Associated audios (bitfield) */ - __u32 tuner; /* enum v4l2_tuner_type */ + __u32 tuner; /* Tuner index */ v4l2_std_id std; __u32 status; __u32 capabilities; diff --git a/kernel/async.c b/kernel/async.c index 4bf1b00a28d86..e59bd2240cb86 100644 --- a/kernel/async.c +++ b/kernel/async.c @@ -115,7 +115,7 @@ static void async_run_entry_fn(struct work_struct *work) struct async_entry *entry = container_of(work, struct async_entry, work); unsigned long flags; - ktime_t uninitialized_var(calltime), delta, rettime; + ktime_t calltime, delta, rettime; /* 1) run (and print duration) */ if (initcall_debug && system_state < SYSTEM_RUNNING) { @@ -283,7 +283,7 @@ EXPORT_SYMBOL_GPL(async_synchronize_full_domain); */ void async_synchronize_cookie_domain(async_cookie_t cookie, struct async_domain *domain) { - ktime_t uninitialized_var(starttime), delta, endtime; + ktime_t starttime, delta, endtime; if (initcall_debug && system_state < SYSTEM_RUNNING) { pr_debug("async_waiting @ %i\n", task_pid_nr(current)); diff --git a/kernel/audit.c b/kernel/audit.c index 7dc14a4d9e3cf..471d3ad910aa5 100644 --- a/kernel/audit.c +++ b/kernel/audit.c @@ -1796,7 +1796,7 @@ struct audit_buffer *audit_log_start(struct audit_context *ctx, gfp_t gfp_mask, { struct audit_buffer *ab; struct timespec64 t; - unsigned int uninitialized_var(serial); + unsigned int serial; if (audit_initialized != AUDIT_INITIALIZED) return NULL; diff --git a/kernel/bpf/bpf_lru_list.c b/kernel/bpf/bpf_lru_list.c index 9b5eeff72fd37..39a0e768adc39 100644 --- a/kernel/bpf/bpf_lru_list.c +++ b/kernel/bpf/bpf_lru_list.c @@ -44,7 +44,12 @@ static struct list_head *local_pending_list(struct bpf_lru_locallist *loc_l) /* bpf_lru_node helpers */ static bool bpf_lru_node_is_ref(const struct bpf_lru_node *node) { - return node->ref; + return READ_ONCE(node->ref); +} + +static void bpf_lru_node_clear_ref(struct bpf_lru_node *node) +{ + WRITE_ONCE(node->ref, 0); } static void bpf_lru_list_count_inc(struct bpf_lru_list *l, @@ -92,7 +97,7 @@ static void __bpf_lru_node_move_in(struct bpf_lru_list *l, bpf_lru_list_count_inc(l, tgt_type); node->type = tgt_type; - node->ref = 0; + bpf_lru_node_clear_ref(node); list_move(&node->list, &l->lists[tgt_type]); } @@ -113,7 +118,7 @@ static void __bpf_lru_node_move(struct bpf_lru_list *l, bpf_lru_list_count_inc(l, tgt_type); node->type = tgt_type; } - node->ref = 0; + bpf_lru_node_clear_ref(node); /* If the moving node is the next_inactive_rotation candidate, * move the next_inactive_rotation pointer also. @@ -356,7 +361,7 @@ static void __local_list_add_pending(struct bpf_lru *lru, *(u32 *)((void *)node + lru->hash_offset) = hash; node->cpu = cpu; node->type = BPF_LRU_LOCAL_LIST_T_PENDING; - node->ref = 0; + bpf_lru_node_clear_ref(node); list_add(&node->list, local_pending_list(loc_l)); } @@ -422,7 +427,7 @@ static struct bpf_lru_node *bpf_percpu_lru_pop_free(struct bpf_lru *lru, if (!list_empty(free_list)) { node = list_first_entry(free_list, struct bpf_lru_node, list); *(u32 *)((void *)node + lru->hash_offset) = hash; - node->ref = 0; + bpf_lru_node_clear_ref(node); __bpf_lru_node_move(l, node, BPF_LRU_LIST_T_INACTIVE); } @@ -525,7 +530,7 @@ static void bpf_common_lru_push_free(struct bpf_lru *lru, } node->type = BPF_LRU_LOCAL_LIST_T_FREE; - node->ref = 0; + bpf_lru_node_clear_ref(node); list_move(&node->list, local_free_list(loc_l)); raw_spin_unlock_irqrestore(&loc_l->lock, flags); @@ -571,7 +576,7 @@ static void bpf_common_lru_populate(struct bpf_lru *lru, void *buf, node = (struct bpf_lru_node *)(buf + node_offset); node->type = BPF_LRU_LIST_T_FREE; - node->ref = 0; + bpf_lru_node_clear_ref(node); list_add(&node->list, &l->lists[BPF_LRU_LIST_T_FREE]); buf += elem_size; } @@ -597,7 +602,7 @@ again: node = (struct bpf_lru_node *)(buf + node_offset); node->cpu = cpu; node->type = BPF_LRU_LIST_T_FREE; - node->ref = 0; + bpf_lru_node_clear_ref(node); list_add(&node->list, &l->lists[BPF_LRU_LIST_T_FREE]); i++; buf += elem_size; diff --git a/kernel/bpf/bpf_lru_list.h b/kernel/bpf/bpf_lru_list.h index 7d4f89b7cb841..08da78b59f0b9 100644 --- a/kernel/bpf/bpf_lru_list.h +++ b/kernel/bpf/bpf_lru_list.h @@ -66,11 +66,8 @@ struct bpf_lru { static inline void bpf_lru_node_set_ref(struct bpf_lru_node *node) { - /* ref is an approximation on access frequency. It does not - * have to be very accurate. Hence, no protection is used. - */ - if (!node->ref) - node->ref = 1; + if (!READ_ONCE(node->ref)) + WRITE_ONCE(node->ref, 1); } int bpf_lru_init(struct bpf_lru *lru, bool percpu, u32 hash_offset, diff --git a/kernel/dma/debug.c b/kernel/dma/debug.c index 7c6cd00d0fca9..c345a6e2f7b7e 100644 --- a/kernel/dma/debug.c +++ b/kernel/dma/debug.c @@ -963,7 +963,7 @@ static int device_dma_allocations(struct device *dev, struct dma_debug_entry **o static int dma_debug_device_change(struct notifier_block *nb, unsigned long action, void *data) { struct device *dev = data; - struct dma_debug_entry *uninitialized_var(entry); + struct dma_debug_entry *entry; int count; if (dma_debug_disabled()) diff --git a/kernel/events/core.c b/kernel/events/core.c index 2bf4b6b109bf4..cb2b717666cee 100644 --- a/kernel/events/core.c +++ b/kernel/events/core.c @@ -1133,6 +1133,11 @@ static int perf_mux_hrtimer_restart(struct perf_cpu_context *cpuctx) return 0; } +static int perf_mux_hrtimer_restart_ipi(void *arg) +{ + return perf_mux_hrtimer_restart(arg); +} + void perf_pmu_disable(struct pmu *pmu) { int *count = this_cpu_ptr(pmu->pmu_disable_count); @@ -9644,8 +9649,7 @@ perf_event_mux_interval_ms_store(struct device *dev, cpuctx = per_cpu_ptr(pmu->pmu_cpu_context, cpu); cpuctx->hrtimer_interval = ns_to_ktime(NSEC_PER_MSEC * timer); - cpu_function_call(cpu, - (remote_function_f)perf_mux_hrtimer_restart, cpuctx); + cpu_function_call(cpu, perf_mux_hrtimer_restart_ipi, cpuctx); } cpus_read_unlock(); mutex_unlock(&mux_interval_mutex); @@ -10575,7 +10579,7 @@ SYSCALL_DEFINE5(perf_event_open, struct perf_event *group_leader = NULL, *output_event = NULL; struct perf_event *event, *sibling; struct perf_event_attr attr; - struct perf_event_context *ctx, *uninitialized_var(gctx); + struct perf_event_context *ctx, *gctx; struct file *event_file = NULL; struct fd group = {NULL, 0}; struct task_struct *task = NULL; diff --git a/kernel/events/uprobes.c b/kernel/events/uprobes.c index 24342bca11f2f..72ae05d650661 100644 --- a/kernel/events/uprobes.c +++ b/kernel/events/uprobes.c @@ -1887,7 +1887,7 @@ static void handle_swbp(struct pt_regs *regs) { struct uprobe *uprobe; unsigned long bp_vaddr; - int uninitialized_var(is_swbp); + int is_swbp; bp_vaddr = uprobe_get_swbp_addr(regs); if (bp_vaddr == get_trampoline_vaddr()) diff --git a/kernel/exit.c b/kernel/exit.c index 02360ec3b1225..0d1cca15e66fe 100644 --- a/kernel/exit.c +++ b/kernel/exit.c @@ -140,7 +140,7 @@ static void __exit_signal(struct task_struct *tsk) struct signal_struct *sig = tsk->signal; bool group_dead = thread_group_leader(tsk); struct sighand_struct *sighand; - struct tty_struct *uninitialized_var(tty); + struct tty_struct *tty; u64 utime, stime; sighand = rcu_dereference_check(tsk->sighand, diff --git a/kernel/futex.c b/kernel/futex.c index 3c67da9b84086..ca2a2a8948395 100644 --- a/kernel/futex.c +++ b/kernel/futex.c @@ -1398,7 +1398,7 @@ static int lookup_pi_state(u32 __user *uaddr, u32 uval, static int lock_pi_update_atomic(u32 __user *uaddr, u32 uval, u32 newval) { int err; - u32 uninitialized_var(curval); + u32 curval; if (unlikely(should_fail_futex(true))) return -EFAULT; @@ -1569,7 +1569,7 @@ static void mark_wake_futex(struct wake_q_head *wake_q, struct futex_q *q) */ static int wake_futex_pi(u32 __user *uaddr, u32 uval, struct futex_pi_state *pi_state) { - u32 uninitialized_var(curval), newval; + u32 curval, newval; struct task_struct *new_owner; bool postunlock = false; DEFINE_WAKE_Q(wake_q); @@ -3083,7 +3083,7 @@ uaddr_faulted: */ static int futex_unlock_pi(u32 __user *uaddr, unsigned int flags) { - u32 uninitialized_var(curval), uval, vpid = task_pid_vnr(current); + u32 curval, uval, vpid = task_pid_vnr(current); union futex_key key = FUTEX_KEY_INIT; struct futex_hash_bucket *hb; struct futex_q *top_waiter; @@ -3558,7 +3558,7 @@ err_unlock: static int handle_futex_death(u32 __user *uaddr, struct task_struct *curr, bool pi, bool pending_op) { - u32 uval, uninitialized_var(nval), mval; + u32 uval, nval, mval; int err; /* Futex address must be 32bit aligned */ @@ -3688,7 +3688,7 @@ static void exit_robust_list(struct task_struct *curr) struct robust_list_head __user *head = curr->robust_list; struct robust_list __user *entry, *next_entry, *pending; unsigned int limit = ROBUST_LIST_LIMIT, pi, pip; - unsigned int uninitialized_var(next_pi); + unsigned int next_pi; unsigned long futex_offset; int rc; @@ -3987,7 +3987,7 @@ static void compat_exit_robust_list(struct task_struct *curr) struct compat_robust_list_head __user *head = curr->compat_robust_list; struct robust_list __user *entry, *next_entry, *pending; unsigned int limit = ROBUST_LIST_LIMIT, pi, pip; - unsigned int uninitialized_var(next_pi); + unsigned int next_pi; compat_uptr_t uentry, next_uentry, upending; compat_long_t futex_offset; int rc; diff --git a/kernel/kexec_core.c b/kernel/kexec_core.c index 6b3d7f7211dd6..3666d434a8f59 100644 --- a/kernel/kexec_core.c +++ b/kernel/kexec_core.c @@ -1020,6 +1020,7 @@ int crash_shrink_memory(unsigned long new_size) start = crashk_res.start; end = crashk_res.end; old_size = (end == 0) ? 0 : end - start + 1; + new_size = roundup(new_size, KEXEC_CRASH_MEM_ALIGN); if (new_size >= old_size) { ret = (new_size == old_size) ? 0 : -EINVAL; goto unlock; @@ -1031,9 +1032,7 @@ int crash_shrink_memory(unsigned long new_size) goto unlock; } - start = roundup(start, KEXEC_CRASH_MEM_ALIGN); - end = roundup(start + new_size, KEXEC_CRASH_MEM_ALIGN); - + end = start + new_size; crash_free_reserved_phys_range(end, crashk_res.end); if ((start == end) && (crashk_res.parent != NULL)) diff --git a/kernel/locking/lockdep.c b/kernel/locking/lockdep.c index 4dc79f57af827..46a6d1f7c351d 100644 --- a/kernel/locking/lockdep.c +++ b/kernel/locking/lockdep.c @@ -1246,7 +1246,7 @@ static int noop_count(struct lock_list *entry, void *data) static unsigned long __lockdep_count_forward_deps(struct lock_list *this) { unsigned long count = 0; - struct lock_list *uninitialized_var(target_entry); + struct lock_list *target_entry; __bfs_forwards(this, (void *)&count, noop_count, &target_entry); @@ -1274,7 +1274,7 @@ unsigned long lockdep_count_forward_deps(struct lock_class *class) static unsigned long __lockdep_count_backward_deps(struct lock_list *this) { unsigned long count = 0; - struct lock_list *uninitialized_var(target_entry); + struct lock_list *target_entry; __bfs_backwards(this, (void *)&count, noop_count, &target_entry); @@ -2662,7 +2662,7 @@ check_usage_backwards(struct task_struct *curr, struct held_lock *this, { int ret; struct lock_list root; - struct lock_list *uninitialized_var(target_entry); + struct lock_list *target_entry; root.parent = NULL; root.class = hlock_class(this); diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c index eb67f42fb96ba..09f82c84474b8 100644 --- a/kernel/sched/fair.c +++ b/kernel/sched/fair.c @@ -8721,7 +8721,7 @@ static int load_balance(int this_cpu, struct rq *this_rq, .sd = sd, .dst_cpu = this_cpu, .dst_rq = this_rq, - .dst_grpmask = sched_group_span(sd->groups), + .dst_grpmask = group_balance_mask(sd->groups), .idle = idle, .loop_break = sched_nr_migrate_break, .cpus = cpus, diff --git a/kernel/time/posix-timers.c b/kernel/time/posix-timers.c index 1234868b3b03e..8768ce2c4bf52 100644 --- a/kernel/time/posix-timers.c +++ b/kernel/time/posix-timers.c @@ -159,25 +159,30 @@ static struct k_itimer *posix_timer_by_id(timer_t id) static int posix_timer_add(struct k_itimer *timer) { struct signal_struct *sig = current->signal; - int first_free_id = sig->posix_timer_id; struct hlist_head *head; - int ret = -ENOENT; + unsigned int cnt, id; - do { + /* + * FIXME: Replace this by a per signal struct xarray once there is + * a plan to handle the resulting CRIU regression gracefully. + */ + for (cnt = 0; cnt <= INT_MAX; cnt++) { spin_lock(&hash_lock); - head = &posix_timers_hashtable[hash(sig, sig->posix_timer_id)]; - if (!__posix_timers_find(head, sig, sig->posix_timer_id)) { + id = sig->next_posix_timer_id; + + /* Write the next ID back. Clamp it to the positive space */ + sig->next_posix_timer_id = (id + 1) & INT_MAX; + + head = &posix_timers_hashtable[hash(sig, id)]; + if (!__posix_timers_find(head, sig, id)) { hlist_add_head_rcu(&timer->t_hash, head); - ret = sig->posix_timer_id; + spin_unlock(&hash_lock); + return id; } - if (++sig->posix_timer_id < 0) - sig->posix_timer_id = 0; - if ((sig->posix_timer_id == first_free_id) && (ret == -ENOENT)) - /* Loop over all possible ids completed */ - ret = -EAGAIN; spin_unlock(&hash_lock); - } while (ret == -ENOENT); - return ret; + } + /* POSIX return code when no timer ID could be allocated */ + return -EAGAIN; } static inline void unlock_timer(struct k_itimer *timr, unsigned long flags) diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c index 5c0463dbe16ee..81f5c9c85d066 100644 --- a/kernel/trace/ftrace.c +++ b/kernel/trace/ftrace.c @@ -1124,7 +1124,7 @@ struct ftrace_page { struct ftrace_page *next; struct dyn_ftrace *records; int index; - int size; + int order; }; #define ENTRY_SIZE sizeof(struct dyn_ftrace) @@ -2915,6 +2915,8 @@ static void ftrace_shutdown_sysctl(void) static u64 ftrace_update_time; unsigned long ftrace_update_tot_cnt; +unsigned long ftrace_number_of_pages; +unsigned long ftrace_number_of_groups; static inline int ops_traces_mod(struct ftrace_ops *ops) { @@ -3039,8 +3041,11 @@ static int ftrace_allocate_records(struct ftrace_page *pg, int count) goto again; } + ftrace_number_of_pages += 1 << order; + ftrace_number_of_groups++; + cnt = (PAGE_SIZE << order) / ENTRY_SIZE; - pg->size = cnt; + pg->order = order; if (cnt > count) cnt = count; @@ -3048,12 +3053,27 @@ static int ftrace_allocate_records(struct ftrace_page *pg, int count) return cnt; } +static void ftrace_free_pages(struct ftrace_page *pages) +{ + struct ftrace_page *pg = pages; + + while (pg) { + if (pg->records) { + free_pages((unsigned long)pg->records, pg->order); + ftrace_number_of_pages -= 1 << pg->order; + } + pages = pg->next; + kfree(pg); + pg = pages; + ftrace_number_of_groups--; + } +} + static struct ftrace_page * ftrace_allocate_pages(unsigned long num_to_init) { struct ftrace_page *start_pg; struct ftrace_page *pg; - int order; int cnt; if (!num_to_init) @@ -3087,14 +3107,7 @@ ftrace_allocate_pages(unsigned long num_to_init) return start_pg; free_pages: - pg = start_pg; - while (pg) { - order = get_count_order(pg->size / ENTRIES_PER_PAGE); - free_pages((unsigned long)pg->records, order); - start_pg = pg->next; - kfree(pg); - pg = start_pg; - } + ftrace_free_pages(start_pg); pr_info("ftrace: FAILED to allocate memory for functions\n"); return NULL; } @@ -5586,9 +5599,11 @@ static int ftrace_process_locs(struct module *mod, unsigned long *start, unsigned long *end) { + struct ftrace_page *pg_unuse = NULL; struct ftrace_page *start_pg; struct ftrace_page *pg; struct dyn_ftrace *rec; + unsigned long skipped = 0; unsigned long count; unsigned long *p; unsigned long addr; @@ -5634,6 +5649,7 @@ static int ftrace_process_locs(struct module *mod, p = start; pg = start_pg; while (p < end) { + unsigned long end_offset; addr = ftrace_call_adjust(*p++); /* * Some architecture linkers will pad between @@ -5641,10 +5657,13 @@ static int ftrace_process_locs(struct module *mod, * object files to satisfy alignments. * Skip any NULL pointers. */ - if (!addr) + if (!addr) { + skipped++; continue; + } - if (pg->index == pg->size) { + end_offset = (pg->index+1) * sizeof(pg->records[0]); + if (end_offset > PAGE_SIZE << pg->order) { /* We should have allocated enough */ if (WARN_ON(!pg->next)) break; @@ -5655,8 +5674,10 @@ static int ftrace_process_locs(struct module *mod, rec->ip = addr; } - /* We should have used all pages */ - WARN_ON(pg->next); + if (pg->next) { + pg_unuse = pg->next; + pg->next = NULL; + } /* Assign the last page to ftrace_pages */ ftrace_pages = pg; @@ -5678,6 +5699,11 @@ static int ftrace_process_locs(struct module *mod, out: mutex_unlock(&ftrace_lock); + /* We should have used all pages unless we skipped some */ + if (pg_unuse) { + WARN_ON(!skipped); + ftrace_free_pages(pg_unuse); + } return ret; } @@ -5784,7 +5810,6 @@ void ftrace_release_mod(struct module *mod) struct ftrace_page **last_pg; struct ftrace_page *tmp_page = NULL; struct ftrace_page *pg; - int order; mutex_lock(&ftrace_lock); @@ -5835,10 +5860,13 @@ void ftrace_release_mod(struct module *mod) /* Needs to be called outside of ftrace_lock */ clear_mod_from_hashes(pg); - order = get_count_order(pg->size / ENTRIES_PER_PAGE); - free_pages((unsigned long)pg->records, order); + if (pg->records) { + free_pages((unsigned long)pg->records, pg->order); + ftrace_number_of_pages -= 1 << pg->order; + } tmp_page = pg->next; kfree(pg); + ftrace_number_of_groups--; } } @@ -6144,7 +6172,6 @@ void ftrace_free_mem(struct module *mod, void *start_ptr, void *end_ptr) struct ftrace_mod_map *mod_map = NULL; struct ftrace_init_func *func, *func_next; struct list_head clear_hash; - int order; INIT_LIST_HEAD(&clear_hash); @@ -6182,8 +6209,11 @@ void ftrace_free_mem(struct module *mod, void *start_ptr, void *end_ptr) ftrace_update_tot_cnt--; if (!pg->index) { *last_pg = pg->next; - order = get_count_order(pg->size / ENTRIES_PER_PAGE); - free_pages((unsigned long)pg->records, order); + if (pg->records) { + free_pages((unsigned long)pg->records, pg->order); + ftrace_number_of_pages -= 1 << pg->order; + } + ftrace_number_of_groups--; kfree(pg); pg = container_of(last_pg, struct ftrace_page, next); if (!(*last_pg)) @@ -6239,6 +6269,9 @@ void __init ftrace_init(void) __start_mcount_loc, __stop_mcount_loc); + pr_info("ftrace: allocated %ld pages with %ld groups\n", + ftrace_number_of_pages, ftrace_number_of_groups); + set_ftrace_early_filters(); return; diff --git a/kernel/trace/ring_buffer.c b/kernel/trace/ring_buffer.c index ba8b72f9cdc0b..c8a7de7a1d635 100644 --- a/kernel/trace/ring_buffer.c +++ b/kernel/trace/ring_buffer.c @@ -493,6 +493,8 @@ struct ring_buffer_per_cpu { unsigned long read_bytes; u64 write_stamp; u64 read_stamp; + /* pages removed since last reset */ + unsigned long pages_removed; /* ring buffer pages to update, > 0 to add, < 0 to remove */ long nr_pages_to_update; struct list_head new_pages; /* new pages to add */ @@ -528,6 +530,7 @@ struct ring_buffer_iter { struct buffer_page *head_page; struct buffer_page *cache_reader_page; unsigned long cache_read; + unsigned long cache_pages_removed; u64 read_stamp; }; @@ -561,7 +564,7 @@ static void rb_wake_up_waiters(struct irq_work *work) */ int ring_buffer_wait(struct ring_buffer *buffer, int cpu, bool full) { - struct ring_buffer_per_cpu *uninitialized_var(cpu_buffer); + struct ring_buffer_per_cpu *cpu_buffer; DEFINE_WAIT(wait); struct rb_irq_work *work; int ret = 0; @@ -1514,6 +1517,8 @@ rb_remove_pages(struct ring_buffer_per_cpu *cpu_buffer, unsigned long nr_pages) to_remove = rb_list_head(to_remove)->next; head_bit |= (unsigned long)to_remove & RB_PAGE_HEAD; } + /* Read iterators need to reset themselves when some pages removed */ + cpu_buffer->pages_removed += nr_removed; next_page = rb_list_head(to_remove)->next; @@ -1535,12 +1540,6 @@ rb_remove_pages(struct ring_buffer_per_cpu *cpu_buffer, unsigned long nr_pages) cpu_buffer->head_page = list_entry(next_page, struct buffer_page, list); - /* - * change read pointer to make sure any read iterators reset - * themselves - */ - cpu_buffer->read = 0; - /* pages are removed, resume tracing and then free the pages */ atomic_dec(&cpu_buffer->record_disabled); raw_spin_unlock_irq(&cpu_buffer->reader_lock); @@ -3582,6 +3581,7 @@ static void rb_iter_reset(struct ring_buffer_iter *iter) iter->cache_reader_page = iter->head_page; iter->cache_read = cpu_buffer->read; + iter->cache_pages_removed = cpu_buffer->pages_removed; if (iter->head) iter->read_stamp = cpu_buffer->read_stamp; @@ -4022,12 +4022,13 @@ rb_iter_peek(struct ring_buffer_iter *iter, u64 *ts) buffer = cpu_buffer->buffer; /* - * Check if someone performed a consuming read to - * the buffer. A consuming read invalidates the iterator - * and we need to reset the iterator in this case. + * Check if someone performed a consuming read to the buffer + * or removed some pages from the buffer. In these cases, + * iterator was invalidated and we need to reset it. */ if (unlikely(iter->cache_read != cpu_buffer->read || - iter->cache_reader_page != cpu_buffer->reader_page)) + iter->cache_reader_page != cpu_buffer->reader_page || + iter->cache_pages_removed != cpu_buffer->pages_removed)) rb_iter_reset(iter); again: @@ -4408,28 +4409,34 @@ unsigned long ring_buffer_size(struct ring_buffer *buffer, int cpu) } EXPORT_SYMBOL_GPL(ring_buffer_size); +static void rb_clear_buffer_page(struct buffer_page *page) +{ + local_set(&page->write, 0); + local_set(&page->entries, 0); + rb_init_page(page->page); + page->read = 0; +} + static void rb_reset_cpu(struct ring_buffer_per_cpu *cpu_buffer) { + struct buffer_page *page; + rb_head_page_deactivate(cpu_buffer); cpu_buffer->head_page = list_entry(cpu_buffer->pages, struct buffer_page, list); - local_set(&cpu_buffer->head_page->write, 0); - local_set(&cpu_buffer->head_page->entries, 0); - local_set(&cpu_buffer->head_page->page->commit, 0); - - cpu_buffer->head_page->read = 0; + rb_clear_buffer_page(cpu_buffer->head_page); + list_for_each_entry(page, cpu_buffer->pages, list) { + rb_clear_buffer_page(page); + } cpu_buffer->tail_page = cpu_buffer->head_page; cpu_buffer->commit_page = cpu_buffer->head_page; INIT_LIST_HEAD(&cpu_buffer->reader_page->list); INIT_LIST_HEAD(&cpu_buffer->new_pages); - local_set(&cpu_buffer->reader_page->write, 0); - local_set(&cpu_buffer->reader_page->entries, 0); - local_set(&cpu_buffer->reader_page->page->commit, 0); - cpu_buffer->reader_page->read = 0; + rb_clear_buffer_page(cpu_buffer->reader_page); local_set(&cpu_buffer->entries_bytes, 0); local_set(&cpu_buffer->overrun, 0); @@ -4448,6 +4455,7 @@ rb_reset_cpu(struct ring_buffer_per_cpu *cpu_buffer) cpu_buffer->last_overrun = 0; rb_head_page_activate(cpu_buffer); + cpu_buffer->pages_removed = 0; } /** diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c index 98abff0462366..9da7b10e56d23 100644 --- a/kernel/trace/trace.c +++ b/kernel/trace/trace.c @@ -7107,14 +7107,23 @@ static ssize_t tracing_read_dyn_info(struct file *filp, char __user *ubuf, size_t cnt, loff_t *ppos) { - unsigned long *p = filp->private_data; - char buf[64]; /* Not too big for a shallow stack */ + ssize_t ret; + char *buf; int r; - r = scnprintf(buf, 63, "%ld", *p); - buf[r++] = '\n'; + /* 256 should be plenty to hold the amount needed */ + buf = kmalloc(256, GFP_KERNEL); + if (!buf) + return -ENOMEM; - return simple_read_from_buffer(ubuf, cnt, ppos, buf, r); + r = scnprintf(buf, 256, "%ld pages:%ld groups: %ld\n", + ftrace_update_tot_cnt, + ftrace_number_of_pages, + ftrace_number_of_groups); + + ret = simple_read_from_buffer(ubuf, cnt, ppos, buf, r); + kfree(buf); + return ret; } static const struct file_operations tracing_dyn_info_fops = { @@ -8246,7 +8255,7 @@ static __init int tracer_init_tracefs(void) #ifdef CONFIG_DYNAMIC_FTRACE trace_create_file("dyn_ftrace_total_info", 0444, d_tracer, - &ftrace_update_tot_cnt, &tracing_dyn_info_fops); + NULL, &tracing_dyn_info_fops); #endif create_trace_instances(d_tracer); diff --git a/kernel/trace/trace.h b/kernel/trace/trace.h index 0923d1b18d1fb..f4d83b552a477 100644 --- a/kernel/trace/trace.h +++ b/kernel/trace/trace.h @@ -748,6 +748,8 @@ extern void trace_event_follow_fork(struct trace_array *tr, bool enable); #ifdef CONFIG_DYNAMIC_FTRACE extern unsigned long ftrace_update_tot_cnt; +extern unsigned long ftrace_number_of_pages; +extern unsigned long ftrace_number_of_groups; void ftrace_init_trace_array(struct trace_array *tr); #else static inline void ftrace_init_trace_array(struct trace_array *tr) { } diff --git a/kernel/trace/trace_events.c b/kernel/trace/trace_events.c index d2f9146d1ad74..a3dc6c126b3ee 100644 --- a/kernel/trace/trace_events.c +++ b/kernel/trace/trace_events.c @@ -372,7 +372,6 @@ static int __ftrace_event_enable_disable(struct trace_event_file *file, { struct trace_event_call *call = file->event_call; struct trace_array *tr = file->tr; - unsigned long file_flags = file->flags; int ret = 0; int disable; @@ -396,6 +395,8 @@ static int __ftrace_event_enable_disable(struct trace_event_file *file, break; disable = file->flags & EVENT_FILE_FL_SOFT_DISABLED; clear_bit(EVENT_FILE_FL_SOFT_MODE_BIT, &file->flags); + /* Disable use of trace_buffered_event */ + trace_buffered_event_disable(); } else disable = !(file->flags & EVENT_FILE_FL_SOFT_MODE); @@ -434,6 +435,8 @@ static int __ftrace_event_enable_disable(struct trace_event_file *file, if (atomic_inc_return(&file->sm_ref) > 1) break; set_bit(EVENT_FILE_FL_SOFT_MODE_BIT, &file->flags); + /* Enable use of trace_buffered_event */ + trace_buffered_event_enable(); } if (!(file->flags & EVENT_FILE_FL_ENABLED)) { @@ -473,15 +476,6 @@ static int __ftrace_event_enable_disable(struct trace_event_file *file, break; } - /* Enable or disable use of trace_buffered_event */ - if ((file_flags & EVENT_FILE_FL_SOFT_DISABLED) != - (file->flags & EVENT_FILE_FL_SOFT_DISABLED)) { - if (file->flags & EVENT_FILE_FL_SOFT_DISABLED) - trace_buffered_event_enable(); - else - trace_buffered_event_disable(); - } - return ret; } diff --git a/kernel/trace/trace_events_hist.c b/kernel/trace/trace_events_hist.c index 455cf41aedbbc..e004daf8cad57 100644 --- a/kernel/trace/trace_events_hist.c +++ b/kernel/trace/trace_events_hist.c @@ -5787,13 +5787,16 @@ static int event_hist_trigger_func(struct event_command *cmd_ops, if (get_named_trigger_data(trigger_data)) goto enable; - if (has_hist_vars(hist_data)) - save_hist_vars(hist_data); - ret = create_actions(hist_data, file); if (ret) goto out_unreg; + if (has_hist_vars(hist_data) || hist_data->n_var_refs) { + ret = save_hist_vars(hist_data); + if (ret) + goto out_unreg; + } + ret = tracing_map_init(hist_data->map); if (ret) goto out_unreg; diff --git a/kernel/watchdog_hld.c b/kernel/watchdog_hld.c index 71381168dedef..f8e460b4a59d5 100644 --- a/kernel/watchdog_hld.c +++ b/kernel/watchdog_hld.c @@ -114,14 +114,14 @@ static void watchdog_overflow_callback(struct perf_event *event, /* Ensure the watchdog never gets throttled */ event->hw.interrupts = 0; + if (!watchdog_check_timestamp()) + return; + if (__this_cpu_read(watchdog_nmi_touch) == true) { __this_cpu_write(watchdog_nmi_touch, false); return; } - if (!watchdog_check_timestamp()) - return; - /* check for a hardlockup * This is done by making sure our timer interrupt * is incrementing. The timer interrupt should have diff --git a/kernel/workqueue.c b/kernel/workqueue.c index 4ea2f7fd20ceb..5533206cb6f48 100644 --- a/kernel/workqueue.c +++ b/kernel/workqueue.c @@ -680,12 +680,17 @@ static void clear_work_data(struct work_struct *work) set_work_data(work, WORK_STRUCT_NO_POOL, 0); } +static inline struct pool_workqueue *work_struct_pwq(unsigned long data) +{ + return (struct pool_workqueue *)(data & WORK_STRUCT_WQ_DATA_MASK); +} + static struct pool_workqueue *get_work_pwq(struct work_struct *work) { unsigned long data = atomic_long_read(&work->data); if (data & WORK_STRUCT_PWQ) - return (void *)(data & WORK_STRUCT_WQ_DATA_MASK); + return work_struct_pwq(data); else return NULL; } @@ -713,8 +718,7 @@ static struct worker_pool *get_work_pool(struct work_struct *work) assert_rcu_or_pool_mutex(); if (data & WORK_STRUCT_PWQ) - return ((struct pool_workqueue *) - (data & WORK_STRUCT_WQ_DATA_MASK))->pool; + return work_struct_pwq(data)->pool; pool_id = data >> WORK_OFFQ_POOL_SHIFT; if (pool_id == WORK_OFFQ_POOL_NONE) @@ -735,8 +739,7 @@ static int get_work_pool_id(struct work_struct *work) unsigned long data = atomic_long_read(&work->data); if (data & WORK_STRUCT_PWQ) - return ((struct pool_workqueue *) - (data & WORK_STRUCT_WQ_DATA_MASK))->pool->id; + return work_struct_pwq(data)->pool->id; return data >> WORK_OFFQ_POOL_SHIFT; } diff --git a/lib/debugobjects.c b/lib/debugobjects.c index 5f23d896df55a..62d095fd0c52a 100644 --- a/lib/debugobjects.c +++ b/lib/debugobjects.c @@ -371,6 +371,15 @@ static void debug_print_object(struct debug_obj *obj, char *msg) struct debug_obj_descr *descr = obj->descr; static int limit; + /* + * Don't report if lookup_object_or_alloc() by the current thread + * failed because lookup_object_or_alloc()/debug_objects_oom() by a + * concurrent thread turned off debug_objects_enabled and cleared + * the hash buckets. + */ + if (!debug_objects_enabled) + return; + if (limit < 5 && descr != descr_test) { void *hint = descr->debug_hint ? descr->debug_hint(obj->object) : NULL; diff --git a/lib/radix-tree.c b/lib/radix-tree.c index e5cab5c4e3830..8d29fa5b26957 100644 --- a/lib/radix-tree.c +++ b/lib/radix-tree.c @@ -1498,7 +1498,7 @@ void *radix_tree_tag_clear(struct radix_tree_root *root, { struct radix_tree_node *node, *parent; unsigned long maxindex; - int uninitialized_var(offset); + int offset; radix_tree_load_root(root, &node, &maxindex); if (index > maxindex) diff --git a/lib/test_firmware.c b/lib/test_firmware.c index f4cc874021da2..b5e779bcfb343 100644 --- a/lib/test_firmware.c +++ b/lib/test_firmware.c @@ -160,7 +160,7 @@ static int __kstrncpy(char **dst, const char *name, size_t count, gfp_t gfp) { *dst = kstrndup(name, count, gfp); if (!*dst) - return -ENOSPC; + return -ENOMEM; return count; } @@ -456,7 +456,7 @@ static ssize_t trigger_request_store(struct device *dev, name = kstrndup(buf, count, GFP_KERNEL); if (!name) - return -ENOSPC; + return -ENOMEM; pr_info("loading '%s'\n", name); @@ -497,7 +497,7 @@ static ssize_t trigger_async_request_store(struct device *dev, name = kstrndup(buf, count, GFP_KERNEL); if (!name) - return -ENOSPC; + return -ENOMEM; pr_info("loading '%s'\n", name); @@ -540,7 +540,7 @@ static ssize_t trigger_custom_fallback_store(struct device *dev, name = kstrndup(buf, count, GFP_KERNEL); if (!name) - return -ENOSPC; + return -ENOMEM; pr_info("loading '%s' using custom fallback mechanism\n", name); @@ -618,6 +618,11 @@ static ssize_t trigger_batched_requests_store(struct device *dev, mutex_lock(&test_fw_mutex); + if (test_fw_config->reqs) { + rc = -EBUSY; + goto out_bail; + } + test_fw_config->reqs = vzalloc(array3_size(sizeof(struct test_batched_req), test_fw_config->num_requests, 2)); @@ -721,6 +726,11 @@ ssize_t trigger_batched_requests_async_store(struct device *dev, mutex_lock(&test_fw_mutex); + if (test_fw_config->reqs) { + rc = -EBUSY; + goto out_bail; + } + test_fw_config->reqs = vzalloc(array3_size(sizeof(struct test_batched_req), test_fw_config->num_requests, 2)); diff --git a/lib/ts_bm.c b/lib/ts_bm.c index 9e66ee4020e90..5de382e79a45a 100644 --- a/lib/ts_bm.c +++ b/lib/ts_bm.c @@ -64,10 +64,12 @@ static unsigned int bm_find(struct ts_config *conf, struct ts_state *state) struct ts_bm *bm = ts_config_priv(conf); unsigned int i, text_len, consumed = state->offset; const u8 *text; - int shift = bm->patlen - 1, bs; + int bs; const u8 icase = conf->flags & TS_IGNORECASE; for (;;) { + int shift = bm->patlen - 1; + text_len = conf->get_next_block(consumed, &text, conf, state); if (unlikely(text_len == 0)) diff --git a/mm/frontswap.c b/mm/frontswap.c index 157e5bf635042..80bf870d881a0 100644 --- a/mm/frontswap.c +++ b/mm/frontswap.c @@ -447,7 +447,7 @@ static int __frontswap_shrink(unsigned long target_pages, void frontswap_shrink(unsigned long target_pages) { unsigned long pages_to_unuse = 0; - int uninitialized_var(type), ret; + int type, ret; /* * we don't want to hold swap_lock while doing a very diff --git a/mm/ksm.c b/mm/ksm.c index 87a541ab1474f..9693aadec6e26 100644 --- a/mm/ksm.c +++ b/mm/ksm.c @@ -2381,7 +2381,7 @@ next_mm: static void ksm_do_scan(unsigned int scan_npages) { struct rmap_item *rmap_item; - struct page *uninitialized_var(page); + struct page *page; while (scan_npages-- && likely(!freezing(current))) { cond_resched(); diff --git a/mm/memcontrol.c b/mm/memcontrol.c index bc4c61dcf95c7..5a366cf798214 100644 --- a/mm/memcontrol.c +++ b/mm/memcontrol.c @@ -919,7 +919,7 @@ struct mem_cgroup *mem_cgroup_iter(struct mem_cgroup *root, struct mem_cgroup *prev, struct mem_cgroup_reclaim_cookie *reclaim) { - struct mem_cgroup_reclaim_iter *uninitialized_var(iter); + struct mem_cgroup_reclaim_iter *iter; struct cgroup_subsys_state *css = NULL; struct mem_cgroup *memcg = NULL; struct mem_cgroup *pos = NULL; diff --git a/mm/mempolicy.c b/mm/mempolicy.c index 35088e830bff8..86fd6bedaff4d 100644 --- a/mm/mempolicy.c +++ b/mm/mempolicy.c @@ -1147,7 +1147,7 @@ int do_migrate_pages(struct mm_struct *mm, const nodemask_t *from, static struct page *new_page(struct page *page, unsigned long start) { struct vm_area_struct *vma; - unsigned long uninitialized_var(address); + unsigned long address; vma = find_vma(current->mm, start); while (vma) { @@ -1545,7 +1545,7 @@ static int kernel_get_mempolicy(int __user *policy, unsigned long flags) { int err; - int uninitialized_var(pval); + int pval; nodemask_t nodes; if (nmask != NULL && maxnode < nr_node_ids) diff --git a/mm/percpu.c b/mm/percpu.c index 0151f276ae680..6ae4993214b4d 100644 --- a/mm/percpu.c +++ b/mm/percpu.c @@ -2283,7 +2283,7 @@ static struct pcpu_alloc_info * __init pcpu_build_alloc_info( const size_t static_size = __per_cpu_end - __per_cpu_start; int nr_groups = 1, nr_units = 0; size_t size_sum, min_unit_size, alloc_size; - int upa, max_upa, uninitialized_var(best_upa); /* units_per_alloc */ + int upa, max_upa, best_upa; /* units_per_alloc */ int last_allocs, group, unit; unsigned int cpu, tcpu; struct pcpu_alloc_info *ai; diff --git a/mm/slub.c b/mm/slub.c index ef730ea8263cb..edf766f1de63f 100644 --- a/mm/slub.c +++ b/mm/slub.c @@ -1179,7 +1179,7 @@ static noinline int free_debug_processing( struct kmem_cache_node *n = get_node(s, page_to_nid(page)); void *object = head; int cnt = 0; - unsigned long uninitialized_var(flags); + unsigned long flags; int ret = 0; spin_lock_irqsave(&n->list_lock, flags); @@ -2826,7 +2826,7 @@ static void __slab_free(struct kmem_cache *s, struct page *page, struct page new; unsigned long counters; struct kmem_cache_node *n = NULL; - unsigned long uninitialized_var(flags); + unsigned long flags; stat(s, FREE_SLOWPATH); diff --git a/mm/swap.c b/mm/swap.c index 45fdbfb6b2a60..ce13e428380e9 100644 --- a/mm/swap.c +++ b/mm/swap.c @@ -721,8 +721,8 @@ void release_pages(struct page **pages, int nr) LIST_HEAD(pages_to_free); struct pglist_data *locked_pgdat = NULL; struct lruvec *lruvec; - unsigned long uninitialized_var(flags); - unsigned int uninitialized_var(lock_batch); + unsigned long flags; + unsigned int lock_batch; for (i = 0; i < nr; i++) { struct page *page = pages[i]; diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c index 1c6d01a27e0e8..b831e5fe3ebc1 100644 --- a/net/bluetooth/l2cap_sock.c +++ b/net/bluetooth/l2cap_sock.c @@ -45,6 +45,7 @@ static const struct proto_ops l2cap_sock_ops; static void l2cap_sock_init(struct sock *sk, struct sock *parent); static struct sock *l2cap_sock_alloc(struct net *net, struct socket *sock, int proto, gfp_t prio, int kern); +static void l2cap_sock_cleanup_listen(struct sock *parent); bool l2cap_is_socket(struct socket *sock) { @@ -1205,6 +1206,7 @@ static int l2cap_sock_release(struct socket *sock) if (!sk) return 0; + l2cap_sock_cleanup_listen(sk); bt_sock_unlink(&l2cap_sk_list, sk); err = l2cap_sock_shutdown(sock, 2); diff --git a/net/bridge/br_if.c b/net/bridge/br_if.c index b5fb2b682e191..ab539551b7d39 100644 --- a/net/bridge/br_if.c +++ b/net/bridge/br_if.c @@ -161,8 +161,9 @@ void br_manage_promisc(struct net_bridge *br) * This lets us disable promiscuous mode and write * this config to hw. */ - if (br->auto_cnt == 0 || - (br->auto_cnt == 1 && br_auto_port(p))) + if ((p->dev->priv_flags & IFF_UNICAST_FLT) && + (br->auto_cnt == 0 || + (br->auto_cnt == 1 && br_auto_port(p)))) br_port_clear_promisc(p); else br_port_set_promisc(p); diff --git a/net/can/bcm.c b/net/can/bcm.c index 61269cc2fa828..1c9953c68f095 100644 --- a/net/can/bcm.c +++ b/net/can/bcm.c @@ -1520,6 +1520,12 @@ static int bcm_release(struct socket *sock) lock_sock(sk); +#if IS_ENABLED(CONFIG_PROC_FS) + /* remove procfs entry */ + if (net->can.bcmproc_dir && bo->bcm_proc_read) + remove_proc_entry(bo->procname, net->can.bcmproc_dir); +#endif /* CONFIG_PROC_FS */ + list_for_each_entry_safe(op, next, &bo->tx_ops, list) bcm_remove_op(op); @@ -1555,12 +1561,6 @@ static int bcm_release(struct socket *sock) list_for_each_entry_safe(op, next, &bo->rx_ops, list) bcm_remove_op(op); -#if IS_ENABLED(CONFIG_PROC_FS) - /* remove procfs entry */ - if (net->can.bcmproc_dir && bo->bcm_proc_read) - remove_proc_entry(bo->procname, net->can.bcmproc_dir); -#endif /* CONFIG_PROC_FS */ - /* remove device reference */ if (bo->bound) { bo->bound = 0; diff --git a/net/ceph/osd_client.c b/net/ceph/osd_client.c index 713fe1fbcb181..90ebb0ba927cd 100644 --- a/net/ceph/osd_client.c +++ b/net/ceph/osd_client.c @@ -3137,17 +3137,24 @@ static int linger_reg_commit_wait(struct ceph_osd_linger_request *lreq) int ret; dout("%s lreq %p linger_id %llu\n", __func__, lreq, lreq->linger_id); - ret = wait_for_completion_interruptible(&lreq->reg_commit_wait); + ret = wait_for_completion_killable(&lreq->reg_commit_wait); return ret ?: lreq->reg_commit_error; } -static int linger_notify_finish_wait(struct ceph_osd_linger_request *lreq) +static int linger_notify_finish_wait(struct ceph_osd_linger_request *lreq, + unsigned long timeout) { - int ret; + long left; dout("%s lreq %p linger_id %llu\n", __func__, lreq, lreq->linger_id); - ret = wait_for_completion_interruptible(&lreq->notify_finish_wait); - return ret ?: lreq->notify_finish_error; + left = wait_for_completion_killable_timeout(&lreq->notify_finish_wait, + ceph_timeout_jiffies(timeout)); + if (left <= 0) + left = left ?: -ETIMEDOUT; + else + left = lreq->notify_finish_error; /* completed */ + + return left; } /* @@ -4760,7 +4767,8 @@ int ceph_osdc_notify(struct ceph_osd_client *osdc, ret = linger_reg_commit_wait(lreq); if (!ret) - ret = linger_notify_finish_wait(lreq); + ret = linger_notify_finish_wait(lreq, + msecs_to_jiffies(2 * timeout * MSEC_PER_SEC)); else dout("lreq %p failed to initiate notify %d\n", lreq, ret); diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c index 2837cc03f69e2..79f62517e24a5 100644 --- a/net/core/rtnetlink.c +++ b/net/core/rtnetlink.c @@ -3436,7 +3436,7 @@ static int nlmsg_populate_fdb_fill(struct sk_buff *skb, ndm->ndm_ifindex = dev->ifindex; ndm->ndm_state = ndm_state; - if (nla_put(skb, NDA_LLADDR, ETH_ALEN, addr)) + if (nla_put(skb, NDA_LLADDR, dev->addr_len, addr)) goto nla_put_failure; if (vid) if (nla_put(skb, NDA_VLAN, sizeof(u16), &vid)) @@ -3450,10 +3450,10 @@ nla_put_failure: return -EMSGSIZE; } -static inline size_t rtnl_fdb_nlmsg_size(void) +static inline size_t rtnl_fdb_nlmsg_size(const struct net_device *dev) { return NLMSG_ALIGN(sizeof(struct ndmsg)) + - nla_total_size(ETH_ALEN) + /* NDA_LLADDR */ + nla_total_size(dev->addr_len) + /* NDA_LLADDR */ nla_total_size(sizeof(u16)) + /* NDA_VLAN */ 0; } @@ -3465,7 +3465,7 @@ static void rtnl_fdb_notify(struct net_device *dev, u8 *addr, u16 vid, int type, struct sk_buff *skb; int err = -ENOBUFS; - skb = nlmsg_new(rtnl_fdb_nlmsg_size(), GFP_ATOMIC); + skb = nlmsg_new(rtnl_fdb_nlmsg_size(dev), GFP_ATOMIC); if (!skb) goto errout; diff --git a/net/core/sock.c b/net/core/sock.c index 347a55519d0a5..3e6da3694a5a5 100644 --- a/net/core/sock.c +++ b/net/core/sock.c @@ -1319,7 +1319,7 @@ int sock_getsockopt(struct socket *sock, int level, int optname, if (!sock->ops->set_peek_off) return -EOPNOTSUPP; - v.val = sk->sk_peek_off; + v.val = READ_ONCE(sk->sk_peek_off); break; case SO_NOFCS: v.val = sock_flag(sk, SOCK_NOFCS); @@ -1349,7 +1349,7 @@ int sock_getsockopt(struct socket *sock, int level, int optname, #ifdef CONFIG_NET_RX_BUSY_POLL case SO_BUSY_POLL: - v.val = sk->sk_ll_usec; + v.val = READ_ONCE(sk->sk_ll_usec); break; #endif @@ -1939,13 +1939,24 @@ kuid_t sock_i_uid(struct sock *sk) } EXPORT_SYMBOL(sock_i_uid); -unsigned long sock_i_ino(struct sock *sk) +unsigned long __sock_i_ino(struct sock *sk) { unsigned long ino; - read_lock_bh(&sk->sk_callback_lock); + read_lock(&sk->sk_callback_lock); ino = sk->sk_socket ? SOCK_INODE(sk->sk_socket)->i_ino : 0; - read_unlock_bh(&sk->sk_callback_lock); + read_unlock(&sk->sk_callback_lock); + return ino; +} +EXPORT_SYMBOL(__sock_i_ino); + +unsigned long sock_i_ino(struct sock *sk) +{ + unsigned long ino; + + local_bh_disable(); + ino = __sock_i_ino(sk); + local_bh_enable(); return ino; } EXPORT_SYMBOL(sock_i_ino); @@ -2548,7 +2559,7 @@ EXPORT_SYMBOL(__sk_mem_reclaim); int sk_set_peek_off(struct sock *sk, int val) { - sk->sk_peek_off = val; + WRITE_ONCE(sk->sk_peek_off, val); return 0; } EXPORT_SYMBOL_GPL(sk_set_peek_off); diff --git a/net/dccp/options.c b/net/dccp/options.c index 4e40db017e198..3c464d63b0bb3 100644 --- a/net/dccp/options.c +++ b/net/dccp/options.c @@ -60,7 +60,7 @@ int dccp_parse_options(struct sock *sk, struct dccp_request_sock *dreq, (dh->dccph_doff * 4); struct dccp_options_received *opt_recv = &dp->dccps_options_received; unsigned char opt, len; - unsigned char *uninitialized_var(value); + unsigned char *value; u32 elapsed_time; __be32 opt_val; int rc; diff --git a/net/ipv4/inet_hashtables.c b/net/ipv4/inet_hashtables.c index 5a272d09b8248..c6d670cd872f0 100644 --- a/net/ipv4/inet_hashtables.c +++ b/net/ipv4/inet_hashtables.c @@ -579,20 +579,8 @@ bool inet_ehash_insert(struct sock *sk, struct sock *osk, bool *found_dup_sk) spin_lock(lock); if (osk) { WARN_ON_ONCE(sk->sk_hash != osk->sk_hash); - ret = sk_hashed(osk); - if (ret) { - /* Before deleting the node, we insert a new one to make - * sure that the look-up-sk process would not miss either - * of them and that at least one node would exist in ehash - * table all the time. Otherwise there's a tiny chance - * that lookup process could find nothing in ehash table. - */ - __sk_nulls_add_node_tail_rcu(sk, list); - sk_nulls_del_node_init_rcu(osk); - } - goto unlock; - } - if (found_dup_sk) { + ret = sk_nulls_del_node_init_rcu(osk); + } else if (found_dup_sk) { *found_dup_sk = inet_ehash_lookup_by_sk(sk, list); if (*found_dup_sk) ret = false; @@ -601,7 +589,6 @@ bool inet_ehash_insert(struct sock *sk, struct sock *osk, bool *found_dup_sk) if (ret) __sk_nulls_add_node_rcu(sk, list); -unlock: spin_unlock(lock); return ret; diff --git a/net/ipv4/inet_timewait_sock.c b/net/ipv4/inet_timewait_sock.c index fedd19c22b392..88c5069b5d20c 100644 --- a/net/ipv4/inet_timewait_sock.c +++ b/net/ipv4/inet_timewait_sock.c @@ -80,10 +80,10 @@ void inet_twsk_put(struct inet_timewait_sock *tw) } EXPORT_SYMBOL_GPL(inet_twsk_put); -static void inet_twsk_add_node_tail_rcu(struct inet_timewait_sock *tw, - struct hlist_nulls_head *list) +static void inet_twsk_add_node_rcu(struct inet_timewait_sock *tw, + struct hlist_nulls_head *list) { - hlist_nulls_add_tail_rcu(&tw->tw_node, list); + hlist_nulls_add_head_rcu(&tw->tw_node, list); } static void inet_twsk_add_bind_node(struct inet_timewait_sock *tw, @@ -119,7 +119,7 @@ void inet_twsk_hashdance(struct inet_timewait_sock *tw, struct sock *sk, spin_lock(lock); - inet_twsk_add_node_tail_rcu(tw, &ehead->chain); + inet_twsk_add_node_rcu(tw, &ehead->chain); /* Step 3: Remove SK from hash chain */ if (__sk_nulls_del_node_init_rcu(sk)) diff --git a/net/ipv4/netfilter/nf_socket_ipv4.c b/net/ipv4/netfilter/nf_socket_ipv4.c index 4824b1e183a1d..bff2b85c5fd6b 100644 --- a/net/ipv4/netfilter/nf_socket_ipv4.c +++ b/net/ipv4/netfilter/nf_socket_ipv4.c @@ -96,11 +96,11 @@ nf_socket_get_sock_v4(struct net *net, struct sk_buff *skb, const int doff, struct sock *nf_sk_lookup_slow_v4(struct net *net, const struct sk_buff *skb, const struct net_device *indev) { - __be32 uninitialized_var(daddr), uninitialized_var(saddr); - __be16 uninitialized_var(dport), uninitialized_var(sport); + __be32 daddr, saddr; + __be16 dport, sport; const struct iphdr *iph = ip_hdr(skb); struct sk_buff *data_skb = NULL; - u8 uninitialized_var(protocol); + u8 protocol; #if IS_ENABLED(CONFIG_NF_CONNTRACK) enum ip_conntrack_info ctinfo; struct nf_conn const *ct; diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index cb96775fc86f6..00648a478c6a5 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c @@ -3000,18 +3000,18 @@ static int do_tcp_setsockopt(struct sock *sk, int level, case TCP_LINGER2: if (val < 0) - tp->linger2 = -1; - else if (val > net->ipv4.sysctl_tcp_fin_timeout / HZ) - tp->linger2 = 0; + WRITE_ONCE(tp->linger2, -1); + else if (val > TCP_FIN_TIMEOUT_MAX / HZ) + WRITE_ONCE(tp->linger2, TCP_FIN_TIMEOUT_MAX); else - tp->linger2 = val * HZ; + WRITE_ONCE(tp->linger2, val * HZ); break; case TCP_DEFER_ACCEPT: /* Translate value in seconds to number of retransmits */ - icsk->icsk_accept_queue.rskq_defer_accept = - secs_to_retrans(val, TCP_TIMEOUT_INIT / HZ, - TCP_RTO_MAX / HZ); + WRITE_ONCE(icsk->icsk_accept_queue.rskq_defer_accept, + secs_to_retrans(val, TCP_TIMEOUT_INIT / HZ, + TCP_RTO_MAX / HZ)); break; case TCP_WINDOW_CLAMP: @@ -3099,7 +3099,7 @@ static int do_tcp_setsockopt(struct sock *sk, int level, err = tcp_repair_set_window(tp, optval, optlen); break; case TCP_NOTSENT_LOWAT: - tp->notsent_lowat = val; + WRITE_ONCE(tp->notsent_lowat, val); sk->sk_write_space(sk); break; case TCP_INQ: @@ -3401,13 +3401,14 @@ static int do_tcp_getsockopt(struct sock *sk, int level, val = icsk->icsk_syn_retries ? : net->ipv4.sysctl_tcp_syn_retries; break; case TCP_LINGER2: - val = tp->linger2; + val = READ_ONCE(tp->linger2); if (val >= 0) val = (val ? : READ_ONCE(net->ipv4.sysctl_tcp_fin_timeout)) / HZ; break; case TCP_DEFER_ACCEPT: - val = retrans_to_secs(icsk->icsk_accept_queue.rskq_defer_accept, - TCP_TIMEOUT_INIT / HZ, TCP_RTO_MAX / HZ); + val = READ_ONCE(icsk->icsk_accept_queue.rskq_defer_accept); + val = retrans_to_secs(val, TCP_TIMEOUT_INIT / HZ, + TCP_RTO_MAX / HZ); break; case TCP_WINDOW_CLAMP: val = tp->window_clamp; @@ -3553,7 +3554,7 @@ static int do_tcp_getsockopt(struct sock *sk, int level, break; case TCP_FASTOPEN: - val = icsk->icsk_accept_queue.fastopenq.max_qlen; + val = READ_ONCE(icsk->icsk_accept_queue.fastopenq.max_qlen); break; case TCP_FASTOPEN_CONNECT: @@ -3568,7 +3569,7 @@ static int do_tcp_getsockopt(struct sock *sk, int level, val = tcp_time_stamp_raw() + tp->tsoffset; break; case TCP_NOTSENT_LOWAT: - val = tp->notsent_lowat; + val = READ_ONCE(tp->notsent_lowat); break; case TCP_INQ: val = tp->recvmsg_inq; diff --git a/net/ipv4/tcp_fastopen.c b/net/ipv4/tcp_fastopen.c index f726591de7c7a..f7bb78b443fa9 100644 --- a/net/ipv4/tcp_fastopen.c +++ b/net/ipv4/tcp_fastopen.c @@ -276,6 +276,7 @@ static struct sock *tcp_fastopen_create_child(struct sock *sk, static bool tcp_fastopen_queue_check(struct sock *sk) { struct fastopen_queue *fastopenq; + int max_qlen; /* Make sure the listener has enabled fastopen, and we don't * exceed the max # of pending TFO requests allowed before trying @@ -288,10 +289,11 @@ static bool tcp_fastopen_queue_check(struct sock *sk) * temporarily vs a server not supporting Fast Open at all. */ fastopenq = &inet_csk(sk)->icsk_accept_queue.fastopenq; - if (fastopenq->max_qlen == 0) + max_qlen = READ_ONCE(fastopenq->max_qlen); + if (max_qlen == 0) return false; - if (fastopenq->qlen >= fastopenq->max_qlen) { + if (fastopenq->qlen >= max_qlen) { struct request_sock *req1; spin_lock(&fastopenq->lock); req1 = fastopenq->rskq_rst_head; diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index bd921fa7b9ab4..281f7799aeafc 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c @@ -3429,8 +3429,11 @@ static int tcp_ack_update_window(struct sock *sk, const struct sk_buff *skb, u32 static bool __tcp_oow_rate_limited(struct net *net, int mib_idx, u32 *last_oow_ack_time) { - if (*last_oow_ack_time) { - s32 elapsed = (s32)(tcp_jiffies32 - *last_oow_ack_time); + /* Paired with the WRITE_ONCE() in this function. */ + u32 val = READ_ONCE(*last_oow_ack_time); + + if (val) { + s32 elapsed = (s32)(tcp_jiffies32 - val); if (0 <= elapsed && elapsed < READ_ONCE(net->ipv4.sysctl_tcp_invalid_ratelimit)) { @@ -3439,7 +3442,10 @@ static bool __tcp_oow_rate_limited(struct net *net, int mib_idx, } } - *last_oow_ack_time = tcp_jiffies32; + /* Paired with the prior READ_ONCE() and with itself, + * as we might be lockless. + */ + WRITE_ONCE(*last_oow_ack_time, tcp_jiffies32); return false; /* not rate-limited: go ahead, send dupack now! */ } diff --git a/net/ipv4/tcp_metrics.c b/net/ipv4/tcp_metrics.c index 4960e2b6bd7f7..7bbd9125b5000 100644 --- a/net/ipv4/tcp_metrics.c +++ b/net/ipv4/tcp_metrics.c @@ -40,7 +40,7 @@ struct tcp_fastopen_metrics { struct tcp_metrics_block { struct tcp_metrics_block __rcu *tcpm_next; - possible_net_t tcpm_net; + struct net *tcpm_net; struct inetpeer_addr tcpm_saddr; struct inetpeer_addr tcpm_daddr; unsigned long tcpm_stamp; @@ -51,34 +51,38 @@ struct tcp_metrics_block { struct rcu_head rcu_head; }; -static inline struct net *tm_net(struct tcp_metrics_block *tm) +static inline struct net *tm_net(const struct tcp_metrics_block *tm) { - return read_pnet(&tm->tcpm_net); + /* Paired with the WRITE_ONCE() in tcpm_new() */ + return READ_ONCE(tm->tcpm_net); } static bool tcp_metric_locked(struct tcp_metrics_block *tm, enum tcp_metric_index idx) { - return tm->tcpm_lock & (1 << idx); + /* Paired with WRITE_ONCE() in tcpm_suck_dst() */ + return READ_ONCE(tm->tcpm_lock) & (1 << idx); } -static u32 tcp_metric_get(struct tcp_metrics_block *tm, +static u32 tcp_metric_get(const struct tcp_metrics_block *tm, enum tcp_metric_index idx) { - return tm->tcpm_vals[idx]; + /* Paired with WRITE_ONCE() in tcp_metric_set() */ + return READ_ONCE(tm->tcpm_vals[idx]); } static void tcp_metric_set(struct tcp_metrics_block *tm, enum tcp_metric_index idx, u32 val) { - tm->tcpm_vals[idx] = val; + /* Paired with READ_ONCE() in tcp_metric_get() */ + WRITE_ONCE(tm->tcpm_vals[idx], val); } static bool addr_same(const struct inetpeer_addr *a, const struct inetpeer_addr *b) { - return inetpeer_addr_cmp(a, b) == 0; + return (a->family == b->family) && !inetpeer_addr_cmp(a, b); } struct tcpm_hash_bucket { @@ -89,6 +93,7 @@ static struct tcpm_hash_bucket *tcp_metrics_hash __read_mostly; static unsigned int tcp_metrics_hash_log __read_mostly; static DEFINE_SPINLOCK(tcp_metrics_lock); +static DEFINE_SEQLOCK(fastopen_seqlock); static void tcpm_suck_dst(struct tcp_metrics_block *tm, const struct dst_entry *dst, @@ -97,7 +102,7 @@ static void tcpm_suck_dst(struct tcp_metrics_block *tm, u32 msval; u32 val; - tm->tcpm_stamp = jiffies; + WRITE_ONCE(tm->tcpm_stamp, jiffies); val = 0; if (dst_metric_locked(dst, RTAX_RTT)) @@ -110,30 +115,42 @@ static void tcpm_suck_dst(struct tcp_metrics_block *tm, val |= 1 << TCP_METRIC_CWND; if (dst_metric_locked(dst, RTAX_REORDERING)) val |= 1 << TCP_METRIC_REORDERING; - tm->tcpm_lock = val; + /* Paired with READ_ONCE() in tcp_metric_locked() */ + WRITE_ONCE(tm->tcpm_lock, val); msval = dst_metric_raw(dst, RTAX_RTT); - tm->tcpm_vals[TCP_METRIC_RTT] = msval * USEC_PER_MSEC; + tcp_metric_set(tm, TCP_METRIC_RTT, msval * USEC_PER_MSEC); msval = dst_metric_raw(dst, RTAX_RTTVAR); - tm->tcpm_vals[TCP_METRIC_RTTVAR] = msval * USEC_PER_MSEC; - tm->tcpm_vals[TCP_METRIC_SSTHRESH] = dst_metric_raw(dst, RTAX_SSTHRESH); - tm->tcpm_vals[TCP_METRIC_CWND] = dst_metric_raw(dst, RTAX_CWND); - tm->tcpm_vals[TCP_METRIC_REORDERING] = dst_metric_raw(dst, RTAX_REORDERING); + tcp_metric_set(tm, TCP_METRIC_RTTVAR, msval * USEC_PER_MSEC); + tcp_metric_set(tm, TCP_METRIC_SSTHRESH, + dst_metric_raw(dst, RTAX_SSTHRESH)); + tcp_metric_set(tm, TCP_METRIC_CWND, + dst_metric_raw(dst, RTAX_CWND)); + tcp_metric_set(tm, TCP_METRIC_REORDERING, + dst_metric_raw(dst, RTAX_REORDERING)); if (fastopen_clear) { + write_seqlock(&fastopen_seqlock); tm->tcpm_fastopen.mss = 0; tm->tcpm_fastopen.syn_loss = 0; tm->tcpm_fastopen.try_exp = 0; tm->tcpm_fastopen.cookie.exp = false; tm->tcpm_fastopen.cookie.len = 0; + write_sequnlock(&fastopen_seqlock); } } #define TCP_METRICS_TIMEOUT (60 * 60 * HZ) -static void tcpm_check_stamp(struct tcp_metrics_block *tm, struct dst_entry *dst) +static void tcpm_check_stamp(struct tcp_metrics_block *tm, + const struct dst_entry *dst) { - if (tm && unlikely(time_after(jiffies, tm->tcpm_stamp + TCP_METRICS_TIMEOUT))) + unsigned long limit; + + if (!tm) + return; + limit = READ_ONCE(tm->tcpm_stamp) + TCP_METRICS_TIMEOUT; + if (unlikely(time_after(jiffies, limit))) tcpm_suck_dst(tm, dst, false); } @@ -174,20 +191,23 @@ static struct tcp_metrics_block *tcpm_new(struct dst_entry *dst, oldest = deref_locked(tcp_metrics_hash[hash].chain); for (tm = deref_locked(oldest->tcpm_next); tm; tm = deref_locked(tm->tcpm_next)) { - if (time_before(tm->tcpm_stamp, oldest->tcpm_stamp)) + if (time_before(READ_ONCE(tm->tcpm_stamp), + READ_ONCE(oldest->tcpm_stamp))) oldest = tm; } tm = oldest; } else { - tm = kmalloc(sizeof(*tm), GFP_ATOMIC); + tm = kzalloc(sizeof(*tm), GFP_ATOMIC); if (!tm) goto out_unlock; } - write_pnet(&tm->tcpm_net, net); + /* Paired with the READ_ONCE() in tm_net() */ + WRITE_ONCE(tm->tcpm_net, net); + tm->tcpm_saddr = *saddr; tm->tcpm_daddr = *daddr; - tcpm_suck_dst(tm, dst, true); + tcpm_suck_dst(tm, dst, reclaim); if (likely(!reclaim)) { tm->tcpm_next = tcp_metrics_hash[hash].chain; @@ -431,7 +451,7 @@ void tcp_update_metrics(struct sock *sk) tp->reordering); } } - tm->tcpm_stamp = jiffies; + WRITE_ONCE(tm->tcpm_stamp, jiffies); out_unlock: rcu_read_unlock(); } @@ -544,8 +564,6 @@ bool tcp_peer_is_proven(struct request_sock *req, struct dst_entry *dst) return ret; } -static DEFINE_SEQLOCK(fastopen_seqlock); - void tcp_fastopen_cache_get(struct sock *sk, u16 *mss, struct tcp_fastopen_cookie *cookie) { @@ -652,7 +670,7 @@ static int tcp_metrics_fill_info(struct sk_buff *msg, } if (nla_put_msecs(msg, TCP_METRICS_ATTR_AGE, - jiffies - tm->tcpm_stamp, + jiffies - READ_ONCE(tm->tcpm_stamp), TCP_METRICS_ATTR_PAD) < 0) goto nla_put_failure; @@ -663,7 +681,7 @@ static int tcp_metrics_fill_info(struct sk_buff *msg, if (!nest) goto nla_put_failure; for (i = 0; i < TCP_METRIC_MAX_KERNEL + 1; i++) { - u32 val = tm->tcpm_vals[i]; + u32 val = tcp_metric_get(tm, i); if (!val) continue; diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index f261c6d7f1f28..5c5c5736f6892 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c @@ -316,9 +316,8 @@ static void addrconf_del_dad_work(struct inet6_ifaddr *ifp) static void addrconf_mod_rs_timer(struct inet6_dev *idev, unsigned long when) { - if (!timer_pending(&idev->rs_timer)) + if (!mod_timer(&idev->rs_timer, jiffies + when)) in6_dev_hold(idev); - mod_timer(&idev->rs_timer, jiffies + when); } static void addrconf_mod_dad_work(struct inet6_ifaddr *ifp, @@ -2489,12 +2488,18 @@ static void manage_tempaddrs(struct inet6_dev *idev, ipv6_ifa_notify(0, ift); } - if ((create || list_empty(&idev->tempaddr_list)) && - idev->cnf.use_tempaddr > 0) { + /* Also create a temporary address if it's enabled but no temporary + * address currently exists. + * However, we get called with valid_lft == 0, prefered_lft == 0, create == false + * as part of cleanup (ie. deleting the mngtmpaddr). + * We don't want that to result in creating a new temporary ip address. + */ + if (list_empty(&idev->tempaddr_list) && (valid_lft || prefered_lft)) + create = true; + + if (create && idev->cnf.use_tempaddr > 0) { /* When a new public address is created as described * in [ADDRCONF], also create a new temporary address. - * Also create a temporary address if it's enabled but - * no temporary address currently exists. */ read_unlock_bh(&idev->lock); ipv6_create_tempaddr(ifp, NULL, false); diff --git a/net/ipv6/icmp.c b/net/ipv6/icmp.c index fbc8746371b6d..bfafd7649ccb3 100644 --- a/net/ipv6/icmp.c +++ b/net/ipv6/icmp.c @@ -395,23 +395,31 @@ relookup_failed: return ERR_PTR(err); } -static int icmp6_iif(const struct sk_buff *skb) +static struct net_device *icmp6_dev(const struct sk_buff *skb) { - int iif = skb->dev->ifindex; + struct net_device *dev = skb->dev; /* for local traffic to local address, skb dev is the loopback * device. Check if there is a dst attached to the skb and if so * get the real device index. Same is needed for replies to a link * local address on a device enslaved to an L3 master device */ - if (unlikely(iif == LOOPBACK_IFINDEX || netif_is_l3_master(skb->dev))) { + if (unlikely(dev->ifindex == LOOPBACK_IFINDEX || netif_is_l3_master(skb->dev))) { const struct rt6_info *rt6 = skb_rt6_info(skb); - if (rt6) - iif = rt6->rt6i_idev->dev->ifindex; + /* The destination could be an external IP in Ext Hdr (SRv6, RPL, etc.), + * and ip6_null_entry could be set to skb if no route is found. + */ + if (rt6 && rt6->rt6i_idev) + dev = rt6->rt6i_idev->dev; } - return iif; + return dev; +} + +static int icmp6_iif(const struct sk_buff *skb) +{ + return icmp6_dev(skb)->ifindex; } /* @@ -800,7 +808,7 @@ out: static int icmpv6_rcv(struct sk_buff *skb) { struct net *net = dev_net(skb->dev); - struct net_device *dev = skb->dev; + struct net_device *dev = icmp6_dev(skb); struct inet6_dev *idev = __in6_dev_get(dev); const struct in6_addr *saddr, *daddr; struct icmp6hdr *hdr; diff --git a/net/ipv6/ip6_flowlabel.c b/net/ipv6/ip6_flowlabel.c index f994f50e15162..1858cf783a4ff 100644 --- a/net/ipv6/ip6_flowlabel.c +++ b/net/ipv6/ip6_flowlabel.c @@ -518,7 +518,7 @@ int ipv6_flowlabel_opt_get(struct sock *sk, struct in6_flowlabel_req *freq, int ipv6_flowlabel_opt(struct sock *sk, char __user *optval, int optlen) { - int uninitialized_var(err); + int err; struct net *net = sock_net(sk); struct ipv6_pinfo *np = inet6_sk(sk); struct in6_flowlabel_req freq; diff --git a/net/ipv6/ip6_gre.c b/net/ipv6/ip6_gre.c index 45c304b51b2b7..aa8ada354a399 100644 --- a/net/ipv6/ip6_gre.c +++ b/net/ipv6/ip6_gre.c @@ -960,7 +960,8 @@ static netdev_tx_t ip6erspan_tunnel_xmit(struct sk_buff *skb, goto tx_err; if (skb->len > dev->mtu + dev->hard_header_len) { - pskb_trim(skb, dev->mtu + dev->hard_header_len); + if (pskb_trim(skb, dev->mtu + dev->hard_header_len)) + goto tx_err; truncate = true; } diff --git a/net/ipv6/ip6mr.c b/net/ipv6/ip6mr.c index e9eb917342b85..329bad6cbb768 100644 --- a/net/ipv6/ip6mr.c +++ b/net/ipv6/ip6mr.c @@ -1064,7 +1064,7 @@ static int ip6mr_cache_report(struct mr_table *mrt, struct sk_buff *pkt, And all this only to mangle msg->im6_msgtype and to set msg->im6_mbz to "mbz" :-) */ - skb_push(skb, -skb_network_offset(pkt)); + __skb_pull(skb, skb_network_offset(pkt)); skb_push(skb, sizeof(*msg)); skb_reset_transport_header(skb); diff --git a/net/ipv6/netfilter/nf_socket_ipv6.c b/net/ipv6/netfilter/nf_socket_ipv6.c index 58e839e2ce1d3..5e5463459563f 100644 --- a/net/ipv6/netfilter/nf_socket_ipv6.c +++ b/net/ipv6/netfilter/nf_socket_ipv6.c @@ -102,7 +102,7 @@ nf_socket_get_sock_v6(struct net *net, struct sk_buff *skb, int doff, struct sock *nf_sk_lookup_slow_v6(struct net *net, const struct sk_buff *skb, const struct net_device *indev) { - __be16 uninitialized_var(dport), uninitialized_var(sport); + __be16 dport, sport; const struct in6_addr *daddr = NULL, *saddr = NULL; struct ipv6hdr *iph = ipv6_hdr(skb), ipv6_var; struct sk_buff *data_skb = NULL; diff --git a/net/ipv6/reassembly.c b/net/ipv6/reassembly.c index 60dfd0d118512..b596727f04978 100644 --- a/net/ipv6/reassembly.c +++ b/net/ipv6/reassembly.c @@ -302,7 +302,7 @@ static int ip6_frag_reasm(struct frag_queue *fq, struct sk_buff *skb, skb_network_header_len(skb)); rcu_read_lock(); - __IP6_INC_STATS(net, __in6_dev_get(dev), IPSTATS_MIB_REASMOKS); + __IP6_INC_STATS(net, __in6_dev_stats_get(dev, skb), IPSTATS_MIB_REASMOKS); rcu_read_unlock(); fq->q.fragments = NULL; fq->q.rb_fragments = RB_ROOT; @@ -317,7 +317,7 @@ out_oom: net_dbg_ratelimited("ip6_frag_reasm: no memory for reassembly\n"); out_fail: rcu_read_lock(); - __IP6_INC_STATS(net, __in6_dev_get(dev), IPSTATS_MIB_REASMFAILS); + __IP6_INC_STATS(net, __in6_dev_stats_get(dev, skb), IPSTATS_MIB_REASMFAILS); rcu_read_unlock(); inet_frag_kill(&fq->q); return -1; diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c index 9274603514e54..cf0bbe2e3a79f 100644 --- a/net/ipv6/udp.c +++ b/net/ipv6/udp.c @@ -99,7 +99,7 @@ static u32 udp6_ehashfn(const struct net *net, fhash = __ipv6_addr_jhash(faddr, udp_ipv6_hash_secret); return __inet6_ehashfn(lhash, lport, fhash, fport, - udp_ipv6_hash_secret + net_hash_mix(net)); + udp6_ehash_secret + net_hash_mix(net)); } int udp_v6_get_port(struct sock *sk, unsigned short snum) diff --git a/net/llc/llc_input.c b/net/llc/llc_input.c index 82cb93f66b9bd..f9e801cc50f5e 100644 --- a/net/llc/llc_input.c +++ b/net/llc/llc_input.c @@ -162,9 +162,6 @@ int llc_rcv(struct sk_buff *skb, struct net_device *dev, void (*sta_handler)(struct sk_buff *skb); void (*sap_handler)(struct llc_sap *sap, struct sk_buff *skb); - if (!net_eq(dev_net(dev), &init_net)) - goto drop; - /* * When the interface is in promisc. mode, drop all the crap that it * receives, do not try to analyse it. diff --git a/net/netfilter/ipset/ip_set_core.c b/net/netfilter/ipset/ip_set_core.c index 0427e66bc4786..31756d1bf83e7 100644 --- a/net/netfilter/ipset/ip_set_core.c +++ b/net/netfilter/ipset/ip_set_core.c @@ -791,20 +791,9 @@ static struct nlmsghdr * start_msg(struct sk_buff *skb, u32 portid, u32 seq, unsigned int flags, enum ipset_cmd cmd) { - struct nlmsghdr *nlh; - struct nfgenmsg *nfmsg; - - nlh = nlmsg_put(skb, portid, seq, nfnl_msg_type(NFNL_SUBSYS_IPSET, cmd), - sizeof(*nfmsg), flags); - if (!nlh) - return NULL; - - nfmsg = nlmsg_data(nlh); - nfmsg->nfgen_family = NFPROTO_IPV4; - nfmsg->version = NFNETLINK_V0; - nfmsg->res_id = 0; - - return nlh; + return nfnl_msg_put(skb, portid, seq, + nfnl_msg_type(NFNL_SUBSYS_IPSET, cmd), flags, + NFPROTO_IPV4, NFNETLINK_V0, 0); } /* Create a set */ diff --git a/net/netfilter/nf_conntrack_ftp.c b/net/netfilter/nf_conntrack_ftp.c index efc14c7b4f8ef..c2fece0593eaa 100644 --- a/net/netfilter/nf_conntrack_ftp.c +++ b/net/netfilter/nf_conntrack_ftp.c @@ -383,7 +383,7 @@ static int help(struct sk_buff *skb, int ret; u32 seq; int dir = CTINFO2DIR(ctinfo); - unsigned int uninitialized_var(matchlen), uninitialized_var(matchoff); + unsigned int matchlen, matchoff; struct nf_ct_ftp_master *ct_ftp_info = nfct_help_data(ct); struct nf_conntrack_expect *exp; union nf_inet_addr *daddr; diff --git a/net/netfilter/nf_conntrack_helper.c b/net/netfilter/nf_conntrack_helper.c index e24b762ffa1d4..06c70d4584cfe 100644 --- a/net/netfilter/nf_conntrack_helper.c +++ b/net/netfilter/nf_conntrack_helper.c @@ -400,6 +400,9 @@ int nf_conntrack_helper_register(struct nf_conntrack_helper *me) BUG_ON(me->expect_class_max >= NF_CT_MAX_EXPECT_CLASSES); BUG_ON(strlen(me->name) > NF_CT_HELPER_NAME_LEN - 1); + if (!nf_ct_helper_hash) + return -ENOENT; + if (me->expect_policy->max_expected > NF_CT_EXPECT_MAX_CNT) return -EINVAL; @@ -570,4 +573,5 @@ void nf_conntrack_helper_fini(void) { nf_ct_extend_unregister(&helper_extend); kvfree(nf_ct_helper_hash); + nf_ct_helper_hash = NULL; } diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c index b710889a90f6f..83e8566ec3f05 100644 --- a/net/netfilter/nf_conntrack_netlink.c +++ b/net/netfilter/nf_conntrack_netlink.c @@ -517,20 +517,15 @@ ctnetlink_fill_info(struct sk_buff *skb, u32 portid, u32 seq, u32 type, { const struct nf_conntrack_zone *zone; struct nlmsghdr *nlh; - struct nfgenmsg *nfmsg; struct nlattr *nest_parms; unsigned int flags = portid ? NLM_F_MULTI : 0, event; event = nfnl_msg_type(NFNL_SUBSYS_CTNETLINK, IPCTNL_MSG_CT_NEW); - nlh = nlmsg_put(skb, portid, seq, event, sizeof(*nfmsg), flags); - if (nlh == NULL) + nlh = nfnl_msg_put(skb, portid, seq, event, flags, nf_ct_l3num(ct), + NFNETLINK_V0, 0); + if (!nlh) goto nlmsg_failure; - nfmsg = nlmsg_data(nlh); - nfmsg->nfgen_family = nf_ct_l3num(ct); - nfmsg->version = NFNETLINK_V0; - nfmsg->res_id = 0; - zone = nf_ct_zone(ct); nest_parms = nla_nest_start(skb, CTA_TUPLE_ORIG | NLA_F_NESTED); @@ -687,7 +682,6 @@ ctnetlink_conntrack_event(unsigned int events, struct nf_ct_event *item) const struct nf_conntrack_zone *zone; struct net *net; struct nlmsghdr *nlh; - struct nfgenmsg *nfmsg; struct nlattr *nest_parms; struct nf_conn *ct = item->ct; struct sk_buff *skb; @@ -717,15 +711,11 @@ ctnetlink_conntrack_event(unsigned int events, struct nf_ct_event *item) goto errout; type = nfnl_msg_type(NFNL_SUBSYS_CTNETLINK, type); - nlh = nlmsg_put(skb, item->portid, 0, type, sizeof(*nfmsg), flags); - if (nlh == NULL) + nlh = nfnl_msg_put(skb, item->portid, 0, type, flags, nf_ct_l3num(ct), + NFNETLINK_V0, 0); + if (!nlh) goto nlmsg_failure; - nfmsg = nlmsg_data(nlh); - nfmsg->nfgen_family = nf_ct_l3num(ct); - nfmsg->version = NFNETLINK_V0; - nfmsg->res_id = 0; - zone = nf_ct_zone(ct); nest_parms = nla_nest_start(skb, CTA_TUPLE_ORIG | NLA_F_NESTED); @@ -2170,20 +2160,15 @@ ctnetlink_ct_stat_cpu_fill_info(struct sk_buff *skb, u32 portid, u32 seq, __u16 cpu, const struct ip_conntrack_stat *st) { struct nlmsghdr *nlh; - struct nfgenmsg *nfmsg; unsigned int flags = portid ? NLM_F_MULTI : 0, event; event = nfnl_msg_type(NFNL_SUBSYS_CTNETLINK, IPCTNL_MSG_CT_GET_STATS_CPU); - nlh = nlmsg_put(skb, portid, seq, event, sizeof(*nfmsg), flags); - if (nlh == NULL) + nlh = nfnl_msg_put(skb, portid, seq, event, flags, AF_UNSPEC, + NFNETLINK_V0, htons(cpu)); + if (!nlh) goto nlmsg_failure; - nfmsg = nlmsg_data(nlh); - nfmsg->nfgen_family = AF_UNSPEC; - nfmsg->version = NFNETLINK_V0; - nfmsg->res_id = htons(cpu); - if (nla_put_be32(skb, CTA_STATS_FOUND, htonl(st->found)) || nla_put_be32(skb, CTA_STATS_INVALID, htonl(st->invalid)) || nla_put_be32(skb, CTA_STATS_IGNORE, htonl(st->ignore)) || @@ -2254,20 +2239,15 @@ ctnetlink_stat_ct_fill_info(struct sk_buff *skb, u32 portid, u32 seq, u32 type, struct net *net) { struct nlmsghdr *nlh; - struct nfgenmsg *nfmsg; unsigned int flags = portid ? NLM_F_MULTI : 0, event; unsigned int nr_conntracks = atomic_read(&net->ct.count); event = nfnl_msg_type(NFNL_SUBSYS_CTNETLINK, IPCTNL_MSG_CT_GET_STATS); - nlh = nlmsg_put(skb, portid, seq, event, sizeof(*nfmsg), flags); - if (nlh == NULL) + nlh = nfnl_msg_put(skb, portid, seq, event, flags, AF_UNSPEC, + NFNETLINK_V0, 0); + if (!nlh) goto nlmsg_failure; - nfmsg = nlmsg_data(nlh); - nfmsg->nfgen_family = AF_UNSPEC; - nfmsg->version = NFNETLINK_V0; - nfmsg->res_id = 0; - if (nla_put_be32(skb, CTA_STATS_GLOBAL_ENTRIES, htonl(nr_conntracks))) goto nla_put_failure; @@ -2780,19 +2760,14 @@ ctnetlink_exp_fill_info(struct sk_buff *skb, u32 portid, u32 seq, int event, const struct nf_conntrack_expect *exp) { struct nlmsghdr *nlh; - struct nfgenmsg *nfmsg; unsigned int flags = portid ? NLM_F_MULTI : 0; event = nfnl_msg_type(NFNL_SUBSYS_CTNETLINK_EXP, event); - nlh = nlmsg_put(skb, portid, seq, event, sizeof(*nfmsg), flags); - if (nlh == NULL) + nlh = nfnl_msg_put(skb, portid, seq, event, flags, + exp->tuple.src.l3num, NFNETLINK_V0, 0); + if (!nlh) goto nlmsg_failure; - nfmsg = nlmsg_data(nlh); - nfmsg->nfgen_family = exp->tuple.src.l3num; - nfmsg->version = NFNETLINK_V0; - nfmsg->res_id = 0; - if (ctnetlink_exp_dump_expect(skb, exp) < 0) goto nla_put_failure; @@ -2812,7 +2787,6 @@ ctnetlink_expect_event(unsigned int events, struct nf_exp_event *item) struct nf_conntrack_expect *exp = item->exp; struct net *net = nf_ct_exp_net(exp); struct nlmsghdr *nlh; - struct nfgenmsg *nfmsg; struct sk_buff *skb; unsigned int type, group; int flags = 0; @@ -2835,15 +2809,11 @@ ctnetlink_expect_event(unsigned int events, struct nf_exp_event *item) goto errout; type = nfnl_msg_type(NFNL_SUBSYS_CTNETLINK_EXP, type); - nlh = nlmsg_put(skb, item->portid, 0, type, sizeof(*nfmsg), flags); - if (nlh == NULL) + nlh = nfnl_msg_put(skb, item->portid, 0, type, flags, + exp->tuple.src.l3num, NFNETLINK_V0, 0); + if (!nlh) goto nlmsg_failure; - nfmsg = nlmsg_data(nlh); - nfmsg->nfgen_family = exp->tuple.src.l3num; - nfmsg->version = NFNETLINK_V0; - nfmsg->res_id = 0; - if (ctnetlink_exp_dump_expect(skb, exp) < 0) goto nla_put_failure; @@ -3413,20 +3383,15 @@ ctnetlink_exp_stat_fill_info(struct sk_buff *skb, u32 portid, u32 seq, int cpu, const struct ip_conntrack_stat *st) { struct nlmsghdr *nlh; - struct nfgenmsg *nfmsg; unsigned int flags = portid ? NLM_F_MULTI : 0, event; event = nfnl_msg_type(NFNL_SUBSYS_CTNETLINK, IPCTNL_MSG_EXP_GET_STATS_CPU); - nlh = nlmsg_put(skb, portid, seq, event, sizeof(*nfmsg), flags); - if (nlh == NULL) + nlh = nfnl_msg_put(skb, portid, seq, event, flags, AF_UNSPEC, + NFNETLINK_V0, htons(cpu)); + if (!nlh) goto nlmsg_failure; - nfmsg = nlmsg_data(nlh); - nfmsg->nfgen_family = AF_UNSPEC; - nfmsg->version = NFNETLINK_V0; - nfmsg->res_id = htons(cpu); - if (nla_put_be32(skb, CTA_STATS_EXP_NEW, htonl(st->expect_new)) || nla_put_be32(skb, CTA_STATS_EXP_CREATE, htonl(st->expect_create)) || nla_put_be32(skb, CTA_STATS_EXP_DELETE, htonl(st->expect_delete))) diff --git a/net/netfilter/nf_conntrack_sip.c b/net/netfilter/nf_conntrack_sip.c index 046f118dea06b..d16aa43ebd4d6 100644 --- a/net/netfilter/nf_conntrack_sip.c +++ b/net/netfilter/nf_conntrack_sip.c @@ -605,7 +605,7 @@ int ct_sip_parse_numerical_param(const struct nf_conn *ct, const char *dptr, start += strlen(name); *val = simple_strtoul(start, &end, 0); if (start == end) - return 0; + return -1; if (matchoff && matchlen) { *matchoff = start - dptr; *matchlen = end - start; diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c index 2968f21915ddf..115bc79ec9055 100644 --- a/net/netfilter/nf_tables_api.c +++ b/net/netfilter/nf_tables_api.c @@ -22,10 +22,13 @@ #include #include #include +#include #include #define NFT_MODULE_AUTOLOAD_LIMIT (MODULE_NAME_LEN - sizeof("nft-expr-255-")) +unsigned int nf_tables_net_id __read_mostly; + static LIST_HEAD(nf_tables_expressions); static LIST_HEAD(nf_tables_objects); static LIST_HEAD(nf_tables_flowtables); @@ -53,7 +56,9 @@ static const struct rhashtable_params nft_chain_ht_params = { static void nft_validate_state_update(struct net *net, u8 new_validate_state) { - switch (net->nft.validate_state) { + struct nftables_pernet *nft_net = net_generic(net, nf_tables_net_id); + + switch (nft_net->validate_state) { case NFT_VALIDATE_SKIP: WARN_ON_ONCE(new_validate_state == NFT_VALIDATE_DO); break; @@ -64,7 +69,7 @@ static void nft_validate_state_update(struct net *net, u8 new_validate_state) return; } - net->nft.validate_state = new_validate_state; + nft_net->validate_state = new_validate_state; } static void nft_ctx_init(struct nft_ctx *ctx, @@ -97,6 +102,7 @@ static struct nft_trans *nft_trans_alloc_gfp(const struct nft_ctx *ctx, return NULL; INIT_LIST_HEAD(&trans->list); + INIT_LIST_HEAD(&trans->binding_list); trans->msg_type = msg_type; trans->ctx = *ctx; @@ -109,34 +115,68 @@ static struct nft_trans *nft_trans_alloc(const struct nft_ctx *ctx, return nft_trans_alloc_gfp(ctx, msg_type, size, GFP_KERNEL); } -static void nft_trans_destroy(struct nft_trans *trans) +static void nft_trans_list_del(struct nft_trans *trans) { list_del(&trans->list); + list_del(&trans->binding_list); +} + +static void nft_trans_destroy(struct nft_trans *trans) +{ + nft_trans_list_del(trans); kfree(trans); } -static void nft_set_trans_bind(const struct nft_ctx *ctx, struct nft_set *set) +static void __nft_set_trans_bind(const struct nft_ctx *ctx, struct nft_set *set, + bool bind) { + struct nftables_pernet *nft_net; struct net *net = ctx->net; struct nft_trans *trans; if (!nft_set_is_anonymous(set)) return; - list_for_each_entry_reverse(trans, &net->nft.commit_list, list) { + nft_net = net_generic(net, nf_tables_net_id); + list_for_each_entry_reverse(trans, &nft_net->commit_list, list) { switch (trans->msg_type) { case NFT_MSG_NEWSET: if (nft_trans_set(trans) == set) - nft_trans_set_bound(trans) = true; + nft_trans_set_bound(trans) = bind; break; case NFT_MSG_NEWSETELEM: if (nft_trans_elem_set(trans) == set) - nft_trans_elem_set_bound(trans) = true; + nft_trans_elem_set_bound(trans) = bind; break; } } } +static void nft_set_trans_bind(const struct nft_ctx *ctx, struct nft_set *set) +{ + return __nft_set_trans_bind(ctx, set, true); +} + +static void nft_set_trans_unbind(const struct nft_ctx *ctx, struct nft_set *set) +{ + return __nft_set_trans_bind(ctx, set, false); +} + +static void nft_trans_commit_list_add_tail(struct net *net, struct nft_trans *trans) +{ + struct nftables_pernet *nft_net; + + nft_net = net_generic(net, nf_tables_net_id); + switch (trans->msg_type) { + case NFT_MSG_NEWSET: + if (nft_set_is_anonymous(nft_trans_set(trans))) + list_add_tail(&trans->binding_list, &nft_net->binding_list); + break; + } + + list_add_tail(&trans->list, &nft_net->commit_list); +} + static int nf_tables_register_hook(struct net *net, const struct nft_table *table, struct nft_chain *chain) @@ -187,7 +227,7 @@ static int nft_trans_table_add(struct nft_ctx *ctx, int msg_type) if (msg_type == NFT_MSG_NEWTABLE) nft_activate_next(ctx->net, ctx->table); - list_add_tail(&trans->list, &ctx->net->nft.commit_list); + nft_trans_commit_list_add_tail(ctx->net, trans); return 0; } @@ -214,7 +254,7 @@ static int nft_trans_chain_add(struct nft_ctx *ctx, int msg_type) if (msg_type == NFT_MSG_NEWCHAIN) nft_activate_next(ctx->net, ctx->chain); - list_add_tail(&trans->list, &ctx->net->nft.commit_list); + nft_trans_commit_list_add_tail(ctx->net, trans); return 0; } @@ -287,7 +327,7 @@ static struct nft_trans *nft_trans_rule_add(struct nft_ctx *ctx, int msg_type, ntohl(nla_get_be32(ctx->nla[NFTA_RULE_ID])); } nft_trans_rule(trans) = rule; - list_add_tail(&trans->list, &ctx->net->nft.commit_list); + nft_trans_commit_list_add_tail(ctx->net, trans); return trans; } @@ -342,7 +382,7 @@ static int nft_trans_set_add(const struct nft_ctx *ctx, int msg_type, nft_activate_next(ctx->net, set); } nft_trans_set(trans) = set; - list_add_tail(&trans->list, &ctx->net->nft.commit_list); + nft_trans_commit_list_add_tail(ctx->net, trans); return 0; } @@ -374,7 +414,7 @@ static int nft_trans_obj_add(struct nft_ctx *ctx, int msg_type, nft_activate_next(ctx->net, obj); nft_trans_obj(trans) = obj; - list_add_tail(&trans->list, &ctx->net->nft.commit_list); + nft_trans_commit_list_add_tail(ctx->net, trans); return 0; } @@ -407,7 +447,7 @@ static int nft_trans_flowtable_add(struct nft_ctx *ctx, int msg_type, nft_activate_next(ctx->net, flowtable); nft_trans_flowtable(trans) = flowtable; - list_add_tail(&trans->list, &ctx->net->nft.commit_list); + nft_trans_commit_list_add_tail(ctx->net, trans); return 0; } @@ -435,12 +475,14 @@ static struct nft_table *nft_table_lookup(const struct net *net, const struct nlattr *nla, u8 family, u8 genmask) { + struct nftables_pernet *nft_net; struct nft_table *table; if (nla == NULL) return ERR_PTR(-EINVAL); - list_for_each_entry_rcu(table, &net->nft.tables, list) { + nft_net = net_generic(net, nf_tables_net_id); + list_for_each_entry_rcu(table, &nft_net->tables, list) { if (!nla_strcmp(nla, table->name) && table->family == family && nft_active_genmask(table, genmask)) @@ -454,9 +496,11 @@ static struct nft_table *nft_table_lookup_byhandle(const struct net *net, const struct nlattr *nla, u8 genmask) { + struct nftables_pernet *nft_net; struct nft_table *table; - list_for_each_entry(table, &net->nft.tables, list) { + nft_net = net_generic(net, nf_tables_net_id); + list_for_each_entry(table, &nft_net->tables, list) { if (be64_to_cpu(nla_get_be64(nla)) == table->handle && nft_active_genmask(table, genmask)) return table; @@ -509,11 +553,13 @@ __nf_tables_chain_type_lookup(const struct nlattr *nla, u8 family) static void nft_request_module(struct net *net, const char *fmt, ...) { char module_name[MODULE_NAME_LEN]; + struct nftables_pernet *nft_net; LIST_HEAD(commit_list); va_list args; int ret; - list_splice_init(&net->nft.commit_list, &commit_list); + nft_net = net_generic(net, nf_tables_net_id); + list_splice_init(&nft_net->commit_list, &commit_list); va_start(args, fmt); ret = vsnprintf(module_name, MODULE_NAME_LEN, fmt, args); @@ -521,12 +567,12 @@ static void nft_request_module(struct net *net, const char *fmt, ...) if (ret >= MODULE_NAME_LEN) return; - mutex_unlock(&net->nft.commit_mutex); + mutex_unlock(&nft_net->commit_mutex); request_module("%s", module_name); - mutex_lock(&net->nft.commit_mutex); + mutex_lock(&nft_net->commit_mutex); - WARN_ON_ONCE(!list_empty(&net->nft.commit_list)); - list_splice(&commit_list, &net->nft.commit_list); + WARN_ON_ONCE(!list_empty(&nft_net->commit_list)); + list_splice(&commit_list, &nft_net->commit_list); } #endif @@ -561,6 +607,13 @@ nf_tables_chain_type_lookup(struct net *net, const struct nlattr *nla, return ERR_PTR(-ENOENT); } +static __be16 nft_base_seq(const struct net *net) +{ + struct nftables_pernet *nft_net = net_generic(net, nf_tables_net_id); + + return htons(nft_net->base_seq & 0xffff); +} + static const struct nla_policy nft_table_policy[NFTA_TABLE_MAX + 1] = { [NFTA_TABLE_NAME] = { .type = NLA_STRING, .len = NFT_TABLE_MAXNAMELEN - 1 }, @@ -573,18 +626,13 @@ static int nf_tables_fill_table_info(struct sk_buff *skb, struct net *net, int family, const struct nft_table *table) { struct nlmsghdr *nlh; - struct nfgenmsg *nfmsg; event = nfnl_msg_type(NFNL_SUBSYS_NFTABLES, event); - nlh = nlmsg_put(skb, portid, seq, event, sizeof(struct nfgenmsg), flags); - if (nlh == NULL) + nlh = nfnl_msg_put(skb, portid, seq, event, flags, family, + NFNETLINK_V0, nft_base_seq(net)); + if (!nlh) goto nla_put_failure; - nfmsg = nlmsg_data(nlh); - nfmsg->nfgen_family = family; - nfmsg->version = NFNETLINK_V0; - nfmsg->res_id = htons(net->nft.base_seq & 0xffff); - if (nla_put_string(skb, NFTA_TABLE_NAME, table->name) || nla_put_be32(skb, NFTA_TABLE_FLAGS, htonl(table->flags)) || nla_put_be32(skb, NFTA_TABLE_USE, htonl(table->use)) || @@ -631,15 +679,17 @@ static int nf_tables_dump_tables(struct sk_buff *skb, struct netlink_callback *cb) { const struct nfgenmsg *nfmsg = nlmsg_data(cb->nlh); + struct nftables_pernet *nft_net; const struct nft_table *table; unsigned int idx = 0, s_idx = cb->args[0]; struct net *net = sock_net(skb->sk); int family = nfmsg->nfgen_family; rcu_read_lock(); - cb->seq = net->nft.base_seq; + nft_net = net_generic(net, nf_tables_net_id); + cb->seq = nft_net->base_seq; - list_for_each_entry_rcu(table, &net->nft.tables, list) { + list_for_each_entry_rcu(table, &nft_net->tables, list) { if (family != NFPROTO_UNSPEC && family != table->family) continue; @@ -743,7 +793,7 @@ static void nft_table_disable(struct net *net, struct nft_table *table, u32 cnt) if (cnt && i++ == cnt) break; - nf_unregister_net_hook(net, &nft_base_chain(chain)->ops); + nf_tables_unregister_hook(net, table, chain); } } @@ -758,7 +808,7 @@ static int nf_tables_table_enable(struct net *net, struct nft_table *table) if (!nft_is_base_chain(chain)) continue; - err = nf_register_net_hook(net, &nft_base_chain(chain)->ops); + err = nf_tables_register_hook(net, table, chain); if (err < 0) goto err; @@ -802,17 +852,18 @@ static int nf_tables_updtable(struct nft_ctx *ctx) nft_trans_table_enable(trans) = false; } else if (!(flags & NFT_TABLE_F_DORMANT) && ctx->table->flags & NFT_TABLE_F_DORMANT) { + ctx->table->flags &= ~NFT_TABLE_F_DORMANT; ret = nf_tables_table_enable(ctx->net, ctx->table); - if (ret >= 0) { - ctx->table->flags &= ~NFT_TABLE_F_DORMANT; + if (ret >= 0) nft_trans_table_enable(trans) = true; - } + else + ctx->table->flags |= NFT_TABLE_F_DORMANT; } if (ret < 0) goto err; nft_trans_table_update(trans) = true; - list_add_tail(&trans->list, &ctx->net->nft.commit_list); + nft_trans_commit_list_add_tail(ctx->net, trans); return 0; err: nft_trans_destroy(trans); @@ -847,6 +898,7 @@ static int nf_tables_newtable(struct net *net, struct sock *nlsk, const struct nlattr * const nla[], struct netlink_ext_ack *extack) { + struct nftables_pernet *nft_net = net_generic(net, nf_tables_net_id); const struct nfgenmsg *nfmsg = nlmsg_data(nlh); u8 genmask = nft_genmask_next(net); int family = nfmsg->nfgen_family; @@ -856,7 +908,7 @@ static int nf_tables_newtable(struct net *net, struct sock *nlsk, struct nft_ctx ctx; int err; - lockdep_assert_held(&net->nft.commit_mutex); + lockdep_assert_held(&nft_net->commit_mutex); attr = nla[NFTA_TABLE_NAME]; table = nft_table_lookup(net, attr, family, genmask); if (IS_ERR(table)) { @@ -906,7 +958,7 @@ static int nf_tables_newtable(struct net *net, struct sock *nlsk, if (err < 0) goto err_trans; - list_add_tail_rcu(&table->list, &net->nft.tables); + list_add_tail_rcu(&table->list, &nft_net->tables); return 0; err_trans: rhltable_destroy(&table->chains_ht); @@ -986,11 +1038,12 @@ out: static int nft_flush(struct nft_ctx *ctx, int family) { + struct nftables_pernet *nft_net = net_generic(ctx->net, nf_tables_net_id); struct nft_table *table, *nt; const struct nlattr * const *nla = ctx->nla; int err = 0; - list_for_each_entry_safe(table, nt, &ctx->net->nft.tables, list) { + list_for_each_entry_safe(table, nt, &nft_net->tables, list) { if (family != AF_UNSPEC && table->family != family) continue; @@ -1104,7 +1157,9 @@ nft_chain_lookup_byhandle(const struct nft_table *table, u64 handle, u8 genmask) static bool lockdep_commit_lock_is_held(struct net *net) { #ifdef CONFIG_PROVE_LOCKING - return lockdep_is_held(&net->nft.commit_mutex); + struct nftables_pernet *nft_net = net_generic(net, nf_tables_net_id); + + return lockdep_is_held(&nft_net->commit_mutex); #else return true; #endif @@ -1207,18 +1262,13 @@ static int nf_tables_fill_chain_info(struct sk_buff *skb, struct net *net, const struct nft_chain *chain) { struct nlmsghdr *nlh; - struct nfgenmsg *nfmsg; event = nfnl_msg_type(NFNL_SUBSYS_NFTABLES, event); - nlh = nlmsg_put(skb, portid, seq, event, sizeof(struct nfgenmsg), flags); - if (nlh == NULL) + nlh = nfnl_msg_put(skb, portid, seq, event, flags, family, + NFNETLINK_V0, nft_base_seq(net)); + if (!nlh) goto nla_put_failure; - nfmsg = nlmsg_data(nlh); - nfmsg->nfgen_family = family; - nfmsg->version = NFNETLINK_V0; - nfmsg->res_id = htons(net->nft.base_seq & 0xffff); - if (nla_put_string(skb, NFTA_CHAIN_TABLE, table->name)) goto nla_put_failure; if (nla_put_be64(skb, NFTA_CHAIN_HANDLE, cpu_to_be64(chain->handle), @@ -1306,11 +1356,13 @@ static int nf_tables_dump_chains(struct sk_buff *skb, unsigned int idx = 0, s_idx = cb->args[0]; struct net *net = sock_net(skb->sk); int family = nfmsg->nfgen_family; + struct nftables_pernet *nft_net; rcu_read_lock(); - cb->seq = net->nft.base_seq; + nft_net = net_generic(net, nf_tables_net_id); + cb->seq = nft_net->base_seq; - list_for_each_entry_rcu(table, &net->nft.tables, list) { + list_for_each_entry_rcu(table, &nft_net->tables, list) { if (family != NFPROTO_UNSPEC && family != table->family) continue; @@ -1503,12 +1555,13 @@ static int nft_chain_parse_hook(struct net *net, struct nft_chain_hook *hook, u8 family, bool autoload) { + struct nftables_pernet *nft_net = net_generic(net, nf_tables_net_id); struct nlattr *ha[NFTA_HOOK_MAX + 1]; const struct nft_chain_type *type; struct net_device *dev; int err; - lockdep_assert_held(&net->nft.commit_mutex); + lockdep_assert_held(&nft_net->commit_mutex); lockdep_nfnl_nft_mutex_not_held(); err = nla_parse_nested(ha, NFTA_HOOK_MAX, nla[NFTA_CHAIN_HOOK], @@ -1777,6 +1830,7 @@ static int nf_tables_updchain(struct nft_ctx *ctx, u8 genmask, u8 policy) if (nla[NFTA_CHAIN_HANDLE] && nla[NFTA_CHAIN_NAME]) { + struct nftables_pernet *nft_net = net_generic(ctx->net, nf_tables_net_id); struct nft_trans *tmp; char *name; @@ -1786,7 +1840,7 @@ static int nf_tables_updchain(struct nft_ctx *ctx, u8 genmask, u8 policy) goto err; err = -EEXIST; - list_for_each_entry(tmp, &ctx->net->nft.commit_list, list) { + list_for_each_entry(tmp, &nft_net->commit_list, list) { if (tmp->msg_type == NFT_MSG_NEWCHAIN && tmp->ctx.table == table && nft_trans_chain_update(tmp) && @@ -1799,7 +1853,7 @@ static int nf_tables_updchain(struct nft_ctx *ctx, u8 genmask, u8 policy) nft_trans_chain_name(trans) = name; } - list_add_tail(&trans->list, &ctx->net->nft.commit_list); + nft_trans_commit_list_add_tail(ctx->net, trans); return 0; err: @@ -1813,6 +1867,7 @@ static int nf_tables_newchain(struct net *net, struct sock *nlsk, const struct nlattr * const nla[], struct netlink_ext_ack *extack) { + struct nftables_pernet *nft_net = net_generic(net, nf_tables_net_id); const struct nfgenmsg *nfmsg = nlmsg_data(nlh); u8 genmask = nft_genmask_next(net); int family = nfmsg->nfgen_family; @@ -1823,7 +1878,7 @@ static int nf_tables_newchain(struct net *net, struct sock *nlsk, struct nft_ctx ctx; u64 handle = 0; - lockdep_assert_held(&net->nft.commit_mutex); + lockdep_assert_held(&nft_net->commit_mutex); table = nft_table_lookup(net, nla[NFTA_CHAIN_TABLE], family, genmask); if (IS_ERR(table)) { @@ -2251,21 +2306,16 @@ static int nf_tables_fill_rule_info(struct sk_buff *skb, struct net *net, const struct nft_rule *rule) { struct nlmsghdr *nlh; - struct nfgenmsg *nfmsg; const struct nft_expr *expr, *next; struct nlattr *list; const struct nft_rule *prule; u16 type = nfnl_msg_type(NFNL_SUBSYS_NFTABLES, event); - nlh = nlmsg_put(skb, portid, seq, type, sizeof(struct nfgenmsg), flags); - if (nlh == NULL) + nlh = nfnl_msg_put(skb, portid, seq, type, flags, family, NFNETLINK_V0, + nft_base_seq(net)); + if (!nlh) goto nla_put_failure; - nfmsg = nlmsg_data(nlh); - nfmsg->nfgen_family = family; - nfmsg->version = NFNETLINK_V0; - nfmsg->res_id = htons(net->nft.base_seq & 0xffff); - if (nla_put_string(skb, NFTA_RULE_TABLE, table->name)) goto nla_put_failure; if (nla_put_string(skb, NFTA_RULE_CHAIN, chain->name)) @@ -2351,11 +2401,13 @@ static int nf_tables_dump_rules(struct sk_buff *skb, unsigned int idx = 0, s_idx = cb->args[0]; struct net *net = sock_net(skb->sk); int family = nfmsg->nfgen_family; + struct nftables_pernet *nft_net; rcu_read_lock(); - cb->seq = net->nft.base_seq; + nft_net = net_generic(net, nf_tables_net_id); + cb->seq = nft_net->base_seq; - list_for_each_entry_rcu(table, &net->nft.tables, list) { + list_for_each_entry_rcu(table, &nft_net->tables, list) { if (family != NFPROTO_UNSPEC && family != table->family) continue; @@ -2508,7 +2560,6 @@ static void nf_tables_rule_destroy(const struct nft_ctx *ctx, { struct nft_expr *expr, *next; - lockdep_assert_held(&ctx->net->nft.commit_mutex); /* * Careful: some expressions might not be initialized in case this * is called on error from nf_tables_newrule(). @@ -2574,6 +2625,8 @@ static int nft_table_validate(struct net *net, const struct nft_table *table) err = nft_chain_validate(&ctx, chain); if (err < 0) return err; + + cond_resched(); } return 0; @@ -2586,6 +2639,7 @@ static int nf_tables_newrule(struct net *net, struct sock *nlsk, const struct nlattr * const nla[], struct netlink_ext_ack *extack) { + struct nftables_pernet *nft_net = net_generic(net, nf_tables_net_id); const struct nfgenmsg *nfmsg = nlmsg_data(nlh); u8 genmask = nft_genmask_next(net); struct nft_expr_info *info = NULL; @@ -2602,7 +2656,7 @@ static int nf_tables_newrule(struct net *net, struct sock *nlsk, int err, rem; u64 handle, pos_handle; - lockdep_assert_held(&net->nft.commit_mutex); + lockdep_assert_held(&nft_net->commit_mutex); table = nft_table_lookup(net, nla[NFTA_RULE_TABLE], family, genmask); if (IS_ERR(table)) { @@ -2750,12 +2804,13 @@ static int nf_tables_newrule(struct net *net, struct sock *nlsk, kvfree(info); chain->use++; - if (net->nft.validate_state == NFT_VALIDATE_DO) + if (nft_net->validate_state == NFT_VALIDATE_DO) return nft_table_validate(net, table); return 0; err2: - nf_tables_rule_release(&ctx, rule); + nft_rule_expr_deactivate(&ctx, rule, NFT_TRANS_PREPARE_ERROR); + nf_tables_rule_destroy(&ctx, rule); err1: for (i = 0; i < n; i++) { if (info[i].ops) { @@ -2772,10 +2827,11 @@ static struct nft_rule *nft_rule_lookup_byid(const struct net *net, const struct nft_chain *chain, const struct nlattr *nla) { + struct nftables_pernet *nft_net = net_generic(net, nf_tables_net_id); u32 id = ntohl(nla_get_be32(nla)); struct nft_trans *trans; - list_for_each_entry(trans, &net->nft.commit_list, list) { + list_for_each_entry(trans, &nft_net->commit_list, list) { struct nft_rule *rule = nft_trans_rule(trans); if (trans->msg_type == NFT_MSG_NEWRULE && @@ -2894,12 +2950,13 @@ nft_select_set_ops(const struct nft_ctx *ctx, const struct nft_set_desc *desc, enum nft_set_policies policy) { + struct nftables_pernet *nft_net = net_generic(ctx->net, nf_tables_net_id); const struct nft_set_ops *ops, *bops; struct nft_set_estimate est, best; const struct nft_set_type *type; u32 flags = 0; - lockdep_assert_held(&ctx->net->nft.commit_mutex); + lockdep_assert_held(&nft_net->commit_mutex); lockdep_nfnl_nft_mutex_not_held(); #ifdef CONFIG_MODULES if (list_empty(&nf_tables_set_types)) { @@ -3045,10 +3102,11 @@ static struct nft_set *nft_set_lookup_byid(const struct net *net, const struct nft_table *table, const struct nlattr *nla, u8 genmask) { + struct nftables_pernet *nft_net = net_generic(net, nf_tables_net_id); struct nft_trans *trans; u32 id = ntohl(nla_get_be32(nla)); - list_for_each_entry(trans, &net->nft.commit_list, list) { + list_for_each_entry(trans, &nft_net->commit_list, list) { if (trans->msg_type == NFT_MSG_NEWSET) { struct nft_set *set = nft_trans_set(trans); @@ -3158,23 +3216,17 @@ static __be64 nf_jiffies64_to_msecs(u64 input) static int nf_tables_fill_set(struct sk_buff *skb, const struct nft_ctx *ctx, const struct nft_set *set, u16 event, u16 flags) { - struct nfgenmsg *nfmsg; struct nlmsghdr *nlh; struct nlattr *desc; u32 portid = ctx->portid; u32 seq = ctx->seq; event = nfnl_msg_type(NFNL_SUBSYS_NFTABLES, event); - nlh = nlmsg_put(skb, portid, seq, event, sizeof(struct nfgenmsg), - flags); - if (nlh == NULL) + nlh = nfnl_msg_put(skb, portid, seq, event, flags, ctx->family, + NFNETLINK_V0, nft_base_seq(ctx->net)); + if (!nlh) goto nla_put_failure; - nfmsg = nlmsg_data(nlh); - nfmsg->nfgen_family = ctx->family; - nfmsg->version = NFNETLINK_V0; - nfmsg->res_id = htons(ctx->net->nft.base_seq & 0xffff); - if (nla_put_string(skb, NFTA_SET_TABLE, ctx->table->name)) goto nla_put_failure; if (nla_put_string(skb, NFTA_SET_NAME, set->name)) @@ -3270,14 +3322,16 @@ static int nf_tables_dump_sets(struct sk_buff *skb, struct netlink_callback *cb) struct nft_table *table, *cur_table = (struct nft_table *)cb->args[2]; struct net *net = sock_net(skb->sk); struct nft_ctx *ctx = cb->data, ctx_set; + struct nftables_pernet *nft_net; if (cb->args[1]) return skb->len; rcu_read_lock(); - cb->seq = net->nft.base_seq; + nft_net = net_generic(net, nf_tables_net_id); + cb->seq = nft_net->base_seq; - list_for_each_entry_rcu(table, &net->nft.tables, list) { + list_for_each_entry_rcu(table, &nft_net->tables, list) { if (ctx->family != NFPROTO_UNSPEC && ctx->family != table->family) continue; @@ -3780,6 +3834,15 @@ void nf_tables_deactivate_set(const struct nft_ctx *ctx, struct nft_set *set, enum nft_trans_phase phase) { switch (phase) { + case NFT_TRANS_PREPARE_ERROR: + nft_set_trans_unbind(ctx, set); + if (nft_set_is_anonymous(set)) + nft_deactivate_next(ctx->net, set); + else + list_del_rcu(&binding->list); + + set->use--; + break; case NFT_TRANS_PREPARE: if (nft_set_is_anonymous(set)) nft_deactivate_next(ctx->net, set); @@ -3984,18 +4047,19 @@ static int nf_tables_dump_set(struct sk_buff *skb, struct netlink_callback *cb) { struct nft_set_dump_ctx *dump_ctx = cb->data; struct net *net = sock_net(skb->sk); + struct nftables_pernet *nft_net; struct nft_table *table; struct nft_set *set; struct nft_set_dump_args args; bool set_found = false; - struct nfgenmsg *nfmsg; struct nlmsghdr *nlh; struct nlattr *nest; u32 portid, seq; int event; rcu_read_lock(); - list_for_each_entry_rcu(table, &net->nft.tables, list) { + nft_net = net_generic(net, nf_tables_net_id); + list_for_each_entry_rcu(table, &nft_net->tables, list) { if (dump_ctx->ctx.family != NFPROTO_UNSPEC && dump_ctx->ctx.family != table->family) continue; @@ -4021,16 +4085,11 @@ static int nf_tables_dump_set(struct sk_buff *skb, struct netlink_callback *cb) portid = NETLINK_CB(cb->skb).portid; seq = cb->nlh->nlmsg_seq; - nlh = nlmsg_put(skb, portid, seq, event, sizeof(struct nfgenmsg), - NLM_F_MULTI); - if (nlh == NULL) + nlh = nfnl_msg_put(skb, portid, seq, event, NLM_F_MULTI, + table->family, NFNETLINK_V0, nft_base_seq(net)); + if (!nlh) goto nla_put_failure; - nfmsg = nlmsg_data(nlh); - nfmsg->nfgen_family = table->family; - nfmsg->version = NFNETLINK_V0; - nfmsg->res_id = htons(net->nft.base_seq & 0xffff); - if (nla_put_string(skb, NFTA_SET_ELEM_LIST_TABLE, table->name)) goto nla_put_failure; if (nla_put_string(skb, NFTA_SET_ELEM_LIST_SET, set->name)) @@ -4087,22 +4146,16 @@ static int nf_tables_fill_setelem_info(struct sk_buff *skb, const struct nft_set *set, const struct nft_set_elem *elem) { - struct nfgenmsg *nfmsg; struct nlmsghdr *nlh; struct nlattr *nest; int err; event = nfnl_msg_type(NFNL_SUBSYS_NFTABLES, event); - nlh = nlmsg_put(skb, portid, seq, event, sizeof(struct nfgenmsg), - flags); - if (nlh == NULL) + nlh = nfnl_msg_put(skb, portid, seq, event, flags, ctx->family, + NFNETLINK_V0, nft_base_seq(ctx->net)); + if (!nlh) goto nla_put_failure; - nfmsg = nlmsg_data(nlh); - nfmsg->nfgen_family = ctx->family; - nfmsg->version = NFNETLINK_V0; - nfmsg->res_id = htons(ctx->net->nft.base_seq & 0xffff); - if (nla_put_string(skb, NFTA_SET_TABLE, ctx->table->name)) goto nla_put_failure; if (nla_put_string(skb, NFTA_SET_NAME, set->name)) @@ -4596,7 +4649,7 @@ static int nft_add_set_elem(struct nft_ctx *ctx, struct nft_set *set, } nft_trans_elem(trans) = elem; - list_add_tail(&trans->list, &ctx->net->nft.commit_list); + nft_trans_commit_list_add_tail(ctx->net, trans); return 0; err6: @@ -4621,6 +4674,7 @@ static int nf_tables_newsetelem(struct net *net, struct sock *nlsk, const struct nlattr * const nla[], struct netlink_ext_ack *extack) { + struct nftables_pernet *nft_net = net_generic(net, nf_tables_net_id); u8 genmask = nft_genmask_next(net); const struct nlattr *attr; struct nft_set *set; @@ -4650,7 +4704,7 @@ static int nf_tables_newsetelem(struct net *net, struct sock *nlsk, return err; } - if (net->nft.validate_state == NFT_VALIDATE_DO) + if (nft_net->validate_state == NFT_VALIDATE_DO) return nft_table_validate(net, ctx.table); return 0; @@ -4763,7 +4817,7 @@ static int nft_del_setelem(struct nft_ctx *ctx, struct nft_set *set, nft_set_elem_deactivate(ctx->net, set, &elem); nft_trans_elem(trans) = elem; - list_add_tail(&trans->list, &ctx->net->nft.commit_list); + nft_trans_commit_list_add_tail(ctx->net, trans); return 0; fail_ops: @@ -4797,7 +4851,7 @@ static int nft_flush_set(const struct nft_ctx *ctx, nft_set_elem_deactivate(ctx->net, set, elem); nft_trans_elem_set(trans) = set; nft_trans_elem(trans) = *elem; - list_add_tail(&trans->list, &ctx->net->nft.commit_list); + nft_trans_commit_list_add_tail(ctx->net, trans); return 0; err1: @@ -5138,19 +5192,14 @@ static int nf_tables_fill_obj_info(struct sk_buff *skb, struct net *net, int family, const struct nft_table *table, struct nft_object *obj, bool reset) { - struct nfgenmsg *nfmsg; struct nlmsghdr *nlh; event = nfnl_msg_type(NFNL_SUBSYS_NFTABLES, event); - nlh = nlmsg_put(skb, portid, seq, event, sizeof(struct nfgenmsg), flags); - if (nlh == NULL) + nlh = nfnl_msg_put(skb, portid, seq, event, flags, family, + NFNETLINK_V0, nft_base_seq(net)); + if (!nlh) goto nla_put_failure; - nfmsg = nlmsg_data(nlh); - nfmsg->nfgen_family = family; - nfmsg->version = NFNETLINK_V0; - nfmsg->res_id = htons(net->nft.base_seq & 0xffff); - if (nla_put_string(skb, NFTA_OBJ_TABLE, table->name) || nla_put_string(skb, NFTA_OBJ_NAME, obj->name) || nla_put_be32(skb, NFTA_OBJ_TYPE, htonl(obj->ops->type->type)) || @@ -5181,6 +5230,7 @@ static int nf_tables_dump_obj(struct sk_buff *skb, struct netlink_callback *cb) struct nft_obj_filter *filter = cb->data; struct net *net = sock_net(skb->sk); int family = nfmsg->nfgen_family; + struct nftables_pernet *nft_net; struct nft_object *obj; bool reset = false; @@ -5188,9 +5238,10 @@ static int nf_tables_dump_obj(struct sk_buff *skb, struct netlink_callback *cb) reset = true; rcu_read_lock(); - cb->seq = net->nft.base_seq; + nft_net = net_generic(net, nf_tables_net_id); + cb->seq = nft_net->base_seq; - list_for_each_entry_rcu(table, &net->nft.tables, list) { + list_for_each_entry_rcu(table, &nft_net->tables, list) { if (family != NFPROTO_UNSPEC && family != table->family) continue; @@ -5798,20 +5849,15 @@ static int nf_tables_fill_flowtable_info(struct sk_buff *skb, struct net *net, struct nft_flowtable *flowtable) { struct nlattr *nest, *nest_devs; - struct nfgenmsg *nfmsg; struct nlmsghdr *nlh; int i; event = nfnl_msg_type(NFNL_SUBSYS_NFTABLES, event); - nlh = nlmsg_put(skb, portid, seq, event, sizeof(struct nfgenmsg), flags); - if (nlh == NULL) + nlh = nfnl_msg_put(skb, portid, seq, event, flags, family, + NFNETLINK_V0, nft_base_seq(net)); + if (!nlh) goto nla_put_failure; - nfmsg = nlmsg_data(nlh); - nfmsg->nfgen_family = family; - nfmsg->version = NFNETLINK_V0; - nfmsg->res_id = htons(net->nft.base_seq & 0xffff); - if (nla_put_string(skb, NFTA_FLOWTABLE_TABLE, flowtable->table->name) || nla_put_string(skb, NFTA_FLOWTABLE_NAME, flowtable->name) || nla_put_be32(skb, NFTA_FLOWTABLE_USE, htonl(flowtable->use)) || @@ -5861,12 +5907,14 @@ static int nf_tables_dump_flowtable(struct sk_buff *skb, struct net *net = sock_net(skb->sk); int family = nfmsg->nfgen_family; struct nft_flowtable *flowtable; + struct nftables_pernet *nft_net; const struct nft_table *table; rcu_read_lock(); - cb->seq = net->nft.base_seq; + nft_net = net_generic(net, nf_tables_net_id); + cb->seq = nft_net->base_seq; - list_for_each_entry_rcu(table, &net->nft.tables, list) { + list_for_each_entry_rcu(table, &nft_net->tables, list) { if (family != NFPROTO_UNSPEC && family != table->family) continue; @@ -6036,21 +6084,17 @@ static void nf_tables_flowtable_destroy(struct nft_flowtable *flowtable) static int nf_tables_fill_gen_info(struct sk_buff *skb, struct net *net, u32 portid, u32 seq) { + struct nftables_pernet *nft_net = net_generic(net, nf_tables_net_id); struct nlmsghdr *nlh; - struct nfgenmsg *nfmsg; char buf[TASK_COMM_LEN]; int event = nfnl_msg_type(NFNL_SUBSYS_NFTABLES, NFT_MSG_NEWGEN); - nlh = nlmsg_put(skb, portid, seq, event, sizeof(struct nfgenmsg), 0); - if (nlh == NULL) + nlh = nfnl_msg_put(skb, portid, seq, event, 0, AF_UNSPEC, + NFNETLINK_V0, nft_base_seq(net)); + if (!nlh) goto nla_put_failure; - nfmsg = nlmsg_data(nlh); - nfmsg->nfgen_family = AF_UNSPEC; - nfmsg->version = NFNETLINK_V0; - nfmsg->res_id = htons(net->nft.base_seq & 0xffff); - - if (nla_put_be32(skb, NFTA_GEN_ID, htonl(net->nft.base_seq)) || + if (nla_put_be32(skb, NFTA_GEN_ID, htonl(nft_net->base_seq)) || nla_put_be32(skb, NFTA_GEN_PROC_PID, htonl(task_pid_nr(current))) || nla_put_string(skb, NFTA_GEN_PROC_NAME, get_task_comm(buf, current))) goto nla_put_failure; @@ -6083,6 +6127,7 @@ static int nf_tables_flowtable_event(struct notifier_block *this, { struct net_device *dev = netdev_notifier_info_to_dev(ptr); struct nft_flowtable *flowtable; + struct nftables_pernet *nft_net; struct nft_table *table; struct net *net; @@ -6090,13 +6135,14 @@ static int nf_tables_flowtable_event(struct notifier_block *this, return 0; net = dev_net(dev); - mutex_lock(&net->nft.commit_mutex); - list_for_each_entry(table, &net->nft.tables, list) { + nft_net = net_generic(net, nf_tables_net_id); + mutex_lock(&nft_net->commit_mutex); + list_for_each_entry(table, &nft_net->tables, list) { list_for_each_entry(flowtable, &table->flowtables, list) { nft_flowtable_event(event, dev, flowtable); } } - mutex_unlock(&net->nft.commit_mutex); + mutex_unlock(&nft_net->commit_mutex); return NOTIFY_DONE; } @@ -6277,16 +6323,17 @@ static const struct nfnl_callback nf_tables_cb[NFT_MSG_MAX] = { static int nf_tables_validate(struct net *net) { + struct nftables_pernet *nft_net = net_generic(net, nf_tables_net_id); struct nft_table *table; - switch (net->nft.validate_state) { + switch (nft_net->validate_state) { case NFT_VALIDATE_SKIP: break; case NFT_VALIDATE_NEED: nft_validate_state_update(net, NFT_VALIDATE_DO); /* fall through */ case NFT_VALIDATE_DO: - list_for_each_entry(table, &net->nft.tables, list) { + list_for_each_entry(table, &nft_net->tables, list) { if (nft_table_validate(net, table) < 0) return -EAGAIN; } @@ -6363,15 +6410,16 @@ static void nft_commit_release(struct nft_trans *trans) static void nf_tables_commit_release(struct net *net) { + struct nftables_pernet *nft_net = net_generic(net, nf_tables_net_id); struct nft_trans *trans, *next; - if (list_empty(&net->nft.commit_list)) + if (list_empty(&nft_net->commit_list)) return; synchronize_rcu(); - list_for_each_entry_safe(trans, next, &net->nft.commit_list, list) { - list_del(&trans->list); + list_for_each_entry_safe(trans, next, &nft_net->commit_list, list) { + nft_trans_list_del(trans); nft_commit_release(trans); } } @@ -6409,9 +6457,10 @@ static int nf_tables_commit_chain_prepare(struct net *net, struct nft_chain *cha static void nf_tables_commit_chain_prepare_cancel(struct net *net) { + struct nftables_pernet *nft_net = net_generic(net, nf_tables_net_id); struct nft_trans *trans, *next; - list_for_each_entry_safe(trans, next, &net->nft.commit_list, list) { + list_for_each_entry_safe(trans, next, &nft_net->commit_list, list) { struct nft_chain *chain = trans->ctx.chain; if (trans->msg_type == NFT_MSG_NEWRULE || @@ -6503,17 +6552,30 @@ static void nft_chain_del(struct nft_chain *chain) static int nf_tables_commit(struct net *net, struct sk_buff *skb) { + struct nftables_pernet *nft_net = net_generic(net, nf_tables_net_id); struct nft_trans *trans, *next; struct nft_trans_elem *te; struct nft_chain *chain; struct nft_table *table; + list_for_each_entry(trans, &nft_net->binding_list, binding_list) { + switch (trans->msg_type) { + case NFT_MSG_NEWSET: + if (nft_set_is_anonymous(nft_trans_set(trans)) && + !nft_trans_set_bound(trans)) { + pr_warn_once("nftables ruleset with unbound set\n"); + return -EINVAL; + } + break; + } + } + /* 0. Validate ruleset, otherwise roll back for error reporting. */ if (nf_tables_validate(net) < 0) return -EAGAIN; /* 1. Allocate space for next generation rules_gen_X[] */ - list_for_each_entry_safe(trans, next, &net->nft.commit_list, list) { + list_for_each_entry_safe(trans, next, &nft_net->commit_list, list) { int ret; if (trans->msg_type == NFT_MSG_NEWRULE || @@ -6529,7 +6591,7 @@ static int nf_tables_commit(struct net *net, struct sk_buff *skb) } /* step 2. Make rules_gen_X visible to packet path */ - list_for_each_entry(table, &net->nft.tables, list) { + list_for_each_entry(table, &nft_net->tables, list) { list_for_each_entry(chain, &table->chains, list) nf_tables_commit_chain(net, chain); } @@ -6538,12 +6600,13 @@ static int nf_tables_commit(struct net *net, struct sk_buff *skb) * Bump generation counter, invalidate any dump in progress. * Cannot fail after this point. */ - while (++net->nft.base_seq == 0); + while (++nft_net->base_seq == 0) + ; /* step 3. Start new generation, rules_gen_X now in use. */ net->nft.gencursor = nft_gencursor_next(net); - list_for_each_entry_safe(trans, next, &net->nft.commit_list, list) { + list_for_each_entry_safe(trans, next, &nft_net->commit_list, list) { switch (trans->msg_type) { case NFT_MSG_NEWTABLE: if (nft_trans_table_update(trans)) { @@ -6664,7 +6727,7 @@ static int nf_tables_commit(struct net *net, struct sk_buff *skb) nf_tables_commit_release(net); nf_tables_gen_notify(net, skb, NFT_MSG_NEWGEN); - mutex_unlock(&net->nft.commit_mutex); + mutex_unlock(&nft_net->commit_mutex); return 0; } @@ -6700,10 +6763,11 @@ static void nf_tables_abort_release(struct nft_trans *trans) static int __nf_tables_abort(struct net *net) { + struct nftables_pernet *nft_net = net_generic(net, nf_tables_net_id); struct nft_trans *trans, *next; struct nft_trans_elem *te; - list_for_each_entry_safe_reverse(trans, next, &net->nft.commit_list, + list_for_each_entry_safe_reverse(trans, next, &nft_net->commit_list, list) { switch (trans->msg_type) { case NFT_MSG_NEWTABLE: @@ -6810,8 +6874,8 @@ static int __nf_tables_abort(struct net *net) synchronize_rcu(); list_for_each_entry_safe_reverse(trans, next, - &net->nft.commit_list, list) { - list_del(&trans->list); + &nft_net->commit_list, list) { + nft_trans_list_del(trans); nf_tables_abort_release(trans); } @@ -6820,22 +6884,24 @@ static int __nf_tables_abort(struct net *net) static int nf_tables_abort(struct net *net, struct sk_buff *skb) { + struct nftables_pernet *nft_net = net_generic(net, nf_tables_net_id); int ret = __nf_tables_abort(net); - mutex_unlock(&net->nft.commit_mutex); + mutex_unlock(&nft_net->commit_mutex); return ret; } static bool nf_tables_valid_genid(struct net *net, u32 genid) { + struct nftables_pernet *nft_net = net_generic(net, nf_tables_net_id); bool genid_ok; - mutex_lock(&net->nft.commit_mutex); + mutex_lock(&nft_net->commit_mutex); - genid_ok = genid == 0 || net->nft.base_seq == genid; + genid_ok = genid == 0 || nft_net->base_seq == genid; if (!genid_ok) - mutex_unlock(&net->nft.commit_mutex); + mutex_unlock(&nft_net->commit_mutex); /* else, commit mutex has to be released by commit or abort function */ return genid_ok; @@ -7182,6 +7248,9 @@ static int nft_verdict_init(const struct nft_ctx *ctx, struct nft_data *data, if (!tb[NFTA_VERDICT_CODE]) return -EINVAL; + + /* zero padding hole for memcmp */ + memset(data, 0, sizeof(*data)); data->verdict.code = ntohl(nla_get_be32(tb[NFTA_VERDICT_CODE])); switch (data->verdict.code) { @@ -7389,10 +7458,9 @@ int __nft_release_basechain(struct nft_ctx *ctx) } EXPORT_SYMBOL_GPL(__nft_release_basechain); -static void __nft_release_tables(struct net *net) +static void __nft_release_table(struct net *net, struct nft_table *table) { struct nft_flowtable *flowtable, *nf; - struct nft_table *table, *nt; struct nft_chain *chain, *nc; struct nft_object *obj, *ne; struct nft_rule *rule, *nr; @@ -7402,71 +7470,85 @@ static void __nft_release_tables(struct net *net) .family = NFPROTO_NETDEV, }; - list_for_each_entry_safe(table, nt, &net->nft.tables, list) { - ctx.family = table->family; + ctx.family = table->family; - list_for_each_entry(chain, &table->chains, list) - nf_tables_unregister_hook(net, table, chain); - /* No packets are walking on these chains anymore. */ - ctx.table = table; - list_for_each_entry(chain, &table->chains, list) { - ctx.chain = chain; - list_for_each_entry_safe(rule, nr, &chain->rules, list) { - list_del(&rule->list); - chain->use--; - nf_tables_rule_release(&ctx, rule); - } - } - list_for_each_entry_safe(flowtable, nf, &table->flowtables, list) { - list_del(&flowtable->list); - table->use--; - nf_tables_flowtable_destroy(flowtable); - } - list_for_each_entry_safe(set, ns, &table->sets, list) { - list_del(&set->list); - table->use--; - nft_set_destroy(set); - } - list_for_each_entry_safe(obj, ne, &table->objects, list) { - list_del(&obj->list); - table->use--; - nft_obj_destroy(&ctx, obj); - } - list_for_each_entry_safe(chain, nc, &table->chains, list) { - ctx.chain = chain; - nft_chain_del(chain); - table->use--; - nf_tables_chain_destroy(&ctx); + list_for_each_entry(chain, &table->chains, list) + nf_tables_unregister_hook(net, table, chain); + /* No packets are walking on these chains anymore. */ + ctx.table = table; + list_for_each_entry(chain, &table->chains, list) { + ctx.chain = chain; + list_for_each_entry_safe(rule, nr, &chain->rules, list) { + list_del(&rule->list); + chain->use--; + nf_tables_rule_release(&ctx, rule); } - list_del(&table->list); - nf_tables_table_destroy(&ctx); } + list_for_each_entry_safe(flowtable, nf, &table->flowtables, list) { + list_del(&flowtable->list); + table->use--; + nf_tables_flowtable_destroy(flowtable); + } + list_for_each_entry_safe(set, ns, &table->sets, list) { + list_del(&set->list); + table->use--; + nft_set_destroy(set); + } + list_for_each_entry_safe(obj, ne, &table->objects, list) { + list_del(&obj->list); + table->use--; + nft_obj_destroy(&ctx, obj); + } + list_for_each_entry_safe(chain, nc, &table->chains, list) { + ctx.chain = chain; + nft_chain_del(chain); + table->use--; + nf_tables_chain_destroy(&ctx); + } + list_del(&table->list); + nf_tables_table_destroy(&ctx); +} + +static void __nft_release_tables(struct net *net) +{ + struct nftables_pernet *nft_net = net_generic(net, nf_tables_net_id); + struct nft_table *table, *nt; + + list_for_each_entry_safe(table, nt, &nft_net->tables, list) + __nft_release_table(net, table); } static int __net_init nf_tables_init_net(struct net *net) { - INIT_LIST_HEAD(&net->nft.tables); - INIT_LIST_HEAD(&net->nft.commit_list); - mutex_init(&net->nft.commit_mutex); - net->nft.base_seq = 1; - net->nft.validate_state = NFT_VALIDATE_SKIP; + struct nftables_pernet *nft_net = net_generic(net, nf_tables_net_id); + + INIT_LIST_HEAD(&nft_net->tables); + INIT_LIST_HEAD(&nft_net->commit_list); + INIT_LIST_HEAD(&nft_net->binding_list); + mutex_init(&nft_net->commit_mutex); + nft_net->base_seq = 1; + nft_net->validate_state = NFT_VALIDATE_SKIP; return 0; } static void __net_exit nf_tables_exit_net(struct net *net) { - mutex_lock(&net->nft.commit_mutex); - if (!list_empty(&net->nft.commit_list)) + struct nftables_pernet *nft_net = net_generic(net, nf_tables_net_id); + + mutex_lock(&nft_net->commit_mutex); + if (!list_empty(&nft_net->commit_list)) __nf_tables_abort(net); __nft_release_tables(net); - mutex_unlock(&net->nft.commit_mutex); - WARN_ON_ONCE(!list_empty(&net->nft.tables)); + mutex_unlock(&nft_net->commit_mutex); + WARN_ON_ONCE(!list_empty(&nft_net->tables)); } static struct pernet_operations nf_tables_net_ops = { .init = nf_tables_init_net, .exit = nf_tables_exit_net, + .id = &nf_tables_net_id, + .size = sizeof(struct nftables_pernet), }; static int __init nf_tables_module_init(void) diff --git a/net/netfilter/nf_tables_trace.c b/net/netfilter/nf_tables_trace.c index e1dc527a493b8..7a19c517b1918 100644 --- a/net/netfilter/nf_tables_trace.c +++ b/net/netfilter/nf_tables_trace.c @@ -186,7 +186,6 @@ static bool nft_trace_have_verdict_chain(struct nft_traceinfo *info) void nft_trace_notify(struct nft_traceinfo *info) { const struct nft_pktinfo *pkt = info->pkt; - struct nfgenmsg *nfmsg; struct nlmsghdr *nlh; struct sk_buff *skb; unsigned int size; @@ -222,15 +221,11 @@ void nft_trace_notify(struct nft_traceinfo *info) return; event = nfnl_msg_type(NFNL_SUBSYS_NFTABLES, NFT_MSG_TRACE); - nlh = nlmsg_put(skb, 0, 0, event, sizeof(struct nfgenmsg), 0); + nlh = nfnl_msg_put(skb, 0, 0, event, 0, info->basechain->type->family, + NFNETLINK_V0, 0); if (!nlh) goto nla_put_failure; - nfmsg = nlmsg_data(nlh); - nfmsg->nfgen_family = info->basechain->type->family; - nfmsg->version = NFNETLINK_V0; - nfmsg->res_id = 0; - if (nla_put_be32(skb, NFTA_TRACE_NFPROTO, htonl(nft_pf(pkt)))) goto nla_put_failure; diff --git a/net/netfilter/nfnetlink_acct.c b/net/netfilter/nfnetlink_acct.c index 8fa8bf7c48e64..7c5f428dc5c91 100644 --- a/net/netfilter/nfnetlink_acct.c +++ b/net/netfilter/nfnetlink_acct.c @@ -135,21 +135,16 @@ nfnl_acct_fill_info(struct sk_buff *skb, u32 portid, u32 seq, u32 type, int event, struct nf_acct *acct) { struct nlmsghdr *nlh; - struct nfgenmsg *nfmsg; unsigned int flags = portid ? NLM_F_MULTI : 0; u64 pkts, bytes; u32 old_flags; event = nfnl_msg_type(NFNL_SUBSYS_ACCT, event); - nlh = nlmsg_put(skb, portid, seq, event, sizeof(*nfmsg), flags); - if (nlh == NULL) + nlh = nfnl_msg_put(skb, portid, seq, event, flags, AF_UNSPEC, + NFNETLINK_V0, 0); + if (!nlh) goto nlmsg_failure; - nfmsg = nlmsg_data(nlh); - nfmsg->nfgen_family = AF_UNSPEC; - nfmsg->version = NFNETLINK_V0; - nfmsg->res_id = 0; - if (nla_put_string(skb, NFACCT_NAME, acct->name)) goto nla_put_failure; diff --git a/net/netfilter/nfnetlink_cthelper.c b/net/netfilter/nfnetlink_cthelper.c index c8b0f1122c44d..720177721e3c0 100644 --- a/net/netfilter/nfnetlink_cthelper.c +++ b/net/netfilter/nfnetlink_cthelper.c @@ -532,20 +532,15 @@ nfnl_cthelper_fill_info(struct sk_buff *skb, u32 portid, u32 seq, u32 type, int event, struct nf_conntrack_helper *helper) { struct nlmsghdr *nlh; - struct nfgenmsg *nfmsg; unsigned int flags = portid ? NLM_F_MULTI : 0; int status; event = nfnl_msg_type(NFNL_SUBSYS_CTHELPER, event); - nlh = nlmsg_put(skb, portid, seq, event, sizeof(*nfmsg), flags); - if (nlh == NULL) + nlh = nfnl_msg_put(skb, portid, seq, event, flags, AF_UNSPEC, + NFNETLINK_V0, 0); + if (!nlh) goto nlmsg_failure; - nfmsg = nlmsg_data(nlh); - nfmsg->nfgen_family = AF_UNSPEC; - nfmsg->version = NFNETLINK_V0; - nfmsg->res_id = 0; - if (nla_put_string(skb, NFCTH_NAME, helper->name)) goto nla_put_failure; diff --git a/net/netfilter/nfnetlink_cttimeout.c b/net/netfilter/nfnetlink_cttimeout.c index 70a7382b9787c..ae01e9ad55464 100644 --- a/net/netfilter/nfnetlink_cttimeout.c +++ b/net/netfilter/nfnetlink_cttimeout.c @@ -164,20 +164,15 @@ ctnl_timeout_fill_info(struct sk_buff *skb, u32 portid, u32 seq, u32 type, int event, struct ctnl_timeout *timeout) { struct nlmsghdr *nlh; - struct nfgenmsg *nfmsg; unsigned int flags = portid ? NLM_F_MULTI : 0; const struct nf_conntrack_l4proto *l4proto = timeout->timeout.l4proto; event = nfnl_msg_type(NFNL_SUBSYS_CTNETLINK_TIMEOUT, event); - nlh = nlmsg_put(skb, portid, seq, event, sizeof(*nfmsg), flags); - if (nlh == NULL) + nlh = nfnl_msg_put(skb, portid, seq, event, flags, AF_UNSPEC, + NFNETLINK_V0, 0); + if (!nlh) goto nlmsg_failure; - nfmsg = nlmsg_data(nlh); - nfmsg->nfgen_family = AF_UNSPEC; - nfmsg->version = NFNETLINK_V0; - nfmsg->res_id = 0; - if (nla_put_string(skb, CTA_TIMEOUT_NAME, timeout->name) || nla_put_be16(skb, CTA_TIMEOUT_L3PROTO, htons(timeout->timeout.l3num)) || @@ -396,19 +391,14 @@ cttimeout_default_fill_info(struct net *net, struct sk_buff *skb, u32 portid, const unsigned int *timeouts) { struct nlmsghdr *nlh; - struct nfgenmsg *nfmsg; unsigned int flags = portid ? NLM_F_MULTI : 0; event = nfnl_msg_type(NFNL_SUBSYS_CTNETLINK_TIMEOUT, event); - nlh = nlmsg_put(skb, portid, seq, event, sizeof(*nfmsg), flags); - if (nlh == NULL) + nlh = nfnl_msg_put(skb, portid, seq, event, flags, AF_UNSPEC, + NFNETLINK_V0, 0); + if (!nlh) goto nlmsg_failure; - nfmsg = nlmsg_data(nlh); - nfmsg->nfgen_family = AF_UNSPEC; - nfmsg->version = NFNETLINK_V0; - nfmsg->res_id = 0; - if (nla_put_be16(skb, CTA_TIMEOUT_L3PROTO, htons(l4proto->l3proto)) || nla_put_u8(skb, CTA_TIMEOUT_L4PROTO, l4proto->l4proto)) goto nla_put_failure; diff --git a/net/netfilter/nfnetlink_log.c b/net/netfilter/nfnetlink_log.c index 17ca9a681d47b..da05c4d82b944 100644 --- a/net/netfilter/nfnetlink_log.c +++ b/net/netfilter/nfnetlink_log.c @@ -404,20 +404,15 @@ __build_packet_message(struct nfnl_log_net *log, { struct nfulnl_msg_packet_hdr pmsg; struct nlmsghdr *nlh; - struct nfgenmsg *nfmsg; sk_buff_data_t old_tail = inst->skb->tail; struct sock *sk; const unsigned char *hwhdrp; - nlh = nlmsg_put(inst->skb, 0, 0, - nfnl_msg_type(NFNL_SUBSYS_ULOG, NFULNL_MSG_PACKET), - sizeof(struct nfgenmsg), 0); + nlh = nfnl_msg_put(inst->skb, 0, 0, + nfnl_msg_type(NFNL_SUBSYS_ULOG, NFULNL_MSG_PACKET), + 0, pf, NFNETLINK_V0, htons(inst->group_num)); if (!nlh) return -1; - nfmsg = nlmsg_data(nlh); - nfmsg->nfgen_family = pf; - nfmsg->version = NFNETLINK_V0; - nfmsg->res_id = htons(inst->group_num); memset(&pmsg, 0, sizeof(pmsg)); pmsg.hw_protocol = skb->protocol; @@ -637,7 +632,7 @@ nfulnl_log_packet(struct net *net, struct nfnl_log_net *log = nfnl_log_pernet(net); const struct nfnl_ct_hook *nfnl_ct = NULL; struct nf_conn *ct = NULL; - enum ip_conntrack_info uninitialized_var(ctinfo); + enum ip_conntrack_info ctinfo; if (li_user && li_user->type == NF_LOG_TYPE_ULOG) li = li_user; diff --git a/net/netfilter/nfnetlink_queue.c b/net/netfilter/nfnetlink_queue.c index cd496b074a71b..1aacc31a6bf92 100644 --- a/net/netfilter/nfnetlink_queue.c +++ b/net/netfilter/nfnetlink_queue.c @@ -387,12 +387,11 @@ nfqnl_build_packet_message(struct net *net, struct nfqnl_instance *queue, struct nlattr *nla; struct nfqnl_msg_packet_hdr *pmsg; struct nlmsghdr *nlh; - struct nfgenmsg *nfmsg; struct sk_buff *entskb = entry->skb; struct net_device *indev; struct net_device *outdev; struct nf_conn *ct = NULL; - enum ip_conntrack_info uninitialized_var(ctinfo); + enum ip_conntrack_info ctinfo; struct nfnl_ct_hook *nfnl_ct; bool csum_verify; char *secdata = NULL; @@ -473,18 +472,15 @@ nfqnl_build_packet_message(struct net *net, struct nfqnl_instance *queue, goto nlmsg_failure; } - nlh = nlmsg_put(skb, 0, 0, - nfnl_msg_type(NFNL_SUBSYS_QUEUE, NFQNL_MSG_PACKET), - sizeof(struct nfgenmsg), 0); + nlh = nfnl_msg_put(skb, 0, 0, + nfnl_msg_type(NFNL_SUBSYS_QUEUE, NFQNL_MSG_PACKET), + 0, entry->state.pf, NFNETLINK_V0, + htons(queue->queue_num)); if (!nlh) { skb_tx_error(entskb); kfree_skb(skb); goto nlmsg_failure; } - nfmsg = nlmsg_data(nlh); - nfmsg->nfgen_family = entry->state.pf; - nfmsg->version = NFNETLINK_V0; - nfmsg->res_id = htons(queue->queue_num); nla = __nla_reserve(skb, NFQA_PACKET_HDR, sizeof(*pmsg)); pmsg = nla_data(nla); @@ -1191,7 +1187,7 @@ static int nfqnl_recv_verdict(struct net *net, struct sock *ctnl, struct nfqnl_instance *queue; unsigned int verdict; struct nf_queue_entry *entry; - enum ip_conntrack_info uninitialized_var(ctinfo); + enum ip_conntrack_info ctinfo; struct nfnl_ct_hook *nfnl_ct; struct nf_conn *ct = NULL; struct nfnl_queue_net *q = nfnl_queue_pernet(net); diff --git a/net/netfilter/nft_byteorder.c b/net/netfilter/nft_byteorder.c index 5e1fbdd7b2846..dba16126c7eec 100644 --- a/net/netfilter/nft_byteorder.c +++ b/net/netfilter/nft_byteorder.c @@ -33,11 +33,11 @@ static void nft_byteorder_eval(const struct nft_expr *expr, const struct nft_byteorder *priv = nft_expr_priv(expr); u32 *src = ®s->data[priv->sreg]; u32 *dst = ®s->data[priv->dreg]; - union { u32 u32; u16 u16; } *s, *d; + u16 *s16, *d16; unsigned int i; - s = (void *)src; - d = (void *)dst; + s16 = (void *)src; + d16 = (void *)dst; switch (priv->size) { case 8: { @@ -63,11 +63,11 @@ static void nft_byteorder_eval(const struct nft_expr *expr, switch (priv->op) { case NFT_BYTEORDER_NTOH: for (i = 0; i < priv->len / 4; i++) - d[i].u32 = ntohl((__force __be32)s[i].u32); + dst[i] = ntohl((__force __be32)src[i]); break; case NFT_BYTEORDER_HTON: for (i = 0; i < priv->len / 4; i++) - d[i].u32 = (__force __u32)htonl(s[i].u32); + dst[i] = (__force __u32)htonl(src[i]); break; } break; @@ -75,11 +75,11 @@ static void nft_byteorder_eval(const struct nft_expr *expr, switch (priv->op) { case NFT_BYTEORDER_NTOH: for (i = 0; i < priv->len / 2; i++) - d[i].u16 = ntohs((__force __be16)s[i].u16); + d16[i] = ntohs((__force __be16)s16[i]); break; case NFT_BYTEORDER_HTON: for (i = 0; i < priv->len / 2; i++) - d[i].u16 = (__force __u16)htons(s[i].u16); + d16[i] = (__force __u16)htons(s16[i]); break; } break; diff --git a/net/netfilter/nft_chain_filter.c b/net/netfilter/nft_chain_filter.c index 3fd540b2c6baf..a308d45ee95e1 100644 --- a/net/netfilter/nft_chain_filter.c +++ b/net/netfilter/nft_chain_filter.c @@ -2,6 +2,7 @@ #include #include #include +#include #include #include #include @@ -10,6 +11,8 @@ #include #include +extern unsigned int nf_tables_net_id; + #ifdef CONFIG_NF_TABLES_IPV4 static unsigned int nft_do_chain_ipv4(void *priv, struct sk_buff *skb, @@ -315,6 +318,7 @@ static int nf_tables_netdev_event(struct notifier_block *this, unsigned long event, void *ptr) { struct net_device *dev = netdev_notifier_info_to_dev(ptr); + struct nftables_pernet *nft_net; struct nft_table *table; struct nft_chain *chain, *nr; struct nft_ctx ctx = { @@ -325,8 +329,9 @@ static int nf_tables_netdev_event(struct notifier_block *this, event != NETDEV_CHANGENAME) return NOTIFY_DONE; - mutex_lock(&ctx.net->nft.commit_mutex); - list_for_each_entry(table, &ctx.net->nft.tables, list) { + nft_net = net_generic(ctx.net, nf_tables_net_id); + mutex_lock(&nft_net->commit_mutex); + list_for_each_entry(table, &nft_net->tables, list) { if (table->family != NFPROTO_NETDEV) continue; @@ -340,7 +345,7 @@ static int nf_tables_netdev_event(struct notifier_block *this, nft_netdev_event(event, dev, &ctx); } } - mutex_unlock(&ctx.net->nft.commit_mutex); + mutex_unlock(&nft_net->commit_mutex); return NOTIFY_DONE; } diff --git a/net/netfilter/nft_compat.c b/net/netfilter/nft_compat.c index 469f9da5073bf..2846d64659f2f 100644 --- a/net/netfilter/nft_compat.c +++ b/net/netfilter/nft_compat.c @@ -575,19 +575,14 @@ nfnl_compat_fill_info(struct sk_buff *skb, u32 portid, u32 seq, u32 type, int rev, int target) { struct nlmsghdr *nlh; - struct nfgenmsg *nfmsg; unsigned int flags = portid ? NLM_F_MULTI : 0; event = nfnl_msg_type(NFNL_SUBSYS_NFT_COMPAT, event); - nlh = nlmsg_put(skb, portid, seq, event, sizeof(*nfmsg), flags); - if (nlh == NULL) + nlh = nfnl_msg_put(skb, portid, seq, event, flags, family, + NFNETLINK_V0, 0); + if (!nlh) goto nlmsg_failure; - nfmsg = nlmsg_data(nlh); - nfmsg->nfgen_family = family; - nfmsg->version = NFNETLINK_V0; - nfmsg->res_id = 0; - if (nla_put_string(skb, NFTA_COMPAT_NAME, name) || nla_put_be32(skb, NFTA_COMPAT_REV, htonl(rev)) || nla_put_be32(skb, NFTA_COMPAT_TYPE, htonl(target))) diff --git a/net/netfilter/nft_dynset.c b/net/netfilter/nft_dynset.c index c5d42e704f043..651c9784904cb 100644 --- a/net/netfilter/nft_dynset.c +++ b/net/netfilter/nft_dynset.c @@ -15,6 +15,9 @@ #include #include #include +#include + +extern unsigned int nf_tables_net_id; struct nft_dynset { struct nft_set *set; @@ -112,13 +115,14 @@ static int nft_dynset_init(const struct nft_ctx *ctx, const struct nft_expr *expr, const struct nlattr * const tb[]) { + struct nftables_pernet *nft_net = net_generic(ctx->net, nf_tables_net_id); struct nft_dynset *priv = nft_expr_priv(expr); u8 genmask = nft_genmask_next(ctx->net); struct nft_set *set; u64 timeout; int err; - lockdep_assert_held(&ctx->net->nft.commit_mutex); + lockdep_assert_held(&nft_net->commit_mutex); if (tb[NFTA_DYNSET_SET_NAME] == NULL || tb[NFTA_DYNSET_OP] == NULL || diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c index 57fd9b7cfc75f..35ecaa93f213a 100644 --- a/net/netlink/af_netlink.c +++ b/net/netlink/af_netlink.c @@ -1603,6 +1603,7 @@ out: int netlink_set_err(struct sock *ssk, u32 portid, u32 group, int code) { struct netlink_set_err_data info; + unsigned long flags; struct sock *sk; int ret = 0; @@ -1612,12 +1613,12 @@ int netlink_set_err(struct sock *ssk, u32 portid, u32 group, int code) /* sk->sk_err wants a positive error value */ info.code = -code; - read_lock(&nl_table_lock); + read_lock_irqsave(&nl_table_lock, flags); sk_for_each_bound(sk, &nl_table[ssk->sk_protocol].mc_list) ret += do_one_set_err(sk, &info); - read_unlock(&nl_table_lock); + read_unlock_irqrestore(&nl_table_lock, flags); return ret; } EXPORT_SYMBOL(netlink_set_err); diff --git a/net/netlink/diag.c b/net/netlink/diag.c index 7dda33b9b7849..85ee4891c2c7f 100644 --- a/net/netlink/diag.c +++ b/net/netlink/diag.c @@ -93,6 +93,7 @@ static int __netlink_diag_dump(struct sk_buff *skb, struct netlink_callback *cb, struct net *net = sock_net(skb->sk); struct netlink_diag_req *req; struct netlink_sock *nlsk; + unsigned long flags; struct sock *sk; int num = 2; int ret = 0; @@ -151,7 +152,7 @@ static int __netlink_diag_dump(struct sk_buff *skb, struct netlink_callback *cb, num++; mc_list: - read_lock(&nl_table_lock); + read_lock_irqsave(&nl_table_lock, flags); sk_for_each_bound(sk, &tbl->mc_list) { if (sk_hashed(sk)) continue; @@ -166,13 +167,13 @@ mc_list: NETLINK_CB(cb->skb).portid, cb->nlh->nlmsg_seq, NLM_F_MULTI, - sock_i_ino(sk)) < 0) { + __sock_i_ino(sk)) < 0) { ret = 1; break; } num++; } - read_unlock(&nl_table_lock); + read_unlock_irqrestore(&nl_table_lock, flags); done: cb->args[0] = num; diff --git a/net/nfc/core.c b/net/nfc/core.c index a84f824da051d..dd12ee46ac730 100644 --- a/net/nfc/core.c +++ b/net/nfc/core.c @@ -646,7 +646,7 @@ error: return rc; } -int nfc_set_remote_general_bytes(struct nfc_dev *dev, u8 *gb, u8 gb_len) +int nfc_set_remote_general_bytes(struct nfc_dev *dev, const u8 *gb, u8 gb_len) { pr_debug("dev_name=%s gb_len=%d\n", dev_name(&dev->dev), gb_len); @@ -675,7 +675,7 @@ int nfc_tm_data_received(struct nfc_dev *dev, struct sk_buff *skb) EXPORT_SYMBOL(nfc_tm_data_received); int nfc_tm_activated(struct nfc_dev *dev, u32 protocol, u8 comm_mode, - u8 *gb, size_t gb_len) + const u8 *gb, size_t gb_len) { int rc; diff --git a/net/nfc/hci/llc_shdlc.c b/net/nfc/hci/llc_shdlc.c index fe988936ad923..e6863c71f566d 100644 --- a/net/nfc/hci/llc_shdlc.c +++ b/net/nfc/hci/llc_shdlc.c @@ -134,7 +134,7 @@ static bool llc_shdlc_x_lteq_y_lt_z(int x, int y, int z) return ((y >= x) || (y < z)) ? true : false; } -static struct sk_buff *llc_shdlc_alloc_skb(struct llc_shdlc *shdlc, +static struct sk_buff *llc_shdlc_alloc_skb(const struct llc_shdlc *shdlc, int payload_len) { struct sk_buff *skb; @@ -148,7 +148,7 @@ static struct sk_buff *llc_shdlc_alloc_skb(struct llc_shdlc *shdlc, } /* immediately sends an S frame. */ -static int llc_shdlc_send_s_frame(struct llc_shdlc *shdlc, +static int llc_shdlc_send_s_frame(const struct llc_shdlc *shdlc, enum sframe_type sframe_type, int nr) { int r; @@ -170,7 +170,7 @@ static int llc_shdlc_send_s_frame(struct llc_shdlc *shdlc, } /* immediately sends an U frame. skb may contain optional payload */ -static int llc_shdlc_send_u_frame(struct llc_shdlc *shdlc, +static int llc_shdlc_send_u_frame(const struct llc_shdlc *shdlc, struct sk_buff *skb, enum uframe_modifier uframe_modifier) { @@ -372,7 +372,7 @@ static void llc_shdlc_connect_complete(struct llc_shdlc *shdlc, int r) wake_up(shdlc->connect_wq); } -static int llc_shdlc_connect_initiate(struct llc_shdlc *shdlc) +static int llc_shdlc_connect_initiate(const struct llc_shdlc *shdlc) { struct sk_buff *skb; @@ -388,7 +388,7 @@ static int llc_shdlc_connect_initiate(struct llc_shdlc *shdlc) return llc_shdlc_send_u_frame(shdlc, skb, U_FRAME_RSET); } -static int llc_shdlc_connect_send_ua(struct llc_shdlc *shdlc) +static int llc_shdlc_connect_send_ua(const struct llc_shdlc *shdlc) { struct sk_buff *skb; diff --git a/net/nfc/llcp.h b/net/nfc/llcp.h index 1f68724d44d3b..a070a57fc1516 100644 --- a/net/nfc/llcp.h +++ b/net/nfc/llcp.h @@ -233,15 +233,15 @@ struct sock *nfc_llcp_accept_dequeue(struct sock *sk, struct socket *newsock); /* TLV API */ int nfc_llcp_parse_gb_tlv(struct nfc_llcp_local *local, - u8 *tlv_array, u16 tlv_array_len); + const u8 *tlv_array, u16 tlv_array_len); int nfc_llcp_parse_connection_tlv(struct nfc_llcp_sock *sock, - u8 *tlv_array, u16 tlv_array_len); + const u8 *tlv_array, u16 tlv_array_len); /* Commands API */ void nfc_llcp_recv(void *data, struct sk_buff *skb, int err); -u8 *nfc_llcp_build_tlv(u8 type, u8 *value, u8 value_length, u8 *tlv_length); +u8 *nfc_llcp_build_tlv(u8 type, const u8 *value, u8 value_length, u8 *tlv_length); struct nfc_llcp_sdp_tlv *nfc_llcp_build_sdres_tlv(u8 tid, u8 sap); -struct nfc_llcp_sdp_tlv *nfc_llcp_build_sdreq_tlv(u8 tid, char *uri, +struct nfc_llcp_sdp_tlv *nfc_llcp_build_sdreq_tlv(u8 tid, const char *uri, size_t uri_len); void nfc_llcp_free_sdp_tlv(struct nfc_llcp_sdp_tlv *sdp); void nfc_llcp_free_sdp_tlv_list(struct hlist_head *sdp_head); diff --git a/net/nfc/llcp_commands.c b/net/nfc/llcp_commands.c index d1fc019e932e0..737c7aa384f44 100644 --- a/net/nfc/llcp_commands.c +++ b/net/nfc/llcp_commands.c @@ -27,7 +27,7 @@ #include "nfc.h" #include "llcp.h" -static u8 llcp_tlv_length[LLCP_TLV_MAX] = { +static const u8 llcp_tlv_length[LLCP_TLV_MAX] = { 0, 1, /* VERSION */ 2, /* MIUX */ @@ -41,7 +41,7 @@ static u8 llcp_tlv_length[LLCP_TLV_MAX] = { }; -static u8 llcp_tlv8(u8 *tlv, u8 type) +static u8 llcp_tlv8(const u8 *tlv, u8 type) { if (tlv[0] != type || tlv[1] != llcp_tlv_length[tlv[0]]) return 0; @@ -49,7 +49,7 @@ static u8 llcp_tlv8(u8 *tlv, u8 type) return tlv[2]; } -static u16 llcp_tlv16(u8 *tlv, u8 type) +static u16 llcp_tlv16(const u8 *tlv, u8 type) { if (tlv[0] != type || tlv[1] != llcp_tlv_length[tlv[0]]) return 0; @@ -58,37 +58,37 @@ static u16 llcp_tlv16(u8 *tlv, u8 type) } -static u8 llcp_tlv_version(u8 *tlv) +static u8 llcp_tlv_version(const u8 *tlv) { return llcp_tlv8(tlv, LLCP_TLV_VERSION); } -static u16 llcp_tlv_miux(u8 *tlv) +static u16 llcp_tlv_miux(const u8 *tlv) { return llcp_tlv16(tlv, LLCP_TLV_MIUX) & 0x7ff; } -static u16 llcp_tlv_wks(u8 *tlv) +static u16 llcp_tlv_wks(const u8 *tlv) { return llcp_tlv16(tlv, LLCP_TLV_WKS); } -static u16 llcp_tlv_lto(u8 *tlv) +static u16 llcp_tlv_lto(const u8 *tlv) { return llcp_tlv8(tlv, LLCP_TLV_LTO); } -static u8 llcp_tlv_opt(u8 *tlv) +static u8 llcp_tlv_opt(const u8 *tlv) { return llcp_tlv8(tlv, LLCP_TLV_OPT); } -static u8 llcp_tlv_rw(u8 *tlv) +static u8 llcp_tlv_rw(const u8 *tlv) { return llcp_tlv8(tlv, LLCP_TLV_RW) & 0xf; } -u8 *nfc_llcp_build_tlv(u8 type, u8 *value, u8 value_length, u8 *tlv_length) +u8 *nfc_llcp_build_tlv(u8 type, const u8 *value, u8 value_length, u8 *tlv_length) { u8 *tlv, length; @@ -142,7 +142,7 @@ struct nfc_llcp_sdp_tlv *nfc_llcp_build_sdres_tlv(u8 tid, u8 sap) return sdres; } -struct nfc_llcp_sdp_tlv *nfc_llcp_build_sdreq_tlv(u8 tid, char *uri, +struct nfc_llcp_sdp_tlv *nfc_llcp_build_sdreq_tlv(u8 tid, const char *uri, size_t uri_len) { struct nfc_llcp_sdp_tlv *sdreq; @@ -202,9 +202,10 @@ void nfc_llcp_free_sdp_tlv_list(struct hlist_head *head) } int nfc_llcp_parse_gb_tlv(struct nfc_llcp_local *local, - u8 *tlv_array, u16 tlv_array_len) + const u8 *tlv_array, u16 tlv_array_len) { - u8 *tlv = tlv_array, type, length, offset = 0; + const u8 *tlv = tlv_array; + u8 type, length, offset = 0; pr_debug("TLV array length %d\n", tlv_array_len); @@ -251,9 +252,10 @@ int nfc_llcp_parse_gb_tlv(struct nfc_llcp_local *local, } int nfc_llcp_parse_connection_tlv(struct nfc_llcp_sock *sock, - u8 *tlv_array, u16 tlv_array_len) + const u8 *tlv_array, u16 tlv_array_len) { - u8 *tlv = tlv_array, type, length, offset = 0; + const u8 *tlv = tlv_array; + u8 type, length, offset = 0; pr_debug("TLV array length %d\n", tlv_array_len); @@ -307,7 +309,7 @@ static struct sk_buff *llcp_add_header(struct sk_buff *pdu, return pdu; } -static struct sk_buff *llcp_add_tlv(struct sk_buff *pdu, u8 *tlv, +static struct sk_buff *llcp_add_tlv(struct sk_buff *pdu, const u8 *tlv, u8 tlv_length) { /* XXX Add an skb length check */ @@ -401,9 +403,11 @@ int nfc_llcp_send_connect(struct nfc_llcp_sock *sock) { struct nfc_llcp_local *local; struct sk_buff *skb; - u8 *service_name_tlv = NULL, service_name_tlv_length; - u8 *miux_tlv = NULL, miux_tlv_length; - u8 *rw_tlv = NULL, rw_tlv_length, rw; + const u8 *service_name_tlv = NULL; + const u8 *miux_tlv = NULL; + const u8 *rw_tlv = NULL; + u8 service_name_tlv_length = 0; + u8 miux_tlv_length, rw_tlv_length, rw; int err; u16 size = 0; __be16 miux; @@ -477,8 +481,9 @@ int nfc_llcp_send_cc(struct nfc_llcp_sock *sock) { struct nfc_llcp_local *local; struct sk_buff *skb; - u8 *miux_tlv = NULL, miux_tlv_length; - u8 *rw_tlv = NULL, rw_tlv_length, rw; + const u8 *miux_tlv = NULL; + const u8 *rw_tlv = NULL; + u8 miux_tlv_length, rw_tlv_length, rw; int err; u16 size = 0; __be16 miux; diff --git a/net/nfc/llcp_core.c b/net/nfc/llcp_core.c index 3290f2275b857..bdc1a9d0965af 100644 --- a/net/nfc/llcp_core.c +++ b/net/nfc/llcp_core.c @@ -314,7 +314,7 @@ static char *wks[] = { "urn:nfc:sn:snep", }; -static int nfc_llcp_wks_sap(char *service_name, size_t service_name_len) +static int nfc_llcp_wks_sap(const char *service_name, size_t service_name_len) { int sap, num_wks; @@ -338,7 +338,7 @@ static int nfc_llcp_wks_sap(char *service_name, size_t service_name_len) static struct nfc_llcp_sock *nfc_llcp_sock_from_sn(struct nfc_llcp_local *local, - u8 *sn, size_t sn_len) + const u8 *sn, size_t sn_len) { struct sock *sk; struct nfc_llcp_sock *llcp_sock, *tmp_sock; @@ -535,7 +535,7 @@ static int nfc_llcp_build_gb(struct nfc_llcp_local *local) { u8 *gb_cur, version, version_length; u8 lto_length, wks_length, miux_length; - u8 *version_tlv = NULL, *lto_tlv = NULL, + const u8 *version_tlv = NULL, *lto_tlv = NULL, *wks_tlv = NULL, *miux_tlv = NULL; __be16 wks = cpu_to_be16(local->local_wks); u8 gb_len = 0; @@ -625,7 +625,7 @@ u8 *nfc_llcp_general_bytes(struct nfc_dev *dev, size_t *general_bytes_len) return local->gb; } -int nfc_llcp_set_remote_gb(struct nfc_dev *dev, u8 *gb, u8 gb_len) +int nfc_llcp_set_remote_gb(struct nfc_dev *dev, const u8 *gb, u8 gb_len) { struct nfc_llcp_local *local; @@ -652,27 +652,27 @@ int nfc_llcp_set_remote_gb(struct nfc_dev *dev, u8 *gb, u8 gb_len) local->remote_gb_len - 3); } -static u8 nfc_llcp_dsap(struct sk_buff *pdu) +static u8 nfc_llcp_dsap(const struct sk_buff *pdu) { return (pdu->data[0] & 0xfc) >> 2; } -static u8 nfc_llcp_ptype(struct sk_buff *pdu) +static u8 nfc_llcp_ptype(const struct sk_buff *pdu) { return ((pdu->data[0] & 0x03) << 2) | ((pdu->data[1] & 0xc0) >> 6); } -static u8 nfc_llcp_ssap(struct sk_buff *pdu) +static u8 nfc_llcp_ssap(const struct sk_buff *pdu) { return pdu->data[1] & 0x3f; } -static u8 nfc_llcp_ns(struct sk_buff *pdu) +static u8 nfc_llcp_ns(const struct sk_buff *pdu) { return pdu->data[2] >> 4; } -static u8 nfc_llcp_nr(struct sk_buff *pdu) +static u8 nfc_llcp_nr(const struct sk_buff *pdu) { return pdu->data[2] & 0xf; } @@ -814,7 +814,7 @@ out: } static struct nfc_llcp_sock *nfc_llcp_sock_get_sn(struct nfc_llcp_local *local, - u8 *sn, size_t sn_len) + const u8 *sn, size_t sn_len) { struct nfc_llcp_sock *llcp_sock; @@ -828,9 +828,10 @@ static struct nfc_llcp_sock *nfc_llcp_sock_get_sn(struct nfc_llcp_local *local, return llcp_sock; } -static u8 *nfc_llcp_connect_sn(struct sk_buff *skb, size_t *sn_len) +static const u8 *nfc_llcp_connect_sn(const struct sk_buff *skb, size_t *sn_len) { - u8 *tlv = &skb->data[2], type, length; + u8 type, length; + const u8 *tlv = &skb->data[2]; size_t tlv_array_len = skb->len - LLCP_HEADER_SIZE, offset = 0; while (offset < tlv_array_len) { @@ -888,7 +889,7 @@ static void nfc_llcp_recv_ui(struct nfc_llcp_local *local, } static void nfc_llcp_recv_connect(struct nfc_llcp_local *local, - struct sk_buff *skb) + const struct sk_buff *skb) { struct sock *new_sk, *parent; struct nfc_llcp_sock *sock, *new_sock; @@ -906,7 +907,7 @@ static void nfc_llcp_recv_connect(struct nfc_llcp_local *local, goto fail; } } else { - u8 *sn; + const u8 *sn; size_t sn_len; sn = nfc_llcp_connect_sn(skb, &sn_len); @@ -1125,7 +1126,7 @@ static void nfc_llcp_recv_hdlc(struct nfc_llcp_local *local, } static void nfc_llcp_recv_disc(struct nfc_llcp_local *local, - struct sk_buff *skb) + const struct sk_buff *skb) { struct nfc_llcp_sock *llcp_sock; struct sock *sk; @@ -1168,7 +1169,8 @@ static void nfc_llcp_recv_disc(struct nfc_llcp_local *local, nfc_llcp_sock_put(llcp_sock); } -static void nfc_llcp_recv_cc(struct nfc_llcp_local *local, struct sk_buff *skb) +static void nfc_llcp_recv_cc(struct nfc_llcp_local *local, + const struct sk_buff *skb) { struct nfc_llcp_sock *llcp_sock; struct sock *sk; @@ -1201,7 +1203,8 @@ static void nfc_llcp_recv_cc(struct nfc_llcp_local *local, struct sk_buff *skb) nfc_llcp_sock_put(llcp_sock); } -static void nfc_llcp_recv_dm(struct nfc_llcp_local *local, struct sk_buff *skb) +static void nfc_llcp_recv_dm(struct nfc_llcp_local *local, + const struct sk_buff *skb) { struct nfc_llcp_sock *llcp_sock; struct sock *sk; @@ -1239,12 +1242,13 @@ static void nfc_llcp_recv_dm(struct nfc_llcp_local *local, struct sk_buff *skb) } static void nfc_llcp_recv_snl(struct nfc_llcp_local *local, - struct sk_buff *skb) + const struct sk_buff *skb) { struct nfc_llcp_sock *llcp_sock; - u8 dsap, ssap, *tlv, type, length, tid, sap; + u8 dsap, ssap, type, length, tid, sap; + const u8 *tlv; u16 tlv_len, offset; - char *service_name; + const char *service_name; size_t service_name_len; struct nfc_llcp_sdp_tlv *sdp; HLIST_HEAD(llc_sdres_list); diff --git a/net/nfc/nfc.h b/net/nfc/nfc.h index 6c6f76b370b1e..c792165f523f1 100644 --- a/net/nfc/nfc.h +++ b/net/nfc/nfc.h @@ -60,7 +60,7 @@ void nfc_llcp_mac_is_up(struct nfc_dev *dev, u32 target_idx, u8 comm_mode, u8 rf_mode); int nfc_llcp_register_device(struct nfc_dev *dev); void nfc_llcp_unregister_device(struct nfc_dev *dev); -int nfc_llcp_set_remote_gb(struct nfc_dev *dev, u8 *gb, u8 gb_len); +int nfc_llcp_set_remote_gb(struct nfc_dev *dev, const u8 *gb, u8 gb_len); u8 *nfc_llcp_general_bytes(struct nfc_dev *dev, size_t *general_bytes_len); int nfc_llcp_data_received(struct nfc_dev *dev, struct sk_buff *skb); struct nfc_llcp_local *nfc_llcp_find_local(struct nfc_dev *dev); diff --git a/net/sched/act_pedit.c b/net/sched/act_pedit.c index aeb8f84cbd9e2..255d4ecf62522 100644 --- a/net/sched/act_pedit.c +++ b/net/sched/act_pedit.c @@ -29,6 +29,7 @@ static struct tc_action_ops act_pedit_ops; static const struct nla_policy pedit_policy[TCA_PEDIT_MAX + 1] = { [TCA_PEDIT_PARMS] = { .len = sizeof(struct tc_pedit) }, + [TCA_PEDIT_PARMS_EX] = { .len = sizeof(struct tc_pedit) }, [TCA_PEDIT_KEYS_EX] = { .type = NLA_NESTED }, }; diff --git a/net/sched/cls_flow.c b/net/sched/cls_flow.c index 55bf75cb1f16b..164049d20f4d3 100644 --- a/net/sched/cls_flow.c +++ b/net/sched/cls_flow.c @@ -229,7 +229,7 @@ static u32 flow_get_skgid(const struct sk_buff *skb) static u32 flow_get_vlan_tag(const struct sk_buff *skb) { - u16 uninitialized_var(tag); + u16 tag; if (vlan_get_tag(skb, &tag) < 0) return 0; diff --git a/net/sched/cls_fw.c b/net/sched/cls_fw.c index cb2c62605fc76..5284a473c697f 100644 --- a/net/sched/cls_fw.c +++ b/net/sched/cls_fw.c @@ -221,11 +221,6 @@ static int fw_set_parms(struct net *net, struct tcf_proto *tp, if (err < 0) return err; - if (tb[TCA_FW_CLASSID]) { - f->res.classid = nla_get_u32(tb[TCA_FW_CLASSID]); - tcf_bind_filter(tp, &f->res, base); - } - #ifdef CONFIG_NET_CLS_IND if (tb[TCA_FW_INDEV]) { int ret; @@ -244,6 +239,11 @@ static int fw_set_parms(struct net *net, struct tcf_proto *tp, } else if (head->mask != 0xFFFFFFFF) return err; + if (tb[TCA_FW_CLASSID]) { + f->res.classid = nla_get_u32(tb[TCA_FW_CLASSID]); + tcf_bind_filter(tp, &f->res, base); + } + return 0; } diff --git a/net/sched/cls_route.c b/net/sched/cls_route.c index 4c7fa1cfd8e38..a924292623ecf 100644 --- a/net/sched/cls_route.c +++ b/net/sched/cls_route.c @@ -513,7 +513,6 @@ static int route4_change(struct net *net, struct sk_buff *in_skb, if (fold) { f->id = fold->id; f->iif = fold->iif; - f->res = fold->res; f->handle = fold->handle; f->tp = fold->tp; diff --git a/net/sched/cls_u32.c b/net/sched/cls_u32.c index d30256ac35372..1e71ff093c91d 100644 --- a/net/sched/cls_u32.c +++ b/net/sched/cls_u32.c @@ -778,11 +778,22 @@ static int u32_set_parms(struct net *net, struct tcf_proto *tp, struct netlink_ext_ack *extack) { int err; +#ifdef CONFIG_NET_CLS_IND + int ifindex = -1; +#endif err = tcf_exts_validate(net, tp, tb, est, &n->exts, ovr, extack); if (err < 0) return err; +#ifdef CONFIG_NET_CLS_IND + if (tb[TCA_U32_INDEV]) { + ifindex = tcf_change_indev(net, tb[TCA_U32_INDEV], extack); + if (ifindex < 0) + return -EINVAL; + } +#endif + if (tb[TCA_U32_LINK]) { u32 handle = nla_get_u32(tb[TCA_U32_LINK]); struct tc_u_hnode *ht_down = NULL, *ht_old; @@ -814,13 +825,8 @@ static int u32_set_parms(struct net *net, struct tcf_proto *tp, } #ifdef CONFIG_NET_CLS_IND - if (tb[TCA_U32_INDEV]) { - int ret; - ret = tcf_change_indev(net, tb[TCA_U32_INDEV], extack); - if (ret < 0) - return -EINVAL; - n->ifindex = ret; - } + if (ifindex >= 0) + n->ifindex = ifindex; #endif return 0; } @@ -873,7 +879,6 @@ static struct tc_u_knode *u32_init_knode(struct tcf_proto *tp, new->ifindex = n->ifindex; #endif new->fshift = n->fshift; - new->res = n->res; new->flags = n->flags; RCU_INIT_POINTER(new->ht_down, ht); @@ -1061,18 +1066,62 @@ static int u32_change(struct net *net, struct sk_buff *in_skb, return -EINVAL; } + /* At this point, we need to derive the new handle that will be used to + * uniquely map the identity of this table match entry. The + * identity of the entry that we need to construct is 32 bits made of: + * htid(12b):bucketid(8b):node/entryid(12b) + * + * At this point _we have the table(ht)_ in which we will insert this + * entry. We carry the table's id in variable "htid". + * Note that earlier code picked the ht selection either by a) the user + * providing the htid specified via TCA_U32_HASH attribute or b) when + * no such attribute is passed then the root ht, is default to at ID + * 0x[800][00][000]. Rule: the root table has a single bucket with ID 0. + * If OTOH the user passed us the htid, they may also pass a bucketid of + * choice. 0 is fine. For example a user htid is 0x[600][01][000] it is + * indicating hash bucketid of 1. Rule: the entry/node ID _cannot_ be + * passed via the htid, so even if it was non-zero it will be ignored. + * + * We may also have a handle, if the user passed one. The handle also + * carries the same addressing of htid(12b):bucketid(8b):node/entryid(12b). + * Rule: the bucketid on the handle is ignored even if one was passed; + * rather the value on "htid" is always assumed to be the bucketid. + */ if (handle) { + /* Rule: The htid from handle and tableid from htid must match */ if (TC_U32_HTID(handle) && TC_U32_HTID(handle ^ htid)) { NL_SET_ERR_MSG_MOD(extack, "Handle specified hash table address mismatch"); return -EINVAL; } - handle = htid | TC_U32_NODE(handle); - err = idr_alloc_u32(&ht->handle_idr, NULL, &handle, handle, - GFP_KERNEL); - if (err) - return err; - } else + /* Ok, so far we have a valid htid(12b):bucketid(8b) but we + * need to finalize the table entry identification with the last + * part - the node/entryid(12b)). Rule: Nodeid _cannot be 0_ for + * entries. Rule: nodeid of 0 is reserved only for tables(see + * earlier code which processes TC_U32_DIVISOR attribute). + * Rule: The nodeid can only be derived from the handle (and not + * htid). + * Rule: if the handle specified zero for the node id example + * 0x60000000, then pick a new nodeid from the pool of IDs + * this hash table has been allocating from. + * If OTOH it is specified (i.e for example the user passed a + * handle such as 0x60000123), then we use it generate our final + * handle which is used to uniquely identify the match entry. + */ + if (!TC_U32_NODE(handle)) { + handle = gen_new_kid(ht, htid); + } else { + handle = htid | TC_U32_NODE(handle); + err = idr_alloc_u32(&ht->handle_idr, NULL, &handle, + handle, GFP_KERNEL); + if (err) + return err; + } + } else { + /* The user did not give us a handle; lets just generate one + * from the table's pool of nodeids. + */ handle = gen_new_kid(ht, htid); + } if (tb[TCA_U32_SEL] == NULL) { NL_SET_ERR_MSG_MOD(extack, "Selector not specified"); diff --git a/net/sched/sch_cake.c b/net/sched/sch_cake.c index 01a177cfa5333..d91665ea7b14d 100644 --- a/net/sched/sch_cake.c +++ b/net/sched/sch_cake.c @@ -1649,7 +1649,7 @@ static s32 cake_enqueue(struct sk_buff *skb, struct Qdisc *sch, { struct cake_sched_data *q = qdisc_priv(sch); int len = qdisc_pkt_len(skb); - int uninitialized_var(ret); + int ret; struct sk_buff *ack = NULL; ktime_t now = ktime_get(); struct cake_tin_data *b; diff --git a/net/sched/sch_cbq.c b/net/sched/sch_cbq.c index 2974f7262f882..7f0a5d22deaf6 100644 --- a/net/sched/sch_cbq.c +++ b/net/sched/sch_cbq.c @@ -365,7 +365,7 @@ cbq_enqueue(struct sk_buff *skb, struct Qdisc *sch, struct sk_buff **to_free) { struct cbq_sched_data *q = qdisc_priv(sch); - int uninitialized_var(ret); + int ret; struct cbq_class *cl = cbq_classify(skb, sch, &ret); #ifdef CONFIG_NET_CLS_ACT diff --git a/net/sched/sch_fq_codel.c b/net/sched/sch_fq_codel.c index e4f69c779b8cf..7a4777ee0536e 100644 --- a/net/sched/sch_fq_codel.c +++ b/net/sched/sch_fq_codel.c @@ -192,7 +192,7 @@ static int fq_codel_enqueue(struct sk_buff *skb, struct Qdisc *sch, struct fq_codel_sched_data *q = qdisc_priv(sch); unsigned int idx, prev_backlog, prev_qlen; struct fq_codel_flow *flow; - int uninitialized_var(ret); + int ret; unsigned int pkt_len; bool memory_limited; diff --git a/net/sched/sch_mqprio.c b/net/sched/sch_mqprio.c index 64d7f876d7de2..c0ab1e38e80c6 100644 --- a/net/sched/sch_mqprio.c +++ b/net/sched/sch_mqprio.c @@ -132,6 +132,97 @@ static int parse_attr(struct nlattr *tb[], int maxtype, struct nlattr *nla, return 0; } +static int mqprio_parse_nlattr(struct Qdisc *sch, struct tc_mqprio_qopt *qopt, + struct nlattr *opt, + struct netlink_ext_ack *extack) +{ + struct mqprio_sched *priv = qdisc_priv(sch); + struct nlattr *tb[TCA_MQPRIO_MAX + 1]; + struct nlattr *attr; + int i, rem, err; + + err = parse_attr(tb, TCA_MQPRIO_MAX, opt, mqprio_policy, + sizeof(*qopt)); + if (err < 0) + return err; + + if (!qopt->hw) { + NL_SET_ERR_MSG(extack, + "mqprio TCA_OPTIONS can only contain netlink attributes in hardware mode"); + return -EINVAL; + } + + if (tb[TCA_MQPRIO_MODE]) { + priv->flags |= TC_MQPRIO_F_MODE; + priv->mode = *(u16 *)nla_data(tb[TCA_MQPRIO_MODE]); + } + + if (tb[TCA_MQPRIO_SHAPER]) { + priv->flags |= TC_MQPRIO_F_SHAPER; + priv->shaper = *(u16 *)nla_data(tb[TCA_MQPRIO_SHAPER]); + } + + if (tb[TCA_MQPRIO_MIN_RATE64]) { + if (priv->shaper != TC_MQPRIO_SHAPER_BW_RATE) { + NL_SET_ERR_MSG_ATTR(extack, tb[TCA_MQPRIO_MIN_RATE64], + "min_rate accepted only when shaper is in bw_rlimit mode"); + return -EINVAL; + } + i = 0; + nla_for_each_nested(attr, tb[TCA_MQPRIO_MIN_RATE64], + rem) { + if (nla_type(attr) != TCA_MQPRIO_MIN_RATE64) { + NL_SET_ERR_MSG_ATTR(extack, attr, + "Attribute type expected to be TCA_MQPRIO_MIN_RATE64"); + return -EINVAL; + } + + if (nla_len(attr) != sizeof(u64)) { + NL_SET_ERR_MSG_ATTR(extack, attr, + "Attribute TCA_MQPRIO_MIN_RATE64 expected to have 8 bytes length"); + return -EINVAL; + } + + if (i >= qopt->num_tc) + break; + priv->min_rate[i] = *(u64 *)nla_data(attr); + i++; + } + priv->flags |= TC_MQPRIO_F_MIN_RATE; + } + + if (tb[TCA_MQPRIO_MAX_RATE64]) { + if (priv->shaper != TC_MQPRIO_SHAPER_BW_RATE) { + NL_SET_ERR_MSG_ATTR(extack, tb[TCA_MQPRIO_MAX_RATE64], + "max_rate accepted only when shaper is in bw_rlimit mode"); + return -EINVAL; + } + i = 0; + nla_for_each_nested(attr, tb[TCA_MQPRIO_MAX_RATE64], + rem) { + if (nla_type(attr) != TCA_MQPRIO_MAX_RATE64) { + NL_SET_ERR_MSG_ATTR(extack, attr, + "Attribute type expected to be TCA_MQPRIO_MAX_RATE64"); + return -EINVAL; + } + + if (nla_len(attr) != sizeof(u64)) { + NL_SET_ERR_MSG_ATTR(extack, attr, + "Attribute TCA_MQPRIO_MAX_RATE64 expected to have 8 bytes length"); + return -EINVAL; + } + + if (i >= qopt->num_tc) + break; + priv->max_rate[i] = *(u64 *)nla_data(attr); + i++; + } + priv->flags |= TC_MQPRIO_F_MAX_RATE; + } + + return 0; +} + static int mqprio_init(struct Qdisc *sch, struct nlattr *opt, struct netlink_ext_ack *extack) { @@ -141,9 +232,6 @@ static int mqprio_init(struct Qdisc *sch, struct nlattr *opt, struct Qdisc *qdisc; int i, err = -EOPNOTSUPP; struct tc_mqprio_qopt *qopt = NULL; - struct nlattr *tb[TCA_MQPRIO_MAX + 1]; - struct nlattr *attr; - int rem; int len; BUILD_BUG_ON(TC_MAX_QUEUE != TC_QOPT_MAX_QUEUE); @@ -168,55 +256,9 @@ static int mqprio_init(struct Qdisc *sch, struct nlattr *opt, len = nla_len(opt) - NLA_ALIGN(sizeof(*qopt)); if (len > 0) { - err = parse_attr(tb, TCA_MQPRIO_MAX, opt, mqprio_policy, - sizeof(*qopt)); - if (err < 0) + err = mqprio_parse_nlattr(sch, qopt, opt, extack); + if (err) return err; - - if (!qopt->hw) - return -EINVAL; - - if (tb[TCA_MQPRIO_MODE]) { - priv->flags |= TC_MQPRIO_F_MODE; - priv->mode = *(u16 *)nla_data(tb[TCA_MQPRIO_MODE]); - } - - if (tb[TCA_MQPRIO_SHAPER]) { - priv->flags |= TC_MQPRIO_F_SHAPER; - priv->shaper = *(u16 *)nla_data(tb[TCA_MQPRIO_SHAPER]); - } - - if (tb[TCA_MQPRIO_MIN_RATE64]) { - if (priv->shaper != TC_MQPRIO_SHAPER_BW_RATE) - return -EINVAL; - i = 0; - nla_for_each_nested(attr, tb[TCA_MQPRIO_MIN_RATE64], - rem) { - if (nla_type(attr) != TCA_MQPRIO_MIN_RATE64) - return -EINVAL; - if (i >= qopt->num_tc) - break; - priv->min_rate[i] = *(u64 *)nla_data(attr); - i++; - } - priv->flags |= TC_MQPRIO_F_MIN_RATE; - } - - if (tb[TCA_MQPRIO_MAX_RATE64]) { - if (priv->shaper != TC_MQPRIO_SHAPER_BW_RATE) - return -EINVAL; - i = 0; - nla_for_each_nested(attr, tb[TCA_MQPRIO_MAX_RATE64], - rem) { - if (nla_type(attr) != TCA_MQPRIO_MAX_RATE64) - return -EINVAL; - if (i >= qopt->num_tc) - break; - priv->max_rate[i] = *(u64 *)nla_data(attr); - i++; - } - priv->flags |= TC_MQPRIO_F_MAX_RATE; - } } /* pre-allocate qdisc, attachment can't fail */ diff --git a/net/sched/sch_qfq.c b/net/sched/sch_qfq.c index c2a68f6e427ed..e9420ca261d61 100644 --- a/net/sched/sch_qfq.c +++ b/net/sched/sch_qfq.c @@ -387,8 +387,13 @@ static int qfq_change_agg(struct Qdisc *sch, struct qfq_class *cl, u32 weight, u32 lmax) { struct qfq_sched *q = qdisc_priv(sch); - struct qfq_aggregate *new_agg = qfq_find_agg(q, lmax, weight); + struct qfq_aggregate *new_agg; + /* 'lmax' can range from [QFQ_MIN_LMAX, pktlen + stab overhead] */ + if (lmax > (1UL << QFQ_MTU_SHIFT)) + return -EINVAL; + + new_agg = qfq_find_agg(q, lmax, weight); if (new_agg == NULL) { /* create new aggregate */ new_agg = kzalloc(sizeof(*new_agg), GFP_ATOMIC); if (new_agg == NULL) diff --git a/net/sched/sch_sfq.c b/net/sched/sch_sfq.c index 1bfdf90fa0cce..07721a1e98d8a 100644 --- a/net/sched/sch_sfq.c +++ b/net/sched/sch_sfq.c @@ -353,7 +353,7 @@ sfq_enqueue(struct sk_buff *skb, struct Qdisc *sch, struct sk_buff **to_free) unsigned int hash, dropped; sfq_index x, qlen; struct sfq_slot *slot; - int uninitialized_var(ret); + int ret; struct sk_buff *head; int delta; diff --git a/net/sctp/socket.c b/net/sctp/socket.c index a68f3d6b72335..baa825751c393 100644 --- a/net/sctp/socket.c +++ b/net/sctp/socket.c @@ -380,9 +380,9 @@ static void sctp_auto_asconf_init(struct sctp_sock *sp) struct net *net = sock_net(&sp->inet.sk); if (net->sctp.default_auto_asconf) { - spin_lock(&net->sctp.addr_wq_lock); + spin_lock_bh(&net->sctp.addr_wq_lock); list_add_tail(&sp->auto_asconf_list, &net->sctp.auto_asconf_splist); - spin_unlock(&net->sctp.addr_wq_lock); + spin_unlock_bh(&net->sctp.addr_wq_lock); sp->do_auto_asconf = 1; } } diff --git a/net/sunrpc/svcsock.c b/net/sunrpc/svcsock.c index d0b5a1c47a324..b5ee21d5d1f3a 100644 --- a/net/sunrpc/svcsock.c +++ b/net/sunrpc/svcsock.c @@ -757,12 +757,6 @@ static void svc_tcp_listen_data_ready(struct sock *sk) dprintk("svc: socket %p TCP (listen) state change %d\n", sk, sk->sk_state); - if (svsk) { - /* Refer to svc_setup_socket() for details. */ - rmb(); - svsk->sk_odata(sk); - } - /* * This callback may called twice when a new connection * is established as a child socket inherits everything @@ -771,15 +765,20 @@ static void svc_tcp_listen_data_ready(struct sock *sk) * when one of child sockets become ESTABLISHED. * 2) data_ready method of the child socket may be called * when it receives data before the socket is accepted. - * In case of 2, we should ignore it silently. + * In case of 2, we should ignore it silently and DO NOT + * dereference svsk. */ - if (sk->sk_state == TCP_LISTEN) { - if (svsk) { - set_bit(XPT_CONN, &svsk->sk_xprt.xpt_flags); - svc_xprt_enqueue(&svsk->sk_xprt); - } else - printk("svc: socket %p: no user data\n", sk); - } + if (sk->sk_state != TCP_LISTEN) + return; + + if (svsk) { + /* Refer to svc_setup_socket() for details. */ + rmb(); + svsk->sk_odata(sk); + set_bit(XPT_CONN, &svsk->sk_xprt.xpt_flags); + svc_xprt_enqueue(&svsk->sk_xprt); + } else + printk("svc: socket %p: no user data\n", sk); } /* diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c index b0dcbb08e60db..8971341c4f8af 100644 --- a/net/unix/af_unix.c +++ b/net/unix/af_unix.c @@ -706,7 +706,7 @@ static int unix_set_peek_off(struct sock *sk, int val) if (mutex_lock_interruptible(&u->iolock)) return -EINTR; - sk->sk_peek_off = val; + WRITE_ONCE(sk->sk_peek_off, val); mutex_unlock(&u->iolock); return 0; diff --git a/net/wireless/wext-core.c b/net/wireless/wext-core.c index 76a80a41615be..a57f54bc0e1a7 100644 --- a/net/wireless/wext-core.c +++ b/net/wireless/wext-core.c @@ -796,6 +796,12 @@ static int ioctl_standard_iw_point(struct iw_point *iwp, unsigned int cmd, } } + /* Sanity-check to ensure we never end up _allocating_ zero + * bytes of data for extra. + */ + if (extra_size <= 0) + return -EFAULT; + /* kzalloc() ensures NULL-termination for essid_compat. */ extra = kzalloc(extra_size, GFP_KERNEL); if (!extra) diff --git a/samples/bpf/tcp_basertt_kern.c b/samples/bpf/tcp_basertt_kern.c index 4bf4fc597db9a..653d233714ad0 100644 --- a/samples/bpf/tcp_basertt_kern.c +++ b/samples/bpf/tcp_basertt_kern.c @@ -54,7 +54,7 @@ int bpf_basertt(struct bpf_sock_ops *skops) case BPF_SOCK_OPS_BASE_RTT: n = bpf_getsockopt(skops, SOL_TCP, TCP_CONGESTION, cong, sizeof(cong)); - if (!n && !__builtin_memcmp(cong, nv, sizeof(nv)+1)) { + if (!n && !__builtin_memcmp(cong, nv, sizeof(nv))) { /* Set base_rtt to 80us */ rv = 80; } else if (n) { diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c index 8c2847ef4e422..2060a3fe9691d 100644 --- a/scripts/mod/modpost.c +++ b/scripts/mod/modpost.c @@ -1260,6 +1260,10 @@ static Elf_Sym *find_elf_symbol(struct elf_info *elf, Elf64_Sword addr, if (relsym->st_name != 0) return relsym; + /* + * Strive to find a better symbol name, but the resulting name may not + * match the symbol referenced in the original code. + */ relsym_secindex = get_secindex(elf, relsym); for (sym = elf->symtab_start; sym < elf->symtab_stop; sym++) { if (get_secindex(elf, sym) != relsym_secindex) @@ -1747,19 +1751,33 @@ static int addend_386_rel(struct elf_info *elf, Elf_Shdr *sechdr, Elf_Rela *r) #define R_ARM_THM_JUMP19 51 #endif +static int32_t sign_extend32(int32_t value, int index) +{ + uint8_t shift = 31 - index; + + return (int32_t)(value << shift) >> shift; +} + static int addend_arm_rel(struct elf_info *elf, Elf_Shdr *sechdr, Elf_Rela *r) { unsigned int r_typ = ELF_R_TYPE(r->r_info); + Elf_Sym *sym = elf->symtab_start + ELF_R_SYM(r->r_info); + void *loc = reloc_location(elf, sechdr, r); + uint32_t inst; + int32_t offset; switch (r_typ) { case R_ARM_ABS32: - /* From ARM ABI: (S + A) | T */ - r->r_addend = (int)(long) - (elf->symtab_start + ELF_R_SYM(r->r_info)); + inst = TO_NATIVE(*(uint32_t *)loc); + r->r_addend = inst + sym->st_value; break; case R_ARM_PC24: case R_ARM_CALL: case R_ARM_JUMP24: + inst = TO_NATIVE(*(uint32_t *)loc); + offset = sign_extend32((inst & 0x00ffffff) << 2, 25); + r->r_addend = offset + sym->st_value + 8; + break; case R_ARM_THM_CALL: case R_ARM_THM_JUMP24: case R_ARM_THM_JUMP19: diff --git a/scripts/tags.sh b/scripts/tags.sh index 26de7d5aa5c89..de02c44549f73 100755 --- a/scripts/tags.sh +++ b/scripts/tags.sh @@ -28,6 +28,13 @@ fi # ignore userspace tools ignore="$ignore ( -path ${tree}tools ) -prune -o" +# gtags(1) refuses to index any file outside of its current working dir. +# If gtags indexing is requested and the build output directory is not +# the kernel source tree, index all files in absolute-path form. +if [[ "$1" == "gtags" && -n "${tree}" ]]; then + tree=$(realpath "$tree")/ +fi + # Detect if ALLSOURCE_ARCHS is set. If not, we assume SRCARCH if [ "${ALLSOURCE_ARCHS}" = "" ]; then ALLSOURCE_ARCHS=${SRCARCH} @@ -136,7 +143,7 @@ docscope() dogtags() { - all_target_sources | gtags -i -f - + all_target_sources | gtags -i -C "${tree:-.}" -f - "$PWD" } # Basic regular expressions with an optional /kind-spec/ for ctags and diff --git a/security/integrity/evm/evm_main.c b/security/integrity/evm/evm_main.c index 6d1efe1359f17..9c036a41e7347 100644 --- a/security/integrity/evm/evm_main.c +++ b/security/integrity/evm/evm_main.c @@ -474,7 +474,9 @@ void evm_inode_post_removexattr(struct dentry *dentry, const char *xattr_name) /** * evm_inode_setattr - prevent updating an invalid EVM extended attribute + * @idmap: idmap of the mount * @dentry: pointer to the affected dentry + * @attr: iattr structure containing the new file attributes * * Permit update of file attributes when files have a valid EVM signature, * except in the case of them having an immutable portable signature. diff --git a/security/integrity/iint.c b/security/integrity/iint.c index 5a6810041e5c0..d5b9253ebd12b 100644 --- a/security/integrity/iint.c +++ b/security/integrity/iint.c @@ -46,12 +46,10 @@ static struct integrity_iint_cache *__integrity_iint_find(struct inode *inode) else if (inode > iint->inode) n = n->rb_right; else - break; + return iint; } - if (!n) - return NULL; - return iint; + return NULL; } /* @@ -116,10 +114,15 @@ struct integrity_iint_cache *integrity_inode_get(struct inode *inode) parent = *p; test_iint = rb_entry(parent, struct integrity_iint_cache, rb_node); - if (inode < test_iint->inode) + if (inode < test_iint->inode) { p = &(*p)->rb_left; - else + } else if (inode > test_iint->inode) { p = &(*p)->rb_right; + } else { + write_unlock(&integrity_iint_lock); + kmem_cache_free(iint_cache, iint); + return test_iint; + } } iint->inode = inode; diff --git a/sound/core/control_compat.c b/sound/core/control_compat.c index 00d826b048c4a..eb6735f16b933 100644 --- a/sound/core/control_compat.c +++ b/sound/core/control_compat.c @@ -236,7 +236,7 @@ static int copy_ctl_value_from_user(struct snd_card *card, { struct snd_ctl_elem_value32 __user *data32 = userdata; int i, type, size; - int uninitialized_var(count); + int count; unsigned int indirect; if (copy_from_user(&data->id, &data32->id, sizeof(data->id))) diff --git a/sound/core/jack.c b/sound/core/jack.c index 074b15fcb0ac4..06e0fc7b64179 100644 --- a/sound/core/jack.c +++ b/sound/core/jack.c @@ -378,6 +378,7 @@ void snd_jack_report(struct snd_jack *jack, int status) { struct snd_jack_kctl *jack_kctl; #ifdef CONFIG_SND_JACK_INPUT_DEV + struct input_dev *idev; int i; #endif @@ -389,30 +390,28 @@ void snd_jack_report(struct snd_jack *jack, int status) status & jack_kctl->mask_bits); #ifdef CONFIG_SND_JACK_INPUT_DEV - mutex_lock(&jack->input_dev_lock); - if (!jack->input_dev) { - mutex_unlock(&jack->input_dev_lock); + idev = input_get_device(jack->input_dev); + if (!idev) return; - } for (i = 0; i < ARRAY_SIZE(jack->key); i++) { int testbit = SND_JACK_BTN_0 >> i; if (jack->type & testbit) - input_report_key(jack->input_dev, jack->key[i], + input_report_key(idev, jack->key[i], status & testbit); } for (i = 0; i < ARRAY_SIZE(jack_switch_types); i++) { int testbit = 1 << i; if (jack->type & testbit) - input_report_switch(jack->input_dev, + input_report_switch(idev, jack_switch_types[i], status & testbit); } - input_sync(jack->input_dev); - mutex_unlock(&jack->input_dev_lock); + input_sync(idev); + input_put_device(idev); #endif /* CONFIG_SND_JACK_INPUT_DEV */ } EXPORT_SYMBOL(snd_jack_report); diff --git a/sound/isa/sb/sb16_csp.c b/sound/isa/sb/sb16_csp.c index c16c8151160c3..970aef2cf513a 100644 --- a/sound/isa/sb/sb16_csp.c +++ b/sound/isa/sb/sb16_csp.c @@ -116,7 +116,7 @@ static void info_read(struct snd_info_entry *entry, struct snd_info_buffer *buff int snd_sb_csp_new(struct snd_sb *chip, int device, struct snd_hwdep ** rhwdep) { struct snd_sb_csp *p; - int uninitialized_var(version); + int version; int err; struct snd_hwdep *hw; diff --git a/sound/pci/ac97/ac97_codec.c b/sound/pci/ac97/ac97_codec.c index a276c4283c7bb..3f13666a01904 100644 --- a/sound/pci/ac97/ac97_codec.c +++ b/sound/pci/ac97/ac97_codec.c @@ -2026,8 +2026,8 @@ int snd_ac97_mixer(struct snd_ac97_bus *bus, struct snd_ac97_template *template, .dev_disconnect = snd_ac97_dev_disconnect, }; - if (rac97) - *rac97 = NULL; + if (!rac97) + return -EINVAL; if (snd_BUG_ON(!bus || !template)) return -EINVAL; if (snd_BUG_ON(template->num >= 4)) diff --git a/sound/soc/codecs/cs42l51-i2c.c b/sound/soc/codecs/cs42l51-i2c.c index 4b5731a418762..cd93e93a59832 100644 --- a/sound/soc/codecs/cs42l51-i2c.c +++ b/sound/soc/codecs/cs42l51-i2c.c @@ -23,6 +23,12 @@ static struct i2c_device_id cs42l51_i2c_id[] = { }; MODULE_DEVICE_TABLE(i2c, cs42l51_i2c_id); +const struct of_device_id cs42l51_of_match[] = { + { .compatible = "cirrus,cs42l51", }, + { } +}; +MODULE_DEVICE_TABLE(of, cs42l51_of_match); + static int cs42l51_i2c_probe(struct i2c_client *i2c, const struct i2c_device_id *id) { diff --git a/sound/soc/codecs/cs42l51.c b/sound/soc/codecs/cs42l51.c index 5080d7a3c2798..662f1f85ba36f 100644 --- a/sound/soc/codecs/cs42l51.c +++ b/sound/soc/codecs/cs42l51.c @@ -563,13 +563,6 @@ error: } EXPORT_SYMBOL_GPL(cs42l51_probe); -const struct of_device_id cs42l51_of_match[] = { - { .compatible = "cirrus,cs42l51", }, - { } -}; -MODULE_DEVICE_TABLE(of, cs42l51_of_match); -EXPORT_SYMBOL_GPL(cs42l51_of_match); - MODULE_AUTHOR("Arnaud Patard "); MODULE_DESCRIPTION("Cirrus Logic CS42L51 ALSA SoC Codec Driver"); MODULE_LICENSE("GPL"); diff --git a/sound/soc/codecs/cs42l51.h b/sound/soc/codecs/cs42l51.h index 0ca805492ac4b..8c55bf384bc65 100644 --- a/sound/soc/codecs/cs42l51.h +++ b/sound/soc/codecs/cs42l51.h @@ -22,7 +22,6 @@ struct device; extern const struct regmap_config cs42l51_regmap; int cs42l51_probe(struct device *dev, struct regmap *regmap); -extern const struct of_device_id cs42l51_of_match[]; #define CS42L51_CHIP_ID 0x1B #define CS42L51_CHIP_REV_A 0x00 diff --git a/sound/soc/codecs/es8316.c b/sound/soc/codecs/es8316.c index 57130edaf3aba..834e542021fee 100644 --- a/sound/soc/codecs/es8316.c +++ b/sound/soc/codecs/es8316.c @@ -45,7 +45,12 @@ static const SNDRV_CTL_TLVD_DECLARE_DB_SCALE(dac_vol_tlv, -9600, 50, 1); static const SNDRV_CTL_TLVD_DECLARE_DB_SCALE(adc_vol_tlv, -9600, 50, 1); static const SNDRV_CTL_TLVD_DECLARE_DB_SCALE(alc_max_gain_tlv, -650, 150, 0); static const SNDRV_CTL_TLVD_DECLARE_DB_SCALE(alc_min_gain_tlv, -1200, 150, 0); -static const SNDRV_CTL_TLVD_DECLARE_DB_SCALE(alc_target_tlv, -1650, 150, 0); + +static const SNDRV_CTL_TLVD_DECLARE_DB_RANGE(alc_target_tlv, + 0, 10, TLV_DB_SCALE_ITEM(-1650, 150, 0), + 11, 11, TLV_DB_SCALE_ITEM(-150, 0, 0), +); + static const SNDRV_CTL_TLVD_DECLARE_DB_RANGE(hpmixer_gain_tlv, 0, 4, TLV_DB_SCALE_ITEM(-1200, 150, 0), 8, 11, TLV_DB_SCALE_ITEM(-450, 150, 0), @@ -107,7 +112,7 @@ static const struct snd_kcontrol_new es8316_snd_controls[] = { alc_max_gain_tlv), SOC_SINGLE_TLV("ALC Capture Min Volume", ES8316_ADC_ALC2, 0, 28, 0, alc_min_gain_tlv), - SOC_SINGLE_TLV("ALC Capture Target Volume", ES8316_ADC_ALC3, 4, 10, 0, + SOC_SINGLE_TLV("ALC Capture Target Volume", ES8316_ADC_ALC3, 4, 11, 0, alc_target_tlv), SOC_SINGLE("ALC Capture Hold Time", ES8316_ADC_ALC3, 0, 10, 0), SOC_SINGLE("ALC Capture Decay Time", ES8316_ADC_ALC4, 4, 10, 0), diff --git a/sound/soc/codecs/wm8904.c b/sound/soc/codecs/wm8904.c index d14e851b91605..03d3b0f17f877 100644 --- a/sound/soc/codecs/wm8904.c +++ b/sound/soc/codecs/wm8904.c @@ -2264,6 +2264,9 @@ static int wm8904_i2c_probe(struct i2c_client *i2c, regmap_update_bits(wm8904->regmap, WM8904_BIAS_CONTROL_0, WM8904_POBCTRL, 0); + /* Fill the cache for the ADC test register */ + regmap_read(wm8904->regmap, WM8904_ADC_TEST_0, &val); + /* Can leave the device powered off until we need it */ regcache_cache_only(wm8904->regmap, true); regulator_bulk_disable(ARRAY_SIZE(wm8904->supplies), wm8904->supplies); diff --git a/sound/soc/fsl/fsl_spdif.c b/sound/soc/fsl/fsl_spdif.c index 740b90df44bb5..0a1ba64ed63cf 100644 --- a/sound/soc/fsl/fsl_spdif.c +++ b/sound/soc/fsl/fsl_spdif.c @@ -614,6 +614,8 @@ static int fsl_spdif_trigger(struct snd_pcm_substream *substream, case SNDRV_PCM_TRIGGER_PAUSE_PUSH: regmap_update_bits(regmap, REG_SPDIF_SCR, dmaen, 0); regmap_update_bits(regmap, REG_SPDIF_SIE, intr, 0); + regmap_write(regmap, REG_SPDIF_STL, 0x0); + regmap_write(regmap, REG_SPDIF_STR, 0x0); break; default: return -EINVAL; diff --git a/sound/usb/endpoint.c b/sound/usb/endpoint.c index e428d8b36c00a..56119a96d3509 100644 --- a/sound/usb/endpoint.c +++ b/sound/usb/endpoint.c @@ -324,7 +324,7 @@ static void queue_pending_output_urbs(struct snd_usb_endpoint *ep) while (test_bit(EP_FLAG_RUNNING, &ep->flags)) { unsigned long flags; - struct snd_usb_packet_info *uninitialized_var(packet); + struct snd_usb_packet_info *packet; struct snd_urb_ctx *ctx = NULL; int err, i; diff --git a/tools/perf/tests/shell/test_uprobe_from_different_cu.sh b/tools/perf/tests/shell/test_uprobe_from_different_cu.sh new file mode 100644 index 0000000000000..319f36ebb9a40 --- /dev/null +++ b/tools/perf/tests/shell/test_uprobe_from_different_cu.sh @@ -0,0 +1,83 @@ +#!/bin/bash +# test perf probe of function from different CU +# SPDX-License-Identifier: GPL-2.0 + +set -e + +# skip if there's no gcc +if ! [ -x "$(command -v gcc)" ]; then + echo "failed: no gcc compiler" + exit 2 +fi + +temp_dir=$(mktemp -d /tmp/perf-uprobe-different-cu-sh.XXXXXXXXXX) + +cleanup() +{ + trap - EXIT TERM INT + if [[ "${temp_dir}" =~ ^/tmp/perf-uprobe-different-cu-sh.*$ ]]; then + echo "--- Cleaning up ---" + perf probe -x ${temp_dir}/testfile -d foo || true + rm -f "${temp_dir}/"* + rmdir "${temp_dir}" + fi +} + +trap_cleanup() +{ + cleanup + exit 1 +} + +trap trap_cleanup EXIT TERM INT + +cat > ${temp_dir}/testfile-foo.h << EOF +struct t +{ + int *p; + int c; +}; + +extern int foo (int i, struct t *t); +EOF + +cat > ${temp_dir}/testfile-foo.c << EOF +#include "testfile-foo.h" + +int +foo (int i, struct t *t) +{ + int j, res = 0; + for (j = 0; j < i && j < t->c; j++) + res += t->p[j]; + + return res; +} +EOF + +cat > ${temp_dir}/testfile-main.c << EOF +#include "testfile-foo.h" + +static struct t g; + +int +main (int argc, char **argv) +{ + int i; + int j[argc]; + g.c = argc; + g.p = j; + for (i = 0; i < argc; i++) + j[i] = (int) argv[i][0]; + return foo (3, &g); +} +EOF + +gcc -g -Og -flto -c ${temp_dir}/testfile-foo.c -o ${temp_dir}/testfile-foo.o +gcc -g -Og -c ${temp_dir}/testfile-main.c -o ${temp_dir}/testfile-main.o +gcc -g -Og -o ${temp_dir}/testfile ${temp_dir}/testfile-foo.o ${temp_dir}/testfile-main.o + +perf probe -x ${temp_dir}/testfile --funcs foo +perf probe -x ${temp_dir}/testfile foo + +cleanup diff --git a/tools/perf/util/dwarf-aux.c b/tools/perf/util/dwarf-aux.c index 6de57d9ee7cc2..db099dc20a682 100644 --- a/tools/perf/util/dwarf-aux.c +++ b/tools/perf/util/dwarf-aux.c @@ -1020,7 +1020,7 @@ int die_get_varname(Dwarf_Die *vr_die, struct strbuf *buf) ret = die_get_typename(vr_die, buf); if (ret < 0) { pr_debug("Failed to get type, make it unknown.\n"); - ret = strbuf_add(buf, " (unknown_type)", 14); + ret = strbuf_add(buf, "(unknown_type)", 14); } return ret < 0 ? ret : strbuf_addf(buf, "\t%s", dwarf_diename(vr_die)); diff --git a/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c b/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c index e2a6c22959f26..aabd423785520 100644 --- a/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c +++ b/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c @@ -1499,6 +1499,8 @@ static void intel_pt_calc_cbr(struct intel_pt_decoder *decoder) decoder->cbr = cbr; decoder->cbr_cyc_to_tsc = decoder->max_non_turbo_ratio_fp / cbr; + decoder->cyc_ref_timestamp = decoder->timestamp; + decoder->cycle_cnt = 0; } static void intel_pt_calc_cyc_timestamp(struct intel_pt_decoder *decoder)