diff options
44 files changed, 643 insertions, 155 deletions
diff --git a/arch/arc/boot/dts/hsdk.dts b/arch/arc/boot/dts/hsdk.dts index 7425bb0f2d1b..acfbed41b020 100644 --- a/arch/arc/boot/dts/hsdk.dts +++ b/arch/arc/boot/dts/hsdk.dts @@ -11,7 +11,6 @@ */ /dts-v1/; -#include <dt-bindings/net/ti-dp83867.h> #include <dt-bindings/reset/snps,hsdk-reset.h> / { @@ -167,6 +166,24 @@ #clock-cells = <0>; }; + gpu_core_clk: gpu-core-clk { + compatible = "fixed-clock"; + clock-frequency = <400000000>; + #clock-cells = <0>; + }; + + gpu_dma_clk: gpu-dma-clk { + compatible = "fixed-clock"; + clock-frequency = <400000000>; + #clock-cells = <0>; + }; + + gpu_cfg_clk: gpu-cfg-clk { + compatible = "fixed-clock"; + clock-frequency = <200000000>; + #clock-cells = <0>; + }; + dmac_core_clk: dmac-core-clk { compatible = "fixed-clock"; clock-frequency = <400000000>; @@ -187,6 +204,7 @@ interrupt-names = "macirq"; phy-mode = "rgmii"; snps,pbl = <32>; + snps,multicast-filter-bins = <256>; clocks = <&gmacclk>; clock-names = "stmmaceth"; phy-handle = <&phy0>; @@ -195,15 +213,15 @@ mac-address = [00 00 00 00 00 00]; /* Filled in by U-Boot */ dma-coherent; + tx-fifo-depth = <4096>; + rx-fifo-depth = <4096>; + mdio { #address-cells = <1>; #size-cells = <0>; compatible = "snps,dwmac-mdio"; phy0: ethernet-phy@0 { reg = <0>; - ti,rx-internal-delay = <DP83867_RGMIIDCTL_2_00_NS>; - ti,tx-internal-delay = <DP83867_RGMIIDCTL_2_00_NS>; - ti,fifo-depth = <DP83867_PHYCR_FIFO_DEPTH_4_B_NIB>; }; }; }; @@ -237,6 +255,14 @@ dma-coherent; }; + creg_gpio: gpio@14b0 { + compatible = "snps,creg-gpio-hsdk"; + reg = <0x14b0 0x4>; + gpio-controller; + #gpio-cells = <2>; + ngpios = <2>; + }; + gpio: gpio@3000 { compatible = "snps,dw-apb-gpio"; reg = <0x3000 0x20>; @@ -252,6 +278,17 @@ }; }; + gpu_3d: gpu@90000 { + compatible = "vivante,gc"; + reg = <0x90000 0x4000>; + clocks = <&gpu_dma_clk>, + <&gpu_cfg_clk>, + <&gpu_core_clk>, + <&gpu_core_clk>; + clock-names = "bus", "reg", "core", "shader"; + interrupts = <28>; + }; + dmac: dmac@80000 { compatible = "snps,axi-dma-1.01a"; reg = <0x80000 0x400>; diff --git a/arch/arc/configs/hsdk_defconfig b/arch/arc/configs/hsdk_defconfig index 0e5fd29ed238..c8fb5d60c53f 100644 --- a/arch/arc/configs/hsdk_defconfig +++ b/arch/arc/configs/hsdk_defconfig @@ -49,10 +49,12 @@ CONFIG_SERIAL_OF_PLATFORM=y CONFIG_GPIOLIB=y CONFIG_GPIO_SYSFS=y CONFIG_GPIO_DWAPB=y +CONFIG_GPIO_SNPS_CREG=y # CONFIG_HWMON is not set CONFIG_DRM=y # CONFIG_DRM_FBDEV_EMULATION is not set CONFIG_DRM_UDL=y +CONFIG_DRM_ETNAVIV=y CONFIG_FB=y CONFIG_FRAMEBUFFER_CONSOLE=y CONFIG_USB_EHCI_HCD=y @@ -64,7 +66,6 @@ CONFIG_MMC=y CONFIG_MMC_SDHCI=y CONFIG_MMC_SDHCI_PLTFM=y CONFIG_MMC_DW=y -# CONFIG_IOMMU_SUPPORT is not set CONFIG_EXT3_FS=y CONFIG_VFAT_FS=y CONFIG_TMPFS=y diff --git a/arch/arc/include/asm/cmpxchg.h b/arch/arc/include/asm/cmpxchg.h index d819de1c5d10..3ea4112c8302 100644 --- a/arch/arc/include/asm/cmpxchg.h +++ b/arch/arc/include/asm/cmpxchg.h @@ -92,8 +92,11 @@ __cmpxchg(volatile void *ptr, unsigned long expected, unsigned long new) #endif /* CONFIG_ARC_HAS_LLSC */ -#define cmpxchg(ptr, o, n) ((typeof(*(ptr)))__cmpxchg((ptr), \ - (unsigned long)(o), (unsigned long)(n))) +#define cmpxchg(ptr, o, n) ({ \ + (typeof(*(ptr)))__cmpxchg((ptr), \ + (unsigned long)(o), \ + (unsigned long)(n)); \ +}) /* * atomic_cmpxchg is same as cmpxchg @@ -198,8 +201,11 @@ static inline unsigned long __xchg(unsigned long val, volatile void *ptr, return __xchg_bad_pointer(); } -#define xchg(ptr, with) ((typeof(*(ptr)))__xchg((unsigned long)(with), (ptr), \ - sizeof(*(ptr)))) +#define xchg(ptr, with) ({ \ + (typeof(*(ptr)))__xchg((unsigned long)(with), \ + (ptr), \ + sizeof(*(ptr))); \ +}) #endif /* CONFIG_ARC_PLAT_EZNPS */ diff --git a/arch/arc/mm/fault.c b/arch/arc/mm/fault.c index 8df1638259f3..6836095251ed 100644 --- a/arch/arc/mm/fault.c +++ b/arch/arc/mm/fault.c @@ -66,7 +66,7 @@ void do_page_fault(unsigned long address, struct pt_regs *regs) struct vm_area_struct *vma = NULL; struct task_struct *tsk = current; struct mm_struct *mm = tsk->mm; - int si_code = 0; + int si_code = SEGV_MAPERR; int ret; vm_fault_t fault; int write = regs->ecr_cause & ECR_C_PROTV_STORE; /* ST/EX */ @@ -81,16 +81,14 @@ void do_page_fault(unsigned long address, struct pt_regs *regs) * only copy the information from the master page table, * nothing more. */ - if (address >= VMALLOC_START) { + if (address >= VMALLOC_START && !user_mode(regs)) { ret = handle_kernel_vaddr_fault(address); if (unlikely(ret)) - goto bad_area_nosemaphore; + goto no_context; else return; } - si_code = SEGV_MAPERR; - /* * If we're in an interrupt or have no user * context, we must not take the fault.. @@ -198,7 +196,6 @@ good_area: bad_area: up_read(&mm->mmap_sem); -bad_area_nosemaphore: /* User mode accesses just cause a SIGSEGV */ if (user_mode(regs)) { tsk->thread.fault_address = address; diff --git a/arch/arc/mm/tlb.c b/arch/arc/mm/tlb.c index 4097764fea23..fa18c00b0cfd 100644 --- a/arch/arc/mm/tlb.c +++ b/arch/arc/mm/tlb.c @@ -911,9 +911,11 @@ void do_tlb_overlap_fault(unsigned long cause, unsigned long address, struct pt_regs *regs) { struct cpuinfo_arc_mmu *mmu = &cpuinfo_arc700[smp_processor_id()].mmu; - unsigned int pd0[mmu->ways]; unsigned long flags; - int set; + int set, n_ways = mmu->ways; + + n_ways = min(n_ways, 4); + BUG_ON(mmu->ways > 4); local_irq_save(flags); @@ -921,9 +923,10 @@ void do_tlb_overlap_fault(unsigned long cause, unsigned long address, for (set = 0; set < mmu->sets; set++) { int is_valid, way; + unsigned int pd0[4]; /* read out all the ways of current set */ - for (way = 0, is_valid = 0; way < mmu->ways; way++) { + for (way = 0, is_valid = 0; way < n_ways; way++) { write_aux_reg(ARC_REG_TLBINDEX, SET_WAY_TO_IDX(mmu, set, way)); write_aux_reg(ARC_REG_TLBCOMMAND, TLBRead); @@ -937,14 +940,14 @@ void do_tlb_overlap_fault(unsigned long cause, unsigned long address, continue; /* Scan the set for duplicate ways: needs a nested loop */ - for (way = 0; way < mmu->ways - 1; way++) { + for (way = 0; way < n_ways - 1; way++) { int n; if (!pd0[way]) continue; - for (n = way + 1; n < mmu->ways; n++) { + for (n = way + 1; n < n_ways; n++) { if (pd0[way] != pd0[n]) continue; diff --git a/arch/nds32/include/asm/bitfield.h b/arch/nds32/include/asm/bitfield.h index e75212c76b20..b02a58e71f80 100644 --- a/arch/nds32/include/asm/bitfield.h +++ b/arch/nds32/include/asm/bitfield.h @@ -937,7 +937,7 @@ #define FPCSR_mskDNIT ( 0x1 << FPCSR_offDNIT ) #define FPCSR_mskRIT ( 0x1 << FPCSR_offRIT ) #define FPCSR_mskALL (FPCSR_mskIVO | FPCSR_mskDBZ | FPCSR_mskOVF | FPCSR_mskUDF | FPCSR_mskIEX) -#define FPCSR_mskALLE_NO_UDFE (FPCSR_mskIVOE | FPCSR_mskDBZE | FPCSR_mskOVFE | FPCSR_mskIEXE) +#define FPCSR_mskALLE_NO_UDF_IEXE (FPCSR_mskIVOE | FPCSR_mskDBZE | FPCSR_mskOVFE) #define FPCSR_mskALLE (FPCSR_mskIVOE | FPCSR_mskDBZE | FPCSR_mskOVFE | FPCSR_mskUDFE | FPCSR_mskIEXE) #define FPCSR_mskALLT (FPCSR_mskIVOT | FPCSR_mskDBZT | FPCSR_mskOVFT | FPCSR_mskUDFT | FPCSR_mskIEXT |FPCSR_mskDNIT | FPCSR_mskRIT) diff --git a/arch/nds32/include/asm/fpu.h b/arch/nds32/include/asm/fpu.h index 019f1bcfc5ee..8294ed4aaa2c 100644 --- a/arch/nds32/include/asm/fpu.h +++ b/arch/nds32/include/asm/fpu.h @@ -36,7 +36,7 @@ extern int do_fpuemu(struct pt_regs *regs, struct fpu_struct *fpu); * enabled by default and kerenl will re-execute it by fpu emulator * when getting underflow exception. */ -#define FPCSR_INIT FPCSR_mskUDFE +#define FPCSR_INIT (FPCSR_mskUDFE | FPCSR_mskIEXE) #else #define FPCSR_INIT 0x0UL #endif diff --git a/arch/nds32/include/asm/fpuemu.h b/arch/nds32/include/asm/fpuemu.h index c4bd0c7faa75..63e7ef5f7969 100644 --- a/arch/nds32/include/asm/fpuemu.h +++ b/arch/nds32/include/asm/fpuemu.h @@ -13,6 +13,12 @@ void fsubs(void *ft, void *fa, void *fb); void fmuls(void *ft, void *fa, void *fb); void fdivs(void *ft, void *fa, void *fb); void fs2d(void *ft, void *fa); +void fs2si(void *ft, void *fa); +void fs2si_z(void *ft, void *fa); +void fs2ui(void *ft, void *fa); +void fs2ui_z(void *ft, void *fa); +void fsi2s(void *ft, void *fa); +void fui2s(void *ft, void *fa); void fsqrts(void *ft, void *fa); void fnegs(void *ft, void *fa); int fcmps(void *ft, void *fa, void *fb, int cop); @@ -26,6 +32,12 @@ void fmuld(void *ft, void *fa, void *fb); void fdivd(void *ft, void *fa, void *fb); void fsqrtd(void *ft, void *fa); void fd2s(void *ft, void *fa); +void fd2si(void *ft, void *fa); +void fd2si_z(void *ft, void *fa); +void fd2ui(void *ft, void *fa); +void fd2ui_z(void *ft, void *fa); +void fsi2d(void *ft, void *fa); +void fui2d(void *ft, void *fa); void fnegd(void *ft, void *fa); int fcmpd(void *ft, void *fa, void *fb, int cop); diff --git a/arch/nds32/include/asm/syscalls.h b/arch/nds32/include/asm/syscalls.h index f3b16f602cb5..4e7216082a67 100644 --- a/arch/nds32/include/asm/syscalls.h +++ b/arch/nds32/include/asm/syscalls.h @@ -7,7 +7,7 @@ asmlinkage long sys_cacheflush(unsigned long addr, unsigned long len, unsigned int op); asmlinkage long sys_fadvise64_64_wrapper(int fd, int advice, loff_t offset, loff_t len); asmlinkage long sys_rt_sigreturn_wrapper(void); -asmlinkage long sys_udftrap(int option); +asmlinkage long sys_fp_udfiex_crtl(int cmd, int act); #include <asm-generic/syscalls.h> diff --git a/arch/nds32/include/uapi/asm/fp_udfiex_crtl.h b/arch/nds32/include/uapi/asm/fp_udfiex_crtl.h new file mode 100644 index 000000000000..d54a5d6c6538 --- /dev/null +++ b/arch/nds32/include/uapi/asm/fp_udfiex_crtl.h @@ -0,0 +1,16 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright (C) 2005-2019 Andes Technology Corporation */ +#ifndef _FP_UDF_IEX_CRTL_H +#define _FP_UDF_IEX_CRTL_H + +/* + * The cmd list of sys_fp_udfiex_crtl() + */ +/* Disable UDF or IEX trap based on the content of parameter act */ +#define DISABLE_UDF_IEX_TRAP 0 +/* Enable UDF or IEX trap based on the content of parameter act */ +#define ENABLE_UDF_IEX_TRAP 1 +/* Get current status of UDF and IEX trap */ +#define GET_UDF_IEX_TRAP 2 + +#endif /* _FP_UDF_IEX_CRTL_H */ diff --git a/arch/nds32/include/uapi/asm/sigcontext.h b/arch/nds32/include/uapi/asm/sigcontext.h index 628ff6b75825..dc89af7ddcc3 100644 --- a/arch/nds32/include/uapi/asm/sigcontext.h +++ b/arch/nds32/include/uapi/asm/sigcontext.h @@ -13,14 +13,24 @@ struct fpu_struct { unsigned long long fd_regs[32]; unsigned long fpcsr; /* - * UDF_trap is used to recognize whether underflow trap is enabled - * or not. When UDF_trap == 1, this process will be traped and then - * get a SIGFPE signal when encountering an underflow exception. - * UDF_trap is only modified through setfputrap syscall. Therefore, - * UDF_trap needn't be saved or loaded to context in each context - * switch. + * When CONFIG_SUPPORT_DENORMAL_ARITHMETIC is defined, kernel prevents + * hardware from treating the denormalized output as an underflow case + * and rounding it to a normal number. Hence kernel enables the UDF and + * IEX trap in the fpcsr register to step in the calculation. + * However, the UDF and IEX trap enable bit in $fpcsr also lose + * their use. + * + * UDF_IEX_trap replaces the feature of UDF and IEX trap enable bit in + * $fpcsr to control the trap of underflow and inexact. The bit filed + * of UDF_IEX_trap is the same as $fpcsr, 10th bit is used to enable UDF + * exception trapping and 11th bit is used to enable IEX exception + * trapping. + * + * UDF_IEX_trap is only modified through fp_udfiex_crtl syscall. + * Therefore, UDF_IEX_trap needn't be saved and restored in each + * context switch. */ - unsigned long UDF_trap; + unsigned long UDF_IEX_trap; }; struct zol_struct { diff --git a/arch/nds32/include/uapi/asm/udftrap.h b/arch/nds32/include/uapi/asm/udftrap.h deleted file mode 100644 index 433f79d679c0..000000000000 --- a/arch/nds32/include/uapi/asm/udftrap.h +++ /dev/null @@ -1,13 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* Copyright (C) 2005-2018 Andes Technology Corporation */ -#ifndef _ASM_SETFPUTRAP -#define _ASM_SETFPUTRAP - -/* - * Options for setfputrap system call - */ -#define DISABLE_UDFTRAP 0 /* disable underflow exception trap */ -#define ENABLE_UDFTRAP 1 /* enable undeflos exception trap */ -#define GET_UDFTRAP 2 /* only get undeflos exception trap status */ - -#endif /* _ASM_CACHECTL */ diff --git a/arch/nds32/include/uapi/asm/unistd.h b/arch/nds32/include/uapi/asm/unistd.h index c691735017ed..a0b2f7b9c0f2 100644 --- a/arch/nds32/include/uapi/asm/unistd.h +++ b/arch/nds32/include/uapi/asm/unistd.h @@ -11,6 +11,6 @@ /* Additional NDS32 specific syscalls. */ #define __NR_cacheflush (__NR_arch_specific_syscall) -#define __NR_udftrap (__NR_arch_specific_syscall + 1) +#define __NR_fp_udfiex_crtl (__NR_arch_specific_syscall + 1) __SYSCALL(__NR_cacheflush, sys_cacheflush) -__SYSCALL(__NR_udftrap, sys_udftrap) +__SYSCALL(__NR_fp_udfiex_crtl, sys_fp_udfiex_crtl) diff --git a/arch/nds32/kernel/fpu.c b/arch/nds32/kernel/fpu.c index fddd40c7a16f..cf0b8760f261 100644 --- a/arch/nds32/kernel/fpu.c +++ b/arch/nds32/kernel/fpu.c @@ -14,7 +14,7 @@ const struct fpu_struct init_fpuregs = { .fd_regs = {[0 ... 31] = sNAN64}, .fpcsr = FPCSR_INIT, #if IS_ENABLED(CONFIG_SUPPORT_DENORMAL_ARITHMETIC) - .UDF_trap = 0 + .UDF_IEX_trap = 0 #endif }; @@ -178,7 +178,7 @@ inline void do_fpu_context_switch(struct pt_regs *regs) /* First time FPU user. */ load_fpu(&init_fpuregs); #if IS_ENABLED(CONFIG_SUPPORT_DENORMAL_ARITHMETIC) - current->thread.fpu.UDF_trap = init_fpuregs.UDF_trap; + current->thread.fpu.UDF_IEX_trap = init_fpuregs.UDF_IEX_trap; #endif set_used_math(); } @@ -206,7 +206,7 @@ inline void handle_fpu_exception(struct pt_regs *regs) unsigned int fpcsr; int si_code = 0, si_signo = SIGFPE; #if IS_ENABLED(CONFIG_SUPPORT_DENORMAL_ARITHMETIC) - unsigned long redo_except = FPCSR_mskDNIT|FPCSR_mskUDFT; + unsigned long redo_except = FPCSR_mskDNIT|FPCSR_mskUDFT|FPCSR_mskIEXT; #else unsigned long redo_except = FPCSR_mskDNIT; #endif @@ -215,21 +215,18 @@ inline void handle_fpu_exception(struct pt_regs *regs) fpcsr = current->thread.fpu.fpcsr; if (fpcsr & redo_except) { -#if IS_ENABLED(CONFIG_SUPPORT_DENORMAL_ARITHMETIC) - if (fpcsr & FPCSR_mskUDFT) - current->thread.fpu.fpcsr &= ~FPCSR_mskIEX; -#endif si_signo = do_fpuemu(regs, ¤t->thread.fpu); fpcsr = current->thread.fpu.fpcsr; - if (!si_signo) + if (!si_signo) { + current->thread.fpu.fpcsr &= ~(redo_except); goto done; + } } else if (fpcsr & FPCSR_mskRIT) { if (!user_mode(regs)) do_exit(SIGILL); si_signo = SIGILL; } - switch (si_signo) { case SIGFPE: fill_sigfpe_signo(fpcsr, &si_code); diff --git a/arch/nds32/kernel/sys_nds32.c b/arch/nds32/kernel/sys_nds32.c index 0835277636ce..cb2d1e219bb3 100644 --- a/arch/nds32/kernel/sys_nds32.c +++ b/arch/nds32/kernel/sys_nds32.c @@ -6,8 +6,8 @@ #include <asm/cachectl.h> #include <asm/proc-fns.h> -#include <asm/udftrap.h> #include <asm/fpu.h> +#include <asm/fp_udfiex_crtl.h> SYSCALL_DEFINE6(mmap2, unsigned long, addr, unsigned long, len, unsigned long, prot, unsigned long, flags, @@ -51,31 +51,33 @@ SYSCALL_DEFINE3(cacheflush, unsigned int, start, unsigned int, end, int, cache) return 0; } -SYSCALL_DEFINE1(udftrap, int, option) +SYSCALL_DEFINE2(fp_udfiex_crtl, unsigned int, cmd, unsigned int, act) { #if IS_ENABLED(CONFIG_SUPPORT_DENORMAL_ARITHMETIC) - int old_udftrap; + int old_udf_iex; if (!used_math()) { load_fpu(&init_fpuregs); - current->thread.fpu.UDF_trap = init_fpuregs.UDF_trap; + current->thread.fpu.UDF_IEX_trap = init_fpuregs.UDF_IEX_trap; set_used_math(); } - old_udftrap = current->thread.fpu.UDF_trap; - switch (option) { - case DISABLE_UDFTRAP: - current->thread.fpu.UDF_trap = 0; + old_udf_iex = current->thread.fpu.UDF_IEX_trap; + act &= (FPCSR_mskUDFE | FPCSR_mskIEXE); + + switch (cmd) { + case DISABLE_UDF_IEX_TRAP: + current->thread.fpu.UDF_IEX_trap &= ~act; break; - case ENABLE_UDFTRAP: - current->thread.fpu.UDF_trap = FPCSR_mskUDFE; + case ENABLE_UDF_IEX_TRAP: + current->thread.fpu.UDF_IEX_trap |= act; break; - case GET_UDFTRAP: + case GET_UDF_IEX_TRAP: break; default: return -EINVAL; } - return old_udftrap; + return old_udf_iex; #else return -ENOTSUPP; #endif diff --git a/arch/nds32/math-emu/Makefile b/arch/nds32/math-emu/Makefile index 14fa01f4574a..3bed7e5d5d05 100644 --- a/arch/nds32/math-emu/Makefile +++ b/arch/nds32/math-emu/Makefile @@ -5,4 +5,6 @@ obj-y := fpuemu.o \ fdivd.o fmuld.o fsubd.o faddd.o fs2d.o fsqrtd.o fcmpd.o fnegs.o \ - fdivs.o fmuls.o fsubs.o fadds.o fd2s.o fsqrts.o fcmps.o fnegd.o + fd2si.o fd2ui.o fd2siz.o fd2uiz.o fsi2d.o fui2d.o \ + fdivs.o fmuls.o fsubs.o fadds.o fd2s.o fsqrts.o fcmps.o fnegd.o \ + fs2si.o fs2ui.o fs2siz.o fs2uiz.o fsi2s.o fui2s.o diff --git a/arch/nds32/math-emu/fd2si.c b/arch/nds32/math-emu/fd2si.c new file mode 100644 index 000000000000..fae3e16a0a10 --- /dev/null +++ b/arch/nds32/math-emu/fd2si.c @@ -0,0 +1,30 @@ +// SPDX-License-Identifier: GPL-2.0 +// Copyright (C) 2005-2019 Andes Technology Corporation +#include <linux/uaccess.h> + +#include <asm/sfp-machine.h> +#include <math-emu/soft-fp.h> +#include <math-emu/double.h> + +void fd2si(void *ft, void *fa) +{ + int r; + + FP_DECL_D(A); + FP_DECL_EX; + + FP_UNPACK_DP(A, fa); + + if (A_c == FP_CLS_INF) { + *(int *)ft = (A_s == 0) ? 0x7fffffff : 0x80000000; + __FPU_FPCSR |= FP_EX_INVALID; + } else if (A_c == FP_CLS_NAN) { + *(int *)ft = 0xffffffff; + __FPU_FPCSR |= FP_EX_INVALID; + } else { + FP_TO_INT_ROUND_D(r, A, 32, 1); + __FPU_FPCSR |= FP_CUR_EXCEPTIONS; + *(int *)ft = r; + } + +} diff --git a/arch/nds32/math-emu/fd2siz.c b/arch/nds32/math-emu/fd2siz.c new file mode 100644 index 000000000000..92fe6774f112 --- /dev/null +++ b/arch/nds32/math-emu/fd2siz.c @@ -0,0 +1,30 @@ +// SPDX-License-Identifier: GPL-2.0 +// Copyright (C) 2005-2019 Andes Technology Corporation +#include <linux/uaccess.h> + +#include <asm/sfp-machine.h> +#include <math-emu/soft-fp.h> +#include <math-emu/double.h> + +void fd2si_z(void *ft, void *fa) +{ + int r; + + FP_DECL_D(A); + FP_DECL_EX; + + FP_UNPACK_DP(A, fa); + + if (A_c == FP_CLS_INF) { + *(int *)ft = (A_s == 0) ? 0x7fffffff : 0x80000000; + __FPU_FPCSR |= FP_EX_INVALID; + } else if (A_c == FP_CLS_NAN) { + *(int *)ft = 0xffffffff; + __FPU_FPCSR |= FP_EX_INVALID; + } else { + FP_TO_INT_D(r, A, 32, 1); + __FPU_FPCSR |= FP_CUR_EXCEPTIONS; + *(int *)ft = r; + } + +} diff --git a/arch/nds32/math-emu/fd2ui.c b/arch/nds32/math-emu/fd2ui.c new file mode 100644 index 000000000000..a0423b699aa4 --- /dev/null +++ b/arch/nds32/math-emu/fd2ui.c @@ -0,0 +1,30 @@ +// SPDX-License-Identifier: GPL-2.0 +// Copyright (C) 2005-2019 Andes Technology Corporation +#include <linux/uaccess.h> + +#include <asm/sfp-machine.h> +#include <math-emu/soft-fp.h> +#include <math-emu/double.h> + +void fd2ui(void *ft, void *fa) +{ + unsigned int r; + + FP_DECL_D(A); + FP_DECL_EX; + + FP_UNPACK_DP(A, fa); + + if (A_c == FP_CLS_INF) { + *(unsigned int *)ft = (A_s == 0) ? 0xffffffff : 0x00000000; + __FPU_FPCSR |= FP_EX_INVALID; + } else if (A_c == FP_CLS_NAN) { + *(unsigned int *)ft = 0xffffffff; + __FPU_FPCSR |= FP_EX_INVALID; + } else { + FP_TO_INT_ROUND_D(r, A, 32, 0); + __FPU_FPCSR |= FP_CUR_EXCEPTIONS; + *(unsigned int *)ft = r; + } + +} diff --git a/arch/nds32/math-emu/fd2uiz.c b/arch/nds32/math-emu/fd2uiz.c new file mode 100644 index 000000000000..8ae17cfce90d --- /dev/null +++ b/arch/nds32/math-emu/fd2uiz.c @@ -0,0 +1,30 @@ +// SPDX-License-Identifier: GPL-2.0 +// Copyright (C) 2005-2019 Andes Technology Corporation +#include <linux/uaccess.h> + +#include <asm/sfp-machine.h> +#include <math-emu/soft-fp.h> +#include <math-emu/double.h> + +void fd2ui_z(void *ft, void *fa) +{ + unsigned int r; + + FP_DECL_D(A); + FP_DECL_EX; + + FP_UNPACK_DP(A, fa); + + if (A_c == FP_CLS_INF) { + *(unsigned int *)ft = (A_s == 0) ? 0xffffffff : 0x00000000; + __FPU_FPCSR |= FP_EX_INVALID; + } else if (A_c == FP_CLS_NAN) { + *(unsigned int *)ft = 0xffffffff; + __FPU_FPCSR |= FP_EX_INVALID; + } else { + FP_TO_INT_D(r, A, 32, 0); + __FPU_FPCSR |= FP_CUR_EXCEPTIONS; + *(unsigned int *)ft = r; + } + +} diff --git a/arch/nds32/math-emu/fpuemu.c b/arch/nds32/math-emu/fpuemu.c index 75cf1643fa78..46558a15c0dc 100644 --- a/arch/nds32/math-emu/fpuemu.c +++ b/arch/nds32/math-emu/fpuemu.c @@ -113,6 +113,30 @@ static int fpu_emu(struct fpu_struct *fpu_reg, unsigned long insn) func.b = fs2d; ftype = S1D; break; + case fs2si_op: + func.b = fs2si; + ftype = S1S; + break; + case fs2si_z_op: + func.b = fs2si_z; + ftype = S1S; + break; + case fs2ui_op: + func.b = fs2ui; + ftype = S1S; + break; + case fs2ui_z_op: + func.b = fs2ui_z; + ftype = S1S; + break; + case fsi2s_op: + func.b = fsi2s; + ftype = S1S; + break; + case fui2s_op: + func.b = fui2s; + ftype = S1S; + break; case fsqrts_op: func.b = fsqrts; ftype = S1S; @@ -182,6 +206,30 @@ static int fpu_emu(struct fpu_struct *fpu_reg, unsigned long insn) func.b = fd2s; ftype = D1S; break; + case fd2si_op: + func.b = fd2si; + ftype = D1S; + break; + case fd2si_z_op: + func.b = fd2si_z; + ftype = D1S; + break; + case fd2ui_op: + func.b = fd2ui; + ftype = D1S; + break; + case fd2ui_z_op: + func.b = fd2ui_z; + ftype = D1S; + break; + case fsi2d_op: + func.b = fsi2d; + ftype = D1S; + break; + case fui2d_op: + func.b = fui2d; + ftype = D1S; + break; case fsqrtd_op: func.b = fsqrtd; ftype = D1D; @@ -305,16 +353,16 @@ static int fpu_emu(struct fpu_struct *fpu_reg, unsigned long insn) * If an exception is required, generate a tidy SIGFPE exception. */ #if IS_ENABLED(CONFIG_SUPPORT_DENORMAL_ARITHMETIC) - if (((fpu_reg->fpcsr << 5) & fpu_reg->fpcsr & FPCSR_mskALLE_NO_UDFE) || - ((fpu_reg->fpcsr & FPCSR_mskUDF) && (fpu_reg->UDF_trap))) + if (((fpu_reg->fpcsr << 5) & fpu_reg->fpcsr & FPCSR_mskALLE_NO_UDF_IEXE) + || ((fpu_reg->fpcsr << 5) & (fpu_reg->UDF_IEX_trap))) { #else - if ((fpu_reg->fpcsr << 5) & fpu_reg->fpcsr & FPCSR_mskALLE) + if ((fpu_reg->fpcsr << 5) & fpu_reg->fpcsr & FPCSR_mskALLE) { #endif return SIGFPE; + } return 0; } - int do_fpuemu(struct pt_regs *regs, struct fpu_struct *fpu) { unsigned long insn = 0, addr = regs->ipc; @@ -336,6 +384,7 @@ int do_fpuemu(struct pt_regs *regs, struct fpu_struct *fpu) if (NDS32Insn_OPCODE(insn) != cop0_op) return SIGILL; + switch (NDS32Insn_OPCODE_COP0(insn)) { case fs1_op: case fs2_op: diff --git a/arch/nds32/math-emu/fs2si.c b/arch/nds32/math-emu/fs2si.c new file mode 100644 index 000000000000..b4931d60980e --- /dev/null +++ b/arch/nds32/math-emu/fs2si.c @@ -0,0 +1,29 @@ +// SPDX-License-Identifier: GPL-2.0 +// Copyright (C) 2005-2019 Andes Technology Corporation +#include <linux/uaccess.h> + +#include <asm/sfp-machine.h> +#include <math-emu/soft-fp.h> +#include <math-emu/single.h> + +void fs2si(void *ft, void *fa) +{ + int r; + + FP_DECL_S(A); + FP_DECL_EX; + + FP_UNPACK_SP(A, fa); + + if (A_c == FP_CLS_INF) { + *(int *)ft = (A_s == 0) ? 0x7fffffff : 0x80000000; + __FPU_FPCSR |= FP_EX_INVALID; + } else if (A_c == FP_CLS_NAN) { + *(int *)ft = 0xffffffff; + __FPU_FPCSR |= FP_EX_INVALID; + } else { + FP_TO_INT_ROUND_S(r, A, 32, 1); + __FPU_FPCSR |= FP_CUR_EXCEPTIONS; + *(int *)ft = r; + } +} diff --git a/arch/nds32/math-emu/fs2siz.c b/arch/nds32/math-emu/fs2siz.c new file mode 100644 index 000000000000..1c2b99ce3e38 --- /dev/null +++ b/arch/nds32/math-emu/fs2siz.c @@ -0,0 +1,29 @@ +// SPDX-License-Identifier: GPL-2.0 +// Copyright (C) 2005-2019 Andes Technology Corporation +#include <linux/uaccess.h> + +#include <asm/sfp-machine.h> +#include <math-emu/soft-fp.h> +#include <math-emu/single.h> + +void fs2si_z(void *ft, void *fa) +{ + int r; + + FP_DECL_S(A); + FP_DECL_EX; + + FP_UNPACK_SP(A, fa); + + if (A_c == FP_CLS_INF) { + *(int *)ft = (A_s == 0) ? 0x7fffffff : 0x80000000; + __FPU_FPCSR |= FP_EX_INVALID; + } else if (A_c == FP_CLS_NAN) { + *(int *)ft = 0xffffffff; + __FPU_FPCSR |= FP_EX_INVALID; + } else { + FP_TO_INT_S(r, A, 32, 1); + __FPU_FPCSR |= FP_CUR_EXCEPTIONS; + *(int *)ft = r; + } +} diff --git a/arch/nds32/math-emu/fs2ui.c b/arch/nds32/math-emu/fs2ui.c new file mode 100644 index 000000000000..c337f0384d06 --- /dev/null +++ b/arch/nds32/math-emu/fs2ui.c @@ -0,0 +1,29 @@ +// SPDX-License-Identifier: GPL-2.0 +// Copyright (C) 2005-2019 Andes Technology Corporation +#include <linux/uaccess.h> + +#include <asm/sfp-machine.h> +#include <math-emu/soft-fp.h> +#include <math-emu/single.h> + +void fs2ui(void *ft, void *fa) +{ + unsigned int r; + + FP_DECL_S(A); + FP_DECL_EX; + + FP_UNPACK_SP(A, fa); + + if (A_c == FP_CLS_INF) { + *(unsigned int *)ft = (A_s == 0) ? 0xffffffff : 0x00000000; + __FPU_FPCSR |= FP_EX_INVALID; + } else if (A_c == FP_CLS_NAN) { + *(unsigned int *)ft = 0xffffffff; + __FPU_FPCSR |= FP_EX_INVALID; + } else { + FP_TO_INT_ROUND_S(r, A, 32, 0); + __FPU_FPCSR |= FP_CUR_EXCEPTIONS; + *(unsigned int *)ft = r; + } +} diff --git a/arch/nds32/math-emu/fs2uiz.c b/arch/nds32/math-emu/fs2uiz.c new file mode 100644 index 000000000000..22c5e4768044 --- /dev/null +++ b/arch/nds32/math-emu/fs2uiz.c @@ -0,0 +1,30 @@ +// SPDX-License-Identifier: GPL-2.0 +// Copyright (C) 2005-2019 Andes Technology Corporation +#include <linux/uaccess.h> + +#include <asm/sfp-machine.h> +#include <math-emu/soft-fp.h> +#include <math-emu/single.h> + +void fs2ui_z(void *ft, void *fa) +{ + unsigned int r; + + FP_DECL_S(A); + FP_DECL_EX; + + FP_UNPACK_SP(A, fa); + + if (A_c == FP_CLS_INF) { + *(unsigned int *)ft = (A_s == 0) ? 0xffffffff : 0x00000000; + __FPU_FPCSR |= FP_EX_INVALID; + } else if (A_c == FP_CLS_NAN) { + *(unsigned int *)ft = 0xffffffff; + __FPU_FPCSR |= FP_EX_INVALID; + } else { + FP_TO_INT_S(r, A, 32, 0); + __FPU_FPCSR |= FP_CUR_EXCEPTIONS; + *(unsigned int *)ft = r; + } + +} diff --git a/arch/nds32/math-emu/fsi2d.c b/arch/nds32/math-emu/fsi2d.c new file mode 100644 index 000000000000..6b04cec0c5c5 --- /dev/null +++ b/arch/nds32/math-emu/fsi2d.c @@ -0,0 +1,22 @@ +// SPDX-License-Identifier: GPL-2.0 +// Copyright (C) 2005-2019 Andes Technology Corporation +#include <linux/uaccess.h> + +#include <asm/sfp-machine.h> +#include <math-emu/soft-fp.h> +#include <math-emu/double.h> + +void fsi2d(void *ft, void *fa) +{ + int a = *(int *)fa; + + FP_DECL_D(R); + FP_DECL_EX; + + FP_FROM_INT_D(R, a, 32, int); + + FP_PACK_DP(ft, R); + + __FPU_FPCSR |= FP_CUR_EXCEPTIONS; + +} diff --git a/arch/nds32/math-emu/fsi2s.c b/arch/nds32/math-emu/fsi2s.c new file mode 100644 index 000000000000..689864a5df90 --- /dev/null +++ b/arch/nds32/math-emu/fsi2s.c @@ -0,0 +1,22 @@ +// SPDX-License-Identifier: GPL-2.0 +// Copyright (C) 2005-2019 Andes Technology Corporation +#include <linux/uaccess.h> + +#include <asm/sfp-machine.h> +#include <math-emu/soft-fp.h> +#include <math-emu/single.h> + +void fsi2s(void *ft, void *fa) +{ + int a = *(int *)fa; + + FP_DECL_S(R); + FP_DECL_EX; + + FP_FROM_INT_S(R, a, 32, int); + + FP_PACK_SP(ft, R); + + __FPU_FPCSR |= FP_CUR_EXCEPTIONS; + +} diff --git a/arch/nds32/math-emu/fui2d.c b/arch/nds32/math-emu/fui2d.c new file mode 100644 index 000000000000..9689d33a8d50 --- /dev/null +++ b/arch/nds32/math-emu/fui2d.c @@ -0,0 +1,22 @@ +// SPDX-License-Identifier: GPL-2.0 +// Copyright (C) 2005-2019 Andes Technology Corporation +#include <linux/uaccess.h> + +#include <asm/sfp-machine.h> +#include <math-emu/soft-fp.h> +#include <math-emu/double.h> + +void fui2d(void *ft, void *fa) +{ + unsigned int a = *(unsigned int *)fa; + + FP_DECL_D(R); + FP_DECL_EX; + + FP_FROM_INT_D(R, a, 32, int); + + FP_PACK_DP(ft, R); + + __FPU_FPCSR |= FP_CUR_EXCEPTIONS; + +} diff --git a/arch/nds32/math-emu/fui2s.c b/arch/nds32/math-emu/fui2s.c new file mode 100644 index 000000000000..f70f0762547d --- /dev/null +++ b/arch/nds32/math-emu/fui2s.c @@ -0,0 +1,22 @@ +// SPDX-License-Identifier: GPL-2.0 +// Copyright (C) 2005-2019 Andes Technology Corporation +#include <linux/uaccess.h> + +#include <asm/sfp-machine.h> +#include <math-emu/soft-fp.h> +#include <math-emu/single.h> + +void fui2s(void *ft, void *fa) +{ + unsigned int a = *(unsigned int *)fa; + + FP_DECL_S(R); + FP_DECL_EX; + + FP_FROM_INT_S(R, a, 32, int); + + FP_PACK_SP(ft, R); + + __FPU_FPCSR |= FP_CUR_EXCEPTIONS; + +} diff --git a/arch/sparc/kernel/mdesc.c b/arch/sparc/kernel/mdesc.c index 9a26b442f820..8e645ddac58e 100644 --- a/arch/sparc/kernel/mdesc.c +++ b/arch/sparc/kernel/mdesc.c @@ -356,6 +356,8 @@ static int get_vdev_port_node_info(struct mdesc_handle *md, u64 node, node_info->vdev_port.id = *idp; node_info->vdev_port.name = kstrdup_const(name, GFP_KERNEL); + if (!node_info->vdev_port.name) + return -1; node_info->vdev_port.parent_cfg_hdl = *parent_cfg_hdlp; return 0; diff --git a/arch/sparc/kernel/perf_event.c b/arch/sparc/kernel/perf_event.c index 6de7c684c29f..a58ae9c42803 100644 --- a/arch/sparc/kernel/perf_event.c +++ b/arch/sparc/kernel/perf_event.c @@ -891,6 +891,10 @@ static int sparc_perf_event_set_period(struct perf_event *event, s64 period = hwc->sample_period; int ret = 0; + /* The period may have been changed by PERF_EVENT_IOC_PERIOD */ + if (unlikely(period != hwc->last_period)) + left = period - (hwc->last_period - left); + if (unlikely(left <= -period)) { left = period; local64_set(&hwc->period_left, left); diff --git a/arch/sparc/mm/ultra.S b/arch/sparc/mm/ultra.S index d245f89d1395..d220b6848746 100644 --- a/arch/sparc/mm/ultra.S +++ b/arch/sparc/mm/ultra.S @@ -587,7 +587,7 @@ xcall_flush_tlb_kernel_range: /* 44 insns */ sub %g7, %g1, %g3 srlx %g3, 18, %g2 brnz,pn %g2, 2f - add %g2, 1, %g2 + sethi %hi(PAGE_SIZE), %g2 sub %g3, %g2, %g3 or %g1, 0x20, %g1 ! Nucleus 1: stxa %g0, [%g1 + %g3] ASI_DMMU_DEMAP @@ -751,7 +751,7 @@ __cheetah_xcall_flush_tlb_kernel_range: /* 44 insns */ sub %g7, %g1, %g3 srlx %g3, 18, %g2 brnz,pn %g2, 2f - add %g2, 1, %g2 + sethi %hi(PAGE_SIZE), %g2 sub %g3, %g2, %g3 or %g1, 0x20, %g1 ! Nucleus 1: stxa %g0, [%g1 + %g3] ASI_DMMU_DEMAP diff --git a/drivers/vhost/net.c b/drivers/vhost/net.c index df51a35cf537..2d9df786a9d3 100644 --- a/drivers/vhost/net.c +++ b/drivers/vhost/net.c @@ -604,12 +604,6 @@ static size_t init_iov_iter(struct vhost_virtqueue *vq, struct iov_iter *iter, return iov_iter_count(iter); } -static bool vhost_exceeds_weight(int pkts, int total_len) -{ - return total_len >= VHOST_NET_WEIGHT || - pkts >= VHOST_NET_PKT_WEIGHT; -} - static int get_tx_bufs(struct vhost_net *net, struct vhost_net_virtqueue *nvq, struct msghdr *msg, @@ -779,7 +773,7 @@ static void handle_tx_copy(struct vhost_net *net, struct socket *sock) int sent_pkts = 0; bool sock_can_batch = (sock->sk->sk_sndbuf == INT_MAX); - for (;;) { + do { bool busyloop_intr = false; if (nvq->done_idx == VHOST_NET_BATCH) @@ -845,11 +839,7 @@ done: vq->heads[nvq->done_idx].id = cpu_to_vhost32(vq, head); vq->heads[nvq->done_idx].len = 0; ++nvq->done_idx; - if (vhost_exceeds_weight(++sent_pkts, total_len)) { - vhost_poll_queue(&vq->poll); - break; - } - } + } while (likely(!vhost_exceeds_weight(vq, ++sent_pkts, total_len))); vhost_tx_batch(net, nvq, sock, &msg); } @@ -874,7 +864,7 @@ static void handle_tx_zerocopy(struct vhost_net *net, struct socket *sock) bool zcopy_used; int sent_pkts = 0; - for (;;) { + do { bool busyloop_intr; /* Release DMAs done buffers first */ @@ -951,11 +941,7 @@ static void handle_tx_zerocopy(struct vhost_net *net, struct socket *sock) else vhost_zerocopy_signal_used(net, vq); vhost_net_tx_packet(net); - if (unlikely(vhost_exceeds_weight(++sent_pkts, total_len))) { - vhost_poll_queue(&vq->poll); - break; - } - } + } while (likely(!vhost_exceeds_weight(vq, ++sent_pkts, total_len))); } /* Expects to be always run from workqueue - which acts as @@ -1153,8 +1139,11 @@ static void handle_rx(struct vhost_net *net) vq->log : NULL; mergeable = vhost_has_feature(vq, VIRTIO_NET_F_MRG_RXBUF); - while ((sock_len = vhost_net_rx_peek_head_len(net, sock->sk, - &busyloop_intr))) { + do { + sock_len = vhost_net_rx_peek_head_len(net, sock->sk, + &busyloop_intr); + if (!sock_len) + break; sock_len += sock_hlen; vhost_len = sock_len + vhost_hlen; headcount = get_rx_bufs(vq, vq->heads + nvq->done_idx, @@ -1239,14 +1228,11 @@ static void handle_rx(struct vhost_net *net) vhost_log_write(vq, vq_log, log, vhost_len, vq->iov, in); total_len += vhost_len; - if (unlikely(vhost_exceeds_weight(++recv_pkts, total_len))) { - vhost_poll_queue(&vq->poll); - goto out; - } - } + } while (likely(!vhost_exceeds_weight(vq, ++recv_pkts, total_len))); + if (unlikely(busyloop_intr)) vhost_poll_queue(&vq->poll); - else + else if (!sock_len) vhost_net_enable_vq(net, vq); out: vhost_net_signal_used(nvq); @@ -1338,7 +1324,8 @@ static int vhost_net_open(struct inode *inode, struct file *f) vhost_net_buf_init(&n->vqs[i].rxq); } vhost_dev_init(dev, vqs, VHOST_NET_VQ_MAX, - UIO_MAXIOV + VHOST_NET_BATCH); + UIO_MAXIOV + VHOST_NET_BATCH, + VHOST_NET_PKT_WEIGHT, VHOST_NET_WEIGHT); vhost_poll_init(n->poll + VHOST_NET_VQ_TX, handle_tx_net, EPOLLOUT, dev); vhost_poll_init(n->poll + VHOST_NET_VQ_RX, handle_rx_net, EPOLLIN, dev); diff --git a/drivers/vhost/scsi.c b/drivers/vhost/scsi.c index c090d177bd75..a9caf1bc3c3e 100644 --- a/drivers/vhost/scsi.c +++ b/drivers/vhost/scsi.c @@ -57,6 +57,12 @@ #define VHOST_SCSI_PREALLOC_UPAGES 2048 #define VHOST_SCSI_PREALLOC_PROT_SGLS 2048 +/* Max number of requests before requeueing the job. + * Using this limit prevents one virtqueue from starving others with + * request. + */ +#define VHOST_SCSI_WEIGHT 256 + struct vhost_scsi_inflight { /* Wait for the flush operation to finish */ struct completion comp; @@ -912,7 +918,7 @@ vhost_scsi_handle_vq(struct vhost_scsi *vs, struct vhost_virtqueue *vq) struct iov_iter in_iter, prot_iter, data_iter; u64 tag; u32 exp_data_len, data_direction; - int ret, prot_bytes; + int ret, prot_bytes, c = 0; u16 lun; u8 task_attr; bool t10_pi = vhost_has_feature(vq, VIRTIO_SCSI_F_T10_PI); @@ -932,7 +938,7 @@ vhost_scsi_handle_vq(struct vhost_scsi *vs, struct vhost_virtqueue *vq) vhost_disable_notify(&vs->dev, vq); - for (;;) { + do { ret = vhost_scsi_get_desc(vs, vq, &vc); if (ret) goto err; @@ -1112,7 +1118,7 @@ err: break; else if (ret == -EIO) vhost_scsi_send_bad_target(vs, vq, vc.head, vc.out); - } + } while (likely(!vhost_exceeds_weight(vq, ++c, 0))); out: mutex_unlock(&vq->mutex); } @@ -1171,7 +1177,7 @@ vhost_scsi_ctl_handle_vq(struct vhost_scsi *vs, struct vhost_virtqueue *vq) } v_req; struct vhost_scsi_ctx vc; size_t typ_size; - int ret; + int ret, c = 0; mutex_lock(&vq->mutex); /* @@ -1185,7 +1191,7 @@ vhost_scsi_ctl_handle_vq(struct vhost_scsi *vs, struct vhost_virtqueue *vq) vhost_disable_notify(&vs->dev, vq); - for (;;) { + do { ret = vhost_scsi_get_desc(vs, vq, &vc); if (ret) goto err; @@ -1264,7 +1270,7 @@ err: break; else if (ret == -EIO) vhost_scsi_send_bad_target(vs, vq, vc.head, vc.out); - } + } while (likely(!vhost_exceeds_weight(vq, ++c, 0))); out: mutex_unlock(&vq->mutex); } @@ -1621,7 +1627,8 @@ static int vhost_scsi_open(struct inode *inode, struct file *f) vqs[i] = &vs->vqs[i].vq; vs->vqs[i].vq.handle_kick = vhost_scsi_handle_kick; } - vhost_dev_init(&vs->dev, vqs, VHOST_SCSI_MAX_VQ, UIO_MAXIOV); + vhost_dev_init(&vs->dev, vqs, VHOST_SCSI_MAX_VQ, UIO_MAXIOV, + VHOST_SCSI_WEIGHT, 0); vhost_scsi_init_inflight(vs, NULL); diff --git a/drivers/vhost/vhost.c b/drivers/vhost/vhost.c index 1e3ed41ae1f3..3f3eac4bcc58 100644 --- a/drivers/vhost/vhost.c +++ b/drivers/vhost/vhost.c @@ -413,8 +413,24 @@ static void vhost_dev_free_iovecs(struct vhost_dev *dev) vhost_vq_free_iovecs(dev->vqs[i]); } +bool vhost_exceeds_weight(struct vhost_virtqueue *vq, + int pkts, int total_len) +{ + struct vhost_dev *dev = vq->dev; + + if ((dev->byte_weight && total_len >= dev->byte_weight) || + pkts >= dev->weight) { + vhost_poll_queue(&vq->poll); + return true; + } + + return false; +} +EXPORT_SYMBOL_GPL(vhost_exceeds_weight); + void vhost_dev_init(struct vhost_dev *dev, - struct vhost_virtqueue **vqs, int nvqs, int iov_limit) + struct vhost_virtqueue **vqs, int nvqs, + int iov_limit, int weight, int byte_weight) { struct vhost_virtqueue *vq; int i; @@ -428,6 +444,8 @@ void vhost_dev_init(struct vhost_dev *dev, dev->mm = NULL; dev->worker = NULL; dev->iov_limit = iov_limit; + dev->weight = weight; + dev->byte_weight = byte_weight; init_llist_head(&dev->work_list); init_waitqueue_head(&dev->wait); INIT_LIST_HEAD(&dev->read_list); diff --git a/drivers/vhost/vhost.h b/drivers/vhost/vhost.h index 9490e7ddb340..27a78a9b8cc7 100644 --- a/drivers/vhost/vhost.h +++ b/drivers/vhost/vhost.h @@ -171,10 +171,13 @@ struct vhost_dev { struct list_head pending_list; wait_queue_head_t wait; int iov_limit; + int weight; + int byte_weight; }; +bool vhost_exceeds_weight(struct vhost_virtqueue *vq, int pkts, int total_len); void vhost_dev_init(struct vhost_dev *, struct vhost_virtqueue **vqs, - int nvqs, int iov_limit); + int nvqs, int iov_limit, int weight, int byte_weight); long vhost_dev_set_owner(struct vhost_dev *dev); bool vhost_dev_has_owner(struct vhost_dev *dev); long vhost_dev_check_owner(struct vhost_dev *); diff --git a/drivers/vhost/vsock.c b/drivers/vhost/vsock.c index bb5fc0e9fbc2..814bed72d793 100644 --- a/drivers/vhost/vsock.c +++ b/drivers/vhost/vsock.c @@ -21,6 +21,14 @@ #include "vhost.h" #define VHOST_VSOCK_DEFAULT_HOST_CID 2 +/* Max number of bytes transferred before requeueing the job. + * Using this limit prevents one virtqueue from starving others. */ +#define VHOST_VSOCK_WEIGHT 0x80000 +/* Max number of packets transferred before requeueing the job. + * Using this limit prevents one virtqueue from starving others with + * small pkts. + */ +#define VHOST_VSOCK_PKT_WEIGHT 256 enum { VHOST_VSOCK_FEATURES = VHOST_FEATURES, @@ -78,6 +86,7 @@ vhost_transport_do_send_pkt(struct vhost_vsock *vsock, struct vhost_virtqueue *vq) { struct vhost_virtqueue *tx_vq = &vsock->vqs[VSOCK_VQ_TX]; + int pkts = 0, total_len = 0; bool added = false; bool restart_tx = false; @@ -89,7 +98,7 @@ vhost_transport_do_send_pkt(struct vhost_vsock *vsock, /* Avoid further vmexits, we're already processing the virtqueue */ vhost_disable_notify(&vsock->dev, vq); - for (;;) { + do { struct virtio_vsock_pkt *pkt; struct iov_iter iov_iter; unsigned out, in; @@ -174,8 +183,9 @@ vhost_transport_do_send_pkt(struct vhost_vsock *vsock, */ virtio_transport_deliver_tap_pkt(pkt); + total_len += pkt->len; virtio_transport_free_pkt(pkt); - } + } while(likely(!vhost_exceeds_weight(vq, ++pkts, total_len))); if (added) vhost_signal(&vsock->dev, vq); @@ -350,7 +360,7 @@ static void vhost_vsock_handle_tx_kick(struct vhost_work *work) struct vhost_vsock *vsock = container_of(vq->dev, struct vhost_vsock, dev); struct virtio_vsock_pkt *pkt; - int head; + int head, pkts = 0, total_len = 0; unsigned int out, in; bool added = false; @@ -360,7 +370,7 @@ static void vhost_vsock_handle_tx_kick(struct vhost_work *work) goto out; vhost_disable_notify(&vsock->dev, vq); - for (;;) { + do { u32 len; if (!vhost_vsock_more_replies(vsock)) { @@ -401,9 +411,11 @@ static void vhost_vsock_handle_tx_kick(struct vhost_work *work) else virtio_transport_free_pkt(pkt); - vhost_add_used(vq, head, sizeof(pkt->hdr) + len); + len += sizeof(pkt->hdr); + vhost_add_used(vq, head, len); + total_len += len; added = true; - } + } while(likely(!vhost_exceeds_weight(vq, ++pkts, total_len))); no_more_replies: if (added) @@ -531,7 +543,9 @@ static int vhost_vsock_dev_open(struct inode *inode, struct file *file) vsock->vqs[VSOCK_VQ_TX].handle_kick = vhost_vsock_handle_tx_kick; vsock->vqs[VSOCK_VQ_RX].handle_kick = vhost_vsock_handle_rx_kick; - vhost_dev_init(&vsock->dev, vqs, ARRAY_SIZE(vsock->vqs), UIO_MAXIOV); + vhost_dev_init(&vsock->dev, vqs, ARRAY_SIZE(vsock->vqs), + UIO_MAXIOV, VHOST_VSOCK_PKT_WEIGHT, + VHOST_VSOCK_WEIGHT); file->private_data = vsock; spin_lock_init(&vsock->send_pkt_list_lock); diff --git a/drivers/virtio/Kconfig b/drivers/virtio/Kconfig index 9aea44ed54c7..023fc3bc01c6 100644 --- a/drivers/virtio/Kconfig +++ b/drivers/virtio/Kconfig @@ -63,12 +63,12 @@ config VIRTIO_INPUT If unsure, say M. - config VIRTIO_MMIO +config VIRTIO_MMIO tristate "Platform bus driver for memory mapped virtio devices" depends on HAS_IOMEM && HAS_DMA - select VIRTIO - ---help--- - This drivers provides support for memory mapped virtio + select VIRTIO + ---help--- + This drivers provides support for memory mapped virtio platform device driver. If unsure, say N. diff --git a/fs/pstore/platform.c b/fs/pstore/platform.c index 75887a269b64..dca07f239bd1 100644 --- a/fs/pstore/platform.c +++ b/fs/pstore/platform.c @@ -347,8 +347,10 @@ static void allocate_buf_for_compression(void) static void free_buf_for_compression(void) { - if (IS_ENABLED(CONFIG_PSTORE_COMPRESS) && tfm) + if (IS_ENABLED(CONFIG_PSTORE_COMPRESS) && tfm) { crypto_free_comp(tfm); + tfm = NULL; + } kfree(big_oops_buf); big_oops_buf = NULL; big_oops_buf_sz = 0; @@ -606,7 +608,8 @@ int pstore_register(struct pstore_info *psi) return -EINVAL; } - allocate_buf_for_compression(); + if (psi->flags & PSTORE_FLAGS_DMESG) + allocate_buf_for_compression(); if (pstore_is_mounted()) pstore_get_records(0); diff --git a/fs/pstore/ram.c b/fs/pstore/ram.c index c5c685589e36..4310d547c3b2 100644 --- a/fs/pstore/ram.c +++ b/fs/pstore/ram.c @@ -800,26 +800,36 @@ static int ramoops_probe(struct platform_device *pdev) cxt->pstore.data = cxt; /* - * Since bufsize is only used for dmesg crash dumps, it - * must match the size of the dprz record (after PRZ header - * and ECC bytes have been accounted for). + * Prepare frontend flags based on which areas are initialized. + * For ramoops_init_przs() cases, the "max count" variable tells + * if there are regions present. For ramoops_init_prz() cases, + * the single region size is how to check. */ - cxt->pstore.bufsize = cxt->dprzs[0]->buffer_size; - cxt->pstore.buf = kzalloc(cxt->pstore.bufsize, GFP_KERNEL); - if (!cxt->pstore.buf) { - pr_err("cannot allocate pstore crash dump buffer\n"); - err = -ENOMEM; - goto fail_clear; - } - - cxt->pstore.flags = PSTORE_FLAGS_DMESG; + cxt->pstore.flags = 0; + if (cxt->max_dump_cnt) + cxt->pstore.flags |= PSTORE_FLAGS_DMESG; if (cxt->console_size) cxt->pstore.flags |= PSTORE_FLAGS_CONSOLE; - if (cxt->ftrace_size) + if (cxt->max_ftrace_cnt) cxt->pstore.flags |= PSTORE_FLAGS_FTRACE; if (cxt->pmsg_size) cxt->pstore.flags |= PSTORE_FLAGS_PMSG; + /* + * Since bufsize is only used for dmesg crash dumps, it + * must match the size of the dprz record (after PRZ header + * and ECC bytes have been accounted for). + */ + if (cxt->pstore.flags & PSTORE_FLAGS_DMESG) { + cxt->pstore.bufsize = cxt->dprzs[0]->buffer_size; + cxt->pstore.buf = kzalloc(cxt->pstore.bufsize, GFP_KERNEL); + if (!cxt->pstore.buf) { + pr_err("cannot allocate pstore crash dump buffer\n"); + err = -ENOMEM; + goto fail_clear; + } + } + err = pstore_register(&cxt->pstore); if (err) { pr_err("registering with pstore failed\n"); diff --git a/include/linux/rcupdate.h b/include/linux/rcupdate.h index 922bb6848813..b25d20822e75 100644 --- a/include/linux/rcupdate.h +++ b/include/linux/rcupdate.h @@ -56,14 +56,12 @@ void __rcu_read_unlock(void); static inline void __rcu_read_lock(void) { - if (IS_ENABLED(CONFIG_PREEMPT_COUNT)) - preempt_disable(); + preempt_disable(); } static inline void __rcu_read_unlock(void) { - if (IS_ENABLED(CONFIG_PREEMPT_COUNT)) - preempt_enable(); + preempt_enable(); } static inline int rcu_preempt_depth(void) diff --git a/include/math-emu/op-2.h b/include/math-emu/op-2.h index 13a374f51a22..244522b02076 100644 --- a/include/math-emu/op-2.h +++ b/include/math-emu/op-2.h @@ -567,16 +567,13 @@ */ #define _FP_FRAC_ASSEMBLE_2(r, X, rsize) \ - do { \ - if (rsize <= _FP_W_TYPE_SIZE) \ - r = X##_f0; \ - else \ - { \ - r = X##_f1; \ - r <<= _FP_W_TYPE_SIZE; \ - r += X##_f0; \ - } \ - } while (0) + (void) (((rsize) <= _FP_W_TYPE_SIZE) \ + ? ({ (r) = X##_f0; }) \ + : ({ \ + (r) = X##_f1; \ + (r) <<= _FP_W_TYPE_SIZE; \ + (r) += X##_f0; \ + })) #define _FP_FRAC_DISASSEMBLE_2(X, r, rsize) \ do { \ diff --git a/include/math-emu/op-common.h b/include/math-emu/op-common.h index 6bdf8c61d221..f37d12877754 100644 --- a/include/math-emu/op-common.h +++ b/include/math-emu/op-common.h @@ -795,11 +795,12 @@ do { \ ur_ = (unsigned rtype) -r; \ else \ ur_ = (unsigned rtype) r; \ - if (rsize <= _FP_W_TYPE_SIZE) \ - __FP_CLZ(X##_e, ur_); \ - else \ - __FP_CLZ_2(X##_e, (_FP_W_TYPE)(ur_ >> _FP_W_TYPE_SIZE), \ - (_FP_W_TYPE)ur_); \ + (void) (((rsize) <= _FP_W_TYPE_SIZE) \ + ? ({ __FP_CLZ(X##_e, ur_); }) \ + : ({ \ + __FP_CLZ_2(X##_e, (_FP_W_TYPE)(ur_ >> _FP_W_TYPE_SIZE), \ + (_FP_W_TYPE)ur_); \ + })); \ if (rsize < _FP_W_TYPE_SIZE) \ X##_e -= (_FP_W_TYPE_SIZE - rsize); \ X##_e = rsize - X##_e - 1; \ diff --git a/tools/virtio/linux/kernel.h b/tools/virtio/linux/kernel.h index 7ef45a4a3cba..6683b4a70b05 100644 --- a/tools/virtio/linux/kernel.h +++ b/tools/virtio/linux/kernel.h @@ -127,7 +127,7 @@ static inline void free_page(unsigned long addr) #define dev_err(dev, format, ...) fprintf (stderr, format, ## __VA_ARGS__) #define dev_warn(dev, format, ...) fprintf (stderr, format, ## __VA_ARGS__) -#define WARN_ON_ONCE(cond) ((cond) ? fprintf (stderr, "WARNING\n") : 0) +#define WARN_ON_ONCE(cond) (unlikely(cond) ? fprintf (stderr, "WARNING\n") : 0) #define min(x, y) ({ \ typeof(x) _min1 = (x); \ |