diff -u linux-lts-xenial-4.4.0/Documentation/ABI/testing/sysfs-devices-system-cpu linux-lts-xenial-4.4.0/Documentation/ABI/testing/sysfs-devices-system-cpu --- linux-lts-xenial-4.4.0/Documentation/ABI/testing/sysfs-devices-system-cpu +++ linux-lts-xenial-4.4.0/Documentation/ABI/testing/sysfs-devices-system-cpu @@ -346,6 +346,7 @@ /sys/devices/system/cpu/vulnerabilities/spectre_v1 /sys/devices/system/cpu/vulnerabilities/spectre_v2 /sys/devices/system/cpu/vulnerabilities/spec_store_bypass + /sys/devices/system/cpu/vulnerabilities/l1tf Date: January 2018 Contact: Linux kernel mailing list Description: Information about CPU vulnerabilities @@ -359,0 +361,23 @@ + + Details about the l1tf file can be found in + Documentation/security/l1tf.txt + +What: /sys/devices/system/cpu/smt + /sys/devices/system/cpu/smt/active + /sys/devices/system/cpu/smt/control +Date: June 2018 +Contact: Linux kernel mailing list +Description: Control Symetric Multi Threading (SMT) + + active: Tells whether SMT is active (enabled and siblings online) + + control: Read/write interface to control SMT. Possible + values: + + "on" SMT is enabled + "off" SMT is disabled + "forceoff" SMT is force disabled. Cannot be changed. + "notsupported" SMT is not supported by the CPU + + If control status is "forceoff" or "notsupported" writes + are rejected. diff -u linux-lts-xenial-4.4.0/Documentation/kernel-parameters.txt linux-lts-xenial-4.4.0/Documentation/kernel-parameters.txt --- linux-lts-xenial-4.4.0/Documentation/kernel-parameters.txt +++ linux-lts-xenial-4.4.0/Documentation/kernel-parameters.txt @@ -1808,10 +1808,84 @@ (virtualized real and unpaged mode) on capable Intel chips. Default is 1 (enabled) + kvm-intel.vmentry_l1d_flush=[KVM,Intel] Mitigation for L1 Terminal Fault + CVE-2018-3620. + + Valid arguments: never, cond, always + + always: L1D cache flush on every VMENTER. + cond: Flush L1D on VMENTER only when the code between + VMEXIT and VMENTER can leak host memory. + never: Disables the mitigation + + Default is cond (do L1 cache flush in specific instances) + kvm-intel.vpid= [KVM,Intel] Disable Virtual Processor Identification feature (tagged TLBs) on capable Intel chips. Default is 1 (enabled) + l1tf= [X86] Control mitigation of the L1TF vulnerability on + affected CPUs + + The kernel PTE inversion protection is unconditionally + enabled and cannot be disabled. + + full + Provides all available mitigations for the + L1TF vulnerability. Disables SMT and + enables all mitigations in the + hypervisors, i.e. unconditional L1D flush. + + SMT control and L1D flush control via the + sysfs interface is still possible after + boot. Hypervisors will issue a warning + when the first VM is started in a + potentially insecure configuration, + i.e. SMT enabled or L1D flush disabled. + + full,force + Same as 'full', but disables SMT and L1D + flush runtime control. Implies the + 'nosmt=force' command line option. + (i.e. sysfs control of SMT is disabled.) + + flush + Leaves SMT enabled and enables the default + hypervisor mitigation, i.e. conditional + L1D flush. + + SMT control and L1D flush control via the + sysfs interface is still possible after + boot. Hypervisors will issue a warning + when the first VM is started in a + potentially insecure configuration, + i.e. SMT enabled or L1D flush disabled. + + flush,nosmt + + Disables SMT and enables the default + hypervisor mitigation. + + SMT control and L1D flush control via the + sysfs interface is still possible after + boot. Hypervisors will issue a warning + when the first VM is started in a + potentially insecure configuration, + i.e. SMT enabled or L1D flush disabled. + + flush,nowarn + Same as 'flush', but hypervisors will not + warn when a VM is started in a potentially + insecure configuration. + + off + Disables hypervisor mitigations and doesn't + emit any warnings. + + Default is 'flush'. + + For details see: Documentation/admin-guide/l1tf.rst + l2cr= [PPC] l3cr= [PPC] @@ -2475,6 +2549,10 @@ nohugeiomap [KNL,x86] Disable kernel huge I/O mappings. + [KNL,x86] Disable symmetric multithreading (SMT). + nosmt=force: Force disable SMT, cannot be undone + via the sysfs control file. + nospectre_v2 [X86] Disable all mitigations for the Spectre variant 2 (indirect branch prediction) vulnerability. System may allow data leaks with this option, which is equivalent reverted: --- linux-lts-xenial-4.4.0/Documentation/networking/netdev-FAQ.txt +++ linux-lts-xenial-4.4.0.orig/Documentation/networking/netdev-FAQ.txt @@ -168,15 +168,6 @@ dash marker line as described in Documentation/SubmittingPatches to temporarily embed that information into the patch that you send. -Q: Are all networking bug fixes backported to all stable releases? - -A: Due to capacity, Dave could only take care of the backports for the last - 2 stable releases. For earlier stable releases, each stable branch maintainer - is supposed to take care of them. If you find any patch is missing from an - earlier stable branch, please notify stable@vger.kernel.org with either a - commit ID or a formal patch backported, and CC Dave and other relevant - networking developers. - Q: Someone said that the comment style and coding convention is different for the networking content. Is this true? reverted: --- linux-lts-xenial-4.4.0/Documentation/printk-formats.txt +++ linux-lts-xenial-4.4.0.orig/Documentation/printk-formats.txt @@ -273,10 +273,11 @@ %pC pll1 %pCn pll1 + %pCr 1560000000 For printing struct clk structures. '%pC' and '%pCn' print the name (Common Clock Framework) or address (legacy clock framework) of the + structure; '%pCr' prints the current clock rate. - structure. Passed by reference. diff -u linux-lts-xenial-4.4.0/Documentation/virtual/kvm/api.txt linux-lts-xenial-4.4.0/Documentation/virtual/kvm/api.txt --- linux-lts-xenial-4.4.0/Documentation/virtual/kvm/api.txt +++ linux-lts-xenial-4.4.0/Documentation/virtual/kvm/api.txt @@ -122,14 +122,15 @@ privileged user (CAP_SYS_ADMIN). -4.3 KVM_GET_MSR_INDEX_LIST +4.3 KVM_GET_MSR_INDEX_LIST, KVM_GET_MSR_FEATURE_INDEX_LIST -Capability: basic +Capability: basic, KVM_CAP_GET_MSR_FEATURES for KVM_GET_MSR_FEATURE_INDEX_LIST Architectures: x86 -Type: system +Type: system ioctl Parameters: struct kvm_msr_list (in/out) Returns: 0 on success; -1 on error Errors: + EFAULT: the msr index list cannot be read from or written to E2BIG: the msr index list is to be to fit in the array specified by the user. @@ -138,16 +139,23 @@ __u32 indices[0]; }; -This ioctl returns the guest msrs that are supported. The list varies -by kvm version and host processor, but does not change otherwise. The -user fills in the size of the indices array in nmsrs, and in return -kvm adjusts nmsrs to reflect the actual number of msrs and fills in -the indices array with their numbers. +The user fills in the size of the indices array in nmsrs, and in return +kvm adjusts nmsrs to reflect the actual number of msrs and fills in the +indices array with their numbers. + +KVM_GET_MSR_INDEX_LIST returns the guest msrs that are supported. The list +varies by kvm version and host processor, but does not change otherwise. Note: if kvm indicates supports MCE (KVM_CAP_MCE), then the MCE bank MSRs are not returned in the MSR list, as different vcpus can have a different number of banks, as set via the KVM_X86_SETUP_MCE ioctl. +KVM_GET_MSR_FEATURE_INDEX_LIST returns the list of MSRs that can be passed +to the KVM_GET_MSRS system ioctl. This lets userspace probe host capabilities +and processor features that are exposed via MSRs (e.g., VMX capabilities). +This list also varies by kvm version and host processor, but does not change +otherwise. + 4.4 KVM_CHECK_EXTENSION @@ -468,14 +476,22 @@ 4.18 KVM_GET_MSRS -Capability: basic +Capability: basic (vcpu), KVM_CAP_GET_MSR_FEATURES (system) Architectures: x86 -Type: vcpu ioctl +Type: system ioctl, vcpu ioctl Parameters: struct kvm_msrs (in/out) -Returns: 0 on success, -1 on error +Returns: number of msrs successfully returned; + -1 on error + +When used as a system ioctl: +Reads the values of MSR-based features that are available for the VM. This +is similar to KVM_GET_SUPPORTED_CPUID, but it returns MSR indices and values. +The list of msr-based features can be obtained using KVM_GET_MSR_FEATURE_INDEX_LIST +in a system ioctl. +When used as a vcpu ioctl: Reads model-specific registers from the vcpu. Supported msr indices can -be obtained using KVM_GET_MSR_INDEX_LIST. +be obtained using KVM_GET_MSR_INDEX_LIST in a system ioctl. struct kvm_msrs { __u32 nmsrs; /* number of msrs in entries */ diff -u linux-lts-xenial-4.4.0/Makefile linux-lts-xenial-4.4.0/Makefile --- linux-lts-xenial-4.4.0/Makefile +++ linux-lts-xenial-4.4.0/Makefile @@ -1,6 +1,6 @@ VERSION = 4 PATCHLEVEL = 4 -SUBLEVEL = 140 +SUBLEVEL = 134 EXTRAVERSION = NAME = Blurry Fish Butt reverted: --- linux-lts-xenial-4.4.0/arch/arm/boot/dts/imx6q.dtsi +++ linux-lts-xenial-4.4.0.orig/arch/arm/boot/dts/imx6q.dtsi @@ -95,7 +95,7 @@ clocks = <&clks IMX6Q_CLK_ECSPI5>, <&clks IMX6Q_CLK_ECSPI5>; clock-names = "ipg", "per"; + dmas = <&sdma 11 7 1>, <&sdma 12 7 2>; - dmas = <&sdma 11 8 1>, <&sdma 12 8 2>; dma-names = "rx", "tx"; status = "disabled"; }; reverted: --- linux-lts-xenial-4.4.0/arch/arm/include/asm/kgdb.h +++ linux-lts-xenial-4.4.0.orig/arch/arm/include/asm/kgdb.h @@ -76,7 +76,7 @@ #define KGDB_MAX_NO_CPUS 1 #define BUFMAX 400 +#define NUMREGBYTES (DBG_MAX_REG_NUM << 2) -#define NUMREGBYTES (GDB_MAX_REGS << 2) #define NUMCRITREGBYTES (32 << 2) #define _R0 0 reverted: --- linux-lts-xenial-4.4.0/arch/arm64/include/asm/atomic_lse.h +++ linux-lts-xenial-4.4.0.orig/arch/arm64/include/asm/atomic_lse.h @@ -114,7 +114,7 @@ /* LSE atomics */ " mvn %w[i], %w[i]\n" " stclr %w[i], %[v]") + : [i] "+r" (w0), [v] "+Q" (v->counter) - : [i] "+&r" (w0), [v] "+Q" (v->counter) : "r" (x1) : "x30"); } @@ -131,7 +131,7 @@ /* LSE atomics */ " neg %w[i], %w[i]\n" " stadd %w[i], %[v]") + : [i] "+r" (w0), [v] "+Q" (v->counter) - : [i] "+&r" (w0), [v] "+Q" (v->counter) : "r" (x1) : "x30"); } @@ -151,7 +151,7 @@ " neg %w[i], %w[i]\n" \ " ldadd" #mb " %w[i], w30, %[v]\n" \ " add %w[i], %w[i], w30") \ + : [i] "+r" (w0), [v] "+Q" (v->counter) \ - : [i] "+&r" (w0), [v] "+Q" (v->counter) \ : "r" (x1) \ : "x30" , ##cl); \ \ @@ -255,7 +255,7 @@ /* LSE atomics */ " mvn %[i], %[i]\n" " stclr %[i], %[v]") + : [i] "+r" (x0), [v] "+Q" (v->counter) - : [i] "+&r" (x0), [v] "+Q" (v->counter) : "r" (x1) : "x30"); } @@ -272,7 +272,7 @@ /* LSE atomics */ " neg %[i], %[i]\n" " stadd %[i], %[v]") + : [i] "+r" (x0), [v] "+Q" (v->counter) - : [i] "+&r" (x0), [v] "+Q" (v->counter) : "r" (x1) : "x30"); } @@ -292,7 +292,7 @@ " neg %[i], %[i]\n" \ " ldadd" #mb " %[i], x30, %[v]\n" \ " add %[i], %[i], x30") \ + : [i] "+r" (x0), [v] "+Q" (v->counter) \ - : [i] "+&r" (x0), [v] "+Q" (v->counter) \ : "r" (x1) \ : "x30" , ##cl); \ \ @@ -412,7 +412,7 @@ " eor %[old1], %[old1], %[oldval1]\n" \ " eor %[old2], %[old2], %[oldval2]\n" \ " orr %[old1], %[old1], %[old2]") \ + : [old1] "+r" (x0), [old2] "+r" (x1), \ - : [old1] "+&r" (x0), [old2] "+&r" (x1), \ [v] "+Q" (*(unsigned long *)ptr) \ : [new1] "r" (x2), [new2] "r" (x3), [ptr] "r" (x4), \ [oldval1] "r" (oldval1), [oldval2] "r" (oldval2) \ reverted: --- linux-lts-xenial-4.4.0/arch/m68k/mm/kmap.c +++ linux-lts-xenial-4.4.0.orig/arch/m68k/mm/kmap.c @@ -88,8 +88,7 @@ for (p = &iolist ; (tmp = *p) ; p = &tmp->next) { if (tmp->addr == addr) { *p = tmp->next; + __iounmap(tmp->addr, tmp->size); - /* remove gap added in get_io_area() */ - __iounmap(tmp->addr, tmp->size - IO_SIZE); kfree(tmp); return; } reverted: --- linux-lts-xenial-4.4.0/arch/mips/bcm47xx/setup.c +++ linux-lts-xenial-4.4.0.orig/arch/mips/bcm47xx/setup.c @@ -249,12 +249,6 @@ */ if (bcm47xx_bus.bcma.bus.chipinfo.id == BCMA_CHIP_ID_BCM4706) cpu_wait = NULL; - - /* - * BCM47XX Erratum "R10: PCIe Transactions Periodically Fail" - * Enable ExternalSync for sync instruction to take effect - */ - set_c0_config7(MIPS_CONF7_ES); break; #endif } reverted: --- linux-lts-xenial-4.4.0/arch/mips/include/asm/io.h +++ linux-lts-xenial-4.4.0.orig/arch/mips/include/asm/io.h @@ -411,8 +411,6 @@ __val = *__addr; \ slow; \ \ - /* prevent prefetching of coherent DMA data prematurely */ \ - rmb(); \ return pfx##ioswab##bwlq(__addr, __val); \ } reverted: --- linux-lts-xenial-4.4.0/arch/mips/include/asm/mipsregs.h +++ linux-lts-xenial-4.4.0.orig/arch/mips/include/asm/mipsregs.h @@ -605,8 +605,6 @@ #define MIPS_CONF7_WII (_ULCAST_(1) << 31) #define MIPS_CONF7_RPS (_ULCAST_(1) << 2) -/* ExternalSync */ -#define MIPS_CONF7_ES (_ULCAST_(1) << 8) #define MIPS_CONF7_IAR (_ULCAST_(1) << 10) #define MIPS_CONF7_AR (_ULCAST_(1) << 16) @@ -2014,7 +2012,6 @@ __BUILD_SET_C0(cause) __BUILD_SET_C0(config) __BUILD_SET_C0(config5) -__BUILD_SET_C0(config7) __BUILD_SET_C0(intcontrol) __BUILD_SET_C0(intctl) __BUILD_SET_C0(srsmap) reverted: --- linux-lts-xenial-4.4.0/arch/mips/kernel/mcount.S +++ linux-lts-xenial-4.4.0.orig/arch/mips/kernel/mcount.S @@ -116,20 +116,10 @@ NESTED(_mcount, PT_SIZE, ra) PTR_LA t1, ftrace_stub PTR_L t2, ftrace_trace_function /* Prepare t2 for (1) */ + bne t1, t2, static_trace - beq t1, t2, fgraph_trace nop - MCOUNT_SAVE_REGS - - move a0, ra /* arg1: self return address */ - jalr t2 /* (1) call *ftrace_trace_function */ - move a1, AT /* arg2: parent's return address */ - - MCOUNT_RESTORE_REGS - -fgraph_trace: #ifdef CONFIG_FUNCTION_GRAPH_TRACER - PTR_LA t1, ftrace_stub PTR_L t3, ftrace_graph_return bne t1, t3, ftrace_graph_caller nop @@ -138,11 +128,24 @@ bne t1, t3, ftrace_graph_caller nop #endif + b ftrace_stub +#ifdef CONFIG_32BIT + addiu sp, sp, 8 +#else + nop +#endif + +static_trace: + MCOUNT_SAVE_REGS + + move a0, ra /* arg1: self return address */ + jalr t2 /* (1) call *ftrace_trace_function */ + move a1, AT /* arg2: parent's return address */ + MCOUNT_RESTORE_REGS #ifdef CONFIG_32BIT addiu sp, sp, 8 #endif - .globl ftrace_stub ftrace_stub: RETURN_BACK diff -u linux-lts-xenial-4.4.0/arch/mips/kernel/process.c linux-lts-xenial-4.4.0/arch/mips/kernel/process.c --- linux-lts-xenial-4.4.0/arch/mips/kernel/process.c +++ linux-lts-xenial-4.4.0/arch/mips/kernel/process.c @@ -680,10 +680,6 @@ if (value & ~known_bits) return -EOPNOTSUPP; - /* Setting FRE without FR is not supported. */ - if ((value & (PR_FP_MODE_FR | PR_FP_MODE_FRE)) == PR_FP_MODE_FRE) - return -EOPNOTSUPP; - /* Avoid inadvertently triggering emulation */ if ((value & PR_FP_MODE_FR) && raw_cpu_has_fpu && !(raw_current_cpu_data.fpu_id & MIPS_FPIR_F64)) diff -u linux-lts-xenial-4.4.0/arch/mips/kernel/ptrace.c linux-lts-xenial-4.4.0/arch/mips/kernel/ptrace.c --- linux-lts-xenial-4.4.0/arch/mips/kernel/ptrace.c +++ linux-lts-xenial-4.4.0/arch/mips/kernel/ptrace.c @@ -841,7 +841,7 @@ break; } #endif - tmp = get_fpr64(&fregs[addr - FPR_BASE], 0); + tmp = get_fpr32(&fregs[addr - FPR_BASE], 0); break; case PC: tmp = regs->cp0_epc; diff -u linux-lts-xenial-4.4.0/arch/mips/kernel/ptrace32.c linux-lts-xenial-4.4.0/arch/mips/kernel/ptrace32.c --- linux-lts-xenial-4.4.0/arch/mips/kernel/ptrace32.c +++ linux-lts-xenial-4.4.0/arch/mips/kernel/ptrace32.c @@ -107,7 +107,7 @@ addr & 1); break; } - tmp = get_fpr64(&fregs[addr - FPR_BASE], 0); + tmp = get_fpr32(&fregs[addr - FPR_BASE], 0); break; case PC: tmp = regs->cp0_epc; reverted: --- linux-lts-xenial-4.4.0/arch/powerpc/kernel/cpu_setup_power.S +++ linux-lts-xenial-4.4.0.orig/arch/powerpc/kernel/cpu_setup_power.S @@ -27,7 +27,6 @@ beqlr li r0,0 mtspr SPRN_LPID,r0 - mtspr SPRN_PCR,r0 mfspr r3,SPRN_LPCR bl __init_LPCR bl __init_tlb_power7 @@ -41,7 +40,6 @@ beqlr li r0,0 mtspr SPRN_LPID,r0 - mtspr SPRN_PCR,r0 mfspr r3,SPRN_LPCR bl __init_LPCR bl __init_tlb_power7 @@ -57,7 +55,6 @@ beqlr li r0,0 mtspr SPRN_LPID,r0 - mtspr SPRN_PCR,r0 mfspr r3,SPRN_LPCR ori r3, r3, LPCR_PECEDH bl __init_LPCR @@ -77,7 +74,6 @@ beqlr li r0,0 mtspr SPRN_LPID,r0 - mtspr SPRN_PCR,r0 mfspr r3,SPRN_LPCR ori r3, r3, LPCR_PECEDH bl __init_LPCR diff -u linux-lts-xenial-4.4.0/arch/powerpc/kernel/entry_64.S linux-lts-xenial-4.4.0/arch/powerpc/kernel/entry_64.S --- linux-lts-xenial-4.4.0/arch/powerpc/kernel/entry_64.S +++ linux-lts-xenial-4.4.0/arch/powerpc/kernel/entry_64.S @@ -574,7 +574,6 @@ * actually hit this code path. */ - isync slbie r6 slbie r6 /* Workaround POWER5 < DD2.1 issue */ slbmte r7,r0 diff -u linux-lts-xenial-4.4.0/arch/powerpc/kernel/fadump.c linux-lts-xenial-4.4.0/arch/powerpc/kernel/fadump.c --- linux-lts-xenial-4.4.0/arch/powerpc/kernel/fadump.c +++ linux-lts-xenial-4.4.0/arch/powerpc/kernel/fadump.c @@ -1025,9 +1025,6 @@ init_fadump_mem_struct(&fdm, be64_to_cpu(fdm_active->cpu_state_data.destination_address)); fadump_invalidate_dump(&fdm); - } else if (fw_dump.dump_registered) { - /* Un-register Firmware-assisted dump if it was registered. */ - fadump_unregister_dump(&fdm); } } diff -u linux-lts-xenial-4.4.0/arch/powerpc/kernel/hw_breakpoint.c linux-lts-xenial-4.4.0/arch/powerpc/kernel/hw_breakpoint.c --- linux-lts-xenial-4.4.0/arch/powerpc/kernel/hw_breakpoint.c +++ linux-lts-xenial-4.4.0/arch/powerpc/kernel/hw_breakpoint.c @@ -174,8 +174,8 @@ if (cpu_has_feature(CPU_FTR_DAWR)) { length_max = 512 ; /* 64 doublewords */ /* DAWR region can't cross 512 boundary */ - if ((bp->attr.bp_addr >> 9) != - ((bp->attr.bp_addr + bp->attr.bp_len - 1) >> 9)) + if ((bp->attr.bp_addr >> 10) != + ((bp->attr.bp_addr + bp->attr.bp_len - 1) >> 10)) return -EINVAL; } if (info->len > diff -u linux-lts-xenial-4.4.0/arch/powerpc/kernel/ptrace.c linux-lts-xenial-4.4.0/arch/powerpc/kernel/ptrace.c --- linux-lts-xenial-4.4.0/arch/powerpc/kernel/ptrace.c +++ linux-lts-xenial-4.4.0/arch/powerpc/kernel/ptrace.c @@ -1004,7 +1004,6 @@ /* Create a new breakpoint request if one doesn't exist already */ hw_breakpoint_init(&attr); attr.bp_addr = hw_brk.address; - attr.bp_len = 8; arch_bp_generic_fields(hw_brk.type, &attr.bp_type); diff -u linux-lts-xenial-4.4.0/arch/s390/kernel/entry.S linux-lts-xenial-4.4.0/arch/s390/kernel/entry.S --- linux-lts-xenial-4.4.0/arch/s390/kernel/entry.S +++ linux-lts-xenial-4.4.0/arch/s390/kernel/entry.S @@ -1170,7 +1170,7 @@ jl 0f clg %r9,BASED(.Lcleanup_table+104) # .Lload_fpu_regs_end jl .Lcleanup_load_fpu_regs -0: BR_EX %r14,%r11 +0: BR_EX %r14 .align 8 .Lcleanup_table: @@ -1200,7 +1200,7 @@ ni __SIE_PROG0C+3(%r9),0xfe # no longer in SIE lctlg %c1,%c1,__LC_USER_ASCE # load primary asce larl %r9,sie_exit # skip forward to sie_exit - BR_EX %r14,%r11 + BR_EX %r14 #endif .Lcleanup_system_call: reverted: --- linux-lts-xenial-4.4.0/arch/sh/kernel/sh_ksyms_32.c +++ linux-lts-xenial-4.4.0.orig/arch/sh/kernel/sh_ksyms_32.c @@ -34,9 +34,6 @@ DECLARE_EXPORT(__lshrsi3); DECLARE_EXPORT(__ashrsi3); DECLARE_EXPORT(__ashlsi3); -DECLARE_EXPORT(__lshrsi3_r0); -DECLARE_EXPORT(__ashrsi3_r0); -DECLARE_EXPORT(__ashlsi3_r0); DECLARE_EXPORT(__ashiftrt_r4_6); DECLARE_EXPORT(__ashiftrt_r4_7); DECLARE_EXPORT(__ashiftrt_r4_8); reverted: --- linux-lts-xenial-4.4.0/arch/sh/lib/ashlsi3.S +++ linux-lts-xenial-4.4.0.orig/arch/sh/lib/ashlsi3.S @@ -54,38 +54,21 @@ ! ! (none) ! -! __ashlsi3_r0 -! -! Entry: -! -! r4: Value to shift -! r0: Shifts -! -! Exit: -! -! r0: Result -! -! Destroys: -! -! (none) - - .global __ashlsi3 - .global __ashlsi3_r0 .align 2 __ashlsi3: + mov #31,r0 + and r0,r5 - mov r5,r0 - .align 2 -__ashlsi3_r0: - and #31,r0 - mov.l r4,@-r15 - mov r0,r4 mova ashlsi3_table,r0 + mov.b @(r0,r5),r5 +#ifdef __sh1__ + add r5,r0 - mov.b @(r0,r4),r4 - add r4,r0 jmp @r0 +#else + braf r5 +#endif + mov r4,r0 - mov.l @r15+,r0 .align 2 ashlsi3_table: reverted: --- linux-lts-xenial-4.4.0/arch/sh/lib/ashrsi3.S +++ linux-lts-xenial-4.4.0.orig/arch/sh/lib/ashrsi3.S @@ -54,37 +54,22 @@ ! ! (none) ! -! __ashrsi3_r0 -! -! Entry: -! -! r4: Value to shift -! r0: Shifts -! -! Exit: -! -! r0: Result -! -! Destroys: -! -! (none) .global __ashrsi3 - .global __ashrsi3_r0 .align 2 __ashrsi3: + mov #31,r0 + and r0,r5 - mov r5,r0 - .align 2 -__ashrsi3_r0: - and #31,r0 - mov.l r4,@-r15 - mov r0,r4 mova ashrsi3_table,r0 + mov.b @(r0,r5),r5 +#ifdef __sh1__ + add r5,r0 - mov.b @(r0,r4),r4 - add r4,r0 jmp @r0 +#else + braf r5 +#endif + mov r4,r0 - mov.l @r15+,r0 .align 2 ashrsi3_table: reverted: --- linux-lts-xenial-4.4.0/arch/sh/lib/lshrsi3.S +++ linux-lts-xenial-4.4.0.orig/arch/sh/lib/lshrsi3.S @@ -54,37 +54,21 @@ ! ! (none) ! -! __lshrsi3_r0 -! -! Entry: -! -! r0: Value to shift -! r5: Shifts -! -! Exit: -! -! r0: Result -! -! Destroys: -! -! (none) -! .global __lshrsi3 - .global __lshrsi3_r0 .align 2 __lshrsi3: + mov #31,r0 + and r0,r5 - mov r5,r0 - .align 2 -__lshrsi3_r0: - and #31,r0 - mov.l r4,@-r15 - mov r0,r4 mova lshrsi3_table,r0 + mov.b @(r0,r5),r5 +#ifdef __sh1__ + add r5,r0 - mov.b @(r0,r4),r4 - add r4,r0 jmp @r0 +#else + braf r5 +#endif + mov r4,r0 - mov.l @r15+,r0 .align 2 lshrsi3_table: reverted: --- linux-lts-xenial-4.4.0/arch/sparc/kernel/ds.c +++ linux-lts-xenial-4.4.0.orig/arch/sparc/kernel/ds.c @@ -908,7 +908,7 @@ pbuf.req.handle = cp->handle; pbuf.req.major = 1; pbuf.req.minor = 0; + strcpy(pbuf.req.svc_id, cp->service_id); - strcpy(pbuf.id_buf, cp->service_id); err = __ds_send(lp, &pbuf, msg_len); if (err > 0) diff -u linux-lts-xenial-4.4.0/arch/x86/Kconfig linux-lts-xenial-4.4.0/arch/x86/Kconfig --- linux-lts-xenial-4.4.0/arch/x86/Kconfig +++ linux-lts-xenial-4.4.0/arch/x86/Kconfig @@ -140,6 +140,7 @@ select HAVE_UID16 if X86_32 || IA32_EMULATION select HAVE_UNSTABLE_SCHED_CLOCK select HAVE_USER_RETURN_NOTIFIER + select HOTPLUG_SMT if SMP select IRQ_FORCED_THREADING select MODULES_USE_ELF_RELA if X86_64 select MODULES_USE_ELF_REL if X86_32 reverted: --- linux-lts-xenial-4.4.0/arch/x86/crypto/chacha20_glue.c +++ linux-lts-xenial-4.4.0.orig/arch/x86/crypto/chacha20_glue.c @@ -125,7 +125,7 @@ static int __init chacha20_simd_mod_init(void) { + if (!cpu_has_ssse3) - if (!boot_cpu_has(X86_FEATURE_SSSE3)) return -ENODEV; #ifdef CONFIG_AS_AVX2 diff -u linux-lts-xenial-4.4.0/arch/x86/crypto/crc32c-intel_glue.c linux-lts-xenial-4.4.0/arch/x86/crypto/crc32c-intel_glue.c --- linux-lts-xenial-4.4.0/arch/x86/crypto/crc32c-intel_glue.c +++ linux-lts-xenial-4.4.0/arch/x86/crypto/crc32c-intel_glue.c @@ -58,11 +58,16 @@ asmlinkage unsigned int crc_pcl(const u8 *buffer, int len, unsigned int crc_init); static int crc32c_pcl_breakeven = CRC32C_PCL_BREAKEVEN_EAGERFPU; +#if defined(X86_FEATURE_EAGER_FPU) #define set_pcl_breakeven_point() \ do { \ if (!use_eager_fpu()) \ crc32c_pcl_breakeven = CRC32C_PCL_BREAKEVEN_NOEAGERFPU; \ } while (0) +#else +#define set_pcl_breakeven_point() \ + (crc32c_pcl_breakeven = CRC32C_PCL_BREAKEVEN_NOEAGERFPU) +#endif #endif /* CONFIG_X86_64 */ static u32 crc32c_intel_le_hw_byte(u32 crc, unsigned char const *data, size_t length) @@ -252,7 +257,7 @@ if (!x86_match_cpu(crc32c_cpu_id)) return -ENODEV; #ifdef CONFIG_X86_64 - if (boot_cpu_has(X86_FEATURE_PCLMULQDQ)) { + if (cpu_has_pclmulqdq) { alg.update = crc32c_pcl_intel_update; alg.finup = crc32c_pcl_intel_finup; alg.digest = crc32c_pcl_intel_digest; diff -u linux-lts-xenial-4.4.0/arch/x86/events/amd/core.c linux-lts-xenial-4.4.0/arch/x86/events/amd/core.c --- linux-lts-xenial-4.4.0/arch/x86/events/amd/core.c +++ linux-lts-xenial-4.4.0/arch/x86/events/amd/core.c @@ -160,7 +160,7 @@ if (offset) return offset; - if (!boot_cpu_has(X86_FEATURE_PERFCTR_CORE)) + if (!cpu_has_perfctr_core) offset = index; else offset = index << 1; @@ -652,7 +652,7 @@ static int __init amd_core_pmu_init(void) { - if (!boot_cpu_has(X86_FEATURE_PERFCTR_CORE)) + if (!cpu_has_perfctr_core) return 0; switch (boot_cpu_data.x86) { diff -u linux-lts-xenial-4.4.0/arch/x86/events/amd/uncore.c linux-lts-xenial-4.4.0/arch/x86/events/amd/uncore.c --- linux-lts-xenial-4.4.0/arch/x86/events/amd/uncore.c +++ linux-lts-xenial-4.4.0/arch/x86/events/amd/uncore.c @@ -523,10 +523,10 @@ if (boot_cpu_data.x86_vendor != X86_VENDOR_AMD) goto fail_nodev; - if (!boot_cpu_has(X86_FEATURE_TOPOEXT)) + if (!cpu_has_topoext) goto fail_nodev; - if (boot_cpu_has(X86_FEATURE_PERFCTR_NB)) { + if (cpu_has_perfctr_nb) { amd_uncore_nb = alloc_percpu(struct amd_uncore *); if (!amd_uncore_nb) { ret = -ENOMEM; @@ -540,7 +540,7 @@ ret = 0; } - if (boot_cpu_has(X86_FEATURE_PERFCTR_L2)) { + if (cpu_has_perfctr_l2) { amd_uncore_l2 = alloc_percpu(struct amd_uncore *); if (!amd_uncore_l2) { ret = -ENOMEM; @@ -583,11 +583,10 @@ /* amd_uncore_nb/l2 should have been freed by cleanup_cpu_online */ amd_uncore_nb = amd_uncore_l2 = NULL; - - if (boot_cpu_has(X86_FEATURE_PERFCTR_L2)) + if (cpu_has_perfctr_l2) perf_pmu_unregister(&amd_l2_pmu); fail_l2: - if (boot_cpu_has(X86_FEATURE_PERFCTR_NB)) + if (cpu_has_perfctr_nb) perf_pmu_unregister(&amd_nb_pmu); if (amd_uncore_l2) free_percpu(amd_uncore_l2); diff -u linux-lts-xenial-4.4.0/arch/x86/include/asm/apic.h linux-lts-xenial-4.4.0/arch/x86/include/asm/apic.h --- linux-lts-xenial-4.4.0/arch/x86/include/asm/apic.h +++ linux-lts-xenial-4.4.0/arch/x86/include/asm/apic.h @@ -11,6 +11,7 @@ #include #include #include +#include #include #define ARCH_APICTIMER_STOPS_ON_C3 1 @@ -626,12 +627,20 @@ #endif #endif /* CONFIG_X86_LOCAL_APIC */ + +#ifdef CONFIG_SMP +bool apic_id_is_primary_thread(unsigned int id); +#else +static inline bool apic_id_is_primary_thread(unsigned int id) { return false; } +#endif + extern void irq_enter(void); extern void irq_exit(void); static inline void entering_irq(void) { irq_enter(); + kvm_set_cpu_l1tf_flush_l1d(); exit_idle(); } @@ -643,8 +652,9 @@ static inline void ipi_entering_ack_irq(void) { - ack_APIC_irq(); irq_enter(); + ack_APIC_irq(); + kvm_set_cpu_l1tf_flush_l1d(); } static inline void exiting_irq(void) @@ -654,9 +664,8 @@ static inline void exiting_ack_irq(void) { - irq_exit(); - /* Ack only at the end to avoid potential reentry */ ack_APIC_irq(); + irq_exit(); } extern void ioapic_zap_locks(void); diff -u linux-lts-xenial-4.4.0/arch/x86/include/asm/barrier.h linux-lts-xenial-4.4.0/arch/x86/include/asm/barrier.h --- linux-lts-xenial-4.4.0/arch/x86/include/asm/barrier.h +++ linux-lts-xenial-4.4.0/arch/x86/include/asm/barrier.h @@ -38,7 +38,7 @@ { unsigned long mask; - asm volatile ("cmp %1,%2; sbb %0,%0;" + asm ("cmp %1,%2; sbb %0,%0;" :"=r" (mask) :"r"(size),"r" (index) :"cc"); reverted: --- linux-lts-xenial-4.4.0/arch/x86/include/asm/cmpxchg_32.h +++ linux-lts-xenial-4.4.0.orig/arch/x86/include/asm/cmpxchg_32.h @@ -109,6 +109,6 @@ #endif +#define system_has_cmpxchg_double() cpu_has_cx8 -#define system_has_cmpxchg_double() boot_cpu_has(X86_FEATURE_CX8) #endif /* _ASM_X86_CMPXCHG_32_H */ reverted: --- linux-lts-xenial-4.4.0/arch/x86/include/asm/cmpxchg_64.h +++ linux-lts-xenial-4.4.0.orig/arch/x86/include/asm/cmpxchg_64.h @@ -18,6 +18,6 @@ cmpxchg_local((ptr), (o), (n)); \ }) +#define system_has_cmpxchg_double() cpu_has_cx16 -#define system_has_cmpxchg_double() boot_cpu_has(X86_FEATURE_CX16) #endif /* _ASM_X86_CMPXCHG_64_H */ diff -u linux-lts-xenial-4.4.0/arch/x86/include/asm/cpufeature.h linux-lts-xenial-4.4.0/arch/x86/include/asm/cpufeature.h --- linux-lts-xenial-4.4.0/arch/x86/include/asm/cpufeature.h +++ linux-lts-xenial-4.4.0/arch/x86/include/asm/cpufeature.h @@ -128,29 +128,58 @@ #define setup_force_cpu_bug(bit) setup_force_cpu_cap(bit) #define cpu_has_fpu boot_cpu_has(X86_FEATURE_FPU) +#define cpu_has_de boot_cpu_has(X86_FEATURE_DE) #define cpu_has_pse boot_cpu_has(X86_FEATURE_PSE) #define cpu_has_tsc boot_cpu_has(X86_FEATURE_TSC) #define cpu_has_pge boot_cpu_has(X86_FEATURE_PGE) #define cpu_has_apic boot_cpu_has(X86_FEATURE_APIC) +#define cpu_has_sep boot_cpu_has(X86_FEATURE_SEP) +#define cpu_has_mtrr boot_cpu_has(X86_FEATURE_MTRR) +#define cpu_has_mmx boot_cpu_has(X86_FEATURE_MMX) #define cpu_has_fxsr boot_cpu_has(X86_FEATURE_FXSR) #define cpu_has_xmm boot_cpu_has(X86_FEATURE_XMM) #define cpu_has_xmm2 boot_cpu_has(X86_FEATURE_XMM2) +#define cpu_has_xmm3 boot_cpu_has(X86_FEATURE_XMM3) +#define cpu_has_ssse3 boot_cpu_has(X86_FEATURE_SSSE3) #define cpu_has_aes boot_cpu_has(X86_FEATURE_AES) #define cpu_has_avx boot_cpu_has(X86_FEATURE_AVX) #define cpu_has_avx2 boot_cpu_has(X86_FEATURE_AVX2) +#define cpu_has_ht boot_cpu_has(X86_FEATURE_HT) +#define cpu_has_nx boot_cpu_has(X86_FEATURE_NX) +#define cpu_has_xstore boot_cpu_has(X86_FEATURE_XSTORE) +#define cpu_has_xstore_enabled boot_cpu_has(X86_FEATURE_XSTORE_EN) +#define cpu_has_xcrypt boot_cpu_has(X86_FEATURE_XCRYPT) +#define cpu_has_xcrypt_enabled boot_cpu_has(X86_FEATURE_XCRYPT_EN) +#define cpu_has_ace2 boot_cpu_has(X86_FEATURE_ACE2) +#define cpu_has_ace2_enabled boot_cpu_has(X86_FEATURE_ACE2_EN) +#define cpu_has_phe boot_cpu_has(X86_FEATURE_PHE) +#define cpu_has_phe_enabled boot_cpu_has(X86_FEATURE_PHE_EN) +#define cpu_has_pmm boot_cpu_has(X86_FEATURE_PMM) +#define cpu_has_pmm_enabled boot_cpu_has(X86_FEATURE_PMM_EN) +#define cpu_has_ds boot_cpu_has(X86_FEATURE_DS) +#define cpu_has_pebs boot_cpu_has(X86_FEATURE_PEBS) #define cpu_has_clflush boot_cpu_has(X86_FEATURE_CLFLUSH) +#define cpu_has_bts boot_cpu_has(X86_FEATURE_BTS) #define cpu_has_gbpages boot_cpu_has(X86_FEATURE_GBPAGES) #define cpu_has_arch_perfmon boot_cpu_has(X86_FEATURE_ARCH_PERFMON) #define cpu_has_pat boot_cpu_has(X86_FEATURE_PAT) +#define cpu_has_xmm4_1 boot_cpu_has(X86_FEATURE_XMM4_1) +#define cpu_has_xmm4_2 boot_cpu_has(X86_FEATURE_XMM4_2) #define cpu_has_x2apic boot_cpu_has(X86_FEATURE_X2APIC) #define cpu_has_xsave boot_cpu_has(X86_FEATURE_XSAVE) +#define cpu_has_xsaveopt boot_cpu_has(X86_FEATURE_XSAVEOPT) #define cpu_has_xsaves boot_cpu_has(X86_FEATURE_XSAVES) #define cpu_has_osxsave boot_cpu_has(X86_FEATURE_OSXSAVE) #define cpu_has_hypervisor boot_cpu_has(X86_FEATURE_HYPERVISOR) -/* - * Do not add any more of those clumsy macros - use static_cpu_has_safe() for - * fast paths and boot_cpu_has() otherwise! - */ +#define cpu_has_pclmulqdq boot_cpu_has(X86_FEATURE_PCLMULQDQ) +#define cpu_has_perfctr_core boot_cpu_has(X86_FEATURE_PERFCTR_CORE) +#define cpu_has_perfctr_nb boot_cpu_has(X86_FEATURE_PERFCTR_NB) +#define cpu_has_perfctr_l2 boot_cpu_has(X86_FEATURE_PERFCTR_L2) +#define cpu_has_cx8 boot_cpu_has(X86_FEATURE_CX8) +#define cpu_has_cx16 boot_cpu_has(X86_FEATURE_CX16) +#define cpu_has_eager_fpu boot_cpu_has(X86_FEATURE_EAGER_FPU) +#define cpu_has_topoext boot_cpu_has(X86_FEATURE_TOPOEXT) +#define cpu_has_bpext boot_cpu_has(X86_FEATURE_BPEXT) #if __GNUC__ >= 4 extern void warn_pre_alternatives(void); diff -u linux-lts-xenial-4.4.0/arch/x86/include/asm/cpufeatures.h linux-lts-xenial-4.4.0/arch/x86/include/asm/cpufeatures.h --- linux-lts-xenial-4.4.0/arch/x86/include/asm/cpufeatures.h +++ linux-lts-xenial-4.4.0/arch/x86/include/asm/cpufeatures.h @@ -104,7 +104,7 @@ #define X86_FEATURE_EXTD_APICID ( 3*32+26) /* has extended APICID (8 bits) */ #define X86_FEATURE_AMD_DCM ( 3*32+27) /* multi-node processor */ #define X86_FEATURE_APERFMPERF ( 3*32+28) /* APERFMPERF */ -/* free, was #define X86_FEATURE_EAGER_FPU ( 3*32+29) * "eagerfpu" Non lazy FPU restore */ +#define X86_FEATURE_EAGER_FPU ( 3*32+29) /* "eagerfpu" Non lazy FPU restore */ #define X86_FEATURE_NONSTOP_TSC_S3 ( 3*32+30) /* TSC doesn't stop in S3 state */ /* Intel-defined CPU features, CPUID level 0x00000001 (ecx), word 4 */ @@ -210,6 +210,7 @@ #define X86_FEATURE_IBPB ( 7*32+26) /* Indirect Branch Prediction Barrier */ #define X86_FEATURE_STIBP ( 7*32+27) /* Single Thread Indirect Branch Predictors */ #define X86_FEATURE_ZEN ( 7*32+28) /* "" CPU is AMD family 0x17 (Zen) */ +#define X86_FEATURE_L1TF_PTEINV ( 7*32+29) /* "" L1TF workaround PTE inversion */ /* Because the ALTERNATIVE scheme is for members of the X86_FEATURE club... */ #define X86_FEATURE_KAISER ( 7*32+31) /* CONFIG_PAGE_TABLE_ISOLATION w/o nokaiser */ @@ -300,6 +301,7 @@ /* Intel-defined CPU features, CPUID level 0x00000007:0 (EDX), word 18 */ #define X86_FEATURE_SPEC_CTRL (18*32+26) /* "" Speculation Control (IBRS + IBPB) */ #define X86_FEATURE_INTEL_STIBP (18*32+27) /* "" Single Thread Indirect Branch Predictors */ +#define X86_FEATURE_FLUSH_L1D (18*32+28) /* Flush L1D cache */ #define X86_FEATURE_ARCH_CAPABILITIES (18*32+29) /* IA32_ARCH_CAPABILITIES MSR (Intel) */ #define X86_FEATURE_SPEC_CTRL_SSBD (18*32+31) /* "" Speculative Store Bypass Disable */ @@ -324,4 +326,5 @@ #define X86_BUG_SPECTRE_V2 X86_BUG(16) /* CPU is affected by Spectre variant 2 attack with indirect branches */ #define X86_BUG_SPEC_STORE_BYPASS X86_BUG(17) /* CPU is affected by speculative store bypass attack */ +#define X86_BUG_L1TF X86_BUG(18) /* CPU is affected by L1 Terminal Fault */ #endif /* _ASM_X86_CPUFEATURES_H */ diff -u linux-lts-xenial-4.4.0/arch/x86/include/asm/fpu/internal.h linux-lts-xenial-4.4.0/arch/x86/include/asm/fpu/internal.h --- linux-lts-xenial-4.4.0/arch/x86/include/asm/fpu/internal.h +++ linux-lts-xenial-4.4.0/arch/x86/include/asm/fpu/internal.h @@ -59,7 +59,7 @@ */ static __always_inline __pure bool use_eager_fpu(void) { - return true; + return static_cpu_has_safe(X86_FEATURE_EAGER_FPU); } static __always_inline __pure bool use_xsaveopt(void) reverted: --- linux-lts-xenial-4.4.0/arch/x86/include/asm/fpu/xstate.h +++ linux-lts-xenial-4.4.0.orig/arch/x86/include/asm/fpu/xstate.h @@ -22,7 +22,7 @@ #define XFEATURE_MASK_LAZY (XFEATURE_MASK_FP | \ XFEATURE_MASK_SSE | \ XFEATURE_MASK_YMM | \ + XFEATURE_MASK_OPMASK | \ - XFEATURE_MASK_OPMASK | \ XFEATURE_MASK_ZMM_Hi256 | \ XFEATURE_MASK_Hi16_ZMM) diff -u linux-lts-xenial-4.4.0/arch/x86/include/asm/hardirq.h linux-lts-xenial-4.4.0/arch/x86/include/asm/hardirq.h --- linux-lts-xenial-4.4.0/arch/x86/include/asm/hardirq.h +++ linux-lts-xenial-4.4.0/arch/x86/include/asm/hardirq.h @@ -2,10 +2,12 @@ #define _ASM_X86_HARDIRQ_H #include -#include typedef struct { - unsigned int __softirq_pending; + u16 __softirq_pending; +#if IS_ENABLED(CONFIG_KVM_INTEL) + u8 kvm_cpu_l1tf_flush_l1d; +#endif unsigned int __nmi_count; /* arch dependent */ #ifdef CONFIG_X86_LOCAL_APIC unsigned int apic_timer_irqs; /* arch dependent */ @@ -62,2 +64,22 @@ + +#if IS_ENABLED(CONFIG_KVM_INTEL) +static inline void kvm_set_cpu_l1tf_flush_l1d(void) +{ + __this_cpu_write(irq_stat.kvm_cpu_l1tf_flush_l1d, 1); +} + +static inline void kvm_clear_cpu_l1tf_flush_l1d(void) +{ + __this_cpu_write(irq_stat.kvm_cpu_l1tf_flush_l1d, 0); +} + +static inline bool kvm_get_cpu_l1tf_flush_l1d(void) +{ + return __this_cpu_read(irq_stat.kvm_cpu_l1tf_flush_l1d); +} +#else /* !IS_ENABLED(CONFIG_KVM_INTEL) */ +static inline void kvm_set_cpu_l1tf_flush_l1d(void) { } +#endif /* IS_ENABLED(CONFIG_KVM_INTEL) */ + #endif /* _ASM_X86_HARDIRQ_H */ diff -u linux-lts-xenial-4.4.0/arch/x86/include/asm/intel-family.h linux-lts-xenial-4.4.0/arch/x86/include/asm/intel-family.h --- linux-lts-xenial-4.4.0/arch/x86/include/asm/intel-family.h +++ linux-lts-xenial-4.4.0/arch/x86/include/asm/intel-family.h @@ -61,8 +61,10 @@ #define INTEL_FAM6_ATOM_GOLDMONT 0x5C #define INTEL_FAM6_ATOM_DENVERTON 0x5F /* Goldmont Microserver */ +#define INTEL_FAM6_ATOM_GEMINI_LAKE 0x7A /* Xeon Phi */ #define INTEL_FAM6_XEON_PHI_KNL 0x57 /* Knights Landing */ +#define INTEL_FAM6_XEON_PHI_KNM 0x85 /* Knights Mill */ #endif /* _ASM_X86_INTEL_FAMILY_H */ diff -u linux-lts-xenial-4.4.0/arch/x86/include/asm/kvm_host.h linux-lts-xenial-4.4.0/arch/x86/include/asm/kvm_host.h --- linux-lts-xenial-4.4.0/arch/x86/include/asm/kvm_host.h +++ linux-lts-xenial-4.4.0/arch/x86/include/asm/kvm_host.h @@ -17,6 +17,7 @@ #include #include #include +#include #include #include @@ -614,6 +615,9 @@ int pending_ioapic_eoi; int pending_external_vector; + + /* Flush the L1 Data cache for L1TF mitigation on VMENTER */ + bool l1tf_flush_l1d; }; struct kvm_lpage_info { @@ -754,6 +758,7 @@ u32 signal_exits; u32 irq_window_exits; u32 nmi_window_exits; + u32 l1d_flush; u32 halt_exits; u32 halt_successful_poll; u32 halt_attempted_poll; @@ -801,6 +806,9 @@ bool (*has_emulated_msr)(int index); void (*cpuid_update)(struct kvm_vcpu *vcpu); + int (*vm_init)(struct kvm *kvm); + void (*vm_destroy)(struct kvm *kvm); + /* Create, but do not attach this VCPU */ struct kvm_vcpu *(*vcpu_create)(struct kvm *kvm, unsigned id); void (*vcpu_free)(struct kvm_vcpu *vcpu); @@ -944,6 +952,8 @@ void (*post_block)(struct kvm_vcpu *vcpu); int (*update_pi_irte)(struct kvm *kvm, unsigned int host_irq, uint32_t guest_irq, bool set); + + int (*get_msr_feature)(struct kvm_msr_entry *entry); }; struct kvm_arch_async_pf { @@ -1258,6 +1268,7 @@ void kvm_arch_mmu_notifier_invalidate_page(struct kvm *kvm, unsigned long address); +u64 kvm_get_arch_capabilities(void); void kvm_define_shared_msr(unsigned index, u32 msr); int kvm_set_shared_msr(unsigned index, u64 val, u64 mask); diff -u linux-lts-xenial-4.4.0/arch/x86/include/asm/msr-index.h linux-lts-xenial-4.4.0/arch/x86/include/asm/msr-index.h --- linux-lts-xenial-4.4.0/arch/x86/include/asm/msr-index.h +++ linux-lts-xenial-4.4.0/arch/x86/include/asm/msr-index.h @@ -58,12 +58,19 @@ #define MSR_IA32_ARCH_CAPABILITIES 0x0000010a #define ARCH_CAP_RDCL_NO (1 << 0) /* Not susceptible to Meltdown */ #define ARCH_CAP_IBRS_ALL (1 << 1) /* Enhanced IBRS support */ +#define ARCH_CAP_SKIP_VMENTRY_L1DFLUSH (1 << 3) /* Skip L1D flush on vmentry */ #define ARCH_CAP_SSB_NO (1 << 4) /* * Not susceptible to Speculative Store Bypass * attack, so no Speculative Store Bypass * control required. */ +#define MSR_IA32_FLUSH_CMD 0x0000010b +#define L1D_FLUSH (1 << 0) /* + * Writeback and invalidate the + * L1 data cache. + */ + #define MSR_IA32_BBL_CR_CTL 0x00000119 #define MSR_IA32_BBL_CR_CTL3 0x0000011e diff -u linux-lts-xenial-4.4.0/arch/x86/include/asm/pgtable.h linux-lts-xenial-4.4.0/arch/x86/include/asm/pgtable.h --- linux-lts-xenial-4.4.0/arch/x86/include/asm/pgtable.h +++ linux-lts-xenial-4.4.0/arch/x86/include/asm/pgtable.h @@ -148,19 +148,34 @@ return pte_flags(pte) & _PAGE_SPECIAL; } +/* Entries that were set to PROT_NONE are inverted */ + +static inline u64 protnone_mask(u64 val); + static inline unsigned long pte_pfn(pte_t pte) { - return (pte_val(pte) & PTE_PFN_MASK) >> PAGE_SHIFT; + phys_addr_t pfn = pte_val(pte); + pfn ^= protnone_mask(pfn); + return (pfn & PTE_PFN_MASK) >> PAGE_SHIFT; } static inline unsigned long pmd_pfn(pmd_t pmd) { - return (pmd_val(pmd) & pmd_pfn_mask(pmd)) >> PAGE_SHIFT; + phys_addr_t pfn = pmd_val(pmd); + pfn ^= protnone_mask(pfn); + return (pfn & pmd_pfn_mask(pmd)) >> PAGE_SHIFT; } static inline unsigned long pud_pfn(pud_t pud) { - return (pud_val(pud) & pud_pfn_mask(pud)) >> PAGE_SHIFT; + phys_addr_t pfn = pud_val(pud); + pfn ^= protnone_mask(pfn); + return (pfn & pud_pfn_mask(pud)) >> PAGE_SHIFT; +} + +static inline unsigned long pgd_pfn(pgd_t pgd) +{ + return (pgd_val(pgd) & PTE_PFN_MASK) >> PAGE_SHIFT; } #define pte_page(pte) pfn_to_page(pte_pfn(pte)) @@ -305,9 +320,12 @@ return pmd_set_flags(pmd, _PAGE_RW); } -static inline pmd_t pmd_mknotpresent(pmd_t pmd) +/* Only used by arch/x86/mm/pageattr.c: populate_pmd() */ +static inline pud_t pud_mkhuge(pud_t pud) { - return pmd_clear_flags(pmd, _PAGE_PRESENT | _PAGE_PROTNONE); + pudval_t v = native_pud_val(pud); + + return __pud(v | _PAGE_PSE); } #ifdef CONFIG_HAVE_ARCH_SOFT_DIRTY @@ -359,19 +377,40 @@ static inline pte_t pfn_pte(unsigned long page_nr, pgprot_t pgprot) { - return __pte(((phys_addr_t)page_nr << PAGE_SHIFT) | - massage_pgprot(pgprot)); + phys_addr_t pfn = (phys_addr_t)page_nr << PAGE_SHIFT; + pfn ^= protnone_mask(pgprot_val(pgprot)); + pfn &= PTE_PFN_MASK; + return __pte(pfn | massage_pgprot(pgprot)); } static inline pmd_t pfn_pmd(unsigned long page_nr, pgprot_t pgprot) { - return __pmd(((phys_addr_t)page_nr << PAGE_SHIFT) | - massage_pgprot(pgprot)); + phys_addr_t pfn = (phys_addr_t)page_nr << PAGE_SHIFT; + pfn ^= protnone_mask(pgprot_val(pgprot)); + pfn &= PHYSICAL_PMD_PAGE_MASK; + return __pmd(pfn | massage_pgprot(pgprot)); } +static inline pud_t pfn_pud(unsigned long page_nr, pgprot_t pgprot) +{ + phys_addr_t pfn = (phys_addr_t)page_nr << PAGE_SHIFT; + pfn ^= protnone_mask(pgprot_val(pgprot)); + pfn &= PHYSICAL_PUD_PAGE_MASK; + return __pud(pfn | massage_pgprot(pgprot)); +} + +static inline pmd_t pmd_mknotpresent(pmd_t pmd) +{ + return pfn_pmd(pmd_pfn(pmd), + __pgprot(pmd_flags(pmd) & + ~(_PAGE_PRESENT|_PAGE_PROTNONE))); +} + +static inline u64 flip_protnone_guard(u64 oldval, u64 val, u64 mask); + static inline pte_t pte_modify(pte_t pte, pgprot_t newprot) { - pteval_t val = pte_val(pte); + pteval_t val = pte_val(pte), oldval = val; /* * Chop off the NX bit (if present), and add the NX portion of @@ -379,17 +418,17 @@ */ val &= _PAGE_CHG_MASK; val |= massage_pgprot(newprot) & ~_PAGE_CHG_MASK; - + val = flip_protnone_guard(oldval, val, PTE_PFN_MASK); return __pte(val); } static inline pmd_t pmd_modify(pmd_t pmd, pgprot_t newprot) { - pmdval_t val = pmd_val(pmd); + pmdval_t val = pmd_val(pmd), oldval = val; val &= _HPAGE_CHG_MASK; val |= massage_pgprot(newprot) & ~_HPAGE_CHG_MASK; - + val = flip_protnone_guard(oldval, val, PHYSICAL_PMD_PAGE_MASK); return __pmd(val); } @@ -534,8 +573,7 @@ * Currently stuck as a macro due to indirect forward reference to * linux/mmzone.h's __section_mem_map_addr() definition: */ -#define pmd_page(pmd) \ - pfn_to_page((pmd_val(pmd) & pmd_pfn_mask(pmd)) >> PAGE_SHIFT) +#define pmd_page(pmd) pfn_to_page(pmd_pfn(pmd)) /* * the pmd page can be thought of an array like this: pmd_t[PTRS_PER_PMD] @@ -603,8 +641,7 @@ * Currently stuck as a macro due to indirect forward reference to * linux/mmzone.h's __section_mem_map_addr() definition: */ -#define pud_page(pud) \ - pfn_to_page((pud_val(pud) & pud_pfn_mask(pud)) >> PAGE_SHIFT) +#define pud_page(pud) pfn_to_page(pud_pfn(pud)) /* Find an entry in the second-level page table.. */ static inline pmd_t *pmd_offset(pud_t *pud, unsigned long address) @@ -644,7 +681,7 @@ * Currently stuck as a macro due to indirect forward reference to * linux/mmzone.h's __section_mem_map_addr() definition: */ -#define pgd_page(pgd) pfn_to_page(pgd_val(pgd) >> PAGE_SHIFT) +#define pgd_page(pgd) pfn_to_page(pgd_pfn(pgd)) /* to find an entry in a page-table-directory. */ static inline unsigned long pud_index(unsigned long address) @@ -926,6 +963,14 @@ } #endif +#define __HAVE_ARCH_PFN_MODIFY_ALLOWED 1 +extern bool pfn_modify_allowed(unsigned long pfn, pgprot_t prot); + +static inline bool arch_has_pfn_modify_check(void) +{ + return boot_cpu_has_bug(X86_BUG_L1TF); +} + #include #endif /* __ASSEMBLY__ */ diff -u linux-lts-xenial-4.4.0/arch/x86/include/asm/pgtable_64.h linux-lts-xenial-4.4.0/arch/x86/include/asm/pgtable_64.h --- linux-lts-xenial-4.4.0/arch/x86/include/asm/pgtable_64.h +++ linux-lts-xenial-4.4.0/arch/x86/include/asm/pgtable_64.h @@ -163,18 +163,31 @@ #define pte_offset_map(dir, address) pte_offset_kernel((dir), (address)) #define pte_unmap(pte) ((void)(pte))/* NOP */ -/* Encode and de-code a swap entry */ -#define SWP_TYPE_BITS 5 -#define SWP_OFFSET_SHIFT (_PAGE_BIT_PROTNONE + 1) +/* Encode and de-code a swap entry. */ +#define SWP_TYPE_BITS 5 +#define SWP_OFFSET_FIRST_BIT (_PAGE_BIT_PROTNONE + 1) +/* We always extract/encode the offset by shifting it all the way up, + * and then down again + */ +#define SWP_OFFSET_SHIFT (SWP_OFFSET_FIRST_BIT+SWP_TYPE_BITS) #define MAX_SWAPFILES_CHECK() BUILD_BUG_ON(MAX_SWAPFILES_SHIFT > SWP_TYPE_BITS) -#define __swp_type(x) (((x).val >> (_PAGE_BIT_PRESENT + 1)) \ - & ((1U << SWP_TYPE_BITS) - 1)) -#define __swp_offset(x) ((x).val >> SWP_OFFSET_SHIFT) -#define __swp_entry(type, offset) ((swp_entry_t) { \ - ((type) << (_PAGE_BIT_PRESENT + 1)) \ - | ((offset) << SWP_OFFSET_SHIFT) }) +/* Extract the high bits for type */ +#define __swp_type(x) ((x).val >> (64 - SWP_TYPE_BITS)) + +/* Shift up (to get rid of type), then down to get value */ +#define __swp_offset(x) (~(x).val << SWP_TYPE_BITS >> SWP_OFFSET_SHIFT) + +/* + * Shift the offset up "too far" by TYPE bits, then down again. + * The offset is inverted by a binary not operation to make the high + * physical bits set. + */ +#define __swp_entry(type, offset) ((swp_entry_t) { \ + (~(unsigned long)(offset) << SWP_OFFSET_SHIFT >> SWP_TYPE_BITS) \ + | ((unsigned long)(type) << (64-SWP_TYPE_BITS)) }) + #define __pte_to_swp_entry(pte) ((swp_entry_t) { pte_val((pte)) }) #define __swp_entry_to_pte(x) ((pte_t) { .pte = (x).val }) @@ -203,4 +216,5 @@ -#endif /* !__ASSEMBLY__ */ +#include +#endif /* !__ASSEMBLY__ */ #endif /* _ASM_X86_PGTABLE_64_H */ diff -u linux-lts-xenial-4.4.0/arch/x86/include/asm/processor.h linux-lts-xenial-4.4.0/arch/x86/include/asm/processor.h --- linux-lts-xenial-4.4.0/arch/x86/include/asm/processor.h +++ linux-lts-xenial-4.4.0/arch/x86/include/asm/processor.h @@ -174,6 +174,11 @@ extern void cpu_detect(struct cpuinfo_x86 *c); +static inline unsigned long l1tf_pfn_limit(void) +{ + return BIT(boot_cpu_data.x86_phys_bits - 1 - PAGE_SHIFT) - 1; +} + extern void early_cpu_init(void); extern void identify_boot_cpu(void); extern void identify_secondary_cpu(struct cpuinfo_x86 *); @@ -185,8 +190,9 @@ u8 reg); extern unsigned int init_intel_cacheinfo(struct cpuinfo_x86 *c); extern void init_amd_cacheinfo(struct cpuinfo_x86 *c); - -extern void detect_extended_topology(struct cpuinfo_x86 *c); +extern int detect_extended_topology_early(struct cpuinfo_x86 *c); +extern int detect_extended_topology(struct cpuinfo_x86 *c); +extern int detect_ht_early(struct cpuinfo_x86 *c); extern void detect_ht(struct cpuinfo_x86 *c); #ifdef CONFIG_X86_32 @@ -845,2 +851,14 @@ void df_debug(struct pt_regs *regs, long error_code); + +enum l1tf_mitigations { + L1TF_MITIGATION_OFF, + L1TF_MITIGATION_FLUSH_NOWARN, + L1TF_MITIGATION_FLUSH, + L1TF_MITIGATION_FLUSH_NOSMT, + L1TF_MITIGATION_FULL, + L1TF_MITIGATION_FULL_FORCE +}; + +extern enum l1tf_mitigations l1tf_mitigation; + #endif /* _ASM_X86_PROCESSOR_H */ diff -u linux-lts-xenial-4.4.0/arch/x86/include/asm/smp.h linux-lts-xenial-4.4.0/arch/x86/include/asm/smp.h --- linux-lts-xenial-4.4.0/arch/x86/include/asm/smp.h +++ linux-lts-xenial-4.4.0/arch/x86/include/asm/smp.h @@ -20,6 +20,15 @@ extern int smp_num_siblings; extern unsigned int num_processors; +static inline bool cpu_has_ht_siblings(void) +{ + bool has_siblings = false; +#ifdef CONFIG_SMP + has_siblings = cpu_has_ht && smp_num_siblings > 1; +#endif + return has_siblings; +} + DECLARE_PER_CPU_READ_MOSTLY(cpumask_var_t, cpu_sibling_map); DECLARE_PER_CPU_READ_MOSTLY(cpumask_var_t, cpu_core_map); /* cpus sharing the last level cache: */ diff -u linux-lts-xenial-4.4.0/arch/x86/include/asm/topology.h linux-lts-xenial-4.4.0/arch/x86/include/asm/topology.h --- linux-lts-xenial-4.4.0/arch/x86/include/asm/topology.h +++ linux-lts-xenial-4.4.0/arch/x86/include/asm/topology.h @@ -130,13 +130,26 @@ extern unsigned int __max_logical_packages; #define topology_max_packages() (__max_logical_packages) + +extern int __max_smt_threads; + +static inline int topology_max_smt_threads(void) +{ + return __max_smt_threads; +} + int topology_update_package_map(unsigned int apicid, unsigned int cpu); -extern int topology_phys_to_logical_pkg(unsigned int pkg); +int topology_phys_to_logical_pkg(unsigned int pkg); +bool topology_is_primary_thread(unsigned int cpu); +bool topology_smt_supported(void); #else #define topology_max_packages() (1) static inline int topology_update_package_map(unsigned int apicid, unsigned int cpu) { return 0; } static inline int topology_phys_to_logical_pkg(unsigned int pkg) { return 0; } +static inline int topology_max_smt_threads(void) { return 1; } +static inline bool topology_is_primary_thread(unsigned int cpu) { return true; } +static inline bool topology_smt_supported(void) { return false; } #endif static inline void arch_fix_phys_package_id(int num, u32 slot) diff -u linux-lts-xenial-4.4.0/arch/x86/include/asm/vmx.h linux-lts-xenial-4.4.0/arch/x86/include/asm/vmx.h --- linux-lts-xenial-4.4.0/arch/x86/include/asm/vmx.h +++ linux-lts-xenial-4.4.0/arch/x86/include/asm/vmx.h @@ -502,2 +502,13 @@ +enum vmx_l1d_flush_state { + VMENTER_L1D_FLUSH_AUTO, + VMENTER_L1D_FLUSH_NEVER, + VMENTER_L1D_FLUSH_COND, + VMENTER_L1D_FLUSH_ALWAYS, + VMENTER_L1D_FLUSH_EPT_DISABLED, + VMENTER_L1D_FLUSH_NOT_REQUIRED, +}; + +extern enum vmx_l1d_flush_state l1tf_vmx_mitigation; + #endif reverted: --- linux-lts-xenial-4.4.0/arch/x86/include/asm/xor_32.h +++ linux-lts-xenial-4.4.0.orig/arch/x86/include/asm/xor_32.h @@ -553,7 +553,7 @@ if (cpu_has_xmm) { \ xor_speed(&xor_block_pIII_sse); \ xor_speed(&xor_block_sse_pf64); \ + } else if (cpu_has_mmx) { \ - } else if (boot_cpu_has(X86_FEATURE_MMX)) { \ xor_speed(&xor_block_pII_mmx); \ xor_speed(&xor_block_p5_mmx); \ } else { \ diff -u linux-lts-xenial-4.4.0/arch/x86/kernel/apic/apic.c linux-lts-xenial-4.4.0/arch/x86/kernel/apic/apic.c --- linux-lts-xenial-4.4.0/arch/x86/kernel/apic/apic.c +++ linux-lts-xenial-4.4.0/arch/x86/kernel/apic/apic.c @@ -55,6 +55,7 @@ #include #include #include +#include unsigned int num_processors; @@ -1991,6 +1992,21 @@ apic_write(APIC_LVT1, value); } +/** + * apic_id_is_primary_thread - Check whether APIC ID belongs to a primary thread + * @id: APIC ID to check + */ +bool apic_id_is_primary_thread(unsigned int apicid) +{ + u32 mask; + + if (smp_num_siblings == 1) + return true; + /* Isolate the SMT bit(s) in the APICID and check for 0 */ + mask = (1U << (fls(smp_num_siblings) - 1)) - 1; + return !(apicid & mask); +} + int generic_processor_info(int apicid, int version) { int cpu, max = nr_cpu_ids; diff -u linux-lts-xenial-4.4.0/arch/x86/kernel/apic/io_apic.c linux-lts-xenial-4.4.0/arch/x86/kernel/apic/io_apic.c --- linux-lts-xenial-4.4.0/arch/x86/kernel/apic/io_apic.c +++ linux-lts-xenial-4.4.0/arch/x86/kernel/apic/io_apic.c @@ -32,6 +32,7 @@ #include #include +#include #include #include #include diff -u linux-lts-xenial-4.4.0/arch/x86/kernel/apic/msi.c linux-lts-xenial-4.4.0/arch/x86/kernel/apic/msi.c --- linux-lts-xenial-4.4.0/arch/x86/kernel/apic/msi.c +++ linux-lts-xenial-4.4.0/arch/x86/kernel/apic/msi.c @@ -12,6 +12,7 @@ */ #include #include +#include #include #include #include diff -u linux-lts-xenial-4.4.0/arch/x86/kernel/apic/vector.c linux-lts-xenial-4.4.0/arch/x86/kernel/apic/vector.c --- linux-lts-xenial-4.4.0/arch/x86/kernel/apic/vector.c +++ linux-lts-xenial-4.4.0/arch/x86/kernel/apic/vector.c @@ -11,6 +11,7 @@ * published by the Free Software Foundation. */ #include +#include #include #include #include diff -u linux-lts-xenial-4.4.0/arch/x86/kernel/cpu/amd.c linux-lts-xenial-4.4.0/arch/x86/kernel/cpu/amd.c --- linux-lts-xenial-4.4.0/arch/x86/kernel/cpu/amd.c +++ linux-lts-xenial-4.4.0/arch/x86/kernel/cpu/amd.c @@ -291,6 +291,14 @@ } #endif +static void amd_get_topology_early(struct cpuinfo_x86 *c) +{ +#ifdef CONFIG_SMP + if (boot_cpu_has(X86_FEATURE_TOPOEXT)) + smp_num_siblings = ((cpuid_ebx(0x8000001e) >> 8) & 0x3) + 1; +#endif +} + /* * Fixup core topology information for * (1) AMD multi-node processors @@ -305,7 +313,7 @@ int cpu = smp_processor_id(); /* get information required for multi-node processors */ - if (boot_cpu_has(X86_FEATURE_TOPOEXT)) { + if (cpu_has_topoext) { u32 eax, ebx, ecx, edx; cpuid(0x8000001e, &eax, &ebx, &ecx, &edx); @@ -313,7 +321,7 @@ node_id = ecx & 7; /* get compute unit information */ - cores_per_cu = smp_num_siblings = ((ebx >> 8) & 3) + 1; + cores_per_cu = smp_num_siblings; c->x86_max_cores /= smp_num_siblings; c->compute_unit_id = ebx & 0xff; } else if (cpu_has(c, X86_FEATURE_NODEID_MSR)) { @@ -544,6 +552,8 @@ static void early_init_amd(struct cpuinfo_x86 *c) { + u64 value; + early_init_amd_mc(c); /* @@ -594,6 +604,22 @@ /* F16h erratum 793, CVE-2013-6885 */ if (c->x86 == 0x16 && c->x86_model <= 0xf) msr_set_bit(MSR_AMD64_LS_CFG, 15); + + /* Re-enable TopologyExtensions if switched off by BIOS */ + if (c->x86 == 0x15 && + (c->x86_model >= 0x10 && c->x86_model <= 0x6f) && + !cpu_has(c, X86_FEATURE_TOPOEXT)) { + + if (msr_set_bit(0xc0011005, 54) > 0) { + rdmsrl(0xc0011005, value); + if (value & BIT_64(54)) { + set_cpu_cap(c, X86_FEATURE_TOPOEXT); + pr_info_once(FW_INFO "CPU: Re-enabling disabled Topology Extensions Support.\n"); + } + } + } + + amd_get_topology_early(c); } static const int amd_erratum_383[]; @@ -688,19 +714,6 @@ { u64 value; - /* re-enable TopologyExtensions if switched off by BIOS */ - if ((c->x86_model >= 0x10) && (c->x86_model <= 0x1f) && - !cpu_has(c, X86_FEATURE_TOPOEXT)) { - - if (msr_set_bit(0xc0011005, 54) > 0) { - rdmsrl(0xc0011005, value); - if (value & BIT_64(54)) { - set_cpu_cap(c, X86_FEATURE_TOPOEXT); - pr_info(FW_INFO "CPU: Re-enabling disabled Topology Extensions Support.\n"); - } - } - } - /* * The way access filter has a performance penalty on some workloads. * Disable it on the affected CPUs. @@ -757,10 +770,6 @@ srat_detect_node(c); } -#ifdef CONFIG_X86_32 - detect_ht(c); -#endif - init_amd_cacheinfo(c); if (c->x86 >= 0xf) @@ -1006,7 +1015,7 @@ void set_dr_addr_mask(unsigned long mask, int dr) { - if (!boot_cpu_has(X86_FEATURE_BPEXT)) + if (!cpu_has_bpext) return; switch (dr) { diff -u linux-lts-xenial-4.4.0/arch/x86/kernel/cpu/bugs.c linux-lts-xenial-4.4.0/arch/x86/kernel/cpu/bugs.c --- linux-lts-xenial-4.4.0/arch/x86/kernel/cpu/bugs.c +++ linux-lts-xenial-4.4.0/arch/x86/kernel/cpu/bugs.c @@ -22,14 +22,17 @@ #include #include #include +#include #include #include #include #include #include +#include static void __init spectre_v2_select_mitigation(void); static void __init ssb_select_mitigation(void); +static void __init l1tf_select_mitigation(void); /* * Our boot-time value of the SPEC_CTRL MSR. We read it once so that any @@ -55,6 +58,12 @@ { identify_boot_cpu(); + /* + * identify_boot_cpu() initialized SMT support information, let the + * core code know. + */ + cpu_smt_check_topology_early(); + if (!IS_ENABLED(CONFIG_SMP)) { pr_info("CPU: "); print_cpu_info(&boot_cpu_data); @@ -81,6 +90,8 @@ */ ssb_select_mitigation(); + l1tf_select_mitigation(); + #ifdef CONFIG_X86_32 /* * Check whether we are able to run this kernel safely on SMP. @@ -679,8 +690,121 @@ x86_amd_ssb_disable(); } +#undef pr_fmt +#define pr_fmt(fmt) "L1TF: " fmt + +/* Default mitigation for L1TF-affected CPUs */ +enum l1tf_mitigations l1tf_mitigation __ro_after_init = L1TF_MITIGATION_FLUSH; +#if IS_ENABLED(CONFIG_KVM_INTEL) +EXPORT_SYMBOL_GPL(l1tf_mitigation); + +enum vmx_l1d_flush_state l1tf_vmx_mitigation = VMENTER_L1D_FLUSH_AUTO; +EXPORT_SYMBOL_GPL(l1tf_vmx_mitigation); +#endif + +static void __init l1tf_select_mitigation(void) +{ + u64 half_pa; + + if (!boot_cpu_has_bug(X86_BUG_L1TF)) + return; + + switch (l1tf_mitigation) { + case L1TF_MITIGATION_OFF: + case L1TF_MITIGATION_FLUSH_NOWARN: + case L1TF_MITIGATION_FLUSH: + break; + case L1TF_MITIGATION_FLUSH_NOSMT: + case L1TF_MITIGATION_FULL: + cpu_smt_disable(false); + break; + case L1TF_MITIGATION_FULL_FORCE: + cpu_smt_disable(true); + break; + } + +#if CONFIG_PGTABLE_LEVELS == 2 + pr_warn("Kernel not compiled for PAE. No mitigation for L1TF\n"); + return; +#endif + + /* + * This is extremely unlikely to happen because almost all + * systems have far more MAX_PA/2 than RAM can be fit into + * DIMM slots. + */ + half_pa = (u64)l1tf_pfn_limit() << PAGE_SHIFT; + if (e820_any_mapped(half_pa, ULLONG_MAX - half_pa, E820_RAM)) { + pr_warn("System has more than MAX_PA/2 memory. L1TF mitigation not effective.\n"); + return; + } + + setup_force_cpu_cap(X86_FEATURE_L1TF_PTEINV); +} + +static int __init l1tf_cmdline(char *str) +{ + if (!boot_cpu_has_bug(X86_BUG_L1TF)) + return 0; + + if (!str) + return -EINVAL; + + if (!strcmp(str, "off")) + l1tf_mitigation = L1TF_MITIGATION_OFF; + else if (!strcmp(str, "flush,nowarn")) + l1tf_mitigation = L1TF_MITIGATION_FLUSH_NOWARN; + else if (!strcmp(str, "flush")) + l1tf_mitigation = L1TF_MITIGATION_FLUSH; + else if (!strcmp(str, "flush,nosmt")) + l1tf_mitigation = L1TF_MITIGATION_FLUSH_NOSMT; + else if (!strcmp(str, "full")) + l1tf_mitigation = L1TF_MITIGATION_FULL; + else if (!strcmp(str, "full,force")) + l1tf_mitigation = L1TF_MITIGATION_FULL_FORCE; + + return 0; +} +early_param("l1tf", l1tf_cmdline); + +#undef pr_fmt + #ifdef CONFIG_SYSFS +#define L1TF_DEFAULT_MSG "Mitigation: PTE Inversion" + +#if IS_ENABLED(CONFIG_KVM_INTEL) +static const char *l1tf_vmx_states[] = { + [VMENTER_L1D_FLUSH_AUTO] = "auto", + [VMENTER_L1D_FLUSH_NEVER] = "vulnerable", + [VMENTER_L1D_FLUSH_COND] = "conditional cache flushes", + [VMENTER_L1D_FLUSH_ALWAYS] = "cache flushes", + [VMENTER_L1D_FLUSH_EPT_DISABLED] = "EPT disabled", + [VMENTER_L1D_FLUSH_NOT_REQUIRED] = "flush not necessary" +}; + +static ssize_t l1tf_show_state(char *buf) +{ + if (l1tf_vmx_mitigation == VMENTER_L1D_FLUSH_AUTO) + return sprintf(buf, "%s\n", L1TF_DEFAULT_MSG); + + if (l1tf_vmx_mitigation == VMENTER_L1D_FLUSH_EPT_DISABLED || + (l1tf_vmx_mitigation == VMENTER_L1D_FLUSH_NEVER && + cpu_smt_control == CPU_SMT_ENABLED)) + return sprintf(buf, "%s; VMX: %s\n", L1TF_DEFAULT_MSG, + l1tf_vmx_states[l1tf_vmx_mitigation]); + + return sprintf(buf, "%s; VMX: %s, SMT %s\n", L1TF_DEFAULT_MSG, + l1tf_vmx_states[l1tf_vmx_mitigation], + cpu_smt_control == CPU_SMT_ENABLED ? "vulnerable" : "disabled"); +} +#else +static ssize_t l1tf_show_state(char *buf) +{ + return sprintf(buf, "%s\n", L1TF_DEFAULT_MSG); +} +#endif + static ssize_t cpu_show_common(struct device *dev, struct device_attribute *attr, char *buf, unsigned int bug) { @@ -706,6 +830,10 @@ case X86_BUG_SPEC_STORE_BYPASS: return sprintf(buf, "%s\n", ssb_strings[ssb_mode]); + case X86_BUG_L1TF: + if (boot_cpu_has(X86_FEATURE_L1TF_PTEINV)) + return l1tf_show_state(buf); + break; default: break; } @@ -735,2 +863,7 @@ } + +ssize_t cpu_show_l1tf(struct device *dev, struct device_attribute *attr, char *buf) +{ + return cpu_show_common(dev, attr, buf, X86_BUG_L1TF); +} #endif diff -u linux-lts-xenial-4.4.0/arch/x86/kernel/cpu/common.c linux-lts-xenial-4.4.0/arch/x86/kernel/cpu/common.c --- linux-lts-xenial-4.4.0/arch/x86/kernel/cpu/common.c +++ linux-lts-xenial-4.4.0/arch/x86/kernel/cpu/common.c @@ -558,33 +558,36 @@ tlb_lld_4m[ENTRIES], tlb_lld_1g[ENTRIES]); } -void detect_ht(struct cpuinfo_x86 *c) +int detect_ht_early(struct cpuinfo_x86 *c) { #ifdef CONFIG_SMP u32 eax, ebx, ecx, edx; - int index_msb, core_bits; - static bool printed; if (!cpu_has(c, X86_FEATURE_HT)) - return; + return -1; if (cpu_has(c, X86_FEATURE_CMP_LEGACY)) - goto out; + return -1; if (cpu_has(c, X86_FEATURE_XTOPOLOGY)) - return; + return -1; cpuid(1, &eax, &ebx, &ecx, &edx); smp_num_siblings = (ebx & 0xff0000) >> 16; - - if (smp_num_siblings == 1) { + if (smp_num_siblings == 1) printk_once(KERN_INFO "CPU0: Hyper-Threading is disabled\n"); - goto out; - } +#endif + return 0; +} - if (smp_num_siblings <= 1) - goto out; +void detect_ht(struct cpuinfo_x86 *c) +{ +#ifdef CONFIG_SMP + int index_msb, core_bits; + + if (detect_ht_early(c) < 0) + return; index_msb = get_count_order(smp_num_siblings); c->phys_proc_id = apic->phys_pkg_id(c->initial_apicid, index_msb); @@ -597,15 +600,6 @@ c->cpu_core_id = apic->phys_pkg_id(c->initial_apicid, index_msb) & ((1 << core_bits) - 1); - -out: - if (!printed && (c->x86_max_cores * smp_num_siblings) > 1) { - printk(KERN_INFO "CPU: Physical Processor ID: %d\n", - c->phys_proc_id); - printk(KERN_INFO "CPU: Processor Core ID: %d\n", - c->cpu_core_id); - printed = 1; - } #endif } @@ -870,6 +864,21 @@ {} }; +static const __initconst struct x86_cpu_id cpu_no_l1tf[] = { + /* in addition to cpu_no_speculation */ + { X86_VENDOR_INTEL, 6, INTEL_FAM6_ATOM_SILVERMONT1 }, + { X86_VENDOR_INTEL, 6, INTEL_FAM6_ATOM_SILVERMONT2 }, + { X86_VENDOR_INTEL, 6, INTEL_FAM6_ATOM_AIRMONT }, + { X86_VENDOR_INTEL, 6, INTEL_FAM6_ATOM_MERRIFIELD }, + { X86_VENDOR_INTEL, 6, INTEL_FAM6_ATOM_MOOREFIELD }, + { X86_VENDOR_INTEL, 6, INTEL_FAM6_ATOM_GOLDMONT }, + { X86_VENDOR_INTEL, 6, INTEL_FAM6_ATOM_DENVERTON }, + { X86_VENDOR_INTEL, 6, INTEL_FAM6_ATOM_GEMINI_LAKE }, + { X86_VENDOR_INTEL, 6, INTEL_FAM6_XEON_PHI_KNL }, + { X86_VENDOR_INTEL, 6, INTEL_FAM6_XEON_PHI_KNM }, + {} +}; + static void __init cpu_set_bug_bits(struct cpuinfo_x86 *c) { u64 ia32_cap = 0; @@ -895,6 +904,11 @@ return; setup_force_cpu_bug(X86_BUG_CPU_MELTDOWN); + + if (x86_match_cpu(cpu_no_l1tf)) + return; + + setup_force_cpu_bug(X86_BUG_L1TF); } /* @@ -1650,9 +1664,7 @@ printk(KERN_INFO "Initializing CPU#%d\n", cpu); - if (cpu_feature_enabled(X86_FEATURE_VME) || - cpu_has_tsc || - boot_cpu_has(X86_FEATURE_DE)) + if (cpu_feature_enabled(X86_FEATURE_VME) || cpu_has_tsc || cpu_has_de) cr4_clear_bits(X86_CR4_VME|X86_CR4_PVI|X86_CR4_TSD|X86_CR4_DE); load_current_idt(); diff -u linux-lts-xenial-4.4.0/arch/x86/kernel/cpu/intel.c linux-lts-xenial-4.4.0/arch/x86/kernel/cpu/intel.c --- linux-lts-xenial-4.4.0/arch/x86/kernel/cpu/intel.c +++ linux-lts-xenial-4.4.0/arch/x86/kernel/cpu/intel.c @@ -174,6 +174,13 @@ if (edx & (1U << 28)) c->x86_coreid_bits = get_count_order((ebx >> 16) & 0xff); } + + /* + * Get the number of SMT siblings early from the extended topology + * leaf, if available. Otherwise try the legacy SMT detection. + */ + if (detect_extended_topology_early(c) < 0) + detect_ht_early(c); } #ifdef CONFIG_X86_32 @@ -459,8 +466,7 @@ if (cpu_has_xmm2) set_cpu_cap(c, X86_FEATURE_LFENCE_RDTSC); - - if (boot_cpu_has(X86_FEATURE_DS)) { + if (cpu_has_ds) { unsigned int l1; rdmsr(MSR_IA32_MISC_ENABLE, l1, l2); if (!(l1 & (1<<11))) diff -u linux-lts-xenial-4.4.0/arch/x86/kernel/cpu/intel_cacheinfo.c linux-lts-xenial-4.4.0/arch/x86/kernel/cpu/intel_cacheinfo.c --- linux-lts-xenial-4.4.0/arch/x86/kernel/cpu/intel_cacheinfo.c +++ linux-lts-xenial-4.4.0/arch/x86/kernel/cpu/intel_cacheinfo.c @@ -591,7 +591,7 @@ unsigned edx; if (boot_cpu_data.x86_vendor == X86_VENDOR_AMD) { - if (boot_cpu_has(X86_FEATURE_TOPOEXT)) + if (cpu_has_topoext) cpuid_count(0x8000001d, index, &eax.full, &ebx.full, &ecx.full, &edx); else @@ -637,7 +637,7 @@ void init_amd_cacheinfo(struct cpuinfo_x86 *c) { - if (boot_cpu_has(X86_FEATURE_TOPOEXT)) { + if (cpu_has_topoext) { num_cache_leaves = find_num_cache_leaves(c); } else if (c->extended_cpuid_level >= 0x80000006) { if (cpuid_edx(0x80000006) & 0xf000) @@ -809,7 +809,7 @@ struct cacheinfo *this_leaf; int i, sibling; - if (boot_cpu_has(X86_FEATURE_TOPOEXT)) { + if (cpu_has_topoext) { unsigned int apicid, nshared, first, last; this_leaf = this_cpu_ci->info_list + index; diff -u linux-lts-xenial-4.4.0/arch/x86/kernel/cpu/mcheck/mce.c linux-lts-xenial-4.4.0/arch/x86/kernel/cpu/mcheck/mce.c --- linux-lts-xenial-4.4.0/arch/x86/kernel/cpu/mcheck/mce.c +++ linux-lts-xenial-4.4.0/arch/x86/kernel/cpu/mcheck/mce.c @@ -980,12 +980,11 @@ int i; int worst = 0; int severity; - /* * Establish sequential order between the CPUs entering the machine * check handler. */ - int order = -1; + int order; /* * If no_way_out gets set, there is no safe way to recover from this * MCE. If mca_cfg.tolerant is cranked up, we'll try anyway. @@ -1001,12 +1000,7 @@ char *msg = "Unknown"; u64 recover_paddr = ~0ull; int flags = MF_ACTION_REQUIRED; - - /* - * MCEs are always local on AMD. Same is determined by MCG_STATUS_LMCES - * on Intel. - */ - int lmce = 1; + int lmce = 0; /* If this CPU is offline, just bail out. */ if (cpu_is_offline(smp_processor_id())) { @@ -1045,23 +1039,17 @@ kill_it = 1; /* - * Check if this MCE is signaled to only this logical processor, - * on Intel only. - */ - if (m.cpuvendor == X86_VENDOR_INTEL) - lmce = m.mcgstatus & MCG_STATUS_LMCES; - - /* - * Local machine check may already know that we have to panic. - * Broadcast machine check begins rendezvous in mce_start() - * Go through all banks in exclusion of the other CPUs. This way we - * don't report duplicated events on shared banks because the first one - * to see it will clear it. + * Check if this MCE is signaled to only this logical processor */ - if (lmce) { - if (no_way_out) - mce_panic("Fatal local machine check", &m, msg); - } else { + if (m.mcgstatus & MCG_STATUS_LMCES) + lmce = 1; + else { + /* + * Go through all the banks in exclusion of the other CPUs. + * This way we don't report duplicated events on shared banks + * because the first one to see it will clear it. + * If this is a Local MCE, then no need to perform rendezvous. + */ order = mce_start(&no_way_out); } @@ -1140,17 +1128,12 @@ no_way_out = worst >= MCE_PANIC_SEVERITY; } else { /* - * If there was a fatal machine check we should have - * already called mce_panic earlier in this function. - * Since we re-read the banks, we might have found - * something new. Check again to see if we found a - * fatal error. We call "mce_severity()" again to - * make sure we have the right "msg". + * Local MCE skipped calling mce_reign() + * If we found a fatal error, we need to panic here. */ - if (worst >= MCE_PANIC_SEVERITY && mca_cfg.tolerant < 3) { - mce_severity(&m, cfg->tolerant, &msg, true); - mce_panic("Local fatal machine check!", &m, msg); - } + if (worst >= MCE_PANIC_SEVERITY && mca_cfg.tolerant < 3) + mce_panic("Machine check from unknown source", + NULL, NULL); } /* @@ -1697,6 +1680,9 @@ machine_check_vector(regs, error_code); } +static struct notifier_block mce_cpu_notifier; +static bool mce_cpu_notifier_registered = false; + /* * Called for each booted CPU to set up machine checks. * Must be called with preempt off: @@ -1727,6 +1713,18 @@ __mcheck_cpu_init_generic(); __mcheck_cpu_init_vendor(c); + + if (!mce_cpu_notifier_registered) { + /* + * Register the CPU hotplug notifier early (and it will + * not be unregistered (as before) to not leave timers + * undeleted. This function is called with required locks + * being hold. + */ + __register_hotcpu_notifier(&mce_cpu_notifier); + mce_cpu_notifier_registered = true; + } + __mcheck_cpu_init_timer(); } @@ -2335,6 +2333,7 @@ NULL }; +static bool mce_device_initdone = false; static cpumask_var_t mce_device_initialized; static void mce_device_release(struct device *dev) @@ -2451,14 +2450,16 @@ switch (action & ~CPU_TASKS_FROZEN) { case CPU_ONLINE: - mce_device_create(cpu); + if (mce_device_initdone) + mce_device_create(cpu); if (threshold_cpu_callback) threshold_cpu_callback(action, cpu); break; case CPU_DEAD: if (threshold_cpu_callback) threshold_cpu_callback(action, cpu); - mce_device_remove(cpu); + if (mce_device_initdone) + mce_device_remove(cpu); mce_intel_hcpu_update(cpu); /* intentionally ignoring frozen here */ @@ -2521,23 +2522,15 @@ if (err) goto err_out_mem; - cpu_notifier_register_begin(); + cpu_maps_update_begin(); for_each_online_cpu(i) { err = mce_device_create(i); if (err) { - /* - * Register notifier anyway (and do not unreg it) so - * that we don't leave undeleted timers, see notifier - * callback above. - */ - __register_hotcpu_notifier(&mce_cpu_notifier); - cpu_notifier_register_done(); + cpu_maps_update_done(); goto err_device_create; } } - - __register_hotcpu_notifier(&mce_cpu_notifier); - cpu_notifier_register_done(); + cpu_maps_update_done(); register_syscore_ops(&mce_syscore_ops); @@ -2546,6 +2539,8 @@ if (err) goto err_register; + mce_device_initdone = true; + return 0; err_register: diff -u linux-lts-xenial-4.4.0/arch/x86/kernel/cpu/mtrr/generic.c linux-lts-xenial-4.4.0/arch/x86/kernel/cpu/mtrr/generic.c --- linux-lts-xenial-4.4.0/arch/x86/kernel/cpu/mtrr/generic.c +++ linux-lts-xenial-4.4.0/arch/x86/kernel/cpu/mtrr/generic.c @@ -349,7 +349,7 @@ void mtrr_save_fixed_ranges(void *info) { - if (boot_cpu_has(X86_FEATURE_MTRR)) + if (cpu_has_mtrr) get_fixed_ranges(mtrr_state.fixed_ranges); } diff -u linux-lts-xenial-4.4.0/arch/x86/kernel/cpu/mtrr/main.c linux-lts-xenial-4.4.0/arch/x86/kernel/cpu/mtrr/main.c --- linux-lts-xenial-4.4.0/arch/x86/kernel/cpu/mtrr/main.c +++ linux-lts-xenial-4.4.0/arch/x86/kernel/cpu/mtrr/main.c @@ -682,7 +682,7 @@ phys_addr = 32; - if (boot_cpu_has(X86_FEATURE_MTRR)) { + if (cpu_has_mtrr) { mtrr_if = &generic_mtrr_ops; size_or_mask = SIZE_OR_MASK_BITS(36); size_and_mask = 0x00f00000; diff -u linux-lts-xenial-4.4.0/arch/x86/kernel/fpu/core.c linux-lts-xenial-4.4.0/arch/x86/kernel/fpu/core.c --- linux-lts-xenial-4.4.0/arch/x86/kernel/fpu/core.c +++ linux-lts-xenial-4.4.0/arch/x86/kernel/fpu/core.c @@ -9,6 +9,7 @@ #include #include #include +#include #include diff -u linux-lts-xenial-4.4.0/arch/x86/kernel/fpu/init.c linux-lts-xenial-4.4.0/arch/x86/kernel/fpu/init.c --- linux-lts-xenial-4.4.0/arch/x86/kernel/fpu/init.c +++ linux-lts-xenial-4.4.0/arch/x86/kernel/fpu/init.c @@ -15,7 +15,10 @@ */ static void fpu__init_cpu_ctx_switch(void) { - clts(); + if (!cpu_has_eager_fpu) + stts(); + else + clts(); } /* @@ -232,16 +235,82 @@ } /* + * FPU context switching strategies: + * + * Against popular belief, we don't do lazy FPU saves, due to the + * task migration complications it brings on SMP - we only do + * lazy FPU restores. + * + * 'lazy' is the traditional strategy, which is based on setting + * CR0::TS to 1 during context-switch (instead of doing a full + * restore of the FPU state), which causes the first FPU instruction + * after the context switch (whenever it is executed) to fault - at + * which point we lazily restore the FPU state into FPU registers. + * + * Tasks are of course under no obligation to execute FPU instructions, + * so it can easily happen that another context-switch occurs without + * a single FPU instruction being executed. If we eventually switch + * back to the original task (that still owns the FPU) then we have + * not only saved the restores along the way, but we also have the + * FPU ready to be used for the original task. + * + * 'lazy' is deprecated because it's almost never a performance win + * and it's much more complicated than 'eager'. + * + * 'eager' switching is by default on all CPUs, there we switch the FPU + * state during every context switch, regardless of whether the task + * has used FPU instructions in that time slice or not. This is done + * because modern FPU context saving instructions are able to optimize + * state saving and restoration in hardware: they can detect both + * unused and untouched FPU state and optimize accordingly. + * + * [ Note that even in 'lazy' mode we might optimize context switches + * to use 'eager' restores, if we detect that a task is using the FPU + * frequently. See the fpu->counter logic in fpu/internal.h for that. ] + */ +static enum { ENABLE, DISABLE } eagerfpu = ENABLE; + +/* * Find supported xfeatures based on cpu features and command-line input. * This must be called after fpu__init_parse_early_param() is called and * xfeatures_mask is enumerated. */ u64 __init fpu__get_supported_xfeatures_mask(void) { - return XCNTXT_MASK; + /* Support all xfeatures known to us */ + if (eagerfpu != DISABLE) + return XCNTXT_MASK; + + /* Warning of xfeatures being disabled for no eagerfpu mode */ + if (xfeatures_mask & XFEATURE_MASK_EAGER) { + pr_err("x86/fpu: eagerfpu switching disabled, disabling the following xstate features: 0x%llx.\n", + xfeatures_mask & XFEATURE_MASK_EAGER); + } + + /* Return a mask that masks out all features requiring eagerfpu mode */ + return ~XFEATURE_MASK_EAGER; +} + +/* + * Disable features dependent on eagerfpu. + */ +static void __init fpu__clear_eager_fpu_features(void) +{ + setup_clear_cpu_cap(X86_FEATURE_MPX); } -/* Legacy code to initialize eager fpu mode. */ +/* + * Pick the FPU context switching strategy: + * + * When eagerfpu is AUTO or ENABLE, we ensure it is ENABLE if either of + * the following is true: + * + * (1) the cpu has xsaveopt, as it has the optimization and doing eager + * FPU switching has a relatively low cost compared to a plain xsave; + * (2) the cpu has xsave features (e.g. MPX) that depend on eager FPU + * switching. Should the kernel boot with noxsaveopt, we support MPX + * with eager FPU switching at a higher cost. + */ static void __init fpu__init_system_ctx_switch(void) { static bool on_boot_cpu = 1; @@ -251,6 +320,17 @@ WARN_ON_FPU(current->thread.fpu.fpstate_active); current_thread_info()->status = 0; + + if (cpu_has_xsaveopt && eagerfpu != DISABLE) + eagerfpu = ENABLE; + + if (xfeatures_mask & XFEATURE_MASK_EAGER) + eagerfpu = ENABLE; + + if (eagerfpu == ENABLE) + setup_force_cpu_cap(X86_FEATURE_EAGER_FPU); + + printk(KERN_INFO "x86/fpu: Using '%s' FPU context switches.\n", eagerfpu == ENABLE ? "eager" : "lazy"); } /* @@ -259,6 +339,11 @@ */ static void __init fpu__init_parse_early_param(void) { + if (cmdline_find_option_bool(boot_command_line, "eagerfpu=off")) { + eagerfpu = DISABLE; + fpu__clear_eager_fpu_features(); + } + if (cmdline_find_option_bool(boot_command_line, "no387")) setup_clear_cpu_cap(X86_FEATURE_FPU); diff -u linux-lts-xenial-4.4.0/arch/x86/kernel/ftrace.c linux-lts-xenial-4.4.0/arch/x86/kernel/ftrace.c --- linux-lts-xenial-4.4.0/arch/x86/kernel/ftrace.c +++ linux-lts-xenial-4.4.0/arch/x86/kernel/ftrace.c @@ -28,6 +28,7 @@ #include #include #include +#include #ifdef CONFIG_DYNAMIC_FTRACE diff -u linux-lts-xenial-4.4.0/arch/x86/kernel/hpet.c linux-lts-xenial-4.4.0/arch/x86/kernel/hpet.c --- linux-lts-xenial-4.4.0/arch/x86/kernel/hpet.c +++ linux-lts-xenial-4.4.0/arch/x86/kernel/hpet.c @@ -1,6 +1,7 @@ #include #include #include +#include #include #include #include diff -u linux-lts-xenial-4.4.0/arch/x86/kernel/hw_breakpoint.c linux-lts-xenial-4.4.0/arch/x86/kernel/hw_breakpoint.c --- linux-lts-xenial-4.4.0/arch/x86/kernel/hw_breakpoint.c +++ linux-lts-xenial-4.4.0/arch/x86/kernel/hw_breakpoint.c @@ -301,10 +301,6 @@ return -EINVAL; if (bp->attr.bp_addr & (bp->attr.bp_len - 1)) return -EINVAL; - - if (!boot_cpu_has(X86_FEATURE_BPEXT)) - return -EOPNOTSUPP; - /* * It's impossible to use a range breakpoint to fake out * user vs kernel detection because bp_len - 1 can't @@ -312,6 +308,8 @@ * breakpoints, then we'll have to check for kprobe-blacklisted * addresses anywhere in the range. */ + if (!cpu_has_bpext) + return -EOPNOTSUPP; info->mask = bp->attr.bp_len - 1; info->len = X86_BREAKPOINT_LEN_1; } diff -u linux-lts-xenial-4.4.0/arch/x86/kernel/i8259.c linux-lts-xenial-4.4.0/arch/x86/kernel/i8259.c --- linux-lts-xenial-4.4.0/arch/x86/kernel/i8259.c +++ linux-lts-xenial-4.4.0/arch/x86/kernel/i8259.c @@ -4,6 +4,7 @@ #include #include #include +#include #include #include #include diff -u linux-lts-xenial-4.4.0/arch/x86/kernel/irq.c linux-lts-xenial-4.4.0/arch/x86/kernel/irq.c --- linux-lts-xenial-4.4.0/arch/x86/kernel/irq.c +++ linux-lts-xenial-4.4.0/arch/x86/kernel/irq.c @@ -10,6 +10,7 @@ #include #include #include +#include #include #include diff -u linux-lts-xenial-4.4.0/arch/x86/kernel/irq_32.c linux-lts-xenial-4.4.0/arch/x86/kernel/irq_32.c --- linux-lts-xenial-4.4.0/arch/x86/kernel/irq_32.c +++ linux-lts-xenial-4.4.0/arch/x86/kernel/irq_32.c @@ -10,6 +10,7 @@ #include #include +#include #include #include #include diff -u linux-lts-xenial-4.4.0/arch/x86/kernel/irq_64.c linux-lts-xenial-4.4.0/arch/x86/kernel/irq_64.c --- linux-lts-xenial-4.4.0/arch/x86/kernel/irq_64.c +++ linux-lts-xenial-4.4.0/arch/x86/kernel/irq_64.c @@ -10,6 +10,7 @@ #include #include +#include #include #include #include diff -u linux-lts-xenial-4.4.0/arch/x86/kernel/irqinit.c linux-lts-xenial-4.4.0/arch/x86/kernel/irqinit.c --- linux-lts-xenial-4.4.0/arch/x86/kernel/irqinit.c +++ linux-lts-xenial-4.4.0/arch/x86/kernel/irqinit.c @@ -4,6 +4,7 @@ #include #include #include +#include #include #include #include diff -u linux-lts-xenial-4.4.0/arch/x86/kernel/kprobes/core.c linux-lts-xenial-4.4.0/arch/x86/kernel/kprobes/core.c --- linux-lts-xenial-4.4.0/arch/x86/kernel/kprobes/core.c +++ linux-lts-xenial-4.4.0/arch/x86/kernel/kprobes/core.c @@ -59,6 +59,7 @@ #include #include #include +#include #include "common.h" @@ -412,38 +413,25 @@ module_memfree(page); } -/* Prepare reljump right after instruction to boost */ -static void prepare_boost(struct kprobe *p, int length) -{ - if (can_boost(p->ainsn.insn, p->addr) && - MAX_INSN_SIZE - length >= RELATIVEJUMP_SIZE) { - /* - * These instructions can be executed directly if it - * jumps back to correct address. - */ - synthesize_reljump(p->ainsn.insn + length, p->addr + length); - p->ainsn.boostable = 1; - } else { - p->ainsn.boostable = -1; - } -} - static int arch_copy_kprobe(struct kprobe *p) { - int len; + int ret; set_memory_rw((unsigned long)p->ainsn.insn & PAGE_MASK, 1); /* Copy an instruction with recovering if other optprobe modifies it.*/ - len = __copy_instruction(p->ainsn.insn, p->addr); - if (!len) + ret = __copy_instruction(p->ainsn.insn, p->addr); + if (!ret) return -EINVAL; /* * __copy_instruction can modify the displacement of the instruction, * but it doesn't affect boostable check. */ - prepare_boost(p, len); + if (can_boost(p->ainsn.insn, p->addr)) + p->ainsn.boostable = 0; + else + p->ainsn.boostable = -1; set_memory_ro((unsigned long)p->ainsn.insn & PAGE_MASK, 1); @@ -908,6 +896,21 @@ break; } + if (p->ainsn.boostable == 0) { + if ((regs->ip > copy_ip) && + (regs->ip - copy_ip) + 5 < MAX_INSN_SIZE) { + /* + * These instructions can be executed directly if it + * jumps back to correct address. + */ + synthesize_reljump((void *)regs->ip, + (void *)orig_ip + (regs->ip - copy_ip)); + p->ainsn.boostable = 1; + } else { + p->ainsn.boostable = -1; + } + } + regs->ip += orig_ip - copy_ip; no_change: diff -u linux-lts-xenial-4.4.0/arch/x86/kernel/kprobes/opt.c linux-lts-xenial-4.4.0/arch/x86/kernel/kprobes/opt.c --- linux-lts-xenial-4.4.0/arch/x86/kernel/kprobes/opt.c +++ linux-lts-xenial-4.4.0/arch/x86/kernel/kprobes/opt.c @@ -38,6 +38,7 @@ #include #include #include +#include #include "common.h" diff -u linux-lts-xenial-4.4.0/arch/x86/kernel/setup.c linux-lts-xenial-4.4.0/arch/x86/kernel/setup.c --- linux-lts-xenial-4.4.0/arch/x86/kernel/setup.c +++ linux-lts-xenial-4.4.0/arch/x86/kernel/setup.c @@ -851,6 +851,12 @@ memblock_reserve(__pa_symbol(_text), (unsigned long)__bss_stop - (unsigned long)_text); + /* + * Make sure page 0 is always reserved because on systems with + * L1TF its contents can be leaked to user processes. + */ + memblock_reserve(0, PAGE_SIZE); + early_reserve_initrd(); /* diff -u linux-lts-xenial-4.4.0/arch/x86/kernel/smpboot.c linux-lts-xenial-4.4.0/arch/x86/kernel/smpboot.c --- linux-lts-xenial-4.4.0/arch/x86/kernel/smpboot.c +++ linux-lts-xenial-4.4.0/arch/x86/kernel/smpboot.c @@ -53,6 +53,7 @@ #include #include #include +#include #include #include @@ -108,6 +109,9 @@ static unsigned int logical_packages __read_mostly; static bool logical_packages_frozen __read_mostly; +/* Maximum number of SMT threads on any online core */ +int __max_smt_threads __read_mostly; + static inline void smpboot_setup_warm_reset_vector(unsigned long start_eip) { unsigned long flags; @@ -288,6 +292,23 @@ } /** + * topology_is_primary_thread - Check whether CPU is the primary SMT thread + * @cpu: CPU to check + */ +bool topology_is_primary_thread(unsigned int cpu) +{ + return apic_id_is_primary_thread(per_cpu(x86_cpu_to_apicid, cpu)); +} + +/** + * topology_smt_supported - Check whether SMT is supported by the CPUs + */ +bool topology_smt_supported(void) +{ + return smp_num_siblings > 1; +} + +/** * topology_phys_to_logical_pkg - Map a physical package id to a logical * * Returns logical package id or -1 if not found @@ -424,7 +445,7 @@ static bool match_smt(struct cpuinfo_x86 *c, struct cpuinfo_x86 *o) { - if (boot_cpu_has(X86_FEATURE_TOPOEXT)) { + if (cpu_has_topoext) { int cpu1 = c->cpu_index, cpu2 = o->cpu_index; if (c->phys_proc_id == o->phys_proc_id && @@ -495,7 +516,7 @@ bool has_mp = has_smt || boot_cpu_data.x86_max_cores > 1; struct cpuinfo_x86 *c = &cpu_data(cpu); struct cpuinfo_x86 *o; - int i; + int i, threads; cpumask_set_cpu(cpu, cpu_sibling_setup_mask); @@ -552,6 +573,10 @@ if (match_die(c, o) && !topology_same_node(c, o)) primarily_use_numa_for_topology(); } + + threads = cpumask_weight(topology_sibling_cpumask(cpu)); + if (threads > __max_smt_threads) + __max_smt_threads = threads; } /* maps the cpu to the sched domain representing multi-core */ @@ -1452,6 +1477,21 @@ #ifdef CONFIG_HOTPLUG_CPU +/* Recompute SMT state for all CPUs on offline */ +static void recompute_smt_state(void) +{ + int max_threads, cpu; + + max_threads = 0; + for_each_online_cpu (cpu) { + int threads = cpumask_weight(topology_sibling_cpumask(cpu)); + + if (threads > max_threads) + max_threads = threads; + } + __max_smt_threads = max_threads; +} + static void remove_siblinginfo(int cpu) { int sibling; @@ -1477,6 +1517,7 @@ c->cpu_core_id = 0; c->booted_cores = 0; cpumask_clear_cpu(cpu, cpu_sibling_setup_mask); + recompute_smt_state(); } static void remove_cpu_from_maps(int cpu) diff -u linux-lts-xenial-4.4.0/arch/x86/kernel/vm86_32.c linux-lts-xenial-4.4.0/arch/x86/kernel/vm86_32.c --- linux-lts-xenial-4.4.0/arch/x86/kernel/vm86_32.c +++ linux-lts-xenial-4.4.0/arch/x86/kernel/vm86_32.c @@ -357,10 +357,8 @@ tss = &per_cpu(cpu_tss, get_cpu()); /* make room for real-mode segments */ tsk->thread.sp0 += 16; - - if (static_cpu_has_safe(X86_FEATURE_SEP)) + if (cpu_has_sep) tsk->thread.sysenter_cs = 0; - load_sp0(tss, &tsk->thread); put_cpu(); diff -u linux-lts-xenial-4.4.0/arch/x86/kvm/cpuid.c linux-lts-xenial-4.4.0/arch/x86/kvm/cpuid.c --- linux-lts-xenial-4.4.0/arch/x86/kvm/cpuid.c +++ linux-lts-xenial-4.4.0/arch/x86/kvm/cpuid.c @@ -359,7 +359,7 @@ /* cpuid 7.0.edx */ const u32 kvm_supported_7_0_edx_x86_features = - F(SPEC_CTRL) | F(SPEC_CTRL_SSBD); + F(ARCH_CAPABILITIES) | F(SPEC_CTRL) | F(SPEC_CTRL_SSBD); /* cpuid 0xD.1.eax */ const u32 kvm_cpuid_D_1_eax_x86_features = diff -u linux-lts-xenial-4.4.0/arch/x86/kvm/cpuid.h linux-lts-xenial-4.4.0/arch/x86/kvm/cpuid.h --- linux-lts-xenial-4.4.0/arch/x86/kvm/cpuid.h +++ linux-lts-xenial-4.4.0/arch/x86/kvm/cpuid.h @@ -183,6 +183,14 @@ return best && (best->edx & bit(X86_FEATURE_RDTSCP)); } +static inline bool guest_cpuid_has_arch_capabilities(struct kvm_vcpu *vcpu) +{ + struct kvm_cpuid_entry2 *best; + + best = kvm_find_cpuid_entry(vcpu, 7, 0); + return best && (best->edx & bit(X86_FEATURE_ARCH_CAPABILITIES)); +} + /* * NRIPS is provided through cpuidfn 0x8000000a.edx bit 3 */ diff -u linux-lts-xenial-4.4.0/arch/x86/kvm/svm.c linux-lts-xenial-4.4.0/arch/x86/kvm/svm.c --- linux-lts-xenial-4.4.0/arch/x86/kvm/svm.c +++ linux-lts-xenial-4.4.0/arch/x86/kvm/svm.c @@ -3017,6 +3017,11 @@ return vmcb->control.tsc_offset + host_tsc; } +static int svm_get_msr_feature(struct kvm_msr_entry *msr) +{ + return 1; +} + static int svm_get_msr(struct kvm_vcpu *vcpu, struct msr_data *msr_info) { struct vcpu_svm *svm = to_svm(vcpu); @@ -4360,6 +4365,7 @@ .vcpu_put = svm_vcpu_put, .update_bp_intercept = update_bp_intercept, + .get_msr_feature = svm_get_msr_feature, .get_msr = svm_get_msr, .set_msr = svm_set_msr, .get_segment_base = svm_get_segment_base, diff -u linux-lts-xenial-4.4.0/arch/x86/kvm/vmx.c linux-lts-xenial-4.4.0/arch/x86/kvm/vmx.c --- linux-lts-xenial-4.4.0/arch/x86/kvm/vmx.c +++ linux-lts-xenial-4.4.0/arch/x86/kvm/vmx.c @@ -173,6 +173,150 @@ extern const ulong vmx_return; +static DEFINE_STATIC_KEY_FALSE(vmx_l1d_should_flush); +static DEFINE_STATIC_KEY_FALSE(vmx_l1d_flush_cond); +static DEFINE_MUTEX(vmx_l1d_flush_mutex); + +/* Storage for pre module init parameter parsing */ +static enum vmx_l1d_flush_state __read_mostly vmentry_l1d_flush_param = VMENTER_L1D_FLUSH_AUTO; + +static const struct { + const char *option; + enum vmx_l1d_flush_state cmd; +} vmentry_l1d_param[] = { + {"auto", VMENTER_L1D_FLUSH_AUTO}, + {"never", VMENTER_L1D_FLUSH_NEVER}, + {"cond", VMENTER_L1D_FLUSH_COND}, + {"always", VMENTER_L1D_FLUSH_ALWAYS}, +}; + +#define L1D_CACHE_ORDER 4 +static void *vmx_l1d_flush_pages; + +static int vmx_setup_l1d_flush(enum vmx_l1d_flush_state l1tf) +{ + struct page *page; + unsigned int i; + + if (!enable_ept) { + l1tf_vmx_mitigation = VMENTER_L1D_FLUSH_EPT_DISABLED; + return 0; + } + + if (boot_cpu_has(X86_FEATURE_ARCH_CAPABILITIES)) { + u64 msr; + + rdmsrl(MSR_IA32_ARCH_CAPABILITIES, msr); + if (msr & ARCH_CAP_SKIP_VMENTRY_L1DFLUSH) { + l1tf_vmx_mitigation = VMENTER_L1D_FLUSH_NOT_REQUIRED; + return 0; + } + } + + /* If set to auto use the default l1tf mitigation method */ + if (l1tf == VMENTER_L1D_FLUSH_AUTO) { + switch (l1tf_mitigation) { + case L1TF_MITIGATION_OFF: + l1tf = VMENTER_L1D_FLUSH_NEVER; + break; + case L1TF_MITIGATION_FLUSH_NOWARN: + case L1TF_MITIGATION_FLUSH: + case L1TF_MITIGATION_FLUSH_NOSMT: + l1tf = VMENTER_L1D_FLUSH_COND; + break; + case L1TF_MITIGATION_FULL: + case L1TF_MITIGATION_FULL_FORCE: + l1tf = VMENTER_L1D_FLUSH_ALWAYS; + break; + } + } else if (l1tf_mitigation == L1TF_MITIGATION_FULL_FORCE) { + l1tf = VMENTER_L1D_FLUSH_ALWAYS; + } + + if (l1tf != VMENTER_L1D_FLUSH_NEVER && !vmx_l1d_flush_pages && + !boot_cpu_has(X86_FEATURE_FLUSH_L1D)) { + page = alloc_pages(GFP_KERNEL, L1D_CACHE_ORDER); + if (!page) + return -ENOMEM; + vmx_l1d_flush_pages = page_address(page); + + /* + * Initialize each page with a different pattern in + * order to protect against KSM in the nested + * virtualization case. + */ + for (i = 0; i < 1u << L1D_CACHE_ORDER; ++i) { + memset(vmx_l1d_flush_pages + i * PAGE_SIZE, i + 1, + PAGE_SIZE); + } + } + + l1tf_vmx_mitigation = l1tf; + + if (l1tf != VMENTER_L1D_FLUSH_NEVER) + static_branch_enable(&vmx_l1d_should_flush); + else + static_branch_disable(&vmx_l1d_should_flush); + + if (l1tf == VMENTER_L1D_FLUSH_COND) + static_branch_enable(&vmx_l1d_flush_cond); + else + static_branch_disable(&vmx_l1d_flush_cond); + return 0; +} + +static int vmentry_l1d_flush_parse(const char *s) +{ + unsigned int i; + + if (s) { + for (i = 0; i < ARRAY_SIZE(vmentry_l1d_param); i++) { + if (sysfs_streq(s, vmentry_l1d_param[i].option)) + return vmentry_l1d_param[i].cmd; + } + } + return -EINVAL; +} + +static int vmentry_l1d_flush_set(const char *s, const struct kernel_param *kp) +{ + int l1tf, ret; + + if (!boot_cpu_has(X86_BUG_L1TF)) + return 0; + + l1tf = vmentry_l1d_flush_parse(s); + if (l1tf < 0) + return l1tf; + + /* + * Has vmx_init() run already? If not then this is the pre init + * parameter parsing. In that case just store the value and let + * vmx_init() do the proper setup after enable_ept has been + * established. + */ + if (l1tf_vmx_mitigation == VMENTER_L1D_FLUSH_AUTO) { + vmentry_l1d_flush_param = l1tf; + return 0; + } + + mutex_lock(&vmx_l1d_flush_mutex); + ret = vmx_setup_l1d_flush(l1tf); + mutex_unlock(&vmx_l1d_flush_mutex); + return ret; +} + +static int vmentry_l1d_flush_get(char *s, const struct kernel_param *kp) +{ + return sprintf(s, "%s\n", vmentry_l1d_param[l1tf_vmx_mitigation].option); +} + +static const struct kernel_param_ops vmentry_l1d_flush_ops = { + .set = vmentry_l1d_flush_set, + .get = vmentry_l1d_flush_get, +}; +module_param_cb(vmentry_l1d_flush, &vmentry_l1d_flush_ops, NULL, 0644); + #define NR_AUTOLOAD_MSRS 8 #define VMCS02_POOL_SIZE 1 @@ -528,6 +672,11 @@ (unsigned long *)&pi_desc->control); } +struct vmx_msrs { + unsigned nr; + struct vmx_msr_entry val[NR_AUTOLOAD_MSRS]; +}; + struct vcpu_vmx { struct kvm_vcpu vcpu; unsigned long host_rsp; @@ -544,6 +693,8 @@ u64 msr_host_kernel_gs_base; u64 msr_guest_kernel_gs_base; #endif + u64 arch_capabilities; + u32 vm_entry_controls_shadow; u32 vm_exit_controls_shadow; /* @@ -555,9 +706,8 @@ struct loaded_vmcs *loaded_vmcs; bool __launched; /* temporary, used in vmx_vcpu_run */ struct msr_autoload { - unsigned nr; - struct vmx_msr_entry guest[NR_AUTOLOAD_MSRS]; - struct vmx_msr_entry host[NR_AUTOLOAD_MSRS]; + struct vmx_msrs guest; + struct vmx_msrs host; } msr_autoload; struct { int loaded; @@ -1697,9 +1847,20 @@ vm_exit_controls_clearbit(vmx, exit); } +static int find_msr(struct vmx_msrs *m, int msr) +{ + unsigned int i; + + for (i = 0; i < m->nr; ++i) { + if (m->val[i].index == msr) + return i; + } + return -ENOENT; +} + static void clear_atomic_switch_msr(struct vcpu_vmx *vmx, unsigned msr) { - unsigned i; + int i; struct msr_autoload *m = &vmx->msr_autoload; switch (msr) { @@ -1720,18 +1881,20 @@ } break; } - - for (i = 0; i < m->nr; ++i) - if (m->guest[i].index == msr) - break; - - if (i == m->nr) + i = find_msr(&m->guest, msr); + if (i < 0) + goto skip_guest; + --m->guest.nr; + m->guest.val[i] = m->guest.val[m->guest.nr]; + vmcs_write32(VM_ENTRY_MSR_LOAD_COUNT, m->guest.nr); + +skip_guest: + i = find_msr(&m->host, msr); + if (i < 0) return; - --m->nr; - m->guest[i] = m->guest[m->nr]; - m->host[i] = m->host[m->nr]; - vmcs_write32(VM_ENTRY_MSR_LOAD_COUNT, m->nr); - vmcs_write32(VM_EXIT_MSR_LOAD_COUNT, m->nr); + --m->host.nr; + m->host.val[i] = m->host.val[m->host.nr]; + vmcs_write32(VM_EXIT_MSR_LOAD_COUNT, m->host.nr); } static void add_atomic_switch_msr_special(struct vcpu_vmx *vmx, @@ -1746,9 +1909,9 @@ } static void add_atomic_switch_msr(struct vcpu_vmx *vmx, unsigned msr, - u64 guest_val, u64 host_val) + u64 guest_val, u64 host_val, bool entry_only) { - unsigned i; + int i, j = 0; struct msr_autoload *m = &vmx->msr_autoload; switch (msr) { @@ -1783,24 +1946,31 @@ wrmsrl(MSR_IA32_PEBS_ENABLE, 0); } - for (i = 0; i < m->nr; ++i) - if (m->guest[i].index == msr) - break; + i = find_msr(&m->guest, msr); + if (!entry_only) + j = find_msr(&m->host, msr); - if (i == NR_AUTOLOAD_MSRS) { + if (i == NR_AUTOLOAD_MSRS || j == NR_AUTOLOAD_MSRS) { printk_once(KERN_WARNING "Not enough msr switch entries. " "Can't add msr %x\n", msr); return; - } else if (i == m->nr) { - ++m->nr; - vmcs_write32(VM_ENTRY_MSR_LOAD_COUNT, m->nr); - vmcs_write32(VM_EXIT_MSR_LOAD_COUNT, m->nr); } + if (i < 0) { + i = m->guest.nr++; + vmcs_write32(VM_ENTRY_MSR_LOAD_COUNT, m->guest.nr); + } + m->guest.val[i].index = msr; + m->guest.val[i].value = guest_val; + + if (entry_only) + return; - m->guest[i].index = msr; - m->guest[i].value = guest_val; - m->host[i].index = msr; - m->host[i].value = host_val; + if (j < 0) { + j = m->host.nr++; + vmcs_write32(VM_EXIT_MSR_LOAD_COUNT, m->host.nr); + } + m->host.val[j].index = msr; + m->host.val[j].value = host_val; } static void reload_tss(void) @@ -1857,7 +2027,7 @@ guest_efer &= ~EFER_LME; if (guest_efer != host_efer) add_atomic_switch_msr(vmx, MSR_EFER, - guest_efer, host_efer); + guest_efer, host_efer, false); return false; } else { guest_efer &= ~ignore_bits; @@ -2806,6 +2976,11 @@ return 0; } +static int vmx_get_msr_feature(struct kvm_msr_entry *msr) +{ + return 1; +} + /* * Reads an msr value (of 'msr_index') into 'pdata'. * Returns 0 on success, non-0 otherwise. @@ -2836,6 +3011,12 @@ case MSR_IA32_SPEC_CTRL: msr_info->data = vcpu->arch.spec_ctrl; break; + case MSR_IA32_ARCH_CAPABILITIES: + if (!msr_info->host_initiated && + !guest_cpuid_has_arch_capabilities(vcpu)) + return 1; + msr_info->data = to_vmx(vcpu)->arch_capabilities; + break; case MSR_IA32_SYSENTER_CS: msr_info->data = vmcs_read32(GUEST_SYSENTER_CS); break; @@ -2942,6 +3123,11 @@ vcpu->arch.spec_ctrl = data; break; + case MSR_IA32_ARCH_CAPABILITIES: + if (!msr_info->host_initiated) + return 1; + vmx->arch_capabilities = data; + break; case MSR_IA32_CR_PAT: if (vmcs_config.vmentry_ctrl & VM_ENTRY_LOAD_IA32_PAT) { if (!kvm_mtrr_valid(vcpu, MSR_IA32_CR_PAT, data)) @@ -2978,7 +3164,7 @@ vcpu->arch.ia32_xss = data; if (vcpu->arch.ia32_xss != host_xss) add_atomic_switch_msr(vmx, MSR_IA32_XSS, - vcpu->arch.ia32_xss, host_xss); + vcpu->arch.ia32_xss, host_xss, false); else clear_atomic_switch_msr(vmx, MSR_IA32_XSS); break; @@ -4898,9 +5084,9 @@ vmcs_write32(VM_EXIT_MSR_STORE_COUNT, 0); vmcs_write32(VM_EXIT_MSR_LOAD_COUNT, 0); - vmcs_write64(VM_EXIT_MSR_LOAD_ADDR, __pa(vmx->msr_autoload.host)); + vmcs_write64(VM_EXIT_MSR_LOAD_ADDR, __pa(vmx->msr_autoload.host.val)); vmcs_write32(VM_ENTRY_MSR_LOAD_COUNT, 0); - vmcs_write64(VM_ENTRY_MSR_LOAD_ADDR, __pa(vmx->msr_autoload.guest)); + vmcs_write64(VM_ENTRY_MSR_LOAD_ADDR, __pa(vmx->msr_autoload.guest.val)); if (vmcs_config.vmentry_ctrl & VM_ENTRY_LOAD_IA32_PAT) vmcs_write64(GUEST_IA32_PAT, vmx->vcpu.arch.pat); @@ -4920,6 +5106,7 @@ ++vmx->nmsrs; } + vmx->arch_capabilities = kvm_get_arch_capabilities(); vm_exit_controls_init(vmx, vmcs_config.vmexit_ctrl); @@ -5350,6 +5537,7 @@ /* EPT won't cause page fault directly */ BUG_ON(enable_ept); cr2 = vmcs_readl(EXIT_QUALIFICATION); + vcpu->arch.l1tf_flush_l1d = true; trace_kvm_page_fault(cr2, error_code); if (kvm_event_needs_reinjection(vcpu)) @@ -8215,6 +8403,79 @@ } } +/* + * Software based L1D cache flush which is used when microcode providing + * the cache control MSR is not loaded. + * + * The L1D cache is 32 KiB on Nehalem and later microarchitectures, but to + * flush it is required to read in 64 KiB because the replacement algorithm + * is not exactly LRU. This could be sized at runtime via topology + * information but as all relevant affected CPUs have 32KiB L1D cache size + * there is no point in doing so. + */ +#define L1D_CACHE_ORDER 4 +static void *vmx_l1d_flush_pages; + +static void vmx_l1d_flush(struct kvm_vcpu *vcpu) +{ + int size = PAGE_SIZE << L1D_CACHE_ORDER; + + /* + * This code is only executed when the the flush mode is 'cond' or + * 'always' + */ + if (static_branch_likely(&vmx_l1d_flush_cond)) { + bool flush_l1d; + + /* + * Clear the per-vcpu flush bit, it gets set again + * either from vcpu_run() or from one of the unsafe + * VMEXIT handlers. + */ + flush_l1d = vcpu->arch.l1tf_flush_l1d; + vcpu->arch.l1tf_flush_l1d = false; + + /* + * Clear the per-cpu flush bit, it gets set again from + * the interrupt handlers. + */ + flush_l1d |= kvm_get_cpu_l1tf_flush_l1d(); + kvm_clear_cpu_l1tf_flush_l1d(); + + if (!flush_l1d) + return; + } + + vcpu->stat.l1d_flush++; + + if (static_cpu_has(X86_FEATURE_FLUSH_L1D)) { + wrmsrl(MSR_IA32_FLUSH_CMD, L1D_FLUSH); + return; + } + + asm volatile( + /* First ensure the pages are in the TLB */ + "xorl %%eax, %%eax\n" + ".Lpopulate_tlb:\n\t" + "movzbl (%[flush_pages], %%" _ASM_AX "), %%ecx\n\t" + "addl $4096, %%eax\n\t" + "cmpl %%eax, %[size]\n\t" + "jne .Lpopulate_tlb\n\t" + "xorl %%eax, %%eax\n\t" + "cpuid\n\t" + /* Now fill the cache */ + "xorl %%eax, %%eax\n" + ".Lfill_cache:\n" + "movzbl (%[flush_pages], %%" _ASM_AX "), %%ecx\n\t" + "addl $64, %%eax\n\t" + "cmpl %%eax, %[size]\n\t" + "jne .Lfill_cache\n\t" + "lfence\n" + :: [flush_pages] "r" (vmx_l1d_flush_pages), + [size] "r" (size) + : "eax", "ebx", "ecx", "edx"); +} + static void update_cr8_intercept(struct kvm_vcpu *vcpu, int tpr, int irr) { struct vmcs12 *vmcs12 = get_vmcs12(vcpu); @@ -8588,7 +8849,7 @@ clear_atomic_switch_msr(vmx, msrs[i].msr); else add_atomic_switch_msr(vmx, msrs[i].msr, msrs[i].guest, - msrs[i].host); + msrs[i].host, false); } static void __noclone vmx_vcpu_run(struct kvm_vcpu *vcpu) @@ -8640,6 +8901,9 @@ x86_spec_ctrl_set_guest(vcpu->arch.spec_ctrl, 0); + if (static_branch_unlikely(&vmx_l1d_should_flush)) + vmx_l1d_flush(vcpu); + vmx->__launched = vmx->loaded_vmcs->launched; asm( /* Store host registers */ @@ -8938,6 +9202,38 @@ return ERR_PTR(err); } +#define L1TF_MSG_SMT "L1TF CPU bug present and SMT on, data leak possible. See CVE-2018-3646 and https://www.kernel.org/doc/html/latest/admin-guide/l1tf.html for details.\n" +#define L1TF_MSG_L1D "L1TF CPU bug present and virtualization mitigation disabled, data leak possible. See CVE-2018-3646 and https://www.kernel.org/doc/html/latest/admin-guide/l1tf.html for details.\n" + + +static int vmx_vm_init(struct kvm *kvm) +{ + if (boot_cpu_has(X86_BUG_L1TF) && enable_ept) { + switch (l1tf_mitigation) { + case L1TF_MITIGATION_OFF: + case L1TF_MITIGATION_FLUSH_NOWARN: + /* 'I explicitly don't care' is set */ + break; + case L1TF_MITIGATION_FLUSH: + case L1TF_MITIGATION_FLUSH_NOSMT: + case L1TF_MITIGATION_FULL: + /* + * Warn upon starting the first VM in a potentially + * insecure environment. + */ + if (cpu_smt_control == CPU_SMT_ENABLED) + pr_warn_once(L1TF_MSG_SMT); + if (l1tf_vmx_mitigation == VMENTER_L1D_FLUSH_NEVER) + pr_warn_once(L1TF_MSG_L1D); + break; + case L1TF_MITIGATION_FULL_FORCE: + /* Flush is enforced */ + break; + } + } + return 0; +} + static void __init vmx_check_processor_compat(void *rtn) { struct vmcs_config vmcs_conf; @@ -10077,6 +10373,9 @@ vmcs12->launch_state = 1; + /* Hide L1D cache contents from the nested guest. */ + vmx->vcpu.arch.l1tf_flush_l1d = true; + if (vmcs12->guest_activity_state == GUEST_ACTIVITY_HLT) return kvm_vcpu_halt(vcpu); @@ -10900,4 +11199,6 @@ .has_emulated_msr = vmx_has_emulated_msr, + .vm_init = vmx_vm_init, + .vcpu_create = vmx_create_vcpu, .vcpu_free = vmx_free_vcpu, @@ -10908,6 +11209,7 @@ .vcpu_put = vmx_vcpu_put, .update_bp_intercept = update_exception_bitmap, + .get_msr_feature = vmx_get_msr_feature, .get_msr = vmx_get_msr, .set_msr = vmx_set_msr, .get_segment_base = vmx_get_segment_base, @@ -11014,27 +11316,56 @@ -static int __init vmx_init(void) +static void vmx_cleanup_l1d_flush(void) { - int r = kvm_init(&vmx_x86_ops, sizeof(struct vcpu_vmx), - __alignof__(struct vcpu_vmx), THIS_MODULE); - if (r) - return r; + if (vmx_l1d_flush_pages) { + free_pages((unsigned long)vmx_l1d_flush_pages, L1D_CACHE_ORDER); + vmx_l1d_flush_pages = NULL; + } + /* Restore state so sysfs ignores VMX */ + l1tf_vmx_mitigation = VMENTER_L1D_FLUSH_AUTO; +} +static void vmx_exit(void) +{ #ifdef CONFIG_KEXEC_CORE - rcu_assign_pointer(crash_vmclear_loaded_vmcss, - crash_vmclear_local_loaded_vmcss); + RCU_INIT_POINTER(crash_vmclear_loaded_vmcss, NULL); + synchronize_rcu(); #endif - return 0; + kvm_exit(); + + vmx_cleanup_l1d_flush(); } +module_exit(vmx_exit); -static void __exit vmx_exit(void) +static int __init vmx_init(void) { + int r; + + r = kvm_init(&vmx_x86_ops, sizeof(struct vcpu_vmx), + __alignof__(struct vcpu_vmx), THIS_MODULE); + if (r) + return r; + + /* + * Must be called after kvm_init() so enable_ept is properly set + * up. Hand the parameter mitigation value in which was stored in + * the pre module init parser. If no parameter was given, it will + * contain 'auto' which will be turned into the default 'cond' + * mitigation mode. + */ + if (boot_cpu_has(X86_BUG_L1TF)) { + r = vmx_setup_l1d_flush(vmentry_l1d_flush_param); + if (r) { + vmx_exit(); + return r; + } + } + #ifdef CONFIG_KEXEC_CORE - RCU_INIT_POINTER(crash_vmclear_loaded_vmcss, NULL); - synchronize_rcu(); + rcu_assign_pointer(crash_vmclear_loaded_vmcss, + crash_vmclear_local_loaded_vmcss); #endif - kvm_exit(); + return 0; } module_init(vmx_init) -module_exit(vmx_exit) diff -u linux-lts-xenial-4.4.0/arch/x86/kvm/x86.c linux-lts-xenial-4.4.0/arch/x86/kvm/x86.c --- linux-lts-xenial-4.4.0/arch/x86/kvm/x86.c +++ linux-lts-xenial-4.4.0/arch/x86/kvm/x86.c @@ -169,6 +169,7 @@ { "insn_emulation_fail", VCPU_STAT(insn_emulation_fail) }, { "irq_injections", VCPU_STAT(irq_injections) }, { "nmi_injections", VCPU_STAT(nmi_injections) }, + { "l1d_flush", VCPU_STAT(l1d_flush) }, { "mmu_shadow_zapped", VM_STAT(mmu_shadow_zapped) }, { "mmu_pte_write", VM_STAT(mmu_pte_write) }, { "mmu_pte_updated", VM_STAT(mmu_pte_updated) }, @@ -960,7 +961,8 @@ MSR_CSTAR, MSR_KERNEL_GS_BASE, MSR_SYSCALL_MASK, MSR_LSTAR, #endif MSR_IA32_TSC, MSR_IA32_CR_PAT, MSR_VM_HSAVE_PA, - MSR_IA32_FEATURE_CONTROL, MSR_IA32_BNDCFGS, MSR_TSC_AUX, MSR_IA32_SPEC_CTRL, + MSR_IA32_FEATURE_CONTROL, MSR_IA32_BNDCFGS, MSR_TSC_AUX, + MSR_IA32_ARCH_CAPABILITIES, MSR_IA32_SPEC_CTRL, }; static unsigned num_msrs_to_save; @@ -991,6 +993,66 @@ static unsigned num_emulated_msrs; +/* + * List of msr numbers which are used to expose MSR-based features that + * can be used by a hypervisor to validate requested CPU features. + */ +static u32 msr_based_features[] = { + MSR_IA32_ARCH_CAPABILITIES, +}; + +static unsigned int num_msr_based_features; + +u64 kvm_get_arch_capabilities(void) +{ + u64 data; + + rdmsrl_safe(MSR_IA32_ARCH_CAPABILITIES, &data); + + /* + * If we're doing cache flushes (either "always" or "cond") + * we will do one whenever the guest does a vmlaunch/vmresume. + * If an outer hypervisor is doing the cache flush for us + * (VMENTER_L1D_FLUSH_NESTED_VM), we can safely pass that + * capability to the guest too, and if EPT is disabled we're not + * vulnerable. Overall, only VMENTER_L1D_FLUSH_NEVER will + * require a nested hypervisor to do a flush of its own. + */ + if (l1tf_vmx_mitigation != VMENTER_L1D_FLUSH_NEVER) + data |= ARCH_CAP_SKIP_VMENTRY_L1DFLUSH; + + return data; +} +EXPORT_SYMBOL_GPL(kvm_get_arch_capabilities); + +static int kvm_get_msr_feature(struct kvm_msr_entry *msr) +{ + switch (msr->index) { + case MSR_IA32_ARCH_CAPABILITIES: + msr->data = kvm_get_arch_capabilities(); + break; + default: + if (kvm_x86_ops->get_msr_feature(msr)) + return 1; + } + return 0; +} + +static int do_get_msr_feature(struct kvm_vcpu *vcpu, unsigned index, u64 *data) +{ + struct kvm_msr_entry msr; + int r; + + msr.index = index; + r = kvm_get_msr_feature(&msr); + if (r) + return r; + + *data = msr.data; + + return 0; +} + bool kvm_valid_efer(struct kvm_vcpu *vcpu, u64 efer) { if (efer & efer_reserved_bits) @@ -2471,13 +2533,11 @@ int (*do_msr)(struct kvm_vcpu *vcpu, unsigned index, u64 *data)) { - int i, idx; + int i; - idx = srcu_read_lock(&vcpu->kvm->srcu); for (i = 0; i < msrs->nmsrs; ++i) if (do_msr(vcpu, entries[i].index, &entries[i].data)) break; - srcu_read_unlock(&vcpu->kvm->srcu, idx); return i; } @@ -2578,6 +2638,7 @@ case KVM_CAP_ASSIGN_DEV_IRQ: case KVM_CAP_PCI_2_3: #endif + case KVM_CAP_GET_MSR_FEATURES: r = 1; break; case KVM_CAP_X86_SMM: @@ -2693,6 +2754,31 @@ goto out; r = 0; break; + case KVM_GET_MSR_FEATURE_INDEX_LIST: { + struct kvm_msr_list __user *user_msr_list = argp; + struct kvm_msr_list msr_list; + unsigned int n; + + r = -EFAULT; + if (copy_from_user(&msr_list, user_msr_list, sizeof(msr_list))) + goto out; + n = msr_list.nmsrs; + msr_list.nmsrs = num_msr_based_features; + if (copy_to_user(user_msr_list, &msr_list, sizeof(msr_list))) + goto out; + r = -E2BIG; + if (n < msr_list.nmsrs) + goto out; + r = -EFAULT; + if (copy_to_user(user_msr_list->indices, &msr_based_features, + num_msr_based_features * sizeof(u32))) + goto out; + r = 0; + break; + } + case KVM_GET_MSRS: + r = msr_io(NULL, argp, do_get_msr_feature, 1); + break; } default: r = -EINVAL; @@ -3352,12 +3438,18 @@ r = 0; break; } - case KVM_GET_MSRS: + case KVM_GET_MSRS: { + int idx = srcu_read_lock(&vcpu->kvm->srcu); r = msr_io(vcpu, argp, do_get_msr, 1); + srcu_read_unlock(&vcpu->kvm->srcu, idx); break; - case KVM_SET_MSRS: + } + case KVM_SET_MSRS: { + int idx = srcu_read_lock(&vcpu->kvm->srcu); r = msr_io(vcpu, argp, do_set_msr, 0); + srcu_read_unlock(&vcpu->kvm->srcu, idx); break; + } case KVM_TPR_ACCESS_REPORTING: { struct kvm_tpr_access_ctl tac; @@ -4111,6 +4203,19 @@ j++; } num_emulated_msrs = j; + + for (i = j = 0; i < ARRAY_SIZE(msr_based_features); i++) { + struct kvm_msr_entry msr; + + msr.index = msr_based_features[i]; + if (kvm_get_msr_feature(&msr)) + continue; + + if (j < i) + msr_based_features[j] = msr_based_features[i]; + j++; + } + num_msr_based_features = j; } static int vcpu_mmio_write(struct kvm_vcpu *vcpu, gpa_t addr, int len, @@ -4351,6 +4456,9 @@ int kvm_write_guest_virt_system(struct kvm_vcpu *vcpu, gva_t addr, void *val, unsigned int bytes, struct x86_exception *exception) { + /* kvm_write_guest_virt_system can pull in tons of pages. */ + vcpu->arch.l1tf_flush_l1d = true; + return kvm_write_guest_virt_helper(addr, val, bytes, vcpu, PFERR_WRITE_MASK, exception); } @@ -5449,6 +5557,8 @@ bool writeback = true; bool write_fault_to_spt = vcpu->arch.write_fault_to_shadow_pgtable; + vcpu->arch.l1tf_flush_l1d = true; + /* * Clear write_fault_to_shadow_pgtable here to ensure it is * never reused. @@ -6785,6 +6895,7 @@ struct kvm *kvm = vcpu->kvm; vcpu->srcu_idx = srcu_read_lock(&kvm->srcu); + vcpu->arch.l1tf_flush_l1d = true; for (;;) { if (kvm_vcpu_running(vcpu)) { @@ -7755,6 +7866,7 @@ void kvm_arch_sched_in(struct kvm_vcpu *vcpu, int cpu) { + vcpu->arch.l1tf_flush_l1d = true; kvm_x86_ops->sched_in(vcpu, cpu); } @@ -7784,6 +7896,9 @@ INIT_DELAYED_WORK(&kvm->arch.kvmclock_update_work, kvmclock_update_fn); INIT_DELAYED_WORK(&kvm->arch.kvmclock_sync_work, kvmclock_sync_fn); + if (kvm_x86_ops->vm_init) + return kvm_x86_ops->vm_init(kvm); + return 0; } @@ -7905,6 +8020,8 @@ x86_set_memory_region(kvm, IDENTITY_PAGETABLE_PRIVATE_MEMSLOT, 0, 0); x86_set_memory_region(kvm, TSS_PRIVATE_MEMSLOT, 0, 0); } + if (kvm_x86_ops->vm_destroy) + kvm_x86_ops->vm_destroy(kvm); kvm_iommu_unmap_guest(kvm); kfree(kvm->arch.vpic); kfree(kvm->arch.vioapic); diff -u linux-lts-xenial-4.4.0/arch/x86/lib/cmdline.c linux-lts-xenial-4.4.0/arch/x86/lib/cmdline.c --- linux-lts-xenial-4.4.0/arch/x86/lib/cmdline.c +++ linux-lts-xenial-4.4.0/arch/x86/lib/cmdline.c @@ -21,14 +21,12 @@ * @option: option string to look for * * Returns the position of that @option (starts counting with 1) - * or 0 on not found. @option will only be found if it is found - * as an entire word in @cmdline. For instance, if @option="car" - * then a cmdline which contains "cart" will not match. + * or 0 on not found. */ int cmdline_find_option_bool(const char *cmdline, const char *option) { char c; - int pos = 0, wstart = 0; + int len, pos = 0, wstart = 0; const char *opptr = NULL; enum { st_wordstart = 0, /* Start of word/after whitespace */ @@ -39,14 +37,11 @@ if (!cmdline) return -1; /* No command line */ - if (!strlen(cmdline)) + len = min_t(int, strlen(cmdline), COMMAND_LINE_SIZE); + if (!len) return 0; - /* - * This 'pos' check ensures we do not overrun - * a non-NULL-terminated 'cmdline' - */ - while (pos < COMMAND_LINE_SIZE) { + while (len--) { c = *(char *)cmdline++; pos++; @@ -63,26 +58,17 @@ /* fall through */ case st_wordcmp: - if (!*opptr) { - /* - * We matched all the way to the end of the - * option we were looking for. If the - * command-line has a space _or_ ends, then - * we matched! - */ + if (!*opptr) if (!c || myisspace(c)) return wstart; else state = st_wordskip; - } else if (!c) { - /* - * Hit the NULL terminator on the end of - * cmdline. - */ + else if (!c) return 0; - } else if (c != *opptr++) { + else if (c != *opptr++) state = st_wordskip; - } + else if (!len) /* last word and is matching */ + return wstart; break; case st_wordskip: diff -u linux-lts-xenial-4.4.0/arch/x86/mm/fault.c linux-lts-xenial-4.4.0/arch/x86/mm/fault.c --- linux-lts-xenial-4.4.0/arch/x86/mm/fault.c +++ linux-lts-xenial-4.4.0/arch/x86/mm/fault.c @@ -16,6 +16,7 @@ #include /* faulthandler_disabled() */ #include /* dotraplinkage, ... */ +#include #include /* pgd_*(), ... */ #include /* kmemcheck_*(), ... */ #include /* VSYSCALL_ADDR */ diff -u linux-lts-xenial-4.4.0/arch/x86/mm/init.c linux-lts-xenial-4.4.0/arch/x86/mm/init.c --- linux-lts-xenial-4.4.0/arch/x86/mm/init.c +++ linux-lts-xenial-4.4.0/arch/x86/mm/init.c @@ -4,6 +4,8 @@ #include #include #include /* for max_low_pfn */ +#include +#include #include #include @@ -769,0 +772,21 @@ + +unsigned long max_swapfile_size(void) +{ + unsigned long pages; + + pages = generic_max_swapfile_size(); + + if (boot_cpu_has_bug(X86_BUG_L1TF)) { + /* Limit the swap file size to MAX_PA/2 for L1TF workaround */ + unsigned long l1tf_limit = l1tf_pfn_limit() + 1; + /* + * We encode swap offsets also with 3 bits below those for pfn + * which makes the usable limit higher. + */ +#if CONFIG_PGTABLE_LEVELS > 2 + l1tf_limit <<= PAGE_SHIFT - SWP_OFFSET_FIRST_BIT; +#endif + pages = min_t(unsigned long, l1tf_limit, pages); + } + return pages; +} diff -u linux-lts-xenial-4.4.0/arch/x86/mm/kaiser.c linux-lts-xenial-4.4.0/arch/x86/mm/kaiser.c --- linux-lts-xenial-4.4.0/arch/x86/mm/kaiser.c +++ linux-lts-xenial-4.4.0/arch/x86/mm/kaiser.c @@ -19,6 +19,7 @@ #include #include #include +#include #include #include diff -u linux-lts-xenial-4.4.0/arch/x86/mm/mmap.c linux-lts-xenial-4.4.0/arch/x86/mm/mmap.c --- linux-lts-xenial-4.4.0/arch/x86/mm/mmap.c +++ linux-lts-xenial-4.4.0/arch/x86/mm/mmap.c @@ -123,0 +124,21 @@ + +/* + * Only allow root to set high MMIO mappings to PROT_NONE. + * This prevents an unpriv. user to set them to PROT_NONE and invert + * them, then pointing to valid memory for L1TF speculation. + * + * Note: for locked down kernels may want to disable the root override. + */ +bool pfn_modify_allowed(unsigned long pfn, pgprot_t prot) +{ + if (!boot_cpu_has_bug(X86_BUG_L1TF)) + return true; + if (!__pte_needs_invert(pgprot_val(prot))) + return true; + /* If it's real memory always allow */ + if (pfn_valid(pfn)) + return true; + if (pfn > l1tf_pfn_limit() && !capable(CAP_SYS_ADMIN)) + return false; + return true; +} diff -u linux-lts-xenial-4.4.0/arch/x86/mm/pageattr.c linux-lts-xenial-4.4.0/arch/x86/mm/pageattr.c --- linux-lts-xenial-4.4.0/arch/x86/mm/pageattr.c +++ linux-lts-xenial-4.4.0/arch/x86/mm/pageattr.c @@ -942,15 +942,10 @@ pte = pte_offset_kernel(pmd, start); while (num_pages-- && start < end) { - - /* deal with the NX bit */ - if (!(pgprot_val(pgprot) & _PAGE_NX)) - cpa->pfn &= ~_PAGE_NX; - - set_pte(pte, pfn_pte(cpa->pfn >> PAGE_SHIFT, pgprot)); + set_pte(pte, pfn_pte(cpa->pfn, pgprot)); start += PAGE_SIZE; - cpa->pfn += PAGE_SIZE; + cpa->pfn++; pte++; } } @@ -1006,11 +1001,11 @@ pmd = pmd_offset(pud, start); - set_pmd(pmd, __pmd(cpa->pfn | _PAGE_PSE | - massage_pgprot(pmd_pgprot))); + set_pmd(pmd, pmd_mkhuge(pfn_pmd(cpa->pfn, + canon_pgprot(pmd_pgprot)))); start += PMD_SIZE; - cpa->pfn += PMD_SIZE; + cpa->pfn += PMD_SIZE >> PAGE_SHIFT; cur_pages += PMD_SIZE >> PAGE_SHIFT; } @@ -1079,11 +1074,11 @@ * Map everything starting from the Gb boundary, possibly with 1G pages */ while (end - start >= PUD_SIZE) { - set_pud(pud, __pud(cpa->pfn | _PAGE_PSE | - massage_pgprot(pud_pgprot))); + set_pud(pud, pud_mkhuge(pfn_pud(cpa->pfn, + canon_pgprot(pud_pgprot)))); start += PUD_SIZE; - cpa->pfn += PUD_SIZE; + cpa->pfn += PUD_SIZE >> PAGE_SHIFT; cur_pages += PUD_SIZE >> PAGE_SHIFT; pud++; } diff -u linux-lts-xenial-4.4.0/arch/x86/mm/setup_nx.c linux-lts-xenial-4.4.0/arch/x86/mm/setup_nx.c --- linux-lts-xenial-4.4.0/arch/x86/mm/setup_nx.c +++ linux-lts-xenial-4.4.0/arch/x86/mm/setup_nx.c @@ -32,7 +32,7 @@ void x86_configure_nx(void) { - if (boot_cpu_has(X86_FEATURE_NX) && !disable_nx) + if (cpu_has_nx && !disable_nx) __supported_pte_mask |= _PAGE_NX; else __supported_pte_mask &= ~_PAGE_NX; @@ -40,7 +40,7 @@ void __init x86_report_nx(void) { - if (!boot_cpu_has(X86_FEATURE_NX)) { + if (!cpu_has_nx) { printk(KERN_NOTICE "Notice: NX (Execute Disable) protection " "missing in CPU!\n"); } else { diff -u linux-lts-xenial-4.4.0/arch/x86/platform/efi/quirks.c linux-lts-xenial-4.4.0/arch/x86/platform/efi/quirks.c --- linux-lts-xenial-4.4.0/arch/x86/platform/efi/quirks.c +++ linux-lts-xenial-4.4.0/arch/x86/platform/efi/quirks.c @@ -9,6 +9,7 @@ #include #include #include +#include #include #define EFI_MIN_RESERVE 5120 diff -u linux-lts-xenial-4.4.0/arch/x86/platform/intel-mid/device_libs/platform_wdt.c linux-lts-xenial-4.4.0/arch/x86/platform/intel-mid/device_libs/platform_wdt.c --- linux-lts-xenial-4.4.0/arch/x86/platform/intel-mid/device_libs/platform_wdt.c +++ linux-lts-xenial-4.4.0/arch/x86/platform/intel-mid/device_libs/platform_wdt.c @@ -16,6 +16,7 @@ #include #include #include +#include #define TANGIER_EXT_TIMER0_MSI 12 diff -u linux-lts-xenial-4.4.0/arch/x86/xen/enlighten.c linux-lts-xenial-4.4.0/arch/x86/xen/enlighten.c --- linux-lts-xenial-4.4.0/arch/x86/xen/enlighten.c +++ linux-lts-xenial-4.4.0/arch/x86/xen/enlighten.c @@ -12,6 +12,7 @@ */ #include +#include #include #include #include diff -u linux-lts-xenial-4.4.0/arch/x86/xen/setup.c linux-lts-xenial-4.4.0/arch/x86/xen/setup.c --- linux-lts-xenial-4.4.0/arch/x86/xen/setup.c +++ linux-lts-xenial-4.4.0/arch/x86/xen/setup.c @@ -11,6 +11,7 @@ #include #include #include +#include #include #include reverted: --- linux-lts-xenial-4.4.0/arch/xtensa/kernel/traps.c +++ linux-lts-xenial-4.4.0.orig/arch/xtensa/kernel/traps.c @@ -309,7 +309,7 @@ info.si_errno = 0; info.si_code = BUS_ADRALN; info.si_addr = (void *) regs->excvaddr; + force_sig_info(SIGSEGV, &info, current); - force_sig_info(SIGBUS, &info, current); } #endif diff -u linux-lts-xenial-4.4.0/debian.master/changelog linux-lts-xenial-4.4.0/debian.master/changelog --- linux-lts-xenial-4.4.0/debian.master/changelog +++ linux-lts-xenial-4.4.0/debian.master/changelog @@ -1,317 +1,100 @@ -linux (4.4.0-132.158) xenial; urgency=medium +linux (4.4.0-133.159) xenial; urgency=medium - * linux: 4.4.0-132.158 -proposed tracker (LP: #1784302) + * CVE-2018-5390 + - tcp: avoid collapses in tcp_prune_queue() if possible + - tcp: detect malicious patterns in tcp_collapse_ofo_queue() - * locking sockets broken due to missing AppArmor socket mediation patches - (LP: #1780227) - - UBUNTU SAUCE: apparmor: fix apparmor mediating locking non-fs, unix sockets + * CVE-2018-5391 + - Revert "net: increase fragment memory usage limits" - * Backport namespaced fscaps to xenial 4.4 (LP: #1778286) - - Introduce v3 namespaced file capabilities - - commoncap: move assignment of fs_ns to avoid null pointer dereference - - capabilities: fix buffer overread on very short xattr - - commoncap: Handle memory allocation failure. - - * Xenial update to 4.4.140 stable release (LP: #1784409) - - usb: cdc_acm: Add quirk for Uniden UBC125 scanner - - USB: serial: cp210x: add CESINEL device ids - - USB: serial: cp210x: add Silicon Labs IDs for Windows Update - - n_tty: Fix stall at n_tty_receive_char_special(). - - staging: android: ion: Return an ERR_PTR in ion_map_kernel - - n_tty: Access echo_* variables carefully. - - x86/boot: Fix early command-line parsing when matching at end - - ath10k: fix rfc1042 header retrieval in QCA4019 with eth decap mode - - i2c: rcar: fix resume by always initializing registers before transfer - - ipv4: Fix error return value in fib_convert_metrics() - - kprobes/x86: Do not modify singlestep buffer while resuming - - nvme-pci: initialize queue memory before interrupts - - netfilter: nf_tables: use WARN_ON_ONCE instead of BUG_ON in nft_do_chain() - - ARM: dts: imx6q: Use correct SDMA script for SPI5 core - - ubi: fastmap: Correctly handle interrupted erasures in EBA - - mm: hugetlb: yield when prepping struct pages - - tracing: Fix missing return symbol in function_graph output - - scsi: sg: mitigate read/write abuse - - s390: Correct register corruption in critical section cleanup - - drbd: fix access after free - - cifs: Fix infinite loop when using hard mount option - - jbd2: don't mark block as modified if the handle is out of credits - - ext4: make sure bitmaps and the inode table don't overlap with bg - descriptors - - ext4: always check block group bounds in ext4_init_block_bitmap() - - ext4: only look at the bg_flags field if it is valid - - ext4: verify the depth of extent tree in ext4_find_extent() - - ext4: include the illegal physical block in the bad map ext4_error msg - - ext4: clear i_data in ext4_inode_info when removing inline data - - ext4: add more inode number paranoia checks - - ext4: add more mount time checks of the superblock - - ext4: check superblock mapped prior to committing - - HID: i2c-hid: Fix "incomplete report" noise - - HID: hiddev: fix potential Spectre v1 - - HID: debug: check length before copy_to_user() - - x86/mce: Detect local MCEs properly - - x86/mce: Fix incorrect "Machine check from unknown source" message - - media: cx25840: Use subdev host data for PLL override - - mm, page_alloc: do not break __GFP_THISNODE by zonelist reset - - dm bufio: avoid sleeping while holding the dm_bufio lock - - dm bufio: drop the lock when doing GFP_NOIO allocation - - mtd: rawnand: mxc: set spare area size register explicitly - - dm bufio: don't take the lock in dm_bufio_shrink_count - - mtd: cfi_cmdset_0002: Change definition naming to retry write operation - - mtd: cfi_cmdset_0002: Change erase functions to retry for error - - mtd: cfi_cmdset_0002: Change erase functions to check chip good only - - netfilter: nf_log: don't hold nf_log_mutex during user access - - staging: comedi: quatech_daqp_cs: fix no-op loop daqp_ao_insn_write() - - Linux 4.4.140 - - * Xenial update to 4.4.139 stable release (LP: #1784382) - - xfrm6: avoid potential infinite loop in _decode_session6() - - netfilter: ebtables: handle string from userspace with care - - ipvs: fix buffer overflow with sync daemon and service - - atm: zatm: fix memcmp casting - - net: qmi_wwan: Add Netgear Aircard 779S - - net/sonic: Use dma_mapping_error() - - Revert "Btrfs: fix scrub to repair raid6 corruption" - - tcp: do not overshoot window_clamp in tcp_rcv_space_adjust() - - Btrfs: make raid6 rebuild retry more - - usb: musb: fix remote wakeup racing with suspend - - bonding: re-evaluate force_primary when the primary slave name changes - - tcp: verify the checksum of the first data segment in a new connection - - ext4: update mtime in ext4_punch_hole even if no blocks are released - - ext4: fix fencepost error in check for inode count overflow during resize - - driver core: Don't ignore class_dir_create_and_add() failure. - - btrfs: scrub: Don't use inode pages for device replace - - ALSA: hda - Handle kzalloc() failure in snd_hda_attach_pcm_stream() - - ALSA: hda: add dock and led support for HP EliteBook 830 G5 - - ALSA: hda: add dock and led support for HP ProBook 640 G4 - - cpufreq: Fix new policy initialization during limits updates via sysfs - - libata: zpodd: make arrays cdb static, reduces object code size - - libata: zpodd: small read overflow in eject_tray() - - libata: Drop SanDisk SD7UB3Q*G1001 NOLPM quirk - - w1: mxc_w1: Enable clock before calling clk_get_rate() on it - - x86/spectre_v1: Disable compiler optimizations over - array_index_mask_nospec() - - m68k/mm: Adjust VM area to be unmapped by gap size for __iounmap() - - serial: sh-sci: Use spin_{try}lock_irqsave instead of open coding version - - signal/xtensa: Consistenly use SIGBUS in do_unaligned_user - - usb: do not reset if a low-speed or full-speed device timed out - - 1wire: family module autoload fails because of upper/lower case mismatch. - - ASoC: dapm: delete dapm_kcontrol_data paths list before freeing it - - ASoC: cirrus: i2s: Fix LRCLK configuration - - ASoC: cirrus: i2s: Fix {TX|RX}LinCtrlData setup - - lib/vsprintf: Remove atomic-unsafe support for %pCr - - mips: ftrace: fix static function graph tracing - - branch-check: fix long->int truncation when profiling branches - - ipmi:bt: Set the timeout before doing a capabilities check - - Bluetooth: hci_qca: Avoid missing rampatch failure with userspace fw loader - - fuse: atomic_o_trunc should truncate pagecache - - fuse: don't keep dead fuse_conn at fuse_fill_super(). - - fuse: fix control dir setup and teardown - - powerpc/mm/hash: Add missing isync prior to kernel stack SLB switch - - powerpc/ptrace: Fix setting 512B aligned breakpoints with - PTRACE_SET_DEBUGREG - - powerpc/ptrace: Fix enforcement of DAWR constraints - - cpuidle: powernv: Fix promotion from snooze if next state disabled - - powerpc/fadump: Unregister fadump on kexec down path. - - ARM: 8764/1: kgdb: fix NUMREGBYTES so that gdb_regs[] is the correct size - - of: unittest: for strings, account for trailing \0 in property length field - - IB/qib: Fix DMA api warning with debug kernel - - RDMA/mlx4: Discard unknown SQP work requests - - mtd: cfi_cmdset_0002: Change write buffer to check correct value - - mtd: cfi_cmdset_0002: Use right chip in do_ppb_xxlock() - - mtd: cfi_cmdset_0002: fix SEGV unlocking multiple chips - - mtd: cfi_cmdset_0002: Fix unlocking requests crossing a chip boudary - - mtd: cfi_cmdset_0002: Avoid walking all chips when unlocking. - - MIPS: BCM47XX: Enable 74K Core ExternalSync for PCIe erratum - - PCI: pciehp: Clear Presence Detect and Data Link Layer Status Changed on - resume - - MIPS: io: Add barrier after register read in inX() - - time: Make sure jiffies_to_msecs() preserves non-zero time periods - - Btrfs: fix clone vs chattr NODATASUM race - - iio:buffer: make length types match kfifo types - - scsi: qla2xxx: Fix setting lower transfer speed if GPSC fails - - scsi: zfcp: fix missing SCSI trace for result of eh_host_reset_handler - - scsi: zfcp: fix missing SCSI trace for retry of abort / scsi_eh TMF - - scsi: zfcp: fix misleading REC trigger trace where erp_action setup failed - - scsi: zfcp: fix missing REC trigger trace on terminate_rport_io early return - - scsi: zfcp: fix missing REC trigger trace on terminate_rport_io for - ERP_FAILED - - scsi: zfcp: fix missing REC trigger trace for all objects in ERP_FAILED - - scsi: zfcp: fix missing REC trigger trace on enqueue without ERP thread - - linvdimm, pmem: Preserve read-only setting for pmem devices - - md: fix two problems with setting the "re-add" device state. - - ubi: fastmap: Cancel work upon detach - - UBIFS: Fix potential integer overflow in allocation - - xfrm: skip policies marked as dead while rehashing - - backlight: as3711_bl: Fix Device Tree node lookup - - backlight: max8925_bl: Fix Device Tree node lookup - - backlight: tps65217_bl: Fix Device Tree node lookup - - mfd: intel-lpss: Program REMAP register in PIO mode - - perf tools: Fix symbol and object code resolution for vdso32 and vdsox32 - - perf intel-pt: Fix sync_switch INTEL_PT_SS_NOT_TRACING - - perf intel-pt: Fix decoding to accept CBR between FUP and corresponding TIP - - perf intel-pt: Fix MTC timing after overflow - - perf intel-pt: Fix "Unexpected indirect branch" error - - perf intel-pt: Fix packet decoding of CYC packets - - media: v4l2-compat-ioctl32: prevent go past max size - - media: dvb_frontend: fix locking issues at dvb_frontend_get_event() - - nfsd: restrict rd_maxcount to svc_max_payload in nfsd_encode_readdir - - NFSv4: Fix possible 1-byte stack overflow in - nfs_idmap_read_and_verify_message - - video: uvesafb: Fix integer overflow in allocation - - Input: elan_i2c - add ELAN0618 (Lenovo v330 15IKB) ACPI ID - - xen: Remove unnecessary BUG_ON from __unbind_from_irq() - - udf: Detect incorrect directory size - - Input: elan_i2c_smbus - fix more potential stack buffer overflows - - Input: elantech - enable middle button of touchpads on ThinkPad P52 - - Input: elantech - fix V4 report decoding for module with middle key - - ALSA: hda/realtek - Add a quirk for FSC ESPRIMO U9210 - - Btrfs: fix unexpected cow in run_delalloc_nocow - - spi: Fix scatterlist elements size in spi_map_buf - - block: Fix transfer when chunk sectors exceeds max - - dm thin: handle running out of data space vs concurrent discard - - cdc_ncm: avoid padding beyond end of skb - - Bluetooth: Fix connection if directed advertising and privacy is used - - Linux 4.4.139 - - * Support AverMedia DVD EZMaker 7 USB video capture dongle (LP: #1620762) // - Xenial update to 4.4.139 stable release (LP: #1784382) - - media: cx231xx: Add support for AverMedia DVD EZMaker 7 - - * vfio/pci: cannot assign a i40e pf device to a vm using vfio-pci - (LP: #1779830) - - vfio/pci: Hide broken INTx support from user - - * Kernel error "task zfs:pid blocked for more than 120 seconds" (LP: #1781364) - - SAUCE: (noup) zfs to 0.6.5.6-0ubuntu25 - - * Allow multiple mounts of zfs datasets (LP: #1759848) - - SAUCE: Allow mounting datasets more than once (LP: #1759848) - - * CVE-2018-12233 - - jfs: Fix inconsistency between memory allocation and ea_buf->max_size - - * Redpine: Observed kernel panic while running wireless tests in regression - mode (LP: #1773410) // Redpine: Observed kernel panic while running soft-ap - tests (LP: #1777850) - - SAUCE: Redpine: improve cancel_hw_scan handling to fix kernel panic - - * [HMS] Upgrades to Support SocketCAN over USB on Dell IoT 300x Gateways - (LP: #1783241) - - SAUCE: (no-up) upgrade IXXAT USB SocketCAN driver - - * CVE-2018-13094 - - xfs: don't call xfs_da_shrink_inode with NULL bp - - * other users' coredumps can be read via setgid directory and killpriv bypass - (LP: #1779923) // CVE-2018-13405 - - Fix up non-directory creation in SGID directories - - * snapcraft.yaml: missing ubuntu-retpoline-extract-one script breaks the build - (LP: #1782116) - - snapcraft.yaml: copy retpoline-extract-one to scripts before build - - * Enable basic support for Solarflare 8000 series NIC (LP: #1783152) - - sfc: make TSO version a per-queue parameter - - sfc: Add PCI ID for Solarflare 8000 series 10/40G NIC - - * Redpine: Observed kernel panic while running wireless regressions tests - (LP: #1777858) - - SAUCE: Redpine: improve kernel thread handling to fix kernel panic - - * Xenial update to 4.4.138 stable release (LP: #1777389) - - x86: Remove unused function cpu_has_ht_siblings() - - x86/cpufeature: Remove unused and seldomly used cpu_has_xx macros - - x86/fpu: Disable AVX when eagerfpu is off - - x86/fpu: Revert ("x86/fpu: Disable AVX when eagerfpu is off") - - x86/fpu: Hard-disable lazy FPU mode - - af_key: Always verify length of provided sadb_key - - x86/crypto, x86/fpu: Remove X86_FEATURE_EAGER_FPU #ifdef from the crc32c - code - - gpio: No NULL owner - - Clarify (and fix) MAX_LFS_FILESIZE macros + * CVE-2018-3620 // CVE-2018-3646 - KVM: x86: introduce linear_{read,write}_system - KVM: x86: pass kvm_vcpu to kvm_read_guest_virt and kvm_write_guest_virt_system - - serial: samsung: fix maxburst parameter for DMA transactions - - vmw_balloon: fixing double free when batching mode is off - kvm: x86: use correct privilege level for sgdt/sidt/fxsave/fxrstor access - - Input: goodix - add new ACPI id for GPD Win 2 touch screen - - crypto: vmx - Remove overly verbose printk from AES init routines - - Linux 4.4.138 - - * Redpine: wifi-ap stopped working after restart (LP: #1773400) - - SAUCE: Redpine: fix soft-ap invisible issue - - * Xenial update to 4.4.137 stable release (LP: #1777063) - - tpm: do not suspend/resume if power stays on - - tpm: self test failure should not cause suspend to fail - - mmap: introduce sane default mmap limits - - mmap: relax file size limit for regular files - - kconfig: Avoid format overflow warning from GCC 8.1 - - xfs: fix incorrect log_flushed on fsync - - drm: set FMODE_UNSIGNED_OFFSET for drm files - - brcmfmac: Fix check for ISO3166 code - - bnx2x: use the right constant - - dccp: don't free ccid2_hc_tx_sock struct in dccp_disconnect() - - enic: set DMA mask to 47 bit - - ip6mr: only set ip6mr_table from setsockopt when ip6mr_new_table succeeds - - ipv4: remove warning in ip_recv_error - - isdn: eicon: fix a missing-check bug - - netdev-FAQ: clarify DaveM's position for stable backports - - net/packet: refine check for priv area size - - net: usb: cdc_mbim: add flag FLAG_SEND_ZLP - - packet: fix reserve calculation - - qed: Fix mask for physical address in ILT entry - - net/mlx4: Fix irq-unsafe spinlock usage - - team: use netdev_features_t instead of u32 - - rtnetlink: validate attributes in do_setlink() - - net: phy: broadcom: Fix bcm_write_exp() - - net: metrics: add proper netlink validation - - Linux 4.4.137 - - * Xenial update to 4.4.136 stable release (LP: #1776177) - - arm64: lse: Add early clobbers to some input/output asm operands - - powerpc/64s: Clear PCR on boot - - USB: serial: cp210x: use tcflag_t to fix incompatible pointer type - - sh: New gcc support - - xfs: detect agfl count corruption and reset agfl - - Input: elan_i2c_smbus - fix corrupted stack - - tracing: Fix crash when freeing instances with event triggers - - selinux: KASAN: slab-out-of-bounds in xattr_getsecurity - - cfg80211: further limit wiphy names to 64 bytes - - rtlwifi: rtl8192cu: Remove variable self-assignment in rf.c - - ASoC: Intel: sst: remove redundant variable dma_dev_name - - irda: fix overly long udelay() - - tcp: avoid integer overflows in tcp_rcv_space_adjust() - - i2c: rcar: make sure clocks are on when doing clock calculation - - i2c: rcar: rework hw init - - i2c: rcar: remove unused IOERROR state - - i2c: rcar: remove spinlock - - i2c: rcar: refactor setup of a msg - - i2c: rcar: init new messages in irq - - i2c: rcar: don't issue stop when HW does it automatically - - i2c: rcar: check master irqs before slave irqs - - i2c: rcar: revoke START request early - - dmaengine: usb-dmac: fix endless loop in usb_dmac_chan_terminate_all() - - iio:kfifo_buf: check for uint overflow - - MIPS: ptrace: Fix PTRACE_PEEKUSR requests for 64-bit FGRs - - MIPS: prctl: Disallow FRE without FR with PR_SET_FP_MODE requests - - scsi: scsi_transport_srp: Fix shost to rport translation - - stm class: Use vmalloc for the master map - - hwtracing: stm: fix build error on some arches - - drm/i915: Disable LVDS on Radiant P845 - - Kbuild: change CC_OPTIMIZE_FOR_SIZE definition - - [Config] Add CONFIG_CC_OPTIMIZE_FOR_PERFORMANCE=y - - fix io_destroy()/aio_complete() race - - mm: fix the NULL mapping case in __isolate_lru_page() - - sparc64: Fix build warnings with gcc 7. - - Linux 4.4.136 - - * Xenial update to 4.4.135 stable release (LP: #1776158) - - Revert "vti4: Don't override MTU passed on link creation via IFLA_MTU" - - Linux 4.4.135 + - x86/speculation/l1tf: Increase 32bit PAE __PHYSICAL_PAGE_SHIFT + - x86/speculation/l1tf: Change order of offset/type in swap entry + - x86/speculation/l1tf: Protect swap entries against L1TF + - x86/mm: Simplify p[g4um]d_page() macros + - x86/speculation/l1tf: Protect PROT_NONE PTEs against speculation + - x86/speculation/l1tf: Make sure the first page is always reserved + - SAUCE: x86/cpu: Add Knights Mill/Gemini Lake + - x86/speculation/l1tf: Add sysfs reporting for l1tf + - x86/speculation/l1tf: Disallow non privileged high MMIO PROT_NONE mappings + - x86/speculation/l1tf: Limit swap file size to MAX_PA/2 + - x86/smp: Provide topology_is_primary_thread() + - x86/topology: Provide topology_smt_supported() + - cpu/hotplug: Split do_cpu_down() + - x86/topology: Add topology_max_smt_threads() + - cpu/hotplug: Provide knobs to control SMT + - x86/CPU: Modify detect_extended_topology() to return result + - x86/cpu: Remove the pointless CPU printout + - x86/cpu/AMD: Remove the pointless detect_ht() call + - x86/cpu/common: Provide detect_ht_early() + - x86/cpu/topology: Provide detect_extended_topology_early() + - x86/cpu/intel: Evaluate smp_num_siblings early + - x86/cpu/AMD: Evaluate smp_num_siblings early + - x86/apic: Ignore secondary threads if nosmt=force + - x86/speculation/l1tf: Extend 64bit swap file size limit + - x86/CPU/AMD: Move TOPOEXT reenablement before reading smp_num_siblings + - x86/cpufeatures: Add detection of L1D cache flush support. + - x86/speculation/l1tf: Protect PAE swap entries against L1TF + - x86/speculation/l1tf: Fix up pte->pfn conversion for PAE + - Revert "x86/apic: Ignore secondary threads if nosmt=force" + - SAUCE: x86/mce: register mce notifier earlier + - cpu/hotplug: Boot HT siblings at least once + - KVM: x86: Introducing kvm_x86_ops VM init/destroy hooks + - x86/KVM: Warn user if KVM is loaded SMT and L1TF CPU bug being present. + - x86/KVM/VMX: Add module argument for L1TF mitigation + - x86/KVM/VMX: Add L1D flush algorithm + - x86/KVM/VMX: Add L1D MSR based flush + - x86/KVM/VMX: Add L1D flush logic + - x86/KVM/VMX: Split the VMX MSR LOAD structures to have an host/guest numbers + - x86/KVM/VMX: Add find_msr() helper function + - x86/KVM/VMX: Seperate the VMX AUTOLOAD guest/host number accounting. + - x86/KVM/VMX: Extend add_atomic_switch_msr() to allow VMENTER only MSRs + - x86/KVM/VMX: Use MSR save list for IA32_FLUSH_CMD if required + - cpu/hotplug: Online siblings when SMT control is turned on + - x86/litf: Introduce vmx status variable + - x86/kvm: Drop L1TF MSR list approach + - x86/l1tf: Handle EPT disabled state proper + - x86/kvm: Move l1tf setup function + - x86/kvm: Add static key for flush always + - x86/kvm: Serialize L1D flush parameter setter + - x86/kvm: Allow runtime control of L1D flush + - cpu/hotplug: Expose SMT control init function + - cpu/hotplug: Set CPU_SMT_NOT_SUPPORTED early + - x86/bugs, kvm: Introduce boot-time control of L1TF mitigations + - Documentation: Add section about CPU vulnerabilities + - x86/speculation/l1tf: Unbreak !__HAVE_ARCH_PFN_MODIFY_ALLOWED architectures + - x86/KVM/VMX: Initialize the vmx_l1d_flush_pages' content + - Documentation/l1tf: Fix typos + - cpu/hotplug: detect SMT disabled by BIOS + - x86/KVM/VMX: Don't set l1tf_flush_l1d to true from vmx_l1d_flush() + - x86/KVM/VMX: Replace 'vmx_l1d_flush_always' with 'vmx_l1d_flush_cond' + - x86/KVM/VMX: Move the l1tf_flush_l1d test to vmx_l1d_flush() + - x86/irq: Demote irq_cpustat_t::__softirq_pending to u16 + - x86/KVM/VMX: Introduce per-host-cpu analogue of l1tf_flush_l1d + - x86: Don't include linux/irq.h from asm/hardirq.h + - x86/apic: Order irq_enter/exit() calls correctly vs. ack_APIC_irq() + - x86/irq: Let interrupt handlers set kvm_cpu_l1tf_flush_l1d + - x86/KVM/VMX: Don't set l1tf_flush_l1d from vmx_handle_external_intr() + - Documentation/l1tf: Remove Yonah processors from not vulnerable list + - x86/speculation: Simplify sysfs report of VMX L1TF vulnerability + - x86/speculation: Use ARCH_CAPABILITIES to skip L1D flush on vmentry + - KVM/VMX: Emulate MSR_IA32_ARCH_CAPABILITIES + - KVM: x86: Add a framework for supporting MSR-based features + - KVM: X86: Introduce kvm_get_msr_feature() + - KVM: VMX: support MSR_IA32_ARCH_CAPABILITIES as a feature MSR + - KVM: VMX: Tell the nested hypervisor to skip L1D flush on vmentry + - cpu/hotplug: Fix SMT supported evaluation + - x86/speculation/l1tf: Invert all not present mappings + - x86/speculation/l1tf: Make pmd/pud_mknotpresent() invert + - x86/mm/pat: Ensure cpa->pfn only contains page frame numbers + - SAUCE: Add pfn_pud() and pud_mkhuge() + - x86/mm/pat: Make set_memory_np() L1TF safe - -- Khalid Elmously Tue, 31 Jul 2018 16:20:24 -0400 + -- Stefan Bader Wed, 08 Aug 2018 12:04:38 +0200 linux (4.4.0-131.157) xenial; urgency=medium diff -u linux-lts-xenial-4.4.0/debian.master/config/config.common.ubuntu linux-lts-xenial-4.4.0/debian.master/config/config.common.ubuntu --- linux-lts-xenial-4.4.0/debian.master/config/config.common.ubuntu +++ linux-lts-xenial-4.4.0/debian.master/config/config.common.ubuntu @@ -1121,7 +1121,6 @@ CONFIG_CCW=y CONFIG_CCWGROUP=m CONFIG_CCW_CONSOLE=y -CONFIG_CC_OPTIMIZE_FOR_PERFORMANCE=y # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set # CONFIG_CC_STACKPROTECTOR_NONE is not set # CONFIG_CC_STACKPROTECTOR_REGULAR is not set diff -u linux-lts-xenial-4.4.0/debian.xenial/changelog linux-lts-xenial-4.4.0/debian.xenial/changelog --- linux-lts-xenial-4.4.0/debian.xenial/changelog +++ linux-lts-xenial-4.4.0/debian.xenial/changelog @@ -1,319 +1,100 @@ -linux-lts-xenial (4.4.0-132.158~14.04.1) trusty; urgency=medium +linux-lts-xenial (4.4.0-133.159~14.04.1) trusty; urgency=medium - * linux-lts-xenial: 4.4.0-132.158~14.04.1 -proposed tracker (LP: #1784304) + * CVE-2018-5390 + - tcp: avoid collapses in tcp_prune_queue() if possible + - tcp: detect malicious patterns in tcp_collapse_ofo_queue() - * linux: 4.4.0-132.158 -proposed tracker (LP: #1784302) + * CVE-2018-5391 + - Revert "net: increase fragment memory usage limits" - * locking sockets broken due to missing AppArmor socket mediation patches - (LP: #1780227) - - UBUNTU SAUCE: apparmor: fix apparmor mediating locking non-fs, unix sockets - - * Backport namespaced fscaps to xenial 4.4 (LP: #1778286) - - Introduce v3 namespaced file capabilities - - commoncap: move assignment of fs_ns to avoid null pointer dereference - - capabilities: fix buffer overread on very short xattr - - commoncap: Handle memory allocation failure. - - * Xenial update to 4.4.140 stable release (LP: #1784409) - - usb: cdc_acm: Add quirk for Uniden UBC125 scanner - - USB: serial: cp210x: add CESINEL device ids - - USB: serial: cp210x: add Silicon Labs IDs for Windows Update - - n_tty: Fix stall at n_tty_receive_char_special(). - - staging: android: ion: Return an ERR_PTR in ion_map_kernel - - n_tty: Access echo_* variables carefully. - - x86/boot: Fix early command-line parsing when matching at end - - ath10k: fix rfc1042 header retrieval in QCA4019 with eth decap mode - - i2c: rcar: fix resume by always initializing registers before transfer - - ipv4: Fix error return value in fib_convert_metrics() - - kprobes/x86: Do not modify singlestep buffer while resuming - - nvme-pci: initialize queue memory before interrupts - - netfilter: nf_tables: use WARN_ON_ONCE instead of BUG_ON in nft_do_chain() - - ARM: dts: imx6q: Use correct SDMA script for SPI5 core - - ubi: fastmap: Correctly handle interrupted erasures in EBA - - mm: hugetlb: yield when prepping struct pages - - tracing: Fix missing return symbol in function_graph output - - scsi: sg: mitigate read/write abuse - - s390: Correct register corruption in critical section cleanup - - drbd: fix access after free - - cifs: Fix infinite loop when using hard mount option - - jbd2: don't mark block as modified if the handle is out of credits - - ext4: make sure bitmaps and the inode table don't overlap with bg - descriptors - - ext4: always check block group bounds in ext4_init_block_bitmap() - - ext4: only look at the bg_flags field if it is valid - - ext4: verify the depth of extent tree in ext4_find_extent() - - ext4: include the illegal physical block in the bad map ext4_error msg - - ext4: clear i_data in ext4_inode_info when removing inline data - - ext4: add more inode number paranoia checks - - ext4: add more mount time checks of the superblock - - ext4: check superblock mapped prior to committing - - HID: i2c-hid: Fix "incomplete report" noise - - HID: hiddev: fix potential Spectre v1 - - HID: debug: check length before copy_to_user() - - x86/mce: Detect local MCEs properly - - x86/mce: Fix incorrect "Machine check from unknown source" message - - media: cx25840: Use subdev host data for PLL override - - mm, page_alloc: do not break __GFP_THISNODE by zonelist reset - - dm bufio: avoid sleeping while holding the dm_bufio lock - - dm bufio: drop the lock when doing GFP_NOIO allocation - - mtd: rawnand: mxc: set spare area size register explicitly - - dm bufio: don't take the lock in dm_bufio_shrink_count - - mtd: cfi_cmdset_0002: Change definition naming to retry write operation - - mtd: cfi_cmdset_0002: Change erase functions to retry for error - - mtd: cfi_cmdset_0002: Change erase functions to check chip good only - - netfilter: nf_log: don't hold nf_log_mutex during user access - - staging: comedi: quatech_daqp_cs: fix no-op loop daqp_ao_insn_write() - - Linux 4.4.140 - - * Xenial update to 4.4.139 stable release (LP: #1784382) - - xfrm6: avoid potential infinite loop in _decode_session6() - - netfilter: ebtables: handle string from userspace with care - - ipvs: fix buffer overflow with sync daemon and service - - atm: zatm: fix memcmp casting - - net: qmi_wwan: Add Netgear Aircard 779S - - net/sonic: Use dma_mapping_error() - - Revert "Btrfs: fix scrub to repair raid6 corruption" - - tcp: do not overshoot window_clamp in tcp_rcv_space_adjust() - - Btrfs: make raid6 rebuild retry more - - usb: musb: fix remote wakeup racing with suspend - - bonding: re-evaluate force_primary when the primary slave name changes - - tcp: verify the checksum of the first data segment in a new connection - - ext4: update mtime in ext4_punch_hole even if no blocks are released - - ext4: fix fencepost error in check for inode count overflow during resize - - driver core: Don't ignore class_dir_create_and_add() failure. - - btrfs: scrub: Don't use inode pages for device replace - - ALSA: hda - Handle kzalloc() failure in snd_hda_attach_pcm_stream() - - ALSA: hda: add dock and led support for HP EliteBook 830 G5 - - ALSA: hda: add dock and led support for HP ProBook 640 G4 - - cpufreq: Fix new policy initialization during limits updates via sysfs - - libata: zpodd: make arrays cdb static, reduces object code size - - libata: zpodd: small read overflow in eject_tray() - - libata: Drop SanDisk SD7UB3Q*G1001 NOLPM quirk - - w1: mxc_w1: Enable clock before calling clk_get_rate() on it - - x86/spectre_v1: Disable compiler optimizations over - array_index_mask_nospec() - - m68k/mm: Adjust VM area to be unmapped by gap size for __iounmap() - - serial: sh-sci: Use spin_{try}lock_irqsave instead of open coding version - - signal/xtensa: Consistenly use SIGBUS in do_unaligned_user - - usb: do not reset if a low-speed or full-speed device timed out - - 1wire: family module autoload fails because of upper/lower case mismatch. - - ASoC: dapm: delete dapm_kcontrol_data paths list before freeing it - - ASoC: cirrus: i2s: Fix LRCLK configuration - - ASoC: cirrus: i2s: Fix {TX|RX}LinCtrlData setup - - lib/vsprintf: Remove atomic-unsafe support for %pCr - - mips: ftrace: fix static function graph tracing - - branch-check: fix long->int truncation when profiling branches - - ipmi:bt: Set the timeout before doing a capabilities check - - Bluetooth: hci_qca: Avoid missing rampatch failure with userspace fw loader - - fuse: atomic_o_trunc should truncate pagecache - - fuse: don't keep dead fuse_conn at fuse_fill_super(). - - fuse: fix control dir setup and teardown - - powerpc/mm/hash: Add missing isync prior to kernel stack SLB switch - - powerpc/ptrace: Fix setting 512B aligned breakpoints with - PTRACE_SET_DEBUGREG - - powerpc/ptrace: Fix enforcement of DAWR constraints - - cpuidle: powernv: Fix promotion from snooze if next state disabled - - powerpc/fadump: Unregister fadump on kexec down path. - - ARM: 8764/1: kgdb: fix NUMREGBYTES so that gdb_regs[] is the correct size - - of: unittest: for strings, account for trailing \0 in property length field - - IB/qib: Fix DMA api warning with debug kernel - - RDMA/mlx4: Discard unknown SQP work requests - - mtd: cfi_cmdset_0002: Change write buffer to check correct value - - mtd: cfi_cmdset_0002: Use right chip in do_ppb_xxlock() - - mtd: cfi_cmdset_0002: fix SEGV unlocking multiple chips - - mtd: cfi_cmdset_0002: Fix unlocking requests crossing a chip boudary - - mtd: cfi_cmdset_0002: Avoid walking all chips when unlocking. - - MIPS: BCM47XX: Enable 74K Core ExternalSync for PCIe erratum - - PCI: pciehp: Clear Presence Detect and Data Link Layer Status Changed on - resume - - MIPS: io: Add barrier after register read in inX() - - time: Make sure jiffies_to_msecs() preserves non-zero time periods - - Btrfs: fix clone vs chattr NODATASUM race - - iio:buffer: make length types match kfifo types - - scsi: qla2xxx: Fix setting lower transfer speed if GPSC fails - - scsi: zfcp: fix missing SCSI trace for result of eh_host_reset_handler - - scsi: zfcp: fix missing SCSI trace for retry of abort / scsi_eh TMF - - scsi: zfcp: fix misleading REC trigger trace where erp_action setup failed - - scsi: zfcp: fix missing REC trigger trace on terminate_rport_io early return - - scsi: zfcp: fix missing REC trigger trace on terminate_rport_io for - ERP_FAILED - - scsi: zfcp: fix missing REC trigger trace for all objects in ERP_FAILED - - scsi: zfcp: fix missing REC trigger trace on enqueue without ERP thread - - linvdimm, pmem: Preserve read-only setting for pmem devices - - md: fix two problems with setting the "re-add" device state. - - ubi: fastmap: Cancel work upon detach - - UBIFS: Fix potential integer overflow in allocation - - xfrm: skip policies marked as dead while rehashing - - backlight: as3711_bl: Fix Device Tree node lookup - - backlight: max8925_bl: Fix Device Tree node lookup - - backlight: tps65217_bl: Fix Device Tree node lookup - - mfd: intel-lpss: Program REMAP register in PIO mode - - perf tools: Fix symbol and object code resolution for vdso32 and vdsox32 - - perf intel-pt: Fix sync_switch INTEL_PT_SS_NOT_TRACING - - perf intel-pt: Fix decoding to accept CBR between FUP and corresponding TIP - - perf intel-pt: Fix MTC timing after overflow - - perf intel-pt: Fix "Unexpected indirect branch" error - - perf intel-pt: Fix packet decoding of CYC packets - - media: v4l2-compat-ioctl32: prevent go past max size - - media: dvb_frontend: fix locking issues at dvb_frontend_get_event() - - nfsd: restrict rd_maxcount to svc_max_payload in nfsd_encode_readdir - - NFSv4: Fix possible 1-byte stack overflow in - nfs_idmap_read_and_verify_message - - video: uvesafb: Fix integer overflow in allocation - - Input: elan_i2c - add ELAN0618 (Lenovo v330 15IKB) ACPI ID - - xen: Remove unnecessary BUG_ON from __unbind_from_irq() - - udf: Detect incorrect directory size - - Input: elan_i2c_smbus - fix more potential stack buffer overflows - - Input: elantech - enable middle button of touchpads on ThinkPad P52 - - Input: elantech - fix V4 report decoding for module with middle key - - ALSA: hda/realtek - Add a quirk for FSC ESPRIMO U9210 - - Btrfs: fix unexpected cow in run_delalloc_nocow - - spi: Fix scatterlist elements size in spi_map_buf - - block: Fix transfer when chunk sectors exceeds max - - dm thin: handle running out of data space vs concurrent discard - - cdc_ncm: avoid padding beyond end of skb - - Bluetooth: Fix connection if directed advertising and privacy is used - - Linux 4.4.139 - - * Support AverMedia DVD EZMaker 7 USB video capture dongle (LP: #1620762) // - Xenial update to 4.4.139 stable release (LP: #1784382) - - media: cx231xx: Add support for AverMedia DVD EZMaker 7 - - * vfio/pci: cannot assign a i40e pf device to a vm using vfio-pci - (LP: #1779830) - - vfio/pci: Hide broken INTx support from user - - * Kernel error "task zfs:pid blocked for more than 120 seconds" (LP: #1781364) - - SAUCE: (noup) zfs to 0.6.5.6-0ubuntu25 - - * Allow multiple mounts of zfs datasets (LP: #1759848) - - SAUCE: Allow mounting datasets more than once (LP: #1759848) - - * CVE-2018-12233 - - jfs: Fix inconsistency between memory allocation and ea_buf->max_size - - * Redpine: Observed kernel panic while running wireless tests in regression - mode (LP: #1773410) // Redpine: Observed kernel panic while running soft-ap - tests (LP: #1777850) - - SAUCE: Redpine: improve cancel_hw_scan handling to fix kernel panic - - * [HMS] Upgrades to Support SocketCAN over USB on Dell IoT 300x Gateways - (LP: #1783241) - - SAUCE: (no-up) upgrade IXXAT USB SocketCAN driver - - * CVE-2018-13094 - - xfs: don't call xfs_da_shrink_inode with NULL bp - - * other users' coredumps can be read via setgid directory and killpriv bypass - (LP: #1779923) // CVE-2018-13405 - - Fix up non-directory creation in SGID directories - - * snapcraft.yaml: missing ubuntu-retpoline-extract-one script breaks the build - (LP: #1782116) - - snapcraft.yaml: copy retpoline-extract-one to scripts before build - - * Enable basic support for Solarflare 8000 series NIC (LP: #1783152) - - sfc: make TSO version a per-queue parameter - - sfc: Add PCI ID for Solarflare 8000 series 10/40G NIC - - * Redpine: Observed kernel panic while running wireless regressions tests - (LP: #1777858) - - SAUCE: Redpine: improve kernel thread handling to fix kernel panic - - * Xenial update to 4.4.138 stable release (LP: #1777389) - - x86: Remove unused function cpu_has_ht_siblings() - - x86/cpufeature: Remove unused and seldomly used cpu_has_xx macros - - x86/fpu: Disable AVX when eagerfpu is off - - x86/fpu: Revert ("x86/fpu: Disable AVX when eagerfpu is off") - - x86/fpu: Hard-disable lazy FPU mode - - af_key: Always verify length of provided sadb_key - - x86/crypto, x86/fpu: Remove X86_FEATURE_EAGER_FPU #ifdef from the crc32c - code - - gpio: No NULL owner - - Clarify (and fix) MAX_LFS_FILESIZE macros + * CVE-2018-3620 // CVE-2018-3646 - KVM: x86: introduce linear_{read,write}_system - KVM: x86: pass kvm_vcpu to kvm_read_guest_virt and kvm_write_guest_virt_system - - serial: samsung: fix maxburst parameter for DMA transactions - - vmw_balloon: fixing double free when batching mode is off - kvm: x86: use correct privilege level for sgdt/sidt/fxsave/fxrstor access - - Input: goodix - add new ACPI id for GPD Win 2 touch screen - - crypto: vmx - Remove overly verbose printk from AES init routines - - Linux 4.4.138 - - * Redpine: wifi-ap stopped working after restart (LP: #1773400) - - SAUCE: Redpine: fix soft-ap invisible issue - - * Xenial update to 4.4.137 stable release (LP: #1777063) - - tpm: do not suspend/resume if power stays on - - tpm: self test failure should not cause suspend to fail - - mmap: introduce sane default mmap limits - - mmap: relax file size limit for regular files - - kconfig: Avoid format overflow warning from GCC 8.1 - - xfs: fix incorrect log_flushed on fsync - - drm: set FMODE_UNSIGNED_OFFSET for drm files - - brcmfmac: Fix check for ISO3166 code - - bnx2x: use the right constant - - dccp: don't free ccid2_hc_tx_sock struct in dccp_disconnect() - - enic: set DMA mask to 47 bit - - ip6mr: only set ip6mr_table from setsockopt when ip6mr_new_table succeeds - - ipv4: remove warning in ip_recv_error - - isdn: eicon: fix a missing-check bug - - netdev-FAQ: clarify DaveM's position for stable backports - - net/packet: refine check for priv area size - - net: usb: cdc_mbim: add flag FLAG_SEND_ZLP - - packet: fix reserve calculation - - qed: Fix mask for physical address in ILT entry - - net/mlx4: Fix irq-unsafe spinlock usage - - team: use netdev_features_t instead of u32 - - rtnetlink: validate attributes in do_setlink() - - net: phy: broadcom: Fix bcm_write_exp() - - net: metrics: add proper netlink validation - - Linux 4.4.137 - - * Xenial update to 4.4.136 stable release (LP: #1776177) - - arm64: lse: Add early clobbers to some input/output asm operands - - powerpc/64s: Clear PCR on boot - - USB: serial: cp210x: use tcflag_t to fix incompatible pointer type - - sh: New gcc support - - xfs: detect agfl count corruption and reset agfl - - Input: elan_i2c_smbus - fix corrupted stack - - tracing: Fix crash when freeing instances with event triggers - - selinux: KASAN: slab-out-of-bounds in xattr_getsecurity - - cfg80211: further limit wiphy names to 64 bytes - - rtlwifi: rtl8192cu: Remove variable self-assignment in rf.c - - ASoC: Intel: sst: remove redundant variable dma_dev_name - - irda: fix overly long udelay() - - tcp: avoid integer overflows in tcp_rcv_space_adjust() - - i2c: rcar: make sure clocks are on when doing clock calculation - - i2c: rcar: rework hw init - - i2c: rcar: remove unused IOERROR state - - i2c: rcar: remove spinlock - - i2c: rcar: refactor setup of a msg - - i2c: rcar: init new messages in irq - - i2c: rcar: don't issue stop when HW does it automatically - - i2c: rcar: check master irqs before slave irqs - - i2c: rcar: revoke START request early - - dmaengine: usb-dmac: fix endless loop in usb_dmac_chan_terminate_all() - - iio:kfifo_buf: check for uint overflow - - MIPS: ptrace: Fix PTRACE_PEEKUSR requests for 64-bit FGRs - - MIPS: prctl: Disallow FRE without FR with PR_SET_FP_MODE requests - - scsi: scsi_transport_srp: Fix shost to rport translation - - stm class: Use vmalloc for the master map - - hwtracing: stm: fix build error on some arches - - drm/i915: Disable LVDS on Radiant P845 - - Kbuild: change CC_OPTIMIZE_FOR_SIZE definition - - [Config] Add CONFIG_CC_OPTIMIZE_FOR_PERFORMANCE=y - - fix io_destroy()/aio_complete() race - - mm: fix the NULL mapping case in __isolate_lru_page() - - sparc64: Fix build warnings with gcc 7. - - Linux 4.4.136 - - * Xenial update to 4.4.135 stable release (LP: #1776158) - - Revert "vti4: Don't override MTU passed on link creation via IFLA_MTU" - - Linux 4.4.135 + - x86/speculation/l1tf: Increase 32bit PAE __PHYSICAL_PAGE_SHIFT + - x86/speculation/l1tf: Change order of offset/type in swap entry + - x86/speculation/l1tf: Protect swap entries against L1TF + - x86/mm: Simplify p[g4um]d_page() macros + - x86/speculation/l1tf: Protect PROT_NONE PTEs against speculation + - x86/speculation/l1tf: Make sure the first page is always reserved + - SAUCE: x86/cpu: Add Knights Mill/Gemini Lake + - x86/speculation/l1tf: Add sysfs reporting for l1tf + - x86/speculation/l1tf: Disallow non privileged high MMIO PROT_NONE mappings + - x86/speculation/l1tf: Limit swap file size to MAX_PA/2 + - x86/smp: Provide topology_is_primary_thread() + - x86/topology: Provide topology_smt_supported() + - cpu/hotplug: Split do_cpu_down() + - x86/topology: Add topology_max_smt_threads() + - cpu/hotplug: Provide knobs to control SMT + - x86/CPU: Modify detect_extended_topology() to return result + - x86/cpu: Remove the pointless CPU printout + - x86/cpu/AMD: Remove the pointless detect_ht() call + - x86/cpu/common: Provide detect_ht_early() + - x86/cpu/topology: Provide detect_extended_topology_early() + - x86/cpu/intel: Evaluate smp_num_siblings early + - x86/cpu/AMD: Evaluate smp_num_siblings early + - x86/apic: Ignore secondary threads if nosmt=force + - x86/speculation/l1tf: Extend 64bit swap file size limit + - x86/CPU/AMD: Move TOPOEXT reenablement before reading smp_num_siblings + - x86/cpufeatures: Add detection of L1D cache flush support. + - x86/speculation/l1tf: Protect PAE swap entries against L1TF + - x86/speculation/l1tf: Fix up pte->pfn conversion for PAE + - Revert "x86/apic: Ignore secondary threads if nosmt=force" + - SAUCE: x86/mce: register mce notifier earlier + - cpu/hotplug: Boot HT siblings at least once + - KVM: x86: Introducing kvm_x86_ops VM init/destroy hooks + - x86/KVM: Warn user if KVM is loaded SMT and L1TF CPU bug being present. + - x86/KVM/VMX: Add module argument for L1TF mitigation + - x86/KVM/VMX: Add L1D flush algorithm + - x86/KVM/VMX: Add L1D MSR based flush + - x86/KVM/VMX: Add L1D flush logic + - x86/KVM/VMX: Split the VMX MSR LOAD structures to have an host/guest numbers + - x86/KVM/VMX: Add find_msr() helper function + - x86/KVM/VMX: Seperate the VMX AUTOLOAD guest/host number accounting. + - x86/KVM/VMX: Extend add_atomic_switch_msr() to allow VMENTER only MSRs + - x86/KVM/VMX: Use MSR save list for IA32_FLUSH_CMD if required + - cpu/hotplug: Online siblings when SMT control is turned on + - x86/litf: Introduce vmx status variable + - x86/kvm: Drop L1TF MSR list approach + - x86/l1tf: Handle EPT disabled state proper + - x86/kvm: Move l1tf setup function + - x86/kvm: Add static key for flush always + - x86/kvm: Serialize L1D flush parameter setter + - x86/kvm: Allow runtime control of L1D flush + - cpu/hotplug: Expose SMT control init function + - cpu/hotplug: Set CPU_SMT_NOT_SUPPORTED early + - x86/bugs, kvm: Introduce boot-time control of L1TF mitigations + - Documentation: Add section about CPU vulnerabilities + - x86/speculation/l1tf: Unbreak !__HAVE_ARCH_PFN_MODIFY_ALLOWED architectures + - x86/KVM/VMX: Initialize the vmx_l1d_flush_pages' content + - Documentation/l1tf: Fix typos + - cpu/hotplug: detect SMT disabled by BIOS + - x86/KVM/VMX: Don't set l1tf_flush_l1d to true from vmx_l1d_flush() + - x86/KVM/VMX: Replace 'vmx_l1d_flush_always' with 'vmx_l1d_flush_cond' + - x86/KVM/VMX: Move the l1tf_flush_l1d test to vmx_l1d_flush() + - x86/irq: Demote irq_cpustat_t::__softirq_pending to u16 + - x86/KVM/VMX: Introduce per-host-cpu analogue of l1tf_flush_l1d + - x86: Don't include linux/irq.h from asm/hardirq.h + - x86/apic: Order irq_enter/exit() calls correctly vs. ack_APIC_irq() + - x86/irq: Let interrupt handlers set kvm_cpu_l1tf_flush_l1d + - x86/KVM/VMX: Don't set l1tf_flush_l1d from vmx_handle_external_intr() + - Documentation/l1tf: Remove Yonah processors from not vulnerable list + - x86/speculation: Simplify sysfs report of VMX L1TF vulnerability + - x86/speculation: Use ARCH_CAPABILITIES to skip L1D flush on vmentry + - KVM/VMX: Emulate MSR_IA32_ARCH_CAPABILITIES + - KVM: x86: Add a framework for supporting MSR-based features + - KVM: X86: Introduce kvm_get_msr_feature() + - KVM: VMX: support MSR_IA32_ARCH_CAPABILITIES as a feature MSR + - KVM: VMX: Tell the nested hypervisor to skip L1D flush on vmentry + - cpu/hotplug: Fix SMT supported evaluation + - x86/speculation/l1tf: Invert all not present mappings + - x86/speculation/l1tf: Make pmd/pud_mknotpresent() invert + - x86/mm/pat: Ensure cpa->pfn only contains page frame numbers + - SAUCE: Add pfn_pud() and pud_mkhuge() + - x86/mm/pat: Make set_memory_np() L1TF safe - -- Khalid Elmously Wed, 01 Aug 2018 02:08:11 -0400 + -- Stefan Bader Wed, 08 Aug 2018 12:04:38 +0200 linux (4.4.0-131.157) xenial; urgency=medium diff -u linux-lts-xenial-4.4.0/debian.xenial/config/config.common.ubuntu linux-lts-xenial-4.4.0/debian.xenial/config/config.common.ubuntu --- linux-lts-xenial-4.4.0/debian.xenial/config/config.common.ubuntu +++ linux-lts-xenial-4.4.0/debian.xenial/config/config.common.ubuntu @@ -1121,7 +1121,6 @@ CONFIG_CCW=y CONFIG_CCWGROUP=m CONFIG_CCW_CONSOLE=y -CONFIG_CC_OPTIMIZE_FOR_PERFORMANCE=y # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set # CONFIG_CC_STACKPROTECTOR_NONE is not set CONFIG_CC_STACKPROTECTOR_REGULAR=y @@ -3153,6 +3152,7 @@ CONFIG_HOTPLUG_PCI_RPA=m CONFIG_HOTPLUG_PCI_RPA_DLPAR=m CONFIG_HOTPLUG_PCI_S390=y +CONFIG_HOTPLUG_SMT=y CONFIG_HP100=m CONFIG_HPET_EMULATE_RTC=y CONFIG_HPET_MMAP=y diff -u linux-lts-xenial-4.4.0/debian/changelog linux-lts-xenial-4.4.0/debian/changelog --- linux-lts-xenial-4.4.0/debian/changelog +++ linux-lts-xenial-4.4.0/debian/changelog @@ -1,319 +1,100 @@ -linux-lts-xenial (4.4.0-132.158~14.04.1) trusty; urgency=medium +linux-lts-xenial (4.4.0-133.159~14.04.1) trusty; urgency=medium - * linux-lts-xenial: 4.4.0-132.158~14.04.1 -proposed tracker (LP: #1784304) + * CVE-2018-5390 + - tcp: avoid collapses in tcp_prune_queue() if possible + - tcp: detect malicious patterns in tcp_collapse_ofo_queue() - * linux: 4.4.0-132.158 -proposed tracker (LP: #1784302) + * CVE-2018-5391 + - Revert "net: increase fragment memory usage limits" - * locking sockets broken due to missing AppArmor socket mediation patches - (LP: #1780227) - - UBUNTU SAUCE: apparmor: fix apparmor mediating locking non-fs, unix sockets - - * Backport namespaced fscaps to xenial 4.4 (LP: #1778286) - - Introduce v3 namespaced file capabilities - - commoncap: move assignment of fs_ns to avoid null pointer dereference - - capabilities: fix buffer overread on very short xattr - - commoncap: Handle memory allocation failure. - - * Xenial update to 4.4.140 stable release (LP: #1784409) - - usb: cdc_acm: Add quirk for Uniden UBC125 scanner - - USB: serial: cp210x: add CESINEL device ids - - USB: serial: cp210x: add Silicon Labs IDs for Windows Update - - n_tty: Fix stall at n_tty_receive_char_special(). - - staging: android: ion: Return an ERR_PTR in ion_map_kernel - - n_tty: Access echo_* variables carefully. - - x86/boot: Fix early command-line parsing when matching at end - - ath10k: fix rfc1042 header retrieval in QCA4019 with eth decap mode - - i2c: rcar: fix resume by always initializing registers before transfer - - ipv4: Fix error return value in fib_convert_metrics() - - kprobes/x86: Do not modify singlestep buffer while resuming - - nvme-pci: initialize queue memory before interrupts - - netfilter: nf_tables: use WARN_ON_ONCE instead of BUG_ON in nft_do_chain() - - ARM: dts: imx6q: Use correct SDMA script for SPI5 core - - ubi: fastmap: Correctly handle interrupted erasures in EBA - - mm: hugetlb: yield when prepping struct pages - - tracing: Fix missing return symbol in function_graph output - - scsi: sg: mitigate read/write abuse - - s390: Correct register corruption in critical section cleanup - - drbd: fix access after free - - cifs: Fix infinite loop when using hard mount option - - jbd2: don't mark block as modified if the handle is out of credits - - ext4: make sure bitmaps and the inode table don't overlap with bg - descriptors - - ext4: always check block group bounds in ext4_init_block_bitmap() - - ext4: only look at the bg_flags field if it is valid - - ext4: verify the depth of extent tree in ext4_find_extent() - - ext4: include the illegal physical block in the bad map ext4_error msg - - ext4: clear i_data in ext4_inode_info when removing inline data - - ext4: add more inode number paranoia checks - - ext4: add more mount time checks of the superblock - - ext4: check superblock mapped prior to committing - - HID: i2c-hid: Fix "incomplete report" noise - - HID: hiddev: fix potential Spectre v1 - - HID: debug: check length before copy_to_user() - - x86/mce: Detect local MCEs properly - - x86/mce: Fix incorrect "Machine check from unknown source" message - - media: cx25840: Use subdev host data for PLL override - - mm, page_alloc: do not break __GFP_THISNODE by zonelist reset - - dm bufio: avoid sleeping while holding the dm_bufio lock - - dm bufio: drop the lock when doing GFP_NOIO allocation - - mtd: rawnand: mxc: set spare area size register explicitly - - dm bufio: don't take the lock in dm_bufio_shrink_count - - mtd: cfi_cmdset_0002: Change definition naming to retry write operation - - mtd: cfi_cmdset_0002: Change erase functions to retry for error - - mtd: cfi_cmdset_0002: Change erase functions to check chip good only - - netfilter: nf_log: don't hold nf_log_mutex during user access - - staging: comedi: quatech_daqp_cs: fix no-op loop daqp_ao_insn_write() - - Linux 4.4.140 - - * Xenial update to 4.4.139 stable release (LP: #1784382) - - xfrm6: avoid potential infinite loop in _decode_session6() - - netfilter: ebtables: handle string from userspace with care - - ipvs: fix buffer overflow with sync daemon and service - - atm: zatm: fix memcmp casting - - net: qmi_wwan: Add Netgear Aircard 779S - - net/sonic: Use dma_mapping_error() - - Revert "Btrfs: fix scrub to repair raid6 corruption" - - tcp: do not overshoot window_clamp in tcp_rcv_space_adjust() - - Btrfs: make raid6 rebuild retry more - - usb: musb: fix remote wakeup racing with suspend - - bonding: re-evaluate force_primary when the primary slave name changes - - tcp: verify the checksum of the first data segment in a new connection - - ext4: update mtime in ext4_punch_hole even if no blocks are released - - ext4: fix fencepost error in check for inode count overflow during resize - - driver core: Don't ignore class_dir_create_and_add() failure. - - btrfs: scrub: Don't use inode pages for device replace - - ALSA: hda - Handle kzalloc() failure in snd_hda_attach_pcm_stream() - - ALSA: hda: add dock and led support for HP EliteBook 830 G5 - - ALSA: hda: add dock and led support for HP ProBook 640 G4 - - cpufreq: Fix new policy initialization during limits updates via sysfs - - libata: zpodd: make arrays cdb static, reduces object code size - - libata: zpodd: small read overflow in eject_tray() - - libata: Drop SanDisk SD7UB3Q*G1001 NOLPM quirk - - w1: mxc_w1: Enable clock before calling clk_get_rate() on it - - x86/spectre_v1: Disable compiler optimizations over - array_index_mask_nospec() - - m68k/mm: Adjust VM area to be unmapped by gap size for __iounmap() - - serial: sh-sci: Use spin_{try}lock_irqsave instead of open coding version - - signal/xtensa: Consistenly use SIGBUS in do_unaligned_user - - usb: do not reset if a low-speed or full-speed device timed out - - 1wire: family module autoload fails because of upper/lower case mismatch. - - ASoC: dapm: delete dapm_kcontrol_data paths list before freeing it - - ASoC: cirrus: i2s: Fix LRCLK configuration - - ASoC: cirrus: i2s: Fix {TX|RX}LinCtrlData setup - - lib/vsprintf: Remove atomic-unsafe support for %pCr - - mips: ftrace: fix static function graph tracing - - branch-check: fix long->int truncation when profiling branches - - ipmi:bt: Set the timeout before doing a capabilities check - - Bluetooth: hci_qca: Avoid missing rampatch failure with userspace fw loader - - fuse: atomic_o_trunc should truncate pagecache - - fuse: don't keep dead fuse_conn at fuse_fill_super(). - - fuse: fix control dir setup and teardown - - powerpc/mm/hash: Add missing isync prior to kernel stack SLB switch - - powerpc/ptrace: Fix setting 512B aligned breakpoints with - PTRACE_SET_DEBUGREG - - powerpc/ptrace: Fix enforcement of DAWR constraints - - cpuidle: powernv: Fix promotion from snooze if next state disabled - - powerpc/fadump: Unregister fadump on kexec down path. - - ARM: 8764/1: kgdb: fix NUMREGBYTES so that gdb_regs[] is the correct size - - of: unittest: for strings, account for trailing \0 in property length field - - IB/qib: Fix DMA api warning with debug kernel - - RDMA/mlx4: Discard unknown SQP work requests - - mtd: cfi_cmdset_0002: Change write buffer to check correct value - - mtd: cfi_cmdset_0002: Use right chip in do_ppb_xxlock() - - mtd: cfi_cmdset_0002: fix SEGV unlocking multiple chips - - mtd: cfi_cmdset_0002: Fix unlocking requests crossing a chip boudary - - mtd: cfi_cmdset_0002: Avoid walking all chips when unlocking. - - MIPS: BCM47XX: Enable 74K Core ExternalSync for PCIe erratum - - PCI: pciehp: Clear Presence Detect and Data Link Layer Status Changed on - resume - - MIPS: io: Add barrier after register read in inX() - - time: Make sure jiffies_to_msecs() preserves non-zero time periods - - Btrfs: fix clone vs chattr NODATASUM race - - iio:buffer: make length types match kfifo types - - scsi: qla2xxx: Fix setting lower transfer speed if GPSC fails - - scsi: zfcp: fix missing SCSI trace for result of eh_host_reset_handler - - scsi: zfcp: fix missing SCSI trace for retry of abort / scsi_eh TMF - - scsi: zfcp: fix misleading REC trigger trace where erp_action setup failed - - scsi: zfcp: fix missing REC trigger trace on terminate_rport_io early return - - scsi: zfcp: fix missing REC trigger trace on terminate_rport_io for - ERP_FAILED - - scsi: zfcp: fix missing REC trigger trace for all objects in ERP_FAILED - - scsi: zfcp: fix missing REC trigger trace on enqueue without ERP thread - - linvdimm, pmem: Preserve read-only setting for pmem devices - - md: fix two problems with setting the "re-add" device state. - - ubi: fastmap: Cancel work upon detach - - UBIFS: Fix potential integer overflow in allocation - - xfrm: skip policies marked as dead while rehashing - - backlight: as3711_bl: Fix Device Tree node lookup - - backlight: max8925_bl: Fix Device Tree node lookup - - backlight: tps65217_bl: Fix Device Tree node lookup - - mfd: intel-lpss: Program REMAP register in PIO mode - - perf tools: Fix symbol and object code resolution for vdso32 and vdsox32 - - perf intel-pt: Fix sync_switch INTEL_PT_SS_NOT_TRACING - - perf intel-pt: Fix decoding to accept CBR between FUP and corresponding TIP - - perf intel-pt: Fix MTC timing after overflow - - perf intel-pt: Fix "Unexpected indirect branch" error - - perf intel-pt: Fix packet decoding of CYC packets - - media: v4l2-compat-ioctl32: prevent go past max size - - media: dvb_frontend: fix locking issues at dvb_frontend_get_event() - - nfsd: restrict rd_maxcount to svc_max_payload in nfsd_encode_readdir - - NFSv4: Fix possible 1-byte stack overflow in - nfs_idmap_read_and_verify_message - - video: uvesafb: Fix integer overflow in allocation - - Input: elan_i2c - add ELAN0618 (Lenovo v330 15IKB) ACPI ID - - xen: Remove unnecessary BUG_ON from __unbind_from_irq() - - udf: Detect incorrect directory size - - Input: elan_i2c_smbus - fix more potential stack buffer overflows - - Input: elantech - enable middle button of touchpads on ThinkPad P52 - - Input: elantech - fix V4 report decoding for module with middle key - - ALSA: hda/realtek - Add a quirk for FSC ESPRIMO U9210 - - Btrfs: fix unexpected cow in run_delalloc_nocow - - spi: Fix scatterlist elements size in spi_map_buf - - block: Fix transfer when chunk sectors exceeds max - - dm thin: handle running out of data space vs concurrent discard - - cdc_ncm: avoid padding beyond end of skb - - Bluetooth: Fix connection if directed advertising and privacy is used - - Linux 4.4.139 - - * Support AverMedia DVD EZMaker 7 USB video capture dongle (LP: #1620762) // - Xenial update to 4.4.139 stable release (LP: #1784382) - - media: cx231xx: Add support for AverMedia DVD EZMaker 7 - - * vfio/pci: cannot assign a i40e pf device to a vm using vfio-pci - (LP: #1779830) - - vfio/pci: Hide broken INTx support from user - - * Kernel error "task zfs:pid blocked for more than 120 seconds" (LP: #1781364) - - SAUCE: (noup) zfs to 0.6.5.6-0ubuntu25 - - * Allow multiple mounts of zfs datasets (LP: #1759848) - - SAUCE: Allow mounting datasets more than once (LP: #1759848) - - * CVE-2018-12233 - - jfs: Fix inconsistency between memory allocation and ea_buf->max_size - - * Redpine: Observed kernel panic while running wireless tests in regression - mode (LP: #1773410) // Redpine: Observed kernel panic while running soft-ap - tests (LP: #1777850) - - SAUCE: Redpine: improve cancel_hw_scan handling to fix kernel panic - - * [HMS] Upgrades to Support SocketCAN over USB on Dell IoT 300x Gateways - (LP: #1783241) - - SAUCE: (no-up) upgrade IXXAT USB SocketCAN driver - - * CVE-2018-13094 - - xfs: don't call xfs_da_shrink_inode with NULL bp - - * other users' coredumps can be read via setgid directory and killpriv bypass - (LP: #1779923) // CVE-2018-13405 - - Fix up non-directory creation in SGID directories - - * snapcraft.yaml: missing ubuntu-retpoline-extract-one script breaks the build - (LP: #1782116) - - snapcraft.yaml: copy retpoline-extract-one to scripts before build - - * Enable basic support for Solarflare 8000 series NIC (LP: #1783152) - - sfc: make TSO version a per-queue parameter - - sfc: Add PCI ID for Solarflare 8000 series 10/40G NIC - - * Redpine: Observed kernel panic while running wireless regressions tests - (LP: #1777858) - - SAUCE: Redpine: improve kernel thread handling to fix kernel panic - - * Xenial update to 4.4.138 stable release (LP: #1777389) - - x86: Remove unused function cpu_has_ht_siblings() - - x86/cpufeature: Remove unused and seldomly used cpu_has_xx macros - - x86/fpu: Disable AVX when eagerfpu is off - - x86/fpu: Revert ("x86/fpu: Disable AVX when eagerfpu is off") - - x86/fpu: Hard-disable lazy FPU mode - - af_key: Always verify length of provided sadb_key - - x86/crypto, x86/fpu: Remove X86_FEATURE_EAGER_FPU #ifdef from the crc32c - code - - gpio: No NULL owner - - Clarify (and fix) MAX_LFS_FILESIZE macros + * CVE-2018-3620 // CVE-2018-3646 - KVM: x86: introduce linear_{read,write}_system - KVM: x86: pass kvm_vcpu to kvm_read_guest_virt and kvm_write_guest_virt_system - - serial: samsung: fix maxburst parameter for DMA transactions - - vmw_balloon: fixing double free when batching mode is off - kvm: x86: use correct privilege level for sgdt/sidt/fxsave/fxrstor access - - Input: goodix - add new ACPI id for GPD Win 2 touch screen - - crypto: vmx - Remove overly verbose printk from AES init routines - - Linux 4.4.138 - - * Redpine: wifi-ap stopped working after restart (LP: #1773400) - - SAUCE: Redpine: fix soft-ap invisible issue - - * Xenial update to 4.4.137 stable release (LP: #1777063) - - tpm: do not suspend/resume if power stays on - - tpm: self test failure should not cause suspend to fail - - mmap: introduce sane default mmap limits - - mmap: relax file size limit for regular files - - kconfig: Avoid format overflow warning from GCC 8.1 - - xfs: fix incorrect log_flushed on fsync - - drm: set FMODE_UNSIGNED_OFFSET for drm files - - brcmfmac: Fix check for ISO3166 code - - bnx2x: use the right constant - - dccp: don't free ccid2_hc_tx_sock struct in dccp_disconnect() - - enic: set DMA mask to 47 bit - - ip6mr: only set ip6mr_table from setsockopt when ip6mr_new_table succeeds - - ipv4: remove warning in ip_recv_error - - isdn: eicon: fix a missing-check bug - - netdev-FAQ: clarify DaveM's position for stable backports - - net/packet: refine check for priv area size - - net: usb: cdc_mbim: add flag FLAG_SEND_ZLP - - packet: fix reserve calculation - - qed: Fix mask for physical address in ILT entry - - net/mlx4: Fix irq-unsafe spinlock usage - - team: use netdev_features_t instead of u32 - - rtnetlink: validate attributes in do_setlink() - - net: phy: broadcom: Fix bcm_write_exp() - - net: metrics: add proper netlink validation - - Linux 4.4.137 - - * Xenial update to 4.4.136 stable release (LP: #1776177) - - arm64: lse: Add early clobbers to some input/output asm operands - - powerpc/64s: Clear PCR on boot - - USB: serial: cp210x: use tcflag_t to fix incompatible pointer type - - sh: New gcc support - - xfs: detect agfl count corruption and reset agfl - - Input: elan_i2c_smbus - fix corrupted stack - - tracing: Fix crash when freeing instances with event triggers - - selinux: KASAN: slab-out-of-bounds in xattr_getsecurity - - cfg80211: further limit wiphy names to 64 bytes - - rtlwifi: rtl8192cu: Remove variable self-assignment in rf.c - - ASoC: Intel: sst: remove redundant variable dma_dev_name - - irda: fix overly long udelay() - - tcp: avoid integer overflows in tcp_rcv_space_adjust() - - i2c: rcar: make sure clocks are on when doing clock calculation - - i2c: rcar: rework hw init - - i2c: rcar: remove unused IOERROR state - - i2c: rcar: remove spinlock - - i2c: rcar: refactor setup of a msg - - i2c: rcar: init new messages in irq - - i2c: rcar: don't issue stop when HW does it automatically - - i2c: rcar: check master irqs before slave irqs - - i2c: rcar: revoke START request early - - dmaengine: usb-dmac: fix endless loop in usb_dmac_chan_terminate_all() - - iio:kfifo_buf: check for uint overflow - - MIPS: ptrace: Fix PTRACE_PEEKUSR requests for 64-bit FGRs - - MIPS: prctl: Disallow FRE without FR with PR_SET_FP_MODE requests - - scsi: scsi_transport_srp: Fix shost to rport translation - - stm class: Use vmalloc for the master map - - hwtracing: stm: fix build error on some arches - - drm/i915: Disable LVDS on Radiant P845 - - Kbuild: change CC_OPTIMIZE_FOR_SIZE definition - - [Config] Add CONFIG_CC_OPTIMIZE_FOR_PERFORMANCE=y - - fix io_destroy()/aio_complete() race - - mm: fix the NULL mapping case in __isolate_lru_page() - - sparc64: Fix build warnings with gcc 7. - - Linux 4.4.136 - - * Xenial update to 4.4.135 stable release (LP: #1776158) - - Revert "vti4: Don't override MTU passed on link creation via IFLA_MTU" - - Linux 4.4.135 + - x86/speculation/l1tf: Increase 32bit PAE __PHYSICAL_PAGE_SHIFT + - x86/speculation/l1tf: Change order of offset/type in swap entry + - x86/speculation/l1tf: Protect swap entries against L1TF + - x86/mm: Simplify p[g4um]d_page() macros + - x86/speculation/l1tf: Protect PROT_NONE PTEs against speculation + - x86/speculation/l1tf: Make sure the first page is always reserved + - SAUCE: x86/cpu: Add Knights Mill/Gemini Lake + - x86/speculation/l1tf: Add sysfs reporting for l1tf + - x86/speculation/l1tf: Disallow non privileged high MMIO PROT_NONE mappings + - x86/speculation/l1tf: Limit swap file size to MAX_PA/2 + - x86/smp: Provide topology_is_primary_thread() + - x86/topology: Provide topology_smt_supported() + - cpu/hotplug: Split do_cpu_down() + - x86/topology: Add topology_max_smt_threads() + - cpu/hotplug: Provide knobs to control SMT + - x86/CPU: Modify detect_extended_topology() to return result + - x86/cpu: Remove the pointless CPU printout + - x86/cpu/AMD: Remove the pointless detect_ht() call + - x86/cpu/common: Provide detect_ht_early() + - x86/cpu/topology: Provide detect_extended_topology_early() + - x86/cpu/intel: Evaluate smp_num_siblings early + - x86/cpu/AMD: Evaluate smp_num_siblings early + - x86/apic: Ignore secondary threads if nosmt=force + - x86/speculation/l1tf: Extend 64bit swap file size limit + - x86/CPU/AMD: Move TOPOEXT reenablement before reading smp_num_siblings + - x86/cpufeatures: Add detection of L1D cache flush support. + - x86/speculation/l1tf: Protect PAE swap entries against L1TF + - x86/speculation/l1tf: Fix up pte->pfn conversion for PAE + - Revert "x86/apic: Ignore secondary threads if nosmt=force" + - SAUCE: x86/mce: register mce notifier earlier + - cpu/hotplug: Boot HT siblings at least once + - KVM: x86: Introducing kvm_x86_ops VM init/destroy hooks + - x86/KVM: Warn user if KVM is loaded SMT and L1TF CPU bug being present. + - x86/KVM/VMX: Add module argument for L1TF mitigation + - x86/KVM/VMX: Add L1D flush algorithm + - x86/KVM/VMX: Add L1D MSR based flush + - x86/KVM/VMX: Add L1D flush logic + - x86/KVM/VMX: Split the VMX MSR LOAD structures to have an host/guest numbers + - x86/KVM/VMX: Add find_msr() helper function + - x86/KVM/VMX: Seperate the VMX AUTOLOAD guest/host number accounting. + - x86/KVM/VMX: Extend add_atomic_switch_msr() to allow VMENTER only MSRs + - x86/KVM/VMX: Use MSR save list for IA32_FLUSH_CMD if required + - cpu/hotplug: Online siblings when SMT control is turned on + - x86/litf: Introduce vmx status variable + - x86/kvm: Drop L1TF MSR list approach + - x86/l1tf: Handle EPT disabled state proper + - x86/kvm: Move l1tf setup function + - x86/kvm: Add static key for flush always + - x86/kvm: Serialize L1D flush parameter setter + - x86/kvm: Allow runtime control of L1D flush + - cpu/hotplug: Expose SMT control init function + - cpu/hotplug: Set CPU_SMT_NOT_SUPPORTED early + - x86/bugs, kvm: Introduce boot-time control of L1TF mitigations + - Documentation: Add section about CPU vulnerabilities + - x86/speculation/l1tf: Unbreak !__HAVE_ARCH_PFN_MODIFY_ALLOWED architectures + - x86/KVM/VMX: Initialize the vmx_l1d_flush_pages' content + - Documentation/l1tf: Fix typos + - cpu/hotplug: detect SMT disabled by BIOS + - x86/KVM/VMX: Don't set l1tf_flush_l1d to true from vmx_l1d_flush() + - x86/KVM/VMX: Replace 'vmx_l1d_flush_always' with 'vmx_l1d_flush_cond' + - x86/KVM/VMX: Move the l1tf_flush_l1d test to vmx_l1d_flush() + - x86/irq: Demote irq_cpustat_t::__softirq_pending to u16 + - x86/KVM/VMX: Introduce per-host-cpu analogue of l1tf_flush_l1d + - x86: Don't include linux/irq.h from asm/hardirq.h + - x86/apic: Order irq_enter/exit() calls correctly vs. ack_APIC_irq() + - x86/irq: Let interrupt handlers set kvm_cpu_l1tf_flush_l1d + - x86/KVM/VMX: Don't set l1tf_flush_l1d from vmx_handle_external_intr() + - Documentation/l1tf: Remove Yonah processors from not vulnerable list + - x86/speculation: Simplify sysfs report of VMX L1TF vulnerability + - x86/speculation: Use ARCH_CAPABILITIES to skip L1D flush on vmentry + - KVM/VMX: Emulate MSR_IA32_ARCH_CAPABILITIES + - KVM: x86: Add a framework for supporting MSR-based features + - KVM: X86: Introduce kvm_get_msr_feature() + - KVM: VMX: support MSR_IA32_ARCH_CAPABILITIES as a feature MSR + - KVM: VMX: Tell the nested hypervisor to skip L1D flush on vmentry + - cpu/hotplug: Fix SMT supported evaluation + - x86/speculation/l1tf: Invert all not present mappings + - x86/speculation/l1tf: Make pmd/pud_mknotpresent() invert + - x86/mm/pat: Ensure cpa->pfn only contains page frame numbers + - SAUCE: Add pfn_pud() and pud_mkhuge() + - x86/mm/pat: Make set_memory_np() L1TF safe - -- Khalid Elmously Wed, 01 Aug 2018 02:08:11 -0400 + -- Stefan Bader Wed, 08 Aug 2018 12:04:38 +0200 linux (4.4.0-131.157) xenial; urgency=medium diff -u linux-lts-xenial-4.4.0/debian/control linux-lts-xenial-4.4.0/debian/control --- linux-lts-xenial-4.4.0/debian/control +++ linux-lts-xenial-4.4.0/debian/control @@ -46,7 +46,7 @@ XS-Testsuite: autopkgtest #XS-Testsuite-Depends: gcc-4.7 binutils -Package: linux-headers-4.4.0-132 +Package: linux-headers-4.4.0-133 Architecture: all Multi-Arch: foreign Section: devel @@ -56,40 +56,40 @@ Description: Header files related to Linux kernel version 4.4.0 This package provides kernel header files for version 4.4.0, for sites that want the latest kernel headers. Please read - /usr/share/doc/linux-lts-xenial-headers-4.4.0-132/debian.README.gz for details + /usr/share/doc/linux-lts-xenial-headers-4.4.0-133/debian.README.gz for details -Package: linux-lts-xenial-tools-4.4.0-132 +Package: linux-lts-xenial-tools-4.4.0-133 Architecture: i386 amd64 armhf arm64 powerpc ppc64el s390x Section: devel Priority: optional Depends: ${misc:Depends}, ${shlibs:Depends}, linux-tools-common -Description: Linux kernel version specific tools for version 4.4.0-132 +Description: Linux kernel version specific tools for version 4.4.0-133 This package provides the architecture dependant parts for kernel version locked tools (such as perf and x86_energy_perf_policy) for - version 4.4.0-132 on + version 4.4.0-133 on 64 bit x86. - You probably want to install linux-tools-4.4.0-132-. + You probably want to install linux-tools-4.4.0-133-. -Package: linux-lts-xenial-cloud-tools-4.4.0-132 +Package: linux-lts-xenial-cloud-tools-4.4.0-133 Architecture: i386 amd64 armhf Section: devel Priority: optional Depends: ${misc:Depends}, ${shlibs:Depends}, linux-cloud-tools-common -Description: Linux kernel version specific cloud tools for version 4.4.0-132 +Description: Linux kernel version specific cloud tools for version 4.4.0-133 This package provides the architecture dependant parts for kernel - version locked tools for cloud tools for version 4.4.0-132 on + version locked tools for cloud tools for version 4.4.0-133 on 64 bit x86. - You probably want to install linux-cloud-tools-4.4.0-132-. + You probably want to install linux-cloud-tools-4.4.0-133-. -Package: linux-image-4.4.0-132-generic +Package: linux-image-4.4.0-133-generic Architecture: i386 amd64 armhf arm64 ppc64el s390x Section: kernel Priority: optional Provides: linux-image, fuse-module, kvm-api-4, redhat-cluster-modules, ivtv-modules, virtualbox-guest-modules [i386 amd64 x32]${linux:rprovides} Depends: ${misc:Depends}, ${shlibs:Depends}, initramfs-tools | linux-initramfs-tool, kmod Recommends: grub-pc [i386 amd64 x32] | grub-efi-amd64 [amd64 x32] | grub-efi-ia32 [i386 amd64 x32] | grub [i386 amd64 x32] | lilo [i386 amd64 x32] | flash-kernel [armhf arm64] | grub-ieee1275 [ppc64el] -Suggests: fdutils, linux-lts-xenial-tools, linux-headers-4.4.0-132-generic +Suggests: fdutils, linux-lts-xenial-tools, linux-headers-4.4.0-133-generic Description: Linux kernel image for version 4.4.0 on 64 bit x86 SMP This package contains the Linux kernel image for version 4.4.0 on 64 bit x86 SMP. @@ -106,11 +106,11 @@ the linux-generic meta-package, which will ensure that upgrades work correctly, and that supporting packages are also installed. -Package: linux-image-extra-4.4.0-132-generic +Package: linux-image-extra-4.4.0-133-generic Architecture: i386 amd64 armhf arm64 ppc64el s390x Section: kernel Priority: optional -Depends: ${misc:Depends}, ${shlibs:Depends}, linux-image-4.4.0-132-generic, crda | wireless-crda +Depends: ${misc:Depends}, ${shlibs:Depends}, linux-image-4.4.0-133-generic, crda | wireless-crda Description: Linux kernel extra modules for version 4.4.0 on 64 bit x86 SMP This package contains the Linux kernel extra modules for version 4.4.0 on 64 bit x86 SMP. @@ -127,20 +127,20 @@ the linux-generic meta-package, which will ensure that upgrades work correctly, and that supporting packages are also installed. -Package: linux-headers-4.4.0-132-generic +Package: linux-headers-4.4.0-133-generic Architecture: i386 amd64 armhf arm64 ppc64el s390x Section: devel Priority: optional -Depends: ${misc:Depends}, linux-headers-4.4.0-132, ${shlibs:Depends} +Depends: ${misc:Depends}, linux-headers-4.4.0-133, ${shlibs:Depends} Provides: linux-headers, linux-headers-3.0 Description: Linux kernel headers for version 4.4.0 on 64 bit x86 SMP This package provides kernel header files for version 4.4.0 on 64 bit x86 SMP. . This is for sites that want the latest kernel headers. Please read - /usr/share/doc/linux-headers-4.4.0-132/debian.README.gz for details. + /usr/share/doc/linux-headers-4.4.0-133/debian.README.gz for details. -Package: linux-image-4.4.0-132-generic-dbgsym +Package: linux-image-4.4.0-133-generic-dbgsym Architecture: i386 amd64 armhf arm64 ppc64el s390x Section: devel Priority: optional @@ -156,25 +156,25 @@ is uncompressed, and unstripped. This package also includes the unstripped modules. -Package: linux-tools-4.4.0-132-generic +Package: linux-tools-4.4.0-133-generic Architecture: i386 amd64 armhf arm64 ppc64el s390x Section: devel Priority: optional -Depends: ${misc:Depends}, linux-lts-xenial-tools-4.4.0-132 -Description: Linux kernel version specific tools for version 4.4.0-132 +Depends: ${misc:Depends}, linux-lts-xenial-tools-4.4.0-133 +Description: Linux kernel version specific tools for version 4.4.0-133 This package provides the architecture dependant parts for kernel version locked tools (such as perf and x86_energy_perf_policy) for - version 4.4.0-132 on + version 4.4.0-133 on 64 bit x86. -Package: linux-cloud-tools-4.4.0-132-generic +Package: linux-cloud-tools-4.4.0-133-generic Architecture: i386 amd64 armhf arm64 ppc64el s390x Section: devel Priority: optional -Depends: ${misc:Depends}, linux-lts-xenial-cloud-tools-4.4.0-132 -Description: Linux kernel version specific cloud tools for version 4.4.0-132 +Depends: ${misc:Depends}, linux-lts-xenial-cloud-tools-4.4.0-133 +Description: Linux kernel version specific cloud tools for version 4.4.0-133 This package provides the architecture dependant parts for kernel - version locked tools for cloud for version 4.4.0-132 on + version locked tools for cloud for version 4.4.0-133 on 64 bit x86. Package: linux-lts-xenial-udebs-generic @@ -187,14 +187,14 @@ for easier version and migration tracking. -Package: linux-image-4.4.0-132-generic-lpae +Package: linux-image-4.4.0-133-generic-lpae Architecture: armhf Section: kernel Priority: optional Provides: linux-image, fuse-module, kvm-api-4, redhat-cluster-modules, ivtv-modules${linux:rprovides} Depends: ${misc:Depends}, ${shlibs:Depends}, initramfs-tools | linux-initramfs-tool, kmod Recommends: flash-kernel [armhf] -Suggests: fdutils, linux-lts-xenial-tools, linux-headers-4.4.0-132-generic-lpae +Suggests: fdutils, linux-lts-xenial-tools, linux-headers-4.4.0-133-generic-lpae Description: Linux kernel image for version 4.4.0 on 64 bit x86 SMP This package contains the Linux kernel image for version 4.4.0 on 64 bit x86 SMP. @@ -211,11 +211,11 @@ the linux-generic-lpae meta-package, which will ensure that upgrades work correctly, and that supporting packages are also installed. -Package: linux-image-extra-4.4.0-132-generic-lpae +Package: linux-image-extra-4.4.0-133-generic-lpae Architecture: armhf Section: kernel Priority: optional -Depends: ${misc:Depends}, ${shlibs:Depends}, linux-image-4.4.0-132-generic-lpae, crda | wireless-crda +Depends: ${misc:Depends}, ${shlibs:Depends}, linux-image-4.4.0-133-generic-lpae, crda | wireless-crda Description: Linux kernel extra modules for version 4.4.0 on 64 bit x86 SMP This package contains the Linux kernel extra modules for version 4.4.0 on 64 bit x86 SMP. @@ -232,20 +232,20 @@ the linux-generic-lpae meta-package, which will ensure that upgrades work correctly, and that supporting packages are also installed. -Package: linux-headers-4.4.0-132-generic-lpae +Package: linux-headers-4.4.0-133-generic-lpae Architecture: armhf Section: devel Priority: optional -Depends: ${misc:Depends}, linux-headers-4.4.0-132, ${shlibs:Depends} +Depends: ${misc:Depends}, linux-headers-4.4.0-133, ${shlibs:Depends} Provides: linux-headers, linux-headers-3.0 Description: Linux kernel headers for version 4.4.0 on 64 bit x86 SMP This package provides kernel header files for version 4.4.0 on 64 bit x86 SMP. . This is for sites that want the latest kernel headers. Please read - /usr/share/doc/linux-headers-4.4.0-132/debian.README.gz for details. + /usr/share/doc/linux-headers-4.4.0-133/debian.README.gz for details. -Package: linux-image-4.4.0-132-generic-lpae-dbgsym +Package: linux-image-4.4.0-133-generic-lpae-dbgsym Architecture: armhf Section: devel Priority: optional @@ -261,25 +261,25 @@ is uncompressed, and unstripped. This package also includes the unstripped modules. -Package: linux-tools-4.4.0-132-generic-lpae +Package: linux-tools-4.4.0-133-generic-lpae Architecture: armhf Section: devel Priority: optional -Depends: ${misc:Depends}, linux-lts-xenial-tools-4.4.0-132 -Description: Linux kernel version specific tools for version 4.4.0-132 +Depends: ${misc:Depends}, linux-lts-xenial-tools-4.4.0-133 +Description: Linux kernel version specific tools for version 4.4.0-133 This package provides the architecture dependant parts for kernel version locked tools (such as perf and x86_energy_perf_policy) for - version 4.4.0-132 on + version 4.4.0-133 on 64 bit x86. -Package: linux-cloud-tools-4.4.0-132-generic-lpae +Package: linux-cloud-tools-4.4.0-133-generic-lpae Architecture: armhf Section: devel Priority: optional -Depends: ${misc:Depends}, linux-lts-xenial-cloud-tools-4.4.0-132 -Description: Linux kernel version specific cloud tools for version 4.4.0-132 +Depends: ${misc:Depends}, linux-lts-xenial-cloud-tools-4.4.0-133 +Description: Linux kernel version specific cloud tools for version 4.4.0-133 This package provides the architecture dependant parts for kernel - version locked tools for cloud for version 4.4.0-132 on + version locked tools for cloud for version 4.4.0-133 on 64 bit x86. Package: linux-lts-xenial-udebs-generic-lpae @@ -292,14 +292,14 @@ for easier version and migration tracking. -Package: linux-image-4.4.0-132-lowlatency +Package: linux-image-4.4.0-133-lowlatency Architecture: i386 amd64 Section: kernel Priority: optional Provides: linux-image, fuse-module, kvm-api-4, redhat-cluster-modules, ivtv-modules, virtualbox-guest-modules [i386 amd64 x32]${linux:rprovides} Depends: ${misc:Depends}, ${shlibs:Depends}, initramfs-tools | linux-initramfs-tool, kmod Recommends: grub-pc [i386 amd64 x32] | grub-efi-amd64 [amd64 x32] | grub-efi-ia32 [i386 amd64 x32] | grub [i386 amd64 x32] | lilo [i386 amd64 x32] | flash-kernel [armhf arm64] -Suggests: fdutils, linux-lts-xenial-tools, linux-headers-4.4.0-132-lowlatency +Suggests: fdutils, linux-lts-xenial-tools, linux-headers-4.4.0-133-lowlatency Description: Linux kernel image for version 4.4.0 on 64 bit x86 SMP This package contains the Linux kernel image for version 4.4.0 on 64 bit x86 SMP. @@ -316,11 +316,11 @@ the linux-lowlatency meta-package, which will ensure that upgrades work correctly, and that supporting packages are also installed. -Package: linux-image-extra-4.4.0-132-lowlatency +Package: linux-image-extra-4.4.0-133-lowlatency Architecture: i386 amd64 Section: kernel Priority: optional -Depends: ${misc:Depends}, ${shlibs:Depends}, linux-image-4.4.0-132-lowlatency, crda | wireless-crda +Depends: ${misc:Depends}, ${shlibs:Depends}, linux-image-4.4.0-133-lowlatency, crda | wireless-crda Description: Linux kernel extra modules for version 4.4.0 on 64 bit x86 SMP This package contains the Linux kernel extra modules for version 4.4.0 on 64 bit x86 SMP. @@ -337,20 +337,20 @@ the linux-lowlatency meta-package, which will ensure that upgrades work correctly, and that supporting packages are also installed. -Package: linux-headers-4.4.0-132-lowlatency +Package: linux-headers-4.4.0-133-lowlatency Architecture: i386 amd64 Section: devel Priority: optional -Depends: ${misc:Depends}, linux-headers-4.4.0-132, ${shlibs:Depends} +Depends: ${misc:Depends}, linux-headers-4.4.0-133, ${shlibs:Depends} Provides: linux-headers, linux-headers-3.0 Description: Linux kernel headers for version 4.4.0 on 64 bit x86 SMP This package provides kernel header files for version 4.4.0 on 64 bit x86 SMP. . This is for sites that want the latest kernel headers. Please read - /usr/share/doc/linux-headers-4.4.0-132/debian.README.gz for details. + /usr/share/doc/linux-headers-4.4.0-133/debian.README.gz for details. -Package: linux-image-4.4.0-132-lowlatency-dbgsym +Package: linux-image-4.4.0-133-lowlatency-dbgsym Architecture: i386 amd64 Section: devel Priority: optional @@ -366,25 +366,25 @@ is uncompressed, and unstripped. This package also includes the unstripped modules. -Package: linux-tools-4.4.0-132-lowlatency +Package: linux-tools-4.4.0-133-lowlatency Architecture: i386 amd64 Section: devel Priority: optional -Depends: ${misc:Depends}, linux-lts-xenial-tools-4.4.0-132 -Description: Linux kernel version specific tools for version 4.4.0-132 +Depends: ${misc:Depends}, linux-lts-xenial-tools-4.4.0-133 +Description: Linux kernel version specific tools for version 4.4.0-133 This package provides the architecture dependant parts for kernel version locked tools (such as perf and x86_energy_perf_policy) for - version 4.4.0-132 on + version 4.4.0-133 on 64 bit x86. -Package: linux-cloud-tools-4.4.0-132-lowlatency +Package: linux-cloud-tools-4.4.0-133-lowlatency Architecture: i386 amd64 Section: devel Priority: optional -Depends: ${misc:Depends}, linux-lts-xenial-cloud-tools-4.4.0-132 -Description: Linux kernel version specific cloud tools for version 4.4.0-132 +Depends: ${misc:Depends}, linux-lts-xenial-cloud-tools-4.4.0-133 +Description: Linux kernel version specific cloud tools for version 4.4.0-133 This package provides the architecture dependant parts for kernel - version locked tools for cloud for version 4.4.0-132 on + version locked tools for cloud for version 4.4.0-133 on 64 bit x86. Package: linux-lts-xenial-udebs-lowlatency @@ -397,14 +397,14 @@ for easier version and migration tracking. -Package: linux-image-4.4.0-132-powerpc-e500mc +Package: linux-image-4.4.0-133-powerpc-e500mc Architecture: powerpc Section: kernel Priority: optional Provides: linux-image, fuse-module, redhat-cluster-modules, ivtv-modules${linux:rprovides} Depends: ${misc:Depends}, ${shlibs:Depends}, initramfs-tools | linux-initramfs-tool, kmod Recommends: grub-ieee1275 -Suggests: fdutils, linux-lts-xenial-tools, linux-headers-4.4.0-132-powerpc-e500mc +Suggests: fdutils, linux-lts-xenial-tools, linux-headers-4.4.0-133-powerpc-e500mc Description: Linux kernel image for version 4.4.0 on 32-bit Freescale Power e500mc This package contains the Linux kernel image for version 4.4.0 on 32-bit Freescale Power e500mc. @@ -421,11 +421,11 @@ the linux-powerpc-e500mc meta-package, which will ensure that upgrades work correctly, and that supporting packages are also installed. -Package: linux-image-extra-4.4.0-132-powerpc-e500mc +Package: linux-image-extra-4.4.0-133-powerpc-e500mc Architecture: powerpc Section: kernel Priority: optional -Depends: ${misc:Depends}, ${shlibs:Depends}, linux-image-4.4.0-132-powerpc-e500mc, crda | wireless-crda +Depends: ${misc:Depends}, ${shlibs:Depends}, linux-image-4.4.0-133-powerpc-e500mc, crda | wireless-crda Description: Linux kernel extra modules for version 4.4.0 on 32-bit Freescale Power e500mc This package contains the Linux kernel extra modules for version 4.4.0 on 32-bit Freescale Power e500mc. @@ -442,20 +442,20 @@ the linux-powerpc-e500mc meta-package, which will ensure that upgrades work correctly, and that supporting packages are also installed. -Package: linux-headers-4.4.0-132-powerpc-e500mc +Package: linux-headers-4.4.0-133-powerpc-e500mc Architecture: powerpc Section: devel Priority: optional -Depends: ${misc:Depends}, linux-headers-4.4.0-132, ${shlibs:Depends} +Depends: ${misc:Depends}, linux-headers-4.4.0-133, ${shlibs:Depends} Provides: linux-headers, linux-headers-3.0 Description: Linux kernel headers for version 4.4.0 on 32-bit Freescale Power e500mc This package provides kernel header files for version 4.4.0 on 32-bit Freescale Power e500mc. . This is for sites that want the latest kernel headers. Please read - /usr/share/doc/linux-headers-4.4.0-132/debian.README.gz for details. + /usr/share/doc/linux-headers-4.4.0-133/debian.README.gz for details. -Package: linux-image-4.4.0-132-powerpc-e500mc-dbgsym +Package: linux-image-4.4.0-133-powerpc-e500mc-dbgsym Architecture: powerpc Section: devel Priority: optional @@ -471,25 +471,25 @@ is uncompressed, and unstripped. This package also includes the unstripped modules. -Package: linux-tools-4.4.0-132-powerpc-e500mc +Package: linux-tools-4.4.0-133-powerpc-e500mc Architecture: powerpc Section: devel Priority: optional -Depends: ${misc:Depends}, linux-lts-xenial-tools-4.4.0-132 -Description: Linux kernel version specific tools for version 4.4.0-132 +Depends: ${misc:Depends}, linux-lts-xenial-tools-4.4.0-133 +Description: Linux kernel version specific tools for version 4.4.0-133 This package provides the architecture dependant parts for kernel version locked tools (such as perf and x86_energy_perf_policy) for - version 4.4.0-132 on + version 4.4.0-133 on 64 bit x86. -Package: linux-cloud-tools-4.4.0-132-powerpc-e500mc +Package: linux-cloud-tools-4.4.0-133-powerpc-e500mc Architecture: powerpc Section: devel Priority: optional -Depends: ${misc:Depends}, linux-lts-xenial-cloud-tools-4.4.0-132 -Description: Linux kernel version specific cloud tools for version 4.4.0-132 +Depends: ${misc:Depends}, linux-lts-xenial-cloud-tools-4.4.0-133 +Description: Linux kernel version specific cloud tools for version 4.4.0-133 This package provides the architecture dependant parts for kernel - version locked tools for cloud for version 4.4.0-132 on + version locked tools for cloud for version 4.4.0-133 on 64 bit x86. Package: linux-lts-xenial-udebs-powerpc-e500mc @@ -502,14 +502,14 @@ for easier version and migration tracking. -Package: linux-image-4.4.0-132-powerpc-smp +Package: linux-image-4.4.0-133-powerpc-smp Architecture: powerpc Section: kernel Priority: optional Provides: linux-image, fuse-module, redhat-cluster-modules, ivtv-modules${linux:rprovides} Depends: ${misc:Depends}, ${shlibs:Depends}, initramfs-tools | linux-initramfs-tool, kmod Recommends: yaboot -Suggests: fdutils, linux-lts-xenial-tools, linux-headers-4.4.0-132-powerpc-smp +Suggests: fdutils, linux-lts-xenial-tools, linux-headers-4.4.0-133-powerpc-smp Description: Linux kernel image for version 4.4.0 on 32-bit PowerPC SMP This package contains the Linux kernel image for version 4.4.0 on 32-bit PowerPC SMP. @@ -526,11 +526,11 @@ the linux-powerpc-smp meta-package, which will ensure that upgrades work correctly, and that supporting packages are also installed. -Package: linux-image-extra-4.4.0-132-powerpc-smp +Package: linux-image-extra-4.4.0-133-powerpc-smp Architecture: powerpc Section: kernel Priority: optional -Depends: ${misc:Depends}, ${shlibs:Depends}, linux-image-4.4.0-132-powerpc-smp, crda | wireless-crda +Depends: ${misc:Depends}, ${shlibs:Depends}, linux-image-4.4.0-133-powerpc-smp, crda | wireless-crda Description: Linux kernel extra modules for version 4.4.0 on 32-bit PowerPC SMP This package contains the Linux kernel extra modules for version 4.4.0 on 32-bit PowerPC SMP. @@ -547,20 +547,20 @@ the linux-powerpc-smp meta-package, which will ensure that upgrades work correctly, and that supporting packages are also installed. -Package: linux-headers-4.4.0-132-powerpc-smp +Package: linux-headers-4.4.0-133-powerpc-smp Architecture: powerpc Section: devel Priority: optional -Depends: ${misc:Depends}, linux-headers-4.4.0-132, ${shlibs:Depends} +Depends: ${misc:Depends}, linux-headers-4.4.0-133, ${shlibs:Depends} Provides: linux-headers, linux-headers-3.0 Description: Linux kernel headers for version 4.4.0 on 32-bit PowerPC SMP This package provides kernel header files for version 4.4.0 on 32-bit PowerPC SMP. . This is for sites that want the latest kernel headers. Please read - /usr/share/doc/linux-headers-4.4.0-132/debian.README.gz for details. + /usr/share/doc/linux-headers-4.4.0-133/debian.README.gz for details. -Package: linux-image-4.4.0-132-powerpc-smp-dbgsym +Package: linux-image-4.4.0-133-powerpc-smp-dbgsym Architecture: powerpc Section: devel Priority: optional @@ -576,25 +576,25 @@ is uncompressed, and unstripped. This package also includes the unstripped modules. -Package: linux-tools-4.4.0-132-powerpc-smp +Package: linux-tools-4.4.0-133-powerpc-smp Architecture: powerpc Section: devel Priority: optional -Depends: ${misc:Depends}, linux-lts-xenial-tools-4.4.0-132 -Description: Linux kernel version specific tools for version 4.4.0-132 +Depends: ${misc:Depends}, linux-lts-xenial-tools-4.4.0-133 +Description: Linux kernel version specific tools for version 4.4.0-133 This package provides the architecture dependant parts for kernel version locked tools (such as perf and x86_energy_perf_policy) for - version 4.4.0-132 on + version 4.4.0-133 on 64 bit x86. -Package: linux-cloud-tools-4.4.0-132-powerpc-smp +Package: linux-cloud-tools-4.4.0-133-powerpc-smp Architecture: powerpc Section: devel Priority: optional -Depends: ${misc:Depends}, linux-lts-xenial-cloud-tools-4.4.0-132 -Description: Linux kernel version specific cloud tools for version 4.4.0-132 +Depends: ${misc:Depends}, linux-lts-xenial-cloud-tools-4.4.0-133 +Description: Linux kernel version specific cloud tools for version 4.4.0-133 This package provides the architecture dependant parts for kernel - version locked tools for cloud for version 4.4.0-132 on + version locked tools for cloud for version 4.4.0-133 on 64 bit x86. Package: linux-lts-xenial-udebs-powerpc-smp @@ -607,14 +607,14 @@ for easier version and migration tracking. -Package: linux-image-4.4.0-132-powerpc64-emb +Package: linux-image-4.4.0-133-powerpc64-emb Architecture: powerpc Section: kernel Priority: optional Provides: linux-image, fuse-module, redhat-cluster-modules, ivtv-modules${linux:rprovides} Depends: ${misc:Depends}, ${shlibs:Depends}, initramfs-tools | linux-initramfs-tool, kmod Recommends: grub-ieee1275 -Suggests: fdutils, linux-lts-xenial-tools, linux-headers-4.4.0-132-powerpc64-emb +Suggests: fdutils, linux-lts-xenial-tools, linux-headers-4.4.0-133-powerpc64-emb Description: Linux kernel image for version 4.4.0 on 64-bit PowerPC SMP Book3E This package contains the Linux kernel image for version 4.4.0 on 64-bit PowerPC SMP Book3E. @@ -631,11 +631,11 @@ the linux-powerpc64-emb meta-package, which will ensure that upgrades work correctly, and that supporting packages are also installed. -Package: linux-image-extra-4.4.0-132-powerpc64-emb +Package: linux-image-extra-4.4.0-133-powerpc64-emb Architecture: powerpc Section: kernel Priority: optional -Depends: ${misc:Depends}, ${shlibs:Depends}, linux-image-4.4.0-132-powerpc64-emb, crda | wireless-crda +Depends: ${misc:Depends}, ${shlibs:Depends}, linux-image-4.4.0-133-powerpc64-emb, crda | wireless-crda Description: Linux kernel extra modules for version 4.4.0 on 64-bit PowerPC SMP Book3E This package contains the Linux kernel extra modules for version 4.4.0 on 64-bit PowerPC SMP Book3E. @@ -652,20 +652,20 @@ the linux-powerpc64-emb meta-package, which will ensure that upgrades work correctly, and that supporting packages are also installed. -Package: linux-headers-4.4.0-132-powerpc64-emb +Package: linux-headers-4.4.0-133-powerpc64-emb Architecture: powerpc Section: devel Priority: optional -Depends: ${misc:Depends}, linux-headers-4.4.0-132, ${shlibs:Depends} +Depends: ${misc:Depends}, linux-headers-4.4.0-133, ${shlibs:Depends} Provides: linux-headers, linux-headers-3.0 Description: Linux kernel headers for version 4.4.0 on 64-bit PowerPC SMP Book3E This package provides kernel header files for version 4.4.0 on 64-bit PowerPC SMP Book3E. . This is for sites that want the latest kernel headers. Please read - /usr/share/doc/linux-headers-4.4.0-132/debian.README.gz for details. + /usr/share/doc/linux-headers-4.4.0-133/debian.README.gz for details. -Package: linux-image-4.4.0-132-powerpc64-emb-dbgsym +Package: linux-image-4.4.0-133-powerpc64-emb-dbgsym Architecture: powerpc Section: devel Priority: optional @@ -681,25 +681,25 @@ is uncompressed, and unstripped. This package also includes the unstripped modules. -Package: linux-tools-4.4.0-132-powerpc64-emb +Package: linux-tools-4.4.0-133-powerpc64-emb Architecture: powerpc Section: devel Priority: optional -Depends: ${misc:Depends}, linux-lts-xenial-tools-4.4.0-132 -Description: Linux kernel version specific tools for version 4.4.0-132 +Depends: ${misc:Depends}, linux-lts-xenial-tools-4.4.0-133 +Description: Linux kernel version specific tools for version 4.4.0-133 This package provides the architecture dependant parts for kernel version locked tools (such as perf and x86_energy_perf_policy) for - version 4.4.0-132 on + version 4.4.0-133 on 64 bit x86. -Package: linux-cloud-tools-4.4.0-132-powerpc64-emb +Package: linux-cloud-tools-4.4.0-133-powerpc64-emb Architecture: powerpc Section: devel Priority: optional -Depends: ${misc:Depends}, linux-lts-xenial-cloud-tools-4.4.0-132 -Description: Linux kernel version specific cloud tools for version 4.4.0-132 +Depends: ${misc:Depends}, linux-lts-xenial-cloud-tools-4.4.0-133 +Description: Linux kernel version specific cloud tools for version 4.4.0-133 This package provides the architecture dependant parts for kernel - version locked tools for cloud for version 4.4.0-132 on + version locked tools for cloud for version 4.4.0-133 on 64 bit x86. Package: linux-lts-xenial-udebs-powerpc64-emb @@ -712,14 +712,14 @@ for easier version and migration tracking. -Package: linux-image-4.4.0-132-powerpc64-smp +Package: linux-image-4.4.0-133-powerpc64-smp Architecture: powerpc Section: kernel Priority: optional Provides: linux-image, fuse-module, redhat-cluster-modules, ivtv-modules${linux:rprovides} Depends: ${misc:Depends}, ${shlibs:Depends}, initramfs-tools | linux-initramfs-tool, kmod Recommends: yaboot -Suggests: fdutils, linux-lts-xenial-tools, linux-headers-4.4.0-132-powerpc64-smp +Suggests: fdutils, linux-lts-xenial-tools, linux-headers-4.4.0-133-powerpc64-smp Description: Linux kernel image for version 4.4.0 on 64-bit PowerPC SMP This package contains the Linux kernel image for version 4.4.0 on 64-bit PowerPC SMP. @@ -736,11 +736,11 @@ the linux-powerpc64-smp meta-package, which will ensure that upgrades work correctly, and that supporting packages are also installed. -Package: linux-image-extra-4.4.0-132-powerpc64-smp +Package: linux-image-extra-4.4.0-133-powerpc64-smp Architecture: powerpc Section: kernel Priority: optional -Depends: ${misc:Depends}, ${shlibs:Depends}, linux-image-4.4.0-132-powerpc64-smp, crda | wireless-crda +Depends: ${misc:Depends}, ${shlibs:Depends}, linux-image-4.4.0-133-powerpc64-smp, crda | wireless-crda Description: Linux kernel extra modules for version 4.4.0 on 64-bit PowerPC SMP This package contains the Linux kernel extra modules for version 4.4.0 on 64-bit PowerPC SMP. @@ -757,20 +757,20 @@ the linux-powerpc64-smp meta-package, which will ensure that upgrades work correctly, and that supporting packages are also installed. -Package: linux-headers-4.4.0-132-powerpc64-smp +Package: linux-headers-4.4.0-133-powerpc64-smp Architecture: powerpc Section: devel Priority: optional -Depends: ${misc:Depends}, linux-headers-4.4.0-132, ${shlibs:Depends} +Depends: ${misc:Depends}, linux-headers-4.4.0-133, ${shlibs:Depends} Provides: linux-headers, linux-headers-3.0 Description: Linux kernel headers for version 4.4.0 on 64-bit PowerPC SMP This package provides kernel header files for version 4.4.0 on 64-bit PowerPC SMP. . This is for sites that want the latest kernel headers. Please read - /usr/share/doc/linux-headers-4.4.0-132/debian.README.gz for details. + /usr/share/doc/linux-headers-4.4.0-133/debian.README.gz for details. -Package: linux-image-4.4.0-132-powerpc64-smp-dbgsym +Package: linux-image-4.4.0-133-powerpc64-smp-dbgsym Architecture: powerpc Section: devel Priority: optional @@ -786,25 +786,25 @@ is uncompressed, and unstripped. This package also includes the unstripped modules. -Package: linux-tools-4.4.0-132-powerpc64-smp +Package: linux-tools-4.4.0-133-powerpc64-smp Architecture: powerpc Section: devel Priority: optional -Depends: ${misc:Depends}, linux-lts-xenial-tools-4.4.0-132 -Description: Linux kernel version specific tools for version 4.4.0-132 +Depends: ${misc:Depends}, linux-lts-xenial-tools-4.4.0-133 +Description: Linux kernel version specific tools for version 4.4.0-133 This package provides the architecture dependant parts for kernel version locked tools (such as perf and x86_energy_perf_policy) for - version 4.4.0-132 on + version 4.4.0-133 on 64 bit x86. -Package: linux-cloud-tools-4.4.0-132-powerpc64-smp +Package: linux-cloud-tools-4.4.0-133-powerpc64-smp Architecture: powerpc Section: devel Priority: optional -Depends: ${misc:Depends}, linux-lts-xenial-cloud-tools-4.4.0-132 -Description: Linux kernel version specific cloud tools for version 4.4.0-132 +Depends: ${misc:Depends}, linux-lts-xenial-cloud-tools-4.4.0-133 +Description: Linux kernel version specific cloud tools for version 4.4.0-133 This package provides the architecture dependant parts for kernel - version locked tools for cloud for version 4.4.0-132 on + version locked tools for cloud for version 4.4.0-133 on 64 bit x86. Package: linux-lts-xenial-udebs-powerpc64-smp diff -u linux-lts-xenial-4.4.0/drivers/ata/libata-core.c linux-lts-xenial-4.4.0/drivers/ata/libata-core.c --- linux-lts-xenial-4.4.0/drivers/ata/libata-core.c +++ linux-lts-xenial-4.4.0/drivers/ata/libata-core.c @@ -4247,6 +4247,9 @@ ATA_HORKAGE_ZERO_AFTER_TRIM | ATA_HORKAGE_NOLPM, }, + /* Sandisk devices which are known to not handle LPM well */ + { "SanDisk SD7UB3Q*G1001", NULL, ATA_HORKAGE_NOLPM, }, + /* devices that don't properly handle queued TRIM commands */ { "Micron_M500IT_*", "MU01", ATA_HORKAGE_NO_NCQ_TRIM | ATA_HORKAGE_ZERO_AFTER_TRIM, }, reverted: --- linux-lts-xenial-4.4.0/drivers/ata/libata-zpodd.c +++ linux-lts-xenial-4.4.0.orig/drivers/ata/libata-zpodd.c @@ -34,7 +34,7 @@ static int eject_tray(struct ata_device *dev) { struct ata_taskfile tf; + const char cdb[] = { GPCMD_START_STOP_UNIT, - static const char cdb[ATAPI_CDB_LEN] = { GPCMD_START_STOP_UNIT, 0, 0, 0, 0x02, /* LoEj */ 0, 0, 0, 0, 0, 0, 0, @@ -55,7 +55,7 @@ unsigned int ret; struct rm_feature_desc *desc = (void *)(buf + 8); struct ata_taskfile tf; + char cdb[] = { GPCMD_GET_CONFIGURATION, - static const char cdb[] = { GPCMD_GET_CONFIGURATION, 2, /* only 1 feature descriptor requested */ 0, 3, /* 3, removable medium feature */ 0, 0, 0,/* reserved */ diff -u linux-lts-xenial-4.4.0/drivers/atm/zatm.c linux-lts-xenial-4.4.0/drivers/atm/zatm.c --- linux-lts-xenial-4.4.0/drivers/atm/zatm.c +++ linux-lts-xenial-4.4.0/drivers/atm/zatm.c @@ -1149,8 +1149,8 @@ } -static int eprom_try_esi(struct atm_dev *dev, unsigned short cmd, int offset, - int swap) +static unsigned char eprom_try_esi(struct atm_dev *dev, unsigned short cmd, + int offset, int swap) { unsigned char buf[ZEPROM_SIZE]; struct zatm_dev *zatm_dev; diff -u linux-lts-xenial-4.4.0/drivers/base/core.c linux-lts-xenial-4.4.0/drivers/base/core.c --- linux-lts-xenial-4.4.0/drivers/base/core.c +++ linux-lts-xenial-4.4.0/drivers/base/core.c @@ -759,7 +759,7 @@ dir = kzalloc(sizeof(*dir), GFP_KERNEL); if (!dir) - return ERR_PTR(-ENOMEM); + return NULL; dir->class = class; kobject_init(&dir->kobj, &class_dir_ktype); @@ -769,7 +769,7 @@ retval = kobject_add(&dir->kobj, parent_kobj, "%s", class->name); if (retval < 0) { kobject_put(&dir->kobj); - return ERR_PTR(retval); + return NULL; } return &dir->kobj; } @@ -1076,10 +1076,6 @@ parent = get_device(dev->parent); kobj = get_device_parent(dev, parent); - if (IS_ERR(kobj)) { - error = PTR_ERR(kobj); - goto parent_error; - } if (kobj) dev->kobj.parent = kobj; @@ -1178,7 +1174,6 @@ kobject_del(&dev->kobj); Error: cleanup_glue_dir(dev, glue_dir); -parent_error: put_device(parent); name_error: kfree(dev->p); @@ -1995,11 +1990,6 @@ device_pm_lock(); new_parent = get_device(new_parent); new_parent_kobj = get_device_parent(dev, new_parent); - if (IS_ERR(new_parent_kobj)) { - error = PTR_ERR(new_parent_kobj); - put_device(new_parent); - goto out; - } pr_debug("device: '%s': %s: moving to '%s'\n", dev_name(dev), __func__, new_parent ? dev_name(new_parent) : ""); diff -u linux-lts-xenial-4.4.0/drivers/base/cpu.c linux-lts-xenial-4.4.0/drivers/base/cpu.c --- linux-lts-xenial-4.4.0/drivers/base/cpu.c +++ linux-lts-xenial-4.4.0/drivers/base/cpu.c @@ -524,16 +524,24 @@ return sprintf(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"); +} + static DEVICE_ATTR(meltdown, 0444, cpu_show_meltdown, NULL); static DEVICE_ATTR(spectre_v1, 0444, cpu_show_spectre_v1, NULL); static DEVICE_ATTR(spectre_v2, 0444, cpu_show_spectre_v2, NULL); static DEVICE_ATTR(spec_store_bypass, 0444, cpu_show_spec_store_bypass, NULL); +static DEVICE_ATTR(l1tf, 0444, cpu_show_l1tf, NULL); static struct attribute *cpu_root_vulnerabilities_attrs[] = { &dev_attr_meltdown.attr, &dev_attr_spectre_v1.attr, &dev_attr_spectre_v2.attr, &dev_attr_spec_store_bypass.attr, + &dev_attr_l1tf.attr, NULL }; reverted: --- linux-lts-xenial-4.4.0/drivers/block/drbd/drbd_worker.c +++ linux-lts-xenial-4.4.0.orig/drivers/block/drbd/drbd_worker.c @@ -256,8 +256,8 @@ } else what = COMPLETED_OK; + bio_put(req->private_bio); req->private_bio = ERR_PTR(bio->bi_error); - bio_put(bio); /* not req_mod(), we need irqsave here! */ spin_lock_irqsave(&device->resource->req_lock, flags); diff -u linux-lts-xenial-4.4.0/drivers/bluetooth/hci_qca.c linux-lts-xenial-4.4.0/drivers/bluetooth/hci_qca.c --- linux-lts-xenial-4.4.0/drivers/bluetooth/hci_qca.c +++ linux-lts-xenial-4.4.0/drivers/bluetooth/hci_qca.c @@ -939,12 +939,6 @@ } else if (ret == -ENOENT) { /* No patch/nvm-config found, run with original fw/config */ ret = 0; - } else if (ret == -EAGAIN) { - /* - * Userspace firmware loader will return -EAGAIN in case no - * patch/nvm-config is found, so run with original fw/config. - */ - ret = 0; } /* Setup bdaddr */ reverted: --- linux-lts-xenial-4.4.0/drivers/char/hw_random/via-rng.c +++ linux-lts-xenial-4.4.0.orig/drivers/char/hw_random/via-rng.c @@ -140,7 +140,7 @@ * RNG configuration like it used to be the case in this * register */ if ((c->x86 == 6) && (c->x86_model >= 0x0f)) { + if (!cpu_has_xstore_enabled) { - if (!boot_cpu_has(X86_FEATURE_XSTORE_EN)) { pr_err(PFX "can't enable hardware RNG " "if XSTORE is not enabled\n"); return -ENODEV; @@ -200,9 +200,8 @@ { int err; + if (!cpu_has_xstore) - if (!boot_cpu_has(X86_FEATURE_XSTORE)) return -ENODEV; - pr_info("VIA RNG detected\n"); err = hwrng_register(&via_rng); if (err) { reverted: --- linux-lts-xenial-4.4.0/drivers/char/ipmi/ipmi_bt_sm.c +++ linux-lts-xenial-4.4.0.orig/drivers/char/ipmi/ipmi_bt_sm.c @@ -522,12 +522,11 @@ if (status & BT_H_BUSY) /* clear a leftover H_BUSY */ BT_CONTROL(BT_H_BUSY); - bt->timeout = bt->BT_CAP_req2rsp; - /* Read BT capabilities if it hasn't been done yet */ if (!bt->BT_CAP_outreqs) BT_STATE_CHANGE(BT_STATE_CAPABILITIES_BEGIN, SI_SM_CALL_WITHOUT_DELAY); + bt->timeout = bt->BT_CAP_req2rsp; BT_SI_SM_RETURN(SI_SM_IDLE); case BT_STATE_XACTION_START: diff -u linux-lts-xenial-4.4.0/drivers/char/tpm/tpm-chip.c linux-lts-xenial-4.4.0/drivers/char/tpm/tpm-chip.c --- linux-lts-xenial-4.4.0/drivers/char/tpm/tpm-chip.c +++ linux-lts-xenial-4.4.0/drivers/char/tpm/tpm-chip.c @@ -26,7 +26,6 @@ #include #include #include -#include #include "tpm.h" #include "tpm_eventlog.h" @@ -329,20 +328,8 @@ */ int tpm_chip_register(struct tpm_chip *chip) { -#ifdef CONFIG_OF - struct device_node *np; -#endif int rc; -#ifdef CONFIG_OF - np = of_find_node_by_name(NULL, "vtpm"); - if (np) { - if (of_property_read_bool(np, "powered-while-suspended")) - chip->flags |= TPM_CHIP_FLAG_ALWAYS_POWERED; - } - of_node_put(np); -#endif - rc = tpm1_chip_register(chip); if (rc) return rc; diff -u linux-lts-xenial-4.4.0/drivers/char/tpm/tpm-interface.c linux-lts-xenial-4.4.0/drivers/char/tpm/tpm-interface.c --- linux-lts-xenial-4.4.0/drivers/char/tpm/tpm-interface.c +++ linux-lts-xenial-4.4.0/drivers/char/tpm/tpm-interface.c @@ -804,10 +804,6 @@ loops = jiffies_to_msecs(duration) / delay_msec; rc = tpm_continue_selftest(chip); - if (rc == TPM_ERR_INVALID_POSTINIT) { - chip->flags |= TPM_CHIP_FLAG_ALWAYS_POWERED; - dev_info(&chip->dev, "TPM not ready (%d)\n", rc); - } /* This may fail if there was no TPM driver during a suspend/resume * cycle; some may return 10 (BAD_ORDINAL), others 28 (FAILEDSELFTEST) */ @@ -952,9 +948,6 @@ if (chip == NULL) return -ENODEV; - if (chip->flags & TPM_CHIP_FLAG_ALWAYS_POWERED) - return 0; - if (chip->flags & TPM_CHIP_FLAG_TPM2) { tpm2_shutdown(chip, TPM2_SU_STATE); return 0; diff -u linux-lts-xenial-4.4.0/drivers/char/tpm/tpm.h linux-lts-xenial-4.4.0/drivers/char/tpm/tpm.h --- linux-lts-xenial-4.4.0/drivers/char/tpm/tpm.h +++ linux-lts-xenial-4.4.0/drivers/char/tpm/tpm.h @@ -164,7 +164,6 @@ enum tpm_chip_flags { TPM_CHIP_FLAG_REGISTERED = BIT(0), TPM_CHIP_FLAG_TPM2 = BIT(1), - TPM_CHIP_FLAG_ALWAYS_POWERED = BIT(5), }; struct tpm_chip { diff -u linux-lts-xenial-4.4.0/drivers/cpufreq/cpufreq.c linux-lts-xenial-4.4.0/drivers/cpufreq/cpufreq.c --- linux-lts-xenial-4.4.0/drivers/cpufreq/cpufreq.c +++ linux-lts-xenial-4.4.0/drivers/cpufreq/cpufreq.c @@ -603,8 +603,6 @@ struct cpufreq_policy new_policy; \ \ memcpy(&new_policy, policy, sizeof(*policy)); \ - new_policy.min = policy->user_policy.min; \ - new_policy.max = policy->user_policy.max; \ \ ret = sscanf(buf, "%u", &new_policy.object); \ if (ret != 1) \ diff -u linux-lts-xenial-4.4.0/drivers/cpuidle/cpuidle-powernv.c linux-lts-xenial-4.4.0/drivers/cpuidle/cpuidle-powernv.c --- linux-lts-xenial-4.4.0/drivers/cpuidle/cpuidle-powernv.c +++ linux-lts-xenial-4.4.0/drivers/cpuidle/cpuidle-powernv.c @@ -29,31 +29,9 @@ static int max_idle_state; static struct cpuidle_state *cpuidle_state_table; -static u64 default_snooze_timeout; +static u64 snooze_timeout; static bool snooze_timeout_en; -static u64 get_snooze_timeout(struct cpuidle_device *dev, - struct cpuidle_driver *drv, - int index) -{ - int i; - - if (unlikely(!snooze_timeout_en)) - return default_snooze_timeout; - - for (i = index + 1; i < drv->state_count; i++) { - struct cpuidle_state *s = &drv->states[i]; - struct cpuidle_state_usage *su = &dev->states_usage[i]; - - if (s->disabled || su->disable) - continue; - - return s->target_residency * tb_ticks_per_usec; - } - - return default_snooze_timeout; -} - static int snooze_loop(struct cpuidle_device *dev, struct cpuidle_driver *drv, int index) @@ -63,7 +41,7 @@ local_irq_enable(); set_thread_flag(TIF_POLLING_NRFLAG); - snooze_exit_time = get_tb() + get_snooze_timeout(dev, drv, index); + snooze_exit_time = get_tb() + snooze_timeout; ppc64_runlatch_off(); while (!need_resched()) { HMT_low(); @@ -308,9 +286,11 @@ cpuidle_state_table = powernv_states; /* Device tree can indicate more idle states */ max_idle_state = powernv_add_idle_states(); - default_snooze_timeout = TICK_USEC * tb_ticks_per_usec; - if (max_idle_state > 1) + if (max_idle_state > 1) { snooze_timeout_en = true; + snooze_timeout = powernv_states[1].target_residency * + tb_ticks_per_usec; + } } else return -ENODEV; reverted: --- linux-lts-xenial-4.4.0/drivers/crypto/padlock-aes.c +++ linux-lts-xenial-4.4.0.orig/drivers/crypto/padlock-aes.c @@ -515,7 +515,7 @@ if (!x86_match_cpu(padlock_cpu_id)) return -ENODEV; + if (!cpu_has_xcrypt_enabled) { - if (!boot_cpu_has(X86_FEATURE_XCRYPT_EN)) { printk(KERN_NOTICE PFX "VIA PadLock detected, but not enabled. Hmm, strange...\n"); return -ENODEV; } reverted: --- linux-lts-xenial-4.4.0/drivers/crypto/padlock-sha.c +++ linux-lts-xenial-4.4.0.orig/drivers/crypto/padlock-sha.c @@ -540,7 +540,7 @@ struct shash_alg *sha1; struct shash_alg *sha256; + if (!x86_match_cpu(padlock_sha_ids) || !cpu_has_phe_enabled) - if (!x86_match_cpu(padlock_sha_ids) || !boot_cpu_has(X86_FEATURE_PHE_EN)) return -ENODEV; /* Register the newly added algorithm module if on * diff -u linux-lts-xenial-4.4.0/drivers/crypto/vmx/aes.c linux-lts-xenial-4.4.0/drivers/crypto/vmx/aes.c --- linux-lts-xenial-4.4.0/drivers/crypto/vmx/aes.c +++ linux-lts-xenial-4.4.0/drivers/crypto/vmx/aes.c @@ -53,6 +53,8 @@ alg, PTR_ERR(fallback)); return PTR_ERR(fallback); } + printk(KERN_INFO "Using '%s' as fallback implementation.\n", + crypto_tfm_alg_driver_name((struct crypto_tfm *) fallback)); crypto_cipher_set_flags(fallback, crypto_cipher_get_flags((struct diff -u linux-lts-xenial-4.4.0/drivers/crypto/vmx/aes_cbc.c linux-lts-xenial-4.4.0/drivers/crypto/vmx/aes_cbc.c --- linux-lts-xenial-4.4.0/drivers/crypto/vmx/aes_cbc.c +++ linux-lts-xenial-4.4.0/drivers/crypto/vmx/aes_cbc.c @@ -55,6 +55,8 @@ alg, PTR_ERR(fallback)); return PTR_ERR(fallback); } + printk(KERN_INFO "Using '%s' as fallback implementation.\n", + crypto_tfm_alg_driver_name((struct crypto_tfm *) fallback)); crypto_blkcipher_set_flags( fallback, diff -u linux-lts-xenial-4.4.0/drivers/crypto/vmx/aes_ctr.c linux-lts-xenial-4.4.0/drivers/crypto/vmx/aes_ctr.c --- linux-lts-xenial-4.4.0/drivers/crypto/vmx/aes_ctr.c +++ linux-lts-xenial-4.4.0/drivers/crypto/vmx/aes_ctr.c @@ -53,6 +53,8 @@ alg, PTR_ERR(fallback)); return PTR_ERR(fallback); } + printk(KERN_INFO "Using '%s' as fallback implementation.\n", + crypto_tfm_alg_driver_name((struct crypto_tfm *) fallback)); crypto_blkcipher_set_flags( fallback, diff -u linux-lts-xenial-4.4.0/drivers/crypto/vmx/ghash.c linux-lts-xenial-4.4.0/drivers/crypto/vmx/ghash.c --- linux-lts-xenial-4.4.0/drivers/crypto/vmx/ghash.c +++ linux-lts-xenial-4.4.0/drivers/crypto/vmx/ghash.c @@ -64,6 +64,8 @@ alg, PTR_ERR(fallback)); return PTR_ERR(fallback); } + printk(KERN_INFO "Using '%s' as fallback implementation.\n", + crypto_tfm_alg_driver_name(crypto_shash_tfm(fallback))); crypto_shash_set_flags(fallback, crypto_shash_get_flags((struct crypto_shash diff -u linux-lts-xenial-4.4.0/drivers/dma/sh/usb-dmac.c linux-lts-xenial-4.4.0/drivers/dma/sh/usb-dmac.c --- linux-lts-xenial-4.4.0/drivers/dma/sh/usb-dmac.c +++ linux-lts-xenial-4.4.0/drivers/dma/sh/usb-dmac.c @@ -448,7 +448,7 @@ static int usb_dmac_chan_terminate_all(struct dma_chan *chan) { struct usb_dmac_chan *uchan = to_usb_dmac_chan(chan); - struct usb_dmac_desc *desc, *_desc; + struct usb_dmac_desc *desc; unsigned long flags; LIST_HEAD(head); LIST_HEAD(list); @@ -459,7 +459,7 @@ if (uchan->desc) uchan->desc = NULL; list_splice_init(&uchan->desc_got, &list); - list_for_each_entry_safe(desc, _desc, &list, node) + list_for_each_entry(desc, &list, node) list_move_tail(&desc->node, &uchan->desc_freed); spin_unlock_irqrestore(&uchan->vc.lock, flags); vchan_dma_desc_free_list(&uchan->vc, &head); diff -u linux-lts-xenial-4.4.0/drivers/gpio/gpiolib.c linux-lts-xenial-4.4.0/drivers/gpio/gpiolib.c --- linux-lts-xenial-4.4.0/drivers/gpio/gpiolib.c +++ linux-lts-xenial-4.4.0/drivers/gpio/gpiolib.c @@ -2186,8 +2186,6 @@ struct gpio_desc *desc = NULL; int status; enum gpio_lookup_flags lookupflags = 0; - /* Maybe we have a device name, maybe not */ - const char *devname = dev ? dev_name(dev) : "?"; dev_dbg(dev, "GPIO lookup for consumer %s\n", con_id); @@ -2216,11 +2214,8 @@ return desc; } - /* - * If a connection label was passed use that, else attempt to use - * the device name as label - */ - status = gpiod_request(desc, con_id ? con_id : devname); + /* If a connection label was passed use that, else use the device name as label */ + status = gpiod_request(desc, con_id ? con_id : dev_name(dev)); if (status < 0) return ERR_PTR(status); reverted: --- linux-lts-xenial-4.4.0/drivers/gpu/drm/drm_fops.c +++ linux-lts-xenial-4.4.0.orig/drivers/gpu/drm/drm_fops.c @@ -209,7 +209,6 @@ return -ENOMEM; filp->private_data = priv; - filp->f_mode |= FMODE_UNSIGNED_OFFSET; priv->filp = filp; priv->uid = current_euid(); priv->pid = get_pid(task_pid(current)); reverted: --- linux-lts-xenial-4.4.0/drivers/gpu/drm/i915/intel_lvds.c +++ linux-lts-xenial-4.4.0.orig/drivers/gpu/drm/i915/intel_lvds.c @@ -768,14 +768,6 @@ DMI_EXACT_MATCH(DMI_BOARD_NAME, "D525MW"), }, }, - { - .callback = intel_no_lvds_dmi_callback, - .ident = "Radiant P845", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "Radiant Systems Inc"), - DMI_MATCH(DMI_PRODUCT_NAME, "P845"), - }, - }, { } /* terminating entry */ }; reverted: --- linux-lts-xenial-4.4.0/drivers/hid/hid-debug.c +++ linux-lts-xenial-4.4.0.orig/drivers/hid/hid-debug.c @@ -1152,8 +1152,6 @@ goto out; if (list->tail > list->head) { len = list->tail - list->head; - if (len > count) - len = count; if (copy_to_user(buffer + ret, &list->hid_debug_buf[list->head], len)) { ret = -EFAULT; @@ -1163,8 +1161,6 @@ list->head += len; } else { len = HID_DEBUG_BUFSIZE - list->head; - if (len > count) - len = count; if (copy_to_user(buffer, &list->hid_debug_buf[list->head], len)) { ret = -EFAULT; @@ -1172,9 +1168,7 @@ } list->head = 0; ret += len; + goto copy_rest; - count -= len; - if (count > 0) - goto copy_rest; } } diff -u linux-lts-xenial-4.4.0/drivers/hid/i2c-hid/i2c-hid.c linux-lts-xenial-4.4.0/drivers/hid/i2c-hid/i2c-hid.c --- linux-lts-xenial-4.4.0/drivers/hid/i2c-hid/i2c-hid.c +++ linux-lts-xenial-4.4.0/drivers/hid/i2c-hid/i2c-hid.c @@ -413,7 +413,7 @@ return; } - if ((ret_size > size) || (ret_size < 2)) { + if ((ret_size > size) || (ret_size <= 2)) { dev_err(&ihid->client->dev, "%s: incomplete report (%d/%d)\n", __func__, size, ret_size); return; diff -u linux-lts-xenial-4.4.0/drivers/hid/usbhid/hiddev.c linux-lts-xenial-4.4.0/drivers/hid/usbhid/hiddev.c --- linux-lts-xenial-4.4.0/drivers/hid/usbhid/hiddev.c +++ linux-lts-xenial-4.4.0/drivers/hid/usbhid/hiddev.c @@ -35,7 +35,6 @@ #include #include #include -#include #include "usbhid.h" #ifdef CONFIG_USB_DYNAMIC_MINORS @@ -479,14 +478,10 @@ if (uref->field_index >= report->maxfield) goto inval; - uref->field_index = array_index_nospec(uref->field_index, - report->maxfield); field = report->field[uref->field_index]; if (uref->usage_index >= field->maxusage) goto inval; - uref->usage_index = array_index_nospec(uref->usage_index, - field->maxusage); uref->usage_code = field->usage[uref->usage_index].hid; @@ -513,8 +508,6 @@ if (uref->field_index >= report->maxfield) goto inval; - uref->field_index = array_index_nospec(uref->field_index, - report->maxfield); field = report->field[uref->field_index]; @@ -768,8 +761,6 @@ if (finfo.field_index >= report->maxfield) break; - finfo.field_index = array_index_nospec(finfo.field_index, - report->maxfield); field = report->field[finfo.field_index]; memset(&finfo, 0, sizeof(finfo)); @@ -810,8 +801,6 @@ if (cinfo.index >= hid->maxcollection) break; - cinfo.index = array_index_nospec(cinfo.index, - hid->maxcollection); cinfo.type = hid->collection[cinfo.index].type; cinfo.usage = hid->collection[cinfo.index].usage; diff -u linux-lts-xenial-4.4.0/drivers/hwtracing/stm/core.c linux-lts-xenial-4.4.0/drivers/hwtracing/stm/core.c --- linux-lts-xenial-4.4.0/drivers/hwtracing/stm/core.c +++ linux-lts-xenial-4.4.0/drivers/hwtracing/stm/core.c @@ -26,7 +26,6 @@ #include #include #include -#include #include "stm.h" #include @@ -603,7 +602,7 @@ { struct stm_device *stm = to_stm_device(dev); - vfree(stm); + kfree(stm); } int stm_register_device(struct device *parent, struct stm_data *stm_data, @@ -620,7 +619,7 @@ return -EINVAL; nmasters = stm_data->sw_end - stm_data->sw_start; - stm = vzalloc(sizeof(*stm) + nmasters * sizeof(void *)); + stm = kzalloc(sizeof(*stm) + nmasters * sizeof(void *), GFP_KERNEL); if (!stm) return -ENOMEM; @@ -657,7 +656,7 @@ err_device: put_device(&stm->dev); err_free: - vfree(stm); + kfree(stm); return err; } reverted: --- linux-lts-xenial-4.4.0/drivers/i2c/busses/i2c-rcar.c +++ linux-lts-xenial-4.4.0.orig/drivers/i2c/busses/i2c-rcar.c @@ -33,6 +33,7 @@ #include #include #include +#include /* register offsets */ #define ICSCR 0x00 /* slave ctrl */ @@ -83,7 +84,6 @@ #define RCAR_BUS_PHASE_START (MDBS | MIE | ESG) #define RCAR_BUS_PHASE_DATA (MDBS | MIE) -#define RCAR_BUS_MASK_DATA (~(ESG | FSB) & 0xFF) #define RCAR_BUS_PHASE_STOP (MDBS | MIE | FSB) #define RCAR_IRQ_SEND (MNR | MAL | MST | MAT | MDE) @@ -94,6 +94,7 @@ #define RCAR_IRQ_ACK_RECV (~(MAT | MDR) & 0xFF) #define ID_LAST_MSG (1 << 0) +#define ID_IOERROR (1 << 1) #define ID_DONE (1 << 2) #define ID_ARBLOST (1 << 3) #define ID_NACK (1 << 4) @@ -107,10 +108,10 @@ struct rcar_i2c_priv { void __iomem *io; struct i2c_adapter adap; + struct i2c_msg *msg; - struct i2c_msg *msg; - int msgs_left; struct clk *clk; + spinlock_t lock; wait_queue_head_t wait; int pos; @@ -143,10 +144,9 @@ { /* reset master mode */ rcar_i2c_write(priv, ICMIER, 0); + rcar_i2c_write(priv, ICMCR, 0); - rcar_i2c_write(priv, ICMCR, MDBS); rcar_i2c_write(priv, ICMSR, 0); + rcar_i2c_write(priv, ICMAR, 0); - /* start clock */ - rcar_i2c_write(priv, ICCCR, priv->icccr); } static int rcar_i2c_bus_barrier(struct rcar_i2c_priv *priv) @@ -257,28 +257,16 @@ { int read = !!rcar_i2c_is_recv(priv); - priv->pos = 0; - priv->flags = 0; - if (priv->msgs_left == 1) - rcar_i2c_flags_set(priv, ID_LAST_MSG); - rcar_i2c_write(priv, ICMAR, (priv->msg->addr << 1) | read); rcar_i2c_write(priv, ICMSR, 0); rcar_i2c_write(priv, ICMCR, RCAR_BUS_PHASE_START); rcar_i2c_write(priv, ICMIER, read ? RCAR_IRQ_RECV : RCAR_IRQ_SEND); } -static void rcar_i2c_next_msg(struct rcar_i2c_priv *priv) -{ - priv->msg++; - priv->msgs_left--; - rcar_i2c_prepare_msg(priv); -} - /* * interrupt functions */ +static int rcar_i2c_irq_send(struct rcar_i2c_priv *priv, u32 msr) -static void rcar_i2c_irq_send(struct rcar_i2c_priv *priv, u32 msr) { struct i2c_msg *msg = priv->msg; @@ -288,7 +276,14 @@ * Do nothing */ if (!(msr & MDE)) + return 0; + + /* + * If address transfer phase finished, + * goto data phase. + */ + if (msr & MAT) + rcar_i2c_write(priv, ICMCR, RCAR_BUS_PHASE_DATA); - return; if (priv->pos < msg->len) { /* @@ -310,23 +305,29 @@ * [ICRXTX] -> [SHIFT] -> [I2C bus] */ + if (priv->flags & ID_LAST_MSG) - if (priv->flags & ID_LAST_MSG) { /* * If current msg is the _LAST_ msg, * prepare stop condition here. * ID_DONE will be set on STOP irq. */ rcar_i2c_write(priv, ICMCR, RCAR_BUS_PHASE_STOP); + else + /* + * If current msg is _NOT_ last msg, + * it doesn't call stop phase. + * thus, there is no STOP irq. + * return ID_DONE here. + */ + return ID_DONE; - } else { - rcar_i2c_next_msg(priv); - return; - } } rcar_i2c_write(priv, ICMSR, RCAR_IRQ_ACK_SEND); + + return 0; } +static int rcar_i2c_irq_recv(struct rcar_i2c_priv *priv, u32 msr) -static void rcar_i2c_irq_recv(struct rcar_i2c_priv *priv, u32 msr) { struct i2c_msg *msg = priv->msg; @@ -336,10 +337,14 @@ * Do nothing */ if (!(msr & MDR)) + return 0; - return; if (msr & MAT) { + /* + * Address transfer phase finished, + * but, there is no data at this point. + * Do nothing. + */ - /* Address transfer phase finished, but no data at this point. */ } else if (priv->pos < msg->len) { /* * get received data @@ -355,11 +360,12 @@ */ if (priv->pos + 1 >= msg->len) rcar_i2c_write(priv, ICMCR, RCAR_BUS_PHASE_STOP); + else + rcar_i2c_write(priv, ICMCR, RCAR_BUS_PHASE_DATA); + rcar_i2c_write(priv, ICMSR, RCAR_IRQ_ACK_RECV); + + return 0; - if (priv->pos == msg->len && !(priv->flags & ID_LAST_MSG)) - rcar_i2c_next_msg(priv); - else - rcar_i2c_write(priv, ICMSR, RCAR_IRQ_ACK_RECV); } static bool rcar_i2c_slave_irq(struct rcar_i2c_priv *priv) @@ -420,21 +426,22 @@ static irqreturn_t rcar_i2c_irq(int irq, void *ptr) { struct rcar_i2c_priv *priv = ptr; + irqreturn_t result = IRQ_HANDLED; + u32 msr; - u32 msr, val; + /*-------------- spin lock -----------------*/ + spin_lock(&priv->lock); + + if (rcar_i2c_slave_irq(priv)) + goto exit; - /* Clear START or STOP as soon as we can */ - val = rcar_i2c_read(priv, ICMCR); - rcar_i2c_write(priv, ICMCR, val & RCAR_BUS_MASK_DATA); msr = rcar_i2c_read(priv, ICMSR); /* Only handle interrupts that are currently enabled */ msr &= rcar_i2c_read(priv, ICMIER); if (!msr) { + result = IRQ_NONE; + goto exit; - if (rcar_i2c_slave_irq(priv)) - return IRQ_HANDLED; - - return IRQ_NONE; } /* Arbitration lost */ @@ -445,7 +452,8 @@ /* Nack */ if (msr & MNR) { + /* go to stop phase */ + rcar_i2c_write(priv, ICMCR, RCAR_BUS_PHASE_STOP); - /* HW automatically sends STOP after received NACK */ rcar_i2c_write(priv, ICMIER, RCAR_IRQ_STOP); rcar_i2c_flags_set(priv, ID_NACK); goto out; @@ -453,15 +461,14 @@ /* Stop */ if (msr & MST) { - priv->msgs_left--; /* The last message also made it */ rcar_i2c_flags_set(priv, ID_DONE); goto out; } if (rcar_i2c_is_recv(priv)) + rcar_i2c_flags_set(priv, rcar_i2c_irq_recv(priv, msr)); - rcar_i2c_irq_recv(priv, msr); else + rcar_i2c_flags_set(priv, rcar_i2c_irq_send(priv, msr)); - rcar_i2c_irq_send(priv, msr); out: if (rcar_i2c_flags_has(priv, ID_DONE)) { @@ -470,7 +477,11 @@ wake_up(&priv->wait); } +exit: + spin_unlock(&priv->lock); + /*-------------- spin unlock -----------------*/ + + return result; - return IRQ_HANDLED; } static int rcar_i2c_master_xfer(struct i2c_adapter *adap, @@ -479,12 +490,21 @@ { struct rcar_i2c_priv *priv = i2c_get_adapdata(adap); struct device *dev = rcar_i2c_priv_to_dev(priv); + unsigned long flags; int i, ret; + long timeout; - long time_left; pm_runtime_get_sync(dev); + /*-------------- spin lock -----------------*/ + spin_lock_irqsave(&priv->lock, flags); + rcar_i2c_init(priv); + /* start clock */ + rcar_i2c_write(priv, ICCCR, priv->icccr); + + spin_unlock_irqrestore(&priv->lock, flags); + /*-------------- spin unlock -----------------*/ ret = rcar_i2c_bus_barrier(priv); if (ret < 0) @@ -494,28 +514,48 @@ /* This HW can't send STOP after address phase */ if (msgs[i].len == 0) { ret = -EOPNOTSUPP; + break; + } + + /*-------------- spin lock -----------------*/ + spin_lock_irqsave(&priv->lock, flags); + + /* init each data */ + priv->msg = &msgs[i]; + priv->pos = 0; + priv->flags = 0; + if (i == num - 1) + rcar_i2c_flags_set(priv, ID_LAST_MSG); + + rcar_i2c_prepare_msg(priv); + + spin_unlock_irqrestore(&priv->lock, flags); + /*-------------- spin unlock -----------------*/ + + timeout = wait_event_timeout(priv->wait, + rcar_i2c_flags_has(priv, ID_DONE), + adap->timeout); + if (!timeout) { + ret = -ETIMEDOUT; + break; + } + + if (rcar_i2c_flags_has(priv, ID_NACK)) { + ret = -ENXIO; + break; + } + + if (rcar_i2c_flags_has(priv, ID_ARBLOST)) { + ret = -EAGAIN; + break; + } + + if (rcar_i2c_flags_has(priv, ID_IOERROR)) { + ret = -EIO; + break; - goto out; } - } + ret = i + 1; /* The number of transfer */ - /* init data */ - priv->msg = msgs; - priv->msgs_left = num; - - rcar_i2c_prepare_msg(priv); - - time_left = wait_event_timeout(priv->wait, - rcar_i2c_flags_has(priv, ID_DONE), - num * adap->timeout); - if (!time_left) { - rcar_i2c_init(priv); - ret = -ETIMEDOUT; - } else if (rcar_i2c_flags_has(priv, ID_NACK)) { - ret = -ENXIO; - } else if (rcar_i2c_flags_has(priv, ID_ARBLOST)) { - ret = -EAGAIN; - } else { - ret = num - priv->msgs_left; /* The number of transfer */ } out: pm_runtime_put(dev); @@ -610,26 +650,23 @@ return PTR_ERR(priv->clk); } - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - priv->io = devm_ioremap_resource(dev, res); - if (IS_ERR(priv->io)) - return PTR_ERR(priv->io); - bus_speed = 100000; /* default 100 kHz */ of_property_read_u32(dev->of_node, "clock-frequency", &bus_speed); priv->devtype = (enum rcar_i2c_type)of_match_device(rcar_i2c_dt_ids, dev)->data; - pm_runtime_enable(dev); - pm_runtime_get_sync(dev); ret = rcar_i2c_clock_calculate(priv, bus_speed, dev); if (ret < 0) + return ret; - goto out_pm_put; + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + priv->io = devm_ioremap_resource(dev, res); + if (IS_ERR(priv->io)) + return PTR_ERR(priv->io); - pm_runtime_put(dev); irq = platform_get_irq(pdev, 0); init_waitqueue_head(&priv->wait); + spin_lock_init(&priv->lock); adap = &priv->adap; adap->nr = pdev->id; @@ -645,26 +682,22 @@ dev_name(dev), priv); if (ret < 0) { dev_err(dev, "cannot get irq %d\n", irq); + return ret; - goto out_pm_disable; } + pm_runtime_enable(dev); platform_set_drvdata(pdev, priv); ret = i2c_add_numbered_adapter(adap); if (ret < 0) { dev_err(dev, "reg adap failed: %d\n", ret); + pm_runtime_disable(dev); + return ret; - goto out_pm_disable; } dev_info(dev, "probed\n"); return 0; - - out_pm_put: - pm_runtime_put(dev); - out_pm_disable: - pm_runtime_disable(dev); - return ret; } static int rcar_i2c_remove(struct platform_device *pdev) reverted: --- linux-lts-xenial-4.4.0/drivers/iio/buffer/kfifo_buf.c +++ linux-lts-xenial-4.4.0.orig/drivers/iio/buffer/kfifo_buf.c @@ -19,18 +19,11 @@ #define iio_to_kfifo(r) container_of(r, struct iio_kfifo, buffer) static inline int __iio_allocate_kfifo(struct iio_kfifo *buf, + int bytes_per_datum, int length) - size_t bytes_per_datum, unsigned int length) { if ((length == 0) || (bytes_per_datum == 0)) return -EINVAL; - /* - * Make sure we don't overflow an unsigned int after kfifo rounds up to - * the next power of 2. - */ - if (roundup_pow_of_two(length) > UINT_MAX / bytes_per_datum) - return -EINVAL; - return __kfifo_alloc((struct __kfifo *)&buf->kf, length, bytes_per_datum, GFP_KERNEL); } @@ -71,7 +64,7 @@ return 0; } +static int iio_set_length_kfifo(struct iio_buffer *r, int length) -static int iio_set_length_kfifo(struct iio_buffer *r, unsigned int length) { /* Avoid an invalid state */ if (length < 2) diff -u linux-lts-xenial-4.4.0/drivers/infiniband/hw/mlx4/mad.c linux-lts-xenial-4.4.0/drivers/infiniband/hw/mlx4/mad.c --- linux-lts-xenial-4.4.0/drivers/infiniband/hw/mlx4/mad.c +++ linux-lts-xenial-4.4.0/drivers/infiniband/hw/mlx4/mad.c @@ -1780,6 +1780,7 @@ "buf:%lld\n", wc.wr_id); break; default: + BUG_ON(1); break; } } else { reverted: --- linux-lts-xenial-4.4.0/drivers/infiniband/hw/qib/qib.h +++ linux-lts-xenial-4.4.0.orig/drivers/infiniband/hw/qib/qib.h @@ -1451,7 +1451,8 @@ /* * dma_addr wrappers - all 0's invalid for hw */ +dma_addr_t qib_map_page(struct pci_dev *, struct page *, unsigned long, + size_t, int); -int qib_map_page(struct pci_dev *d, struct page *p, dma_addr_t *daddr); const char *qib_get_unit_name(int unit); /* diff -u linux-lts-xenial-4.4.0/drivers/infiniband/hw/qib/qib_file_ops.c linux-lts-xenial-4.4.0/drivers/infiniband/hw/qib/qib_file_ops.c --- linux-lts-xenial-4.4.0/drivers/infiniband/hw/qib/qib_file_ops.c +++ linux-lts-xenial-4.4.0/drivers/infiniband/hw/qib/qib_file_ops.c @@ -364,8 +364,6 @@ goto done; } for (i = 0; i < cnt; i++, vaddr += PAGE_SIZE) { - dma_addr_t daddr; - for (; ntids--; tid++) { if (tid == tidcnt) tid = 0; @@ -382,14 +380,12 @@ ret = -ENOMEM; break; } - ret = qib_map_page(dd->pcidev, pagep[i], &daddr); - if (ret) - break; - tidlist[i] = tid + tidoff; /* we "know" system pages and TID pages are same size */ dd->pageshadow[ctxttid + tid] = pagep[i]; - dd->physshadow[ctxttid + tid] = daddr; + dd->physshadow[ctxttid + tid] = + qib_map_page(dd->pcidev, pagep[i], 0, PAGE_SIZE, + PCI_DMA_FROMDEVICE); /* * don't need atomic or it's overhead */ reverted: --- linux-lts-xenial-4.4.0/drivers/infiniband/hw/qib/qib_user_pages.c +++ linux-lts-xenial-4.4.0.orig/drivers/infiniband/hw/qib/qib_user_pages.c @@ -98,27 +98,23 @@ * * I'm sure we won't be so lucky with other iommu's, so FIXME. */ +dma_addr_t qib_map_page(struct pci_dev *hwdev, struct page *page, + unsigned long offset, size_t size, int direction) -int qib_map_page(struct pci_dev *hwdev, struct page *page, dma_addr_t *daddr) { dma_addr_t phys; + phys = pci_map_page(hwdev, page, offset, size, direction); - phys = pci_map_page(hwdev, page, 0, PAGE_SIZE, PCI_DMA_FROMDEVICE); - if (pci_dma_mapping_error(hwdev, phys)) - return -ENOMEM; + if (phys == 0) { + pci_unmap_page(hwdev, phys, size, direction); + phys = pci_map_page(hwdev, page, offset, size, direction); - if (!phys) { - pci_unmap_page(hwdev, phys, PAGE_SIZE, PCI_DMA_FROMDEVICE); - phys = pci_map_page(hwdev, page, 0, PAGE_SIZE, - PCI_DMA_FROMDEVICE); - if (pci_dma_mapping_error(hwdev, phys)) - return -ENOMEM; /* * FIXME: If we get 0 again, we should keep this page, * map another, then free the 0 page. */ } + + return phys; - *daddr = phys; - return 0; } /** reverted: --- linux-lts-xenial-4.4.0/drivers/input/mouse/elan_i2c.h +++ linux-lts-xenial-4.4.0.orig/drivers/input/mouse/elan_i2c.h @@ -27,8 +27,6 @@ #define ETP_DISABLE_POWER 0x0001 #define ETP_PRESSURE_OFFSET 25 -#define ETP_CALIBRATE_MAX_LEN 3 - /* IAP Firmware handling */ #define ETP_PRODUCT_ID_FORMAT_STRING "%d.0" #define ETP_FW_NAME "elan_i2c_" ETP_PRODUCT_ID_FORMAT_STRING ".bin" diff -u linux-lts-xenial-4.4.0/drivers/input/mouse/elan_i2c_core.c linux-lts-xenial-4.4.0/drivers/input/mouse/elan_i2c_core.c --- linux-lts-xenial-4.4.0/drivers/input/mouse/elan_i2c_core.c +++ linux-lts-xenial-4.4.0/drivers/input/mouse/elan_i2c_core.c @@ -595,7 +595,7 @@ int tries = 20; int retval; int error; - u8 val[ETP_CALIBRATE_MAX_LEN]; + u8 val[3]; retval = mutex_lock_interruptible(&data->sysfs_mutex); if (retval) @@ -1250,7 +1250,6 @@ { "ELAN060C", 0 }, { "ELAN0611", 0 }, { "ELAN0612", 0 }, - { "ELAN0618", 0 }, { "ELAN1000", 0 }, { } }; reverted: --- linux-lts-xenial-4.4.0/drivers/input/mouse/elan_i2c_smbus.c +++ linux-lts-xenial-4.4.0.orig/drivers/input/mouse/elan_i2c_smbus.c @@ -56,7 +56,7 @@ static int elan_smbus_initialize(struct i2c_client *client) { u8 check[ETP_SMBUS_HELLOPACKET_LEN] = { 0x55, 0x55, 0x55, 0x55, 0x55 }; + u8 values[ETP_SMBUS_HELLOPACKET_LEN] = { 0, 0, 0, 0, 0 }; - u8 values[I2C_SMBUS_BLOCK_MAX] = {0}; int len, error; /* Get hello packet */ @@ -117,16 +117,12 @@ static int elan_smbus_calibrate_result(struct i2c_client *client, u8 *val) { int error; - u8 buf[I2C_SMBUS_BLOCK_MAX] = {0}; - - BUILD_BUG_ON(ETP_CALIBRATE_MAX_LEN > sizeof(buf)); error = i2c_smbus_read_block_data(client, + ETP_SMBUS_CALIBRATE_QUERY, val); - ETP_SMBUS_CALIBRATE_QUERY, buf); if (error < 0) return error; - memcpy(val, buf, ETP_CALIBRATE_MAX_LEN); return 0; } @@ -134,7 +130,7 @@ bool max_baseline, u8 *value) { int error; + u8 val[3]; - u8 val[I2C_SMBUS_BLOCK_MAX] = {0}; error = i2c_smbus_read_block_data(client, max_baseline ? @@ -153,7 +149,7 @@ bool iap, u8 *version) { int error; + u8 val[3]; - u8 val[I2C_SMBUS_BLOCK_MAX] = {0}; error = i2c_smbus_read_block_data(client, iap ? ETP_SMBUS_IAP_VERSION_CMD : @@ -173,7 +169,7 @@ u8 *ic_type, u8 *version) { int error; + u8 val[3]; - u8 val[I2C_SMBUS_BLOCK_MAX] = {0}; error = i2c_smbus_read_block_data(client, ETP_SMBUS_SM_VERSION_CMD, val); @@ -190,7 +186,7 @@ static int elan_smbus_get_product_id(struct i2c_client *client, u16 *id) { int error; + u8 val[3]; - u8 val[I2C_SMBUS_BLOCK_MAX] = {0}; error = i2c_smbus_read_block_data(client, ETP_SMBUS_UNIQUEID_CMD, val); @@ -207,7 +203,7 @@ bool iap, u16 *csum) { int error; + u8 val[3]; - u8 val[I2C_SMBUS_BLOCK_MAX] = {0}; error = i2c_smbus_read_block_data(client, iap ? ETP_SMBUS_FW_CHECKSUM_CMD : @@ -227,7 +223,7 @@ unsigned int *max_x, unsigned int *max_y) { int error; + u8 val[3]; - u8 val[I2C_SMBUS_BLOCK_MAX] = {0}; error = i2c_smbus_read_block_data(client, ETP_SMBUS_RANGE_CMD, val); if (error) { @@ -245,7 +241,7 @@ u8 *hw_res_x, u8 *hw_res_y) { int error; + u8 val[3]; - u8 val[I2C_SMBUS_BLOCK_MAX] = {0}; error = i2c_smbus_read_block_data(client, ETP_SMBUS_RESOLUTION_CMD, val); @@ -265,7 +261,7 @@ unsigned int *y_traces) { int error; + u8 val[3]; - u8 val[I2C_SMBUS_BLOCK_MAX] = {0}; error = i2c_smbus_read_block_data(client, ETP_SMBUS_XY_TRACENUM_CMD, val); @@ -292,7 +288,7 @@ { int error; u16 constant; + u8 val[3]; - u8 val[I2C_SMBUS_BLOCK_MAX] = {0}; error = i2c_smbus_read_block_data(client, ETP_SMBUS_IAP_CTRL_CMD, val); if (error < 0) { @@ -343,7 +339,7 @@ int len; int error; enum tp_mode mode; + u8 val[3]; - u8 val[I2C_SMBUS_BLOCK_MAX] = {0}; u8 cmd[4] = {0x0F, 0x78, 0x00, 0x06}; u16 password; @@ -417,7 +413,7 @@ struct device *dev = &client->dev; int error; u16 result; + u8 val[3]; - u8 val[I2C_SMBUS_BLOCK_MAX] = {0}; /* * Due to the limitation of smbus protocol limiting @@ -470,8 +466,6 @@ { int len; - BUILD_BUG_ON(I2C_SMBUS_BLOCK_MAX > ETP_SMBUS_REPORT_LEN); - len = i2c_smbus_read_block_data(client, ETP_SMBUS_PACKET_QUERY, &report[ETP_SMBUS_REPORT_OFFSET]); diff -u linux-lts-xenial-4.4.0/drivers/input/mouse/elantech.c linux-lts-xenial-4.4.0/drivers/input/mouse/elantech.c --- linux-lts-xenial-4.4.0/drivers/input/mouse/elantech.c +++ linux-lts-xenial-4.4.0/drivers/input/mouse/elantech.c @@ -804,7 +804,7 @@ else if (ic_version == 7 && etd->samples[1] == 0x2A) sanity_check = ((packet[3] & 0x1c) == 0x10); else - sanity_check = ((packet[0] & 0x08) == 0x00 && + sanity_check = ((packet[0] & 0x0c) == 0x04 && (packet[3] & 0x1c) == 0x10); if (!sanity_check) @@ -1177,12 +1177,6 @@ { } }; -static const char * const middle_button_pnp_ids[] = { - "LEN2131", /* ThinkPad P52 w/ NFC */ - "LEN2132", /* ThinkPad P52 */ - NULL -}; - /* * Set the appropriate event bits for the input subsystem */ @@ -1202,8 +1196,7 @@ __clear_bit(EV_REL, dev->evbit); __set_bit(BTN_LEFT, dev->keybit); - if (dmi_check_system(elantech_dmi_has_middle_button) || - psmouse_matches_pnp_id(psmouse, middle_button_pnp_ids)) + if (dmi_check_system(elantech_dmi_has_middle_button)) __set_bit(BTN_MIDDLE, dev->keybit); __set_bit(BTN_RIGHT, dev->keybit); reverted: --- linux-lts-xenial-4.4.0/drivers/input/touchscreen/goodix.c +++ linux-lts-xenial-4.4.0.orig/drivers/input/touchscreen/goodix.c @@ -425,7 +425,6 @@ #ifdef CONFIG_ACPI static const struct acpi_device_id goodix_acpi_match[] = { { "GDIX1001", 0 }, - { "GDIX1002", 0 }, { } }; MODULE_DEVICE_TABLE(acpi, goodix_acpi_match); diff -u linux-lts-xenial-4.4.0/drivers/iommu/intel_irq_remapping.c linux-lts-xenial-4.4.0/drivers/iommu/intel_irq_remapping.c --- linux-lts-xenial-4.4.0/drivers/iommu/intel_irq_remapping.c +++ linux-lts-xenial-4.4.0/drivers/iommu/intel_irq_remapping.c @@ -753,7 +753,7 @@ * should have X86_FEATURE_CX16 support, this has been confirmed * with Intel hardware guys. */ - if (boot_cpu_has(X86_FEATURE_CX16)) + if ( cpu_has_cx16 ) intel_irq_remap_ops.capability |= 1 << IRQ_POSTING_CAP; for_each_iommu(iommu, drhd) reverted: --- linux-lts-xenial-4.4.0/drivers/isdn/hardware/eicon/diva.c +++ linux-lts-xenial-4.4.0.orig/drivers/isdn/hardware/eicon/diva.c @@ -387,10 +387,10 @@ ** Receive and process command from user mode utility */ void *diva_xdi_open_adapter(void *os_handle, const void __user *src, + int length, - int length, void *mptr, divas_xdi_copy_from_user_fn_t cp_fn) { + diva_xdi_um_cfg_cmd_t msg; - diva_xdi_um_cfg_cmd_t *msg = (diva_xdi_um_cfg_cmd_t *)mptr; diva_os_xdi_adapter_t *a = NULL; diva_os_spin_lock_magic_t old_irql; struct list_head *tmp; @@ -400,21 +400,21 @@ length, sizeof(diva_xdi_um_cfg_cmd_t))) return NULL; } + if ((*cp_fn) (os_handle, &msg, src, sizeof(msg)) <= 0) { - if ((*cp_fn) (os_handle, msg, src, sizeof(*msg)) <= 0) { DBG_ERR(("A: A(?) open, write error")) return NULL; } diva_os_enter_spin_lock(&adapter_lock, &old_irql, "open_adapter"); list_for_each(tmp, &adapter_queue) { a = list_entry(tmp, diva_os_xdi_adapter_t, link); + if (a->controller == (int)msg.adapter) - if (a->controller == (int)msg->adapter) break; a = NULL; } diva_os_leave_spin_lock(&adapter_lock, &old_irql, "open_adapter"); if (!a) { + DBG_ERR(("A: A(%d) open, adapter not found", msg.adapter)) - DBG_ERR(("A: A(%d) open, adapter not found", msg->adapter)) } return (a); @@ -436,10 +436,8 @@ int diva_xdi_write(void *adapter, void *os_handle, const void __user *src, + int length, divas_xdi_copy_from_user_fn_t cp_fn) - int length, void *mptr, - divas_xdi_copy_from_user_fn_t cp_fn) { - diva_xdi_um_cfg_cmd_t *msg = (diva_xdi_um_cfg_cmd_t *)mptr; diva_os_xdi_adapter_t *a = (diva_os_xdi_adapter_t *) adapter; void *data; @@ -460,13 +458,7 @@ return (-2); } + length = (*cp_fn) (os_handle, data, src, length); - if (msg) { - *(diva_xdi_um_cfg_cmd_t *)data = *msg; - length = (*cp_fn) (os_handle, (char *)data + sizeof(*msg), - src + sizeof(*msg), length - sizeof(*msg)); - } else { - length = (*cp_fn) (os_handle, data, src, length); - } if (length > 0) { if ((*(a->interface.cmd_proc)) (a, (diva_xdi_um_cfg_cmd_t *) data, length)) { reverted: --- linux-lts-xenial-4.4.0/drivers/isdn/hardware/eicon/diva.h +++ linux-lts-xenial-4.4.0.orig/drivers/isdn/hardware/eicon/diva.h @@ -19,11 +19,10 @@ int max_length, divas_xdi_copy_to_user_fn_t cp_fn); int diva_xdi_write(void *adapter, void *os_handle, const void __user *src, + int length, divas_xdi_copy_from_user_fn_t cp_fn); - int length, void *msg, - divas_xdi_copy_from_user_fn_t cp_fn); void *diva_xdi_open_adapter(void *os_handle, const void __user *src, + int length, - int length, void *msg, divas_xdi_copy_from_user_fn_t cp_fn); void diva_xdi_close_adapter(void *adapter, void *os_handle); reverted: --- linux-lts-xenial-4.4.0/drivers/isdn/hardware/eicon/divasmain.c +++ linux-lts-xenial-4.4.0.orig/drivers/isdn/hardware/eicon/divasmain.c @@ -591,22 +591,19 @@ static ssize_t divas_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos) { - diva_xdi_um_cfg_cmd_t msg; int ret = -EINVAL; if (!file->private_data) { file->private_data = diva_xdi_open_adapter(file, buf, + count, - count, &msg, xdi_copy_from_user); + } + if (!file->private_data) { + return (-ENODEV); - if (!file->private_data) - return (-ENODEV); - ret = diva_xdi_write(file->private_data, file, - buf, count, &msg, xdi_copy_from_user); - } else { - ret = diva_xdi_write(file->private_data, file, - buf, count, NULL, xdi_copy_from_user); } + ret = diva_xdi_write(file->private_data, file, + buf, count, xdi_copy_from_user); switch (ret) { case -1: /* Message should be removed from rx mailbox first */ ret = -EBUSY; @@ -625,12 +622,11 @@ static ssize_t divas_read(struct file *file, char __user *buf, size_t count, loff_t *ppos) { - diva_xdi_um_cfg_cmd_t msg; int ret = -EINVAL; if (!file->private_data) { file->private_data = diva_xdi_open_adapter(file, buf, + count, - count, &msg, xdi_copy_from_user); } if (!file->private_data) { diff -u linux-lts-xenial-4.4.0/drivers/md/dm-bufio.c linux-lts-xenial-4.4.0/drivers/md/dm-bufio.c --- linux-lts-xenial-4.4.0/drivers/md/dm-bufio.c +++ linux-lts-xenial-4.4.0/drivers/md/dm-bufio.c @@ -813,14 +813,12 @@ static struct dm_buffer *__alloc_buffer_wait_no_callback(struct dm_bufio_client *c, enum new_flag nf) { struct dm_buffer *b; - bool tried_noio_alloc = false; /* * dm-bufio is resistant to allocation failures (it just keeps * one buffer reserved in cases all the allocations fail). * So set flags to not try too hard: - * GFP_NOWAIT: don't wait; if we need to sleep we'll release our - * mutex and wait ourselves. + * GFP_NOIO: don't recurse into the I/O layer * __GFP_NORETRY: don't retry and rather return failure * __GFP_NOMEMALLOC: don't use emergency reserves * __GFP_NOWARN: don't print a warning in case of failure @@ -830,7 +828,7 @@ */ while (1) { if (dm_bufio_cache_size_latch != 1) { - b = alloc_buffer(c, GFP_NOWAIT | __GFP_NORETRY | __GFP_NOMEMALLOC | __GFP_NOWARN); + b = alloc_buffer(c, GFP_NOIO | __GFP_NORETRY | __GFP_NOMEMALLOC | __GFP_NOWARN); if (b) return b; } @@ -838,15 +836,6 @@ if (nf == NF_PREFETCH) return NULL; - if (dm_bufio_cache_size_latch != 1 && !tried_noio_alloc) { - dm_bufio_unlock(c); - b = alloc_buffer(c, GFP_NOIO | __GFP_NORETRY | __GFP_NOMEMALLOC | __GFP_NOWARN); - dm_bufio_lock(c); - if (b) - return b; - tried_noio_alloc = true; - } - if (!list_empty(&c->reserved_buffers)) { b = list_entry(c->reserved_buffers.next, struct dm_buffer, lru_list); @@ -1574,11 +1563,19 @@ static unsigned long dm_bufio_shrink_count(struct shrinker *shrink, struct shrink_control *sc) { - struct dm_bufio_client *c = container_of(shrink, struct dm_bufio_client, shrinker); - unsigned long count = READ_ONCE(c->n_buffers[LIST_CLEAN]) + - READ_ONCE(c->n_buffers[LIST_DIRTY]); - unsigned long retain_target = get_retain_buffers(c); - + struct dm_bufio_client *c; + unsigned long count; + unsigned long retain_target; + + c = container_of(shrink, struct dm_bufio_client, shrinker); + if (sc->gfp_mask & __GFP_FS) + dm_bufio_lock(c); + else if (!dm_bufio_trylock(c)) + return 0; + + count = c->n_buffers[LIST_CLEAN] + c->n_buffers[LIST_DIRTY]; + retain_target = get_retain_buffers(c); + dm_bufio_unlock(c); return (count < retain_target) ? 0 : (count - retain_target); } diff -u linux-lts-xenial-4.4.0/drivers/md/dm-thin.c linux-lts-xenial-4.4.0/drivers/md/dm-thin.c --- linux-lts-xenial-4.4.0/drivers/md/dm-thin.c +++ linux-lts-xenial-4.4.0/drivers/md/dm-thin.c @@ -1299,8 +1299,6 @@ static void set_pool_mode(struct pool *pool, enum pool_mode new_mode); -static void requeue_bios(struct pool *pool); - static void check_for_space(struct pool *pool) { int r; @@ -1313,10 +1311,8 @@ if (r) return; - if (nr_free) { + if (nr_free) set_pool_mode(pool, PM_WRITE); - requeue_bios(pool); - } } /* @@ -1393,10 +1389,7 @@ r = dm_pool_alloc_data_block(pool->pmd, result); if (r) { - if (r == -ENOSPC) - set_pool_mode(pool, PM_OUT_OF_DATA_SPACE); - else - metadata_operation_failed(pool, "dm_pool_alloc_data_block", r); + metadata_operation_failed(pool, "dm_pool_alloc_data_block", r); return r; } diff -u linux-lts-xenial-4.4.0/drivers/md/md.c linux-lts-xenial-4.4.0/drivers/md/md.c --- linux-lts-xenial-4.4.0/drivers/md/md.c +++ linux-lts-xenial-4.4.0/drivers/md/md.c @@ -2690,8 +2690,7 @@ err = 0; } } else if (cmd_match(buf, "re-add")) { - if (test_bit(Faulty, &rdev->flags) && (rdev->raid_disk == -1) && - rdev->saved_raid_disk >= 0) { + if (test_bit(Faulty, &rdev->flags) && (rdev->raid_disk == -1)) { /* clear_bit is performed _after_ all the devices * have their local Faulty bit cleared. If any writes * happen in the meantime in the local node, they @@ -8154,7 +8153,6 @@ if (mddev->pers->hot_remove_disk( mddev, rdev) == 0) { sysfs_unlink_rdev(mddev, rdev); - rdev->saved_raid_disk = rdev->raid_disk; rdev->raid_disk = -1; removed++; } diff -u linux-lts-xenial-4.4.0/drivers/media/dvb-core/dvb_frontend.c linux-lts-xenial-4.4.0/drivers/media/dvb-core/dvb_frontend.c --- linux-lts-xenial-4.4.0/drivers/media/dvb-core/dvb_frontend.c +++ linux-lts-xenial-4.4.0/drivers/media/dvb-core/dvb_frontend.c @@ -230,20 +230,8 @@ wake_up_interruptible (&events->wait_queue); } -static int dvb_frontend_test_event(struct dvb_frontend_private *fepriv, - struct dvb_fe_events *events) -{ - int ret; - - up(&fepriv->sem); - ret = events->eventw != events->eventr; - down(&fepriv->sem); - - return ret; -} - static int dvb_frontend_get_event(struct dvb_frontend *fe, - struct dvb_frontend_event *event, int flags) + struct dvb_frontend_event *event, int flags) { struct dvb_frontend_private *fepriv = fe->frontend_priv; struct dvb_fe_events *events = &fepriv->events; @@ -261,8 +249,13 @@ if (flags & O_NONBLOCK) return -EWOULDBLOCK; - ret = wait_event_interruptible(events->wait_queue, - dvb_frontend_test_event(fepriv, events)); + up(&fepriv->sem); + + ret = wait_event_interruptible (events->wait_queue, + events->eventw != events->eventr); + + if (down_interruptible (&fepriv->sem)) + return -ERESTARTSYS; if (ret < 0) return ret; diff -u linux-lts-xenial-4.4.0/drivers/media/i2c/cx25840/cx25840-core.c linux-lts-xenial-4.4.0/drivers/media/i2c/cx25840/cx25840-core.c --- linux-lts-xenial-4.4.0/drivers/media/i2c/cx25840/cx25840-core.c +++ linux-lts-xenial-4.4.0/drivers/media/i2c/cx25840/cx25840-core.c @@ -467,13 +467,8 @@ { DEFINE_WAIT(wait); struct cx25840_state *state = to_state(i2c_get_clientdata(client)); - u32 clk_freq = 0; struct workqueue_struct *q; - /* cx23885 sets hostdata to clk_freq pointer */ - if (v4l2_get_subdev_hostdata(&state->sd)) - clk_freq = *((u32 *)v4l2_get_subdev_hostdata(&state->sd)); - /* * Come out of digital power down * The CX23888, at least, needs this, otherwise registers aside from @@ -509,13 +504,8 @@ * 50.0 MHz * (0xb + 0xe8ba26/0x2000000)/4 = 5 * 28.636363 MHz * 572.73 MHz before post divide */ - if (clk_freq == 25000000) { - /* 888/ImpactVCBe or 25Mhz xtal */ - ; /* nothing to do */ - } else { - /* HVR1850 or 50MHz xtal */ - cx25840_write(client, 0x2, 0x71); - } + /* HVR1850 or 50MHz xtal */ + cx25840_write(client, 0x2, 0x71); cx25840_write4(client, 0x11c, 0x01d1744c); cx25840_write4(client, 0x118, 0x00000416); cx25840_write4(client, 0x404, 0x0010253e); @@ -558,15 +548,9 @@ /* HVR1850 */ switch (state->id) { case CX23888_AV: - if (clk_freq == 25000000) { - /* 888/ImpactVCBe or 25MHz xtal */ - cx25840_write4(client, 0x10c, 0x01b6db7b); - cx25840_write4(client, 0x108, 0x00000512); - } else { - /* 888/HVR1250 or 50MHz xtal */ - cx25840_write4(client, 0x10c, 0x13333333); - cx25840_write4(client, 0x108, 0x00000515); - } + /* 888/HVR1250 specific */ + cx25840_write4(client, 0x10c, 0x13333333); + cx25840_write4(client, 0x108, 0x00000515); break; default: cx25840_write4(client, 0x10c, 0x002be2c9); @@ -593,7 +577,7 @@ * 368.64 MHz before post divide * 122.88 MHz / 0xa = 12.288 MHz */ - /* HVR1850 or 50MHz xtal or 25MHz xtal */ + /* HVR1850 or 50MHz xtal */ cx25840_write4(client, 0x114, 0x017dbf48); cx25840_write4(client, 0x110, 0x000a030e); break; diff -u linux-lts-xenial-4.4.0/drivers/media/usb/cx231xx/cx231xx-cards.c linux-lts-xenial-4.4.0/drivers/media/usb/cx231xx/cx231xx-cards.c --- linux-lts-xenial-4.4.0/drivers/media/usb/cx231xx/cx231xx-cards.c +++ linux-lts-xenial-4.4.0/drivers/media/usb/cx231xx/cx231xx-cards.c @@ -864,9 +864,6 @@ .driver_info = CX231XX_BOARD_CNXT_RDE_250}, {USB_DEVICE(0x0572, 0x58A0), .driver_info = CX231XX_BOARD_CNXT_RDU_250}, - /* AverMedia DVD EZMaker 7 */ - {USB_DEVICE(0x07ca, 0xc039), - .driver_info = CX231XX_BOARD_CNXT_VIDEO_GRABBER}, {USB_DEVICE(0x2040, 0xb110), .driver_info = CX231XX_BOARD_HAUPPAUGE_USB2_FM_PAL}, {USB_DEVICE(0x2040, 0xb111), diff -u linux-lts-xenial-4.4.0/drivers/media/v4l2-core/v4l2-compat-ioctl32.c linux-lts-xenial-4.4.0/drivers/media/v4l2-core/v4l2-compat-ioctl32.c --- linux-lts-xenial-4.4.0/drivers/media/v4l2-core/v4l2-compat-ioctl32.c +++ linux-lts-xenial-4.4.0/drivers/media/v4l2-core/v4l2-compat-ioctl32.c @@ -864,7 +864,7 @@ get_user(kcontrols, &kp->controls)) return -EFAULT; - if (!count || count > (U32_MAX/sizeof(*ucontrols))) + if (!count) return 0; if (get_user(p, &up->controls)) return -EFAULT; diff -u linux-lts-xenial-4.4.0/drivers/mfd/intel-lpss.c linux-lts-xenial-4.4.0/drivers/mfd/intel-lpss.c --- linux-lts-xenial-4.4.0/drivers/mfd/intel-lpss.c +++ linux-lts-xenial-4.4.0/drivers/mfd/intel-lpss.c @@ -275,11 +275,11 @@ intel_lpss_deassert_reset(lpss); - intel_lpss_set_remap_addr(lpss); - if (!intel_lpss_has_idma(lpss)) return; + intel_lpss_set_remap_addr(lpss); + /* Make sure that SPI multiblock DMA transfers are re-enabled */ if (lpss->type == LPSS_DEV_SPI) writel(value, lpss->priv + LPSS_PRIV_SSP_REG); reverted: --- linux-lts-xenial-4.4.0/drivers/misc/vmw_balloon.c +++ linux-lts-xenial-4.4.0.orig/drivers/misc/vmw_balloon.c @@ -576,9 +576,15 @@ } } + if (b->batch_page) { + vunmap(b->batch_page); + b->batch_page = NULL; + } + + if (b->page) { + __free_page(b->page); + b->page = NULL; + } - /* Clearing the batch_page unconditionally has no adverse effect */ - free_page((unsigned long)b->batch_page); - b->batch_page = NULL; } /* @@ -985,13 +991,16 @@ static bool vmballoon_init_batching(struct vmballoon *b) { + b->page = alloc_page(VMW_PAGE_ALLOC_NOSLEEP); + if (!b->page) + return false; - struct page *page; + b->batch_page = vmap(&b->page, 1, VM_MAP, PAGE_KERNEL); + if (!b->batch_page) { + __free_page(b->page); - page = alloc_page(GFP_KERNEL | __GFP_ZERO); - if (!page) return false; + } - b->batch_page = page_address(page); return true; } diff -u linux-lts-xenial-4.4.0/drivers/mtd/chips/cfi_cmdset_0002.c linux-lts-xenial-4.4.0/drivers/mtd/chips/cfi_cmdset_0002.c --- linux-lts-xenial-4.4.0/drivers/mtd/chips/cfi_cmdset_0002.c +++ linux-lts-xenial-4.4.0/drivers/mtd/chips/cfi_cmdset_0002.c @@ -42,7 +42,7 @@ #define AMD_BOOTLOC_BUG #define FORCE_WORD_WRITE 0 -#define MAX_RETRIES 3 +#define MAX_WORD_RETRIES 3 #define SST49LF004B 0x0060 #define SST49LF040B 0x0050 @@ -1645,7 +1645,7 @@ map_write( map, CMD(0xF0), chip->start ); /* FIXME - should have reset delay before continuing */ - if (++retry_cnt <= MAX_RETRIES) + if (++retry_cnt <= MAX_WORD_RETRIES) goto retry; ret = -EIO; @@ -1878,7 +1878,7 @@ if (time_after(jiffies, timeo) && !chip_ready(map, adr)) break; - if (chip_good(map, adr, datum)) { + if (chip_ready(map, adr)) { xip_enable(map, chip, adr); goto op_done; } @@ -2104,7 +2104,7 @@ map_write(map, CMD(0xF0), chip->start); /* FIXME - should have reset delay before continuing */ - if (++retry_cnt <= MAX_RETRIES) + if (++retry_cnt <= MAX_WORD_RETRIES) goto retry; ret = -EIO; @@ -2239,7 +2239,6 @@ unsigned long int adr; DECLARE_WAITQUEUE(wait, current); int ret = 0; - int retry_cnt = 0; adr = cfi->addr_unlock1; @@ -2257,7 +2256,6 @@ ENABLE_VPP(map); xip_disable(map, chip, adr); - retry: cfi_send_gen_cmd(0xAA, cfi->addr_unlock1, chip->start, map, cfi, cfi->device_type, NULL); cfi_send_gen_cmd(0x55, cfi->addr_unlock2, chip->start, map, cfi, cfi->device_type, NULL); cfi_send_gen_cmd(0x80, cfi->addr_unlock1, chip->start, map, cfi, cfi->device_type, NULL); @@ -2294,13 +2292,12 @@ chip->erase_suspended = 0; } - if (chip_good(map, adr, map_word_ff(map))) + if (chip_ready(map, adr)) break; if (time_after(jiffies, timeo)) { printk(KERN_WARNING "MTD %s(): software timeout\n", __func__ ); - ret = -EIO; break; } @@ -2308,15 +2305,12 @@ UDELAY(map, chip, adr, 1000000/HZ); } /* Did we succeed? */ - if (ret) { + if (!chip_good(map, adr, map_word_ff(map))) { /* reset on all failures. */ map_write( map, CMD(0xF0), chip->start ); /* FIXME - should have reset delay before continuing */ - if (++retry_cnt <= MAX_RETRIES) { - ret = 0; - goto retry; - } + ret = -EIO; } chip->state = FL_READY; @@ -2335,7 +2329,6 @@ unsigned long timeo = jiffies + HZ; DECLARE_WAITQUEUE(wait, current); int ret = 0; - int retry_cnt = 0; adr += chip->start; @@ -2353,7 +2346,6 @@ ENABLE_VPP(map); xip_disable(map, chip, adr); - retry: cfi_send_gen_cmd(0xAA, cfi->addr_unlock1, chip->start, map, cfi, cfi->device_type, NULL); cfi_send_gen_cmd(0x55, cfi->addr_unlock2, chip->start, map, cfi, cfi->device_type, NULL); cfi_send_gen_cmd(0x80, cfi->addr_unlock1, chip->start, map, cfi, cfi->device_type, NULL); @@ -2390,7 +2382,7 @@ chip->erase_suspended = 0; } - if (chip_good(map, adr, map_word_ff(map))) { + if (chip_ready(map, adr)) { xip_enable(map, chip, adr); break; } @@ -2399,7 +2391,6 @@ xip_enable(map, chip, adr); printk(KERN_WARNING "MTD %s(): software timeout\n", __func__ ); - ret = -EIO; break; } @@ -2407,15 +2398,12 @@ UDELAY(map, chip, adr, 1000000/HZ); } /* Did we succeed? */ - if (ret) { + if (!chip_good(map, adr, map_word_ff(map))) { /* reset on all failures. */ map_write( map, CMD(0xF0), chip->start ); /* FIXME - should have reset delay before continuing */ - if (++retry_cnt <= MAX_RETRIES) { - ret = 0; - goto retry; - } + ret = -EIO; } chip->state = FL_READY; @@ -2545,7 +2533,7 @@ struct ppb_lock { struct flchip *chip; - unsigned long adr; + loff_t offset; int locked; }; @@ -2563,9 +2551,8 @@ unsigned long timeo; int ret; - adr += chip->start; mutex_lock(&chip->mutex); - ret = get_chip(map, chip, adr, FL_LOCKING); + ret = get_chip(map, chip, adr + chip->start, FL_LOCKING); if (ret) { mutex_unlock(&chip->mutex); return ret; @@ -2583,8 +2570,8 @@ if (thunk == DO_XXLOCK_ONEBLOCK_LOCK) { chip->state = FL_LOCKING; - map_write(map, CMD(0xA0), adr); - map_write(map, CMD(0x00), adr); + map_write(map, CMD(0xA0), chip->start + adr); + map_write(map, CMD(0x00), chip->start + adr); } else if (thunk == DO_XXLOCK_ONEBLOCK_UNLOCK) { /* * Unlocking of one specific sector is not supported, so we @@ -2622,7 +2609,7 @@ map_write(map, CMD(0x00), chip->start); chip->state = FL_READY; - put_chip(map, chip, adr); + put_chip(map, chip, adr + chip->start); mutex_unlock(&chip->mutex); return ret; @@ -2679,9 +2666,9 @@ * sectors shall be unlocked, so lets keep their locking * status at "unlocked" (locked=0) for the final re-locking. */ - if ((offset < ofs) || (offset >= (ofs + len))) { + if ((adr < ofs) || (adr >= (ofs + len))) { sect[sectors].chip = &cfi->chips[chipnum]; - sect[sectors].adr = adr; + sect[sectors].offset = offset; sect[sectors].locked = do_ppb_xxlock( map, &cfi->chips[chipnum], adr, 0, DO_XXLOCK_ONEBLOCK_GETLOCK); @@ -2695,8 +2682,6 @@ i++; if (adr >> cfi->chipshift) { - if (offset >= (ofs + len)) - break; adr = 0; chipnum++; @@ -2727,7 +2712,7 @@ */ for (i = 0; i < sectors; i++) { if (sect[i].locked) - do_ppb_xxlock(map, sect[i].chip, sect[i].adr, 0, + do_ppb_xxlock(map, sect[i].chip, sect[i].offset, 0, DO_XXLOCK_ONEBLOCK_LOCK); } reverted: --- linux-lts-xenial-4.4.0/drivers/mtd/nand/mxc_nand.c +++ linux-lts-xenial-4.4.0.orig/drivers/mtd/nand/mxc_nand.c @@ -49,7 +49,7 @@ #define NFC_V1_V2_CONFIG (host->regs + 0x0a) #define NFC_V1_V2_ECC_STATUS_RESULT (host->regs + 0x0c) #define NFC_V1_V2_RSLTMAIN_AREA (host->regs + 0x0e) +#define NFC_V1_V2_RSLTSPARE_AREA (host->regs + 0x10) -#define NFC_V21_RSLTSPARE_AREA (host->regs + 0x10) #define NFC_V1_V2_WRPROT (host->regs + 0x12) #define NFC_V1_UNLOCKSTART_BLKADDR (host->regs + 0x14) #define NFC_V1_UNLOCKEND_BLKADDR (host->regs + 0x16) @@ -1034,9 +1034,6 @@ writew(config1, NFC_V1_V2_CONFIG1); /* preset operation */ - /* spare area size in 16-bit half-words */ - writew(mtd->oobsize / 2, NFC_V21_RSLTSPARE_AREA); - /* Unlock the internal RAM Buffer */ writew(0x2, NFC_V1_V2_CONFIG); diff -u linux-lts-xenial-4.4.0/drivers/mtd/ubi/build.c linux-lts-xenial-4.4.0/drivers/mtd/ubi/build.c --- linux-lts-xenial-4.4.0/drivers/mtd/ubi/build.c +++ linux-lts-xenial-4.4.0/drivers/mtd/ubi/build.c @@ -1132,9 +1132,6 @@ */ get_device(&ubi->dev); -#ifdef CONFIG_MTD_UBI_FASTMAP - cancel_work_sync(&ubi->fm_work); -#endif ubi_debugfs_exit_dev(ubi); uif_close(ubi); diff -u linux-lts-xenial-4.4.0/drivers/mtd/ubi/eba.c linux-lts-xenial-4.4.0/drivers/mtd/ubi/eba.c --- linux-lts-xenial-4.4.0/drivers/mtd/ubi/eba.c +++ linux-lts-xenial-4.4.0/drivers/mtd/ubi/eba.c @@ -350,82 +350,6 @@ return err; } -#ifdef CONFIG_MTD_UBI_FASTMAP -/** - * check_mapping - check and fixup a mapping - * @ubi: UBI device description object - * @vol: volume description object - * @lnum: logical eraseblock number - * @pnum: physical eraseblock number - * - * Checks whether a given mapping is valid. Fastmap cannot track LEB unmap - * operations, if such an operation is interrupted the mapping still looks - * good, but upon first read an ECC is reported to the upper layer. - * Normaly during the full-scan at attach time this is fixed, for Fastmap - * we have to deal with it while reading. - * If the PEB behind a LEB shows this symthom we change the mapping to - * %UBI_LEB_UNMAPPED and schedule the PEB for erasure. - * - * Returns 0 on success, negative error code in case of failure. - */ -static int check_mapping(struct ubi_device *ubi, struct ubi_volume *vol, int lnum, - int *pnum) -{ - int err; - struct ubi_vid_hdr *vid_hdr; - - if (!ubi->fast_attach) - return 0; - - vid_hdr = ubi_zalloc_vid_hdr(ubi, GFP_NOFS); - if (!vid_hdr) - return -ENOMEM; - - err = ubi_io_read_vid_hdr(ubi, *pnum, vid_hdr, 0); - if (err > 0 && err != UBI_IO_BITFLIPS) { - int torture = 0; - - switch (err) { - case UBI_IO_FF: - case UBI_IO_FF_BITFLIPS: - case UBI_IO_BAD_HDR: - case UBI_IO_BAD_HDR_EBADMSG: - break; - default: - ubi_assert(0); - } - - if (err == UBI_IO_BAD_HDR_EBADMSG || err == UBI_IO_FF_BITFLIPS) - torture = 1; - - down_read(&ubi->fm_eba_sem); - vol->eba_tbl[lnum] = UBI_LEB_UNMAPPED; - up_read(&ubi->fm_eba_sem); - ubi_wl_put_peb(ubi, vol->vol_id, lnum, *pnum, torture); - - *pnum = UBI_LEB_UNMAPPED; - } else if (err < 0) { - ubi_err(ubi, "unable to read VID header back from PEB %i: %i", - *pnum, err); - - goto out_free; - } - - err = 0; - -out_free: - ubi_free_vid_hdr(ubi, vid_hdr); - - return err; -} -#else -static int check_mapping(struct ubi_device *ubi, struct ubi_volume *vol, int lnum, - int *pnum) -{ - return 0; -} -#endif - /** * ubi_eba_read_leb - read data. * @ubi: UBI device description object @@ -457,13 +381,7 @@ return err; pnum = vol->eba_tbl[lnum]; - if (pnum >= 0) { - err = check_mapping(ubi, vol, lnum, &pnum); - if (err < 0) - goto out_unlock; - } - - if (pnum == UBI_LEB_UNMAPPED) { + if (pnum < 0) { /* * The logical eraseblock is not mapped, fill the whole buffer * with 0xFF bytes. The exception is static volumes for which @@ -779,14 +697,6 @@ pnum = vol->eba_tbl[lnum]; if (pnum >= 0) { - err = check_mapping(ubi, vol, lnum, &pnum); - if (err < 0) { - leb_write_unlock(ubi, vol_id, lnum); - return err; - } - } - - if (pnum >= 0) { dbg_eba("write %d bytes at offset %d of LEB %d:%d, PEB %d", len, offset, vol_id, lnum, pnum); diff -u linux-lts-xenial-4.4.0/drivers/mtd/ubi/wl.c linux-lts-xenial-4.4.0/drivers/mtd/ubi/wl.c --- linux-lts-xenial-4.4.0/drivers/mtd/ubi/wl.c +++ linux-lts-xenial-4.4.0/drivers/mtd/ubi/wl.c @@ -1479,7 +1479,6 @@ } dbg_wl("background thread \"%s\" is killed", ubi->bgt_name); - ubi->thread_enabled = 0; return 0; } @@ -1489,6 +1488,9 @@ */ static void shutdown_work(struct ubi_device *ubi) { +#ifdef CONFIG_MTD_UBI_FASTMAP + flush_work(&ubi->fm_work); +#endif while (!list_empty(&ubi->works)) { struct ubi_work *wrk; reverted: --- linux-lts-xenial-4.4.0/drivers/net/bonding/bond_options.c +++ linux-lts-xenial-4.4.0.orig/drivers/net/bonding/bond_options.c @@ -1115,7 +1115,6 @@ slave->dev->name); rcu_assign_pointer(bond->primary_slave, slave); strcpy(bond->params.primary, slave->dev->name); - bond->force_primary = true; bond_select_active_slave(bond); goto out; } reverted: --- linux-lts-xenial-4.4.0/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c +++ linux-lts-xenial-4.4.0.orig/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c @@ -594,7 +594,7 @@ * slots for the highest priority. */ REG_WR(bp, (port) ? NIG_REG_P1_TX_ARB_NUM_STRICT_ARB_SLOTS : + NIG_REG_P1_TX_ARB_NUM_STRICT_ARB_SLOTS, 0x100); - NIG_REG_P0_TX_ARB_NUM_STRICT_ARB_SLOTS, 0x100); /* Mapping between the CREDIT_WEIGHT registers and actual client * numbers */ diff -u linux-lts-xenial-4.4.0/drivers/net/ethernet/cisco/enic/enic_main.c linux-lts-xenial-4.4.0/drivers/net/ethernet/cisco/enic/enic_main.c --- linux-lts-xenial-4.4.0/drivers/net/ethernet/cisco/enic/enic_main.c +++ linux-lts-xenial-4.4.0/drivers/net/ethernet/cisco/enic/enic_main.c @@ -2543,11 +2543,11 @@ pci_set_master(pdev); /* Query PCI controller on system for DMA addressing - * limitation for the device. Try 47-bit first, and + * limitation for the device. Try 64-bit first, and * fail to 32-bit. */ - err = pci_set_dma_mask(pdev, DMA_BIT_MASK(47)); + err = pci_set_dma_mask(pdev, DMA_BIT_MASK(64)); if (err) { err = pci_set_dma_mask(pdev, DMA_BIT_MASK(32)); if (err) { @@ -2561,10 +2561,10 @@ goto err_out_release_regions; } } else { - err = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(47)); + err = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64)); if (err) { dev_err(dev, "Unable to obtain %u-bit DMA " - "for consistent allocations, aborting\n", 47); + "for consistent allocations, aborting\n", 64); goto err_out_release_regions; } using_dac = 1; diff -u linux-lts-xenial-4.4.0/drivers/net/ethernet/mellanox/mlx4/qp.c linux-lts-xenial-4.4.0/drivers/net/ethernet/mellanox/mlx4/qp.c --- linux-lts-xenial-4.4.0/drivers/net/ethernet/mellanox/mlx4/qp.c +++ linux-lts-xenial-4.4.0/drivers/net/ethernet/mellanox/mlx4/qp.c @@ -386,11 +386,11 @@ struct mlx4_qp_table *qp_table = &mlx4_priv(dev)->qp_table; struct mlx4_qp *qp; - spin_lock_irq(&qp_table->lock); + spin_lock(&qp_table->lock); qp = __mlx4_qp_lookup(dev, qpn); - spin_unlock_irq(&qp_table->lock); + spin_unlock(&qp_table->lock); return qp; } reverted: --- linux-lts-xenial-4.4.0/drivers/net/ethernet/natsemi/sonic.c +++ linux-lts-xenial-4.4.0.orig/drivers/net/ethernet/natsemi/sonic.c @@ -71,7 +71,7 @@ for (i = 0; i < SONIC_NUM_RRS; i++) { dma_addr_t laddr = dma_map_single(lp->device, skb_put(lp->rx_skb[i], SONIC_RBSIZE), SONIC_RBSIZE, DMA_FROM_DEVICE); + if (!laddr) { - if (dma_mapping_error(lp->device, laddr)) { while(i > 0) { /* free any that were mapped successfully */ i--; dma_unmap_single(lp->device, lp->rx_laddr[i], SONIC_RBSIZE, DMA_FROM_DEVICE); reverted: --- linux-lts-xenial-4.4.0/drivers/net/ethernet/qlogic/qed/qed_cxt.c +++ linux-lts-xenial-4.4.0.orig/drivers/net/ethernet/qlogic/qed/qed_cxt.c @@ -43,7 +43,7 @@ #define ILT_CFG_REG(cli, reg) PSWRQ2_REG_ ## cli ## _ ## reg ## _RT_OFFSET /* ILT entry structure */ +#define ILT_ENTRY_PHY_ADDR_MASK 0x000FFFFFFFFFFFULL -#define ILT_ENTRY_PHY_ADDR_MASK (~0ULL >> 12) #define ILT_ENTRY_PHY_ADDR_SHIFT 0 #define ILT_ENTRY_VALID_MASK 0x1ULL #define ILT_ENTRY_VALID_SHIFT 52 diff -u linux-lts-xenial-4.4.0/drivers/net/ethernet/sfc/ef10.c linux-lts-xenial-4.4.0/drivers/net/ethernet/sfc/ef10.c --- linux-lts-xenial-4.4.0/drivers/net/ethernet/sfc/ef10.c +++ linux-lts-xenial-4.4.0/drivers/net/ethernet/sfc/ef10.c @@ -181,6 +181,13 @@ MCDI_WORD(outbuf, GET_CAPABILITIES_OUT_TX_DPCPU_FW_ID); if (!(nic_data->datapath_caps & + (1 << MC_CMD_GET_CAPABILITIES_OUT_TX_TSO_LBN))) { + netif_err(efx, drv, efx->net_dev, + "current firmware does not support TSO\n"); + return -ENODEV; + } + + if (!(nic_data->datapath_caps & (1 << MC_CMD_GET_CAPABILITIES_OUT_RX_PREFIX_LEN_14_LBN))) { netif_err(efx, probe, efx->net_dev, "current firmware does not support an RX prefix\n"); @@ -1806,12 +1813,6 @@ ESF_DZ_TX_OPTION_UDP_TCP_CSUM, csum_offload, ESF_DZ_TX_OPTION_IP_CSUM, csum_offload); tx_queue->write_count = 1; - - if (nic_data->datapath_caps & - (1 << MC_CMD_GET_CAPABILITIES_OUT_TX_TSO_LBN)) { - tx_queue->tso_version = 1; - } - wmb(); efx_ef10_push_tx_desc(tx_queue, txd); reverted: --- linux-lts-xenial-4.4.0/drivers/net/ethernet/sfc/efx.c +++ linux-lts-xenial-4.4.0.orig/drivers/net/ethernet/sfc/efx.c @@ -2785,12 +2785,6 @@ .driver_data = (unsigned long) &efx_hunt_a0_vf_nic_type}, {PCI_DEVICE(PCI_VENDOR_ID_SOLARFLARE, 0x0923), /* SFC9140 PF */ .driver_data = (unsigned long) &efx_hunt_a0_nic_type}, - {PCI_DEVICE(PCI_VENDOR_ID_SOLARFLARE, 0x1923), /* SFC9140 VF */ - .driver_data = (unsigned long) &efx_hunt_a0_vf_nic_type}, - {PCI_DEVICE(PCI_VENDOR_ID_SOLARFLARE, 0x0a03), /* SFC9220 PF */ - .driver_data = (unsigned long) &efx_hunt_a0_nic_type}, - {PCI_DEVICE(PCI_VENDOR_ID_SOLARFLARE, 0x1a03), /* SFC9220 VF */ - .driver_data = (unsigned long) &efx_hunt_a0_vf_nic_type}, {0} /* end of list */ }; reverted: --- linux-lts-xenial-4.4.0/drivers/net/ethernet/sfc/net_driver.h +++ linux-lts-xenial-4.4.0.orig/drivers/net/ethernet/sfc/net_driver.h @@ -182,7 +182,6 @@ * * @efx: The associated Efx NIC * @queue: DMA queue number - * @tso_version: Version of TSO in use for this queue. * @channel: The associated channel * @core_txq: The networking core TX queue structure * @buffer: The software buffer ring @@ -229,7 +228,6 @@ /* Members which don't change on the fast path */ struct efx_nic *efx ____cacheline_aligned_in_smp; unsigned queue; - unsigned int tso_version; struct efx_channel *channel; struct netdev_queue *core_txq; struct efx_tx_buffer *buffer; diff -u linux-lts-xenial-4.4.0/drivers/net/ethernet/sfc/tx.c linux-lts-xenial-4.4.0/drivers/net/ethernet/sfc/tx.c --- linux-lts-xenial-4.4.0/drivers/net/ethernet/sfc/tx.c +++ linux-lts-xenial-4.4.0/drivers/net/ethernet/sfc/tx.c @@ -1016,17 +1016,13 @@ /* Parse the SKB header and initialise state. */ static int tso_start(struct tso_state *st, struct efx_nic *efx, - struct efx_tx_queue *tx_queue, const struct sk_buff *skb) { + bool use_opt_desc = efx_nic_rev(efx) >= EFX_REV_HUNT_A0; struct device *dma_dev = &efx->pci_dev->dev; unsigned int header_len, in_len; - bool use_opt_desc = false; dma_addr_t dma_addr; - if (tx_queue->tso_version == 1) - use_opt_desc = true; - st->ip_off = skb_network_header(skb) - skb->data; st->tcp_off = skb_transport_header(skb) - skb->data; header_len = st->tcp_off + (tcp_hdr(skb)->doff << 2u); @@ -1281,7 +1277,7 @@ /* Find the packet protocol and sanity-check it */ state.protocol = efx_tso_check_protocol(skb); - rc = tso_start(&state, efx, tx_queue, skb); + rc = tso_start(&state, efx, skb); if (rc) goto mem_err; reverted: --- linux-lts-xenial-4.4.0/drivers/net/irda/w83977af_ir.c +++ linux-lts-xenial-4.4.0.orig/drivers/net/irda/w83977af_ir.c @@ -518,9 +518,7 @@ mtt = irda_get_mtt(skb); pr_debug("%s(%ld), mtt=%d\n", __func__ , jiffies, mtt); + if (mtt) - if (mtt > 1000) - mdelay(mtt/1000); - else if (mtt) udelay(mtt); /* Enable DMA interrupt */ reverted: --- linux-lts-xenial-4.4.0/drivers/net/phy/bcm-cygnus.c +++ linux-lts-xenial-4.4.0.orig/drivers/net/phy/bcm-cygnus.c @@ -61,17 +61,17 @@ return rc; /* make rcal=100, since rdb default is 000 */ + rc = bcm_phy_write_exp(phydev, MII_BRCM_CORE_EXPB1, 0x10); - rc = bcm_phy_write_exp_sel(phydev, MII_BRCM_CORE_EXPB1, 0x10); if (rc < 0) return rc; /* CORE_EXPB0, Reset R_CAL/RC_CAL Engine */ + rc = bcm_phy_write_exp(phydev, MII_BRCM_CORE_EXPB0, 0x10); - rc = bcm_phy_write_exp_sel(phydev, MII_BRCM_CORE_EXPB0, 0x10); if (rc < 0) return rc; /* CORE_EXPB0, Disable Reset R_CAL/RC_CAL Engine */ + rc = bcm_phy_write_exp(phydev, MII_BRCM_CORE_EXPB0, 0x00); - rc = bcm_phy_write_exp_sel(phydev, MII_BRCM_CORE_EXPB0, 0x00); return 0; } reverted: --- linux-lts-xenial-4.4.0/drivers/net/phy/bcm-phy-lib.h +++ linux-lts-xenial-4.4.0.orig/drivers/net/phy/bcm-phy-lib.h @@ -14,18 +14,11 @@ #ifndef _LINUX_BCM_PHY_LIB_H #define _LINUX_BCM_PHY_LIB_H -#include #include int bcm_phy_write_exp(struct phy_device *phydev, u16 reg, u16 val); int bcm_phy_read_exp(struct phy_device *phydev, u16 reg); -static inline int bcm_phy_write_exp_sel(struct phy_device *phydev, - u16 reg, u16 val) -{ - return bcm_phy_write_exp(phydev, reg | MII_BCM54XX_EXP_SEL_ER, val); -} - int bcm_phy_write_misc(struct phy_device *phydev, u16 reg, u16 chl, u16 value); int bcm_phy_read_misc(struct phy_device *phydev, reverted: --- linux-lts-xenial-4.4.0/drivers/net/phy/bcm7xxx.c +++ linux-lts-xenial-4.4.0.orig/drivers/net/phy/bcm7xxx.c @@ -48,10 +48,10 @@ static void r_rc_cal_reset(struct phy_device *phydev) { /* Reset R_CAL/RC_CAL Engine */ + bcm_phy_write_exp(phydev, 0x00b0, 0x0010); - bcm_phy_write_exp_sel(phydev, 0x00b0, 0x0010); /* Disable Reset R_AL/RC_CAL Engine */ + bcm_phy_write_exp(phydev, 0x00b0, 0x0000); - bcm_phy_write_exp_sel(phydev, 0x00b0, 0x0000); } static int bcm7xxx_28nm_b0_afe_config_init(struct phy_device *phydev) diff -u linux-lts-xenial-4.4.0/drivers/net/team/team.c linux-lts-xenial-4.4.0/drivers/net/team/team.c --- linux-lts-xenial-4.4.0/drivers/net/team/team.c +++ linux-lts-xenial-4.4.0/drivers/net/team/team.c @@ -983,8 +983,7 @@ static void ___team_compute_features(struct team *team) { struct team_port *port; - netdev_features_t vlan_features = TEAM_VLAN_FEATURES & - NETIF_F_ALL_FOR_ALL; + u32 vlan_features = TEAM_VLAN_FEATURES & NETIF_F_ALL_FOR_ALL; unsigned short max_hard_header_len = ETH_HLEN; unsigned int dst_release_flag = IFF_XMIT_DST_RELEASE | IFF_XMIT_DST_RELEASE_PERM; diff -u linux-lts-xenial-4.4.0/drivers/net/usb/cdc_mbim.c linux-lts-xenial-4.4.0/drivers/net/usb/cdc_mbim.c --- linux-lts-xenial-4.4.0/drivers/net/usb/cdc_mbim.c +++ linux-lts-xenial-4.4.0/drivers/net/usb/cdc_mbim.c @@ -593,7 +593,7 @@ */ static const struct driver_info cdc_mbim_info_ndp_to_end = { .description = "CDC MBIM", - .flags = FLAG_NO_SETINT | FLAG_MULTI_PACKET | FLAG_WWAN | FLAG_SEND_ZLP, + .flags = FLAG_NO_SETINT | FLAG_MULTI_PACKET | FLAG_WWAN, .bind = cdc_mbim_bind, .unbind = cdc_mbim_unbind, .manage_power = cdc_mbim_manage_power, diff -u linux-lts-xenial-4.4.0/drivers/net/usb/cdc_ncm.c linux-lts-xenial-4.4.0/drivers/net/usb/cdc_ncm.c --- linux-lts-xenial-4.4.0/drivers/net/usb/cdc_ncm.c +++ linux-lts-xenial-4.4.0/drivers/net/usb/cdc_ncm.c @@ -1075,7 +1075,7 @@ * accordingly. Otherwise, we should check here. */ if (ctx->drvflags & CDC_NCM_FLAG_NDP_TO_END) - delayed_ndp_size = ALIGN(ctx->max_ndp_size, ctx->tx_ndp_modulus); + delayed_ndp_size = ctx->max_ndp_size; else delayed_ndp_size = 0; @@ -1208,7 +1208,7 @@ /* If requested, put NDP at end of frame. */ if (ctx->drvflags & CDC_NCM_FLAG_NDP_TO_END) { nth16 = (struct usb_cdc_ncm_nth16 *)skb_out->data; - cdc_ncm_align_tail(skb_out, ctx->tx_ndp_modulus, 0, ctx->tx_max - ctx->max_ndp_size); + cdc_ncm_align_tail(skb_out, ctx->tx_ndp_modulus, 0, ctx->tx_max); nth16->wNdpIndex = cpu_to_le16(skb_out->len); memcpy(skb_put(skb_out, ctx->max_ndp_size), ctx->delayed_ndp16, ctx->max_ndp_size); diff -u linux-lts-xenial-4.4.0/drivers/net/usb/qmi_wwan.c linux-lts-xenial-4.4.0/drivers/net/usb/qmi_wwan.c --- linux-lts-xenial-4.4.0/drivers/net/usb/qmi_wwan.c +++ linux-lts-xenial-4.4.0/drivers/net/usb/qmi_wwan.c @@ -635,7 +635,6 @@ {QMI_FIXED_INTF(0x05c6, 0x920d, 0)}, {QMI_FIXED_INTF(0x05c6, 0x920d, 5)}, {QMI_FIXED_INTF(0x0846, 0x68a2, 8)}, - {QMI_FIXED_INTF(0x0846, 0x68d3, 8)}, /* Netgear Aircard 779S */ {QMI_FIXED_INTF(0x12d1, 0x140c, 1)}, /* Huawei E173 */ {QMI_FIXED_INTF(0x12d1, 0x14ac, 1)}, /* Huawei E1820 */ {QMI_FIXED_INTF(0x1435, 0xd181, 3)}, /* Wistron NeWeb D18Q1 */ diff -u linux-lts-xenial-4.4.0/drivers/net/wireless/ath/ath10k/htt_rx.c linux-lts-xenial-4.4.0/drivers/net/wireless/ath/ath10k/htt_rx.c --- linux-lts-xenial-4.4.0/drivers/net/wireless/ath/ath10k/htt_rx.c +++ linux-lts-xenial-4.4.0/drivers/net/wireless/ath/ath10k/htt_rx.c @@ -1179,7 +1179,6 @@ size_t hdr_len, crypto_len; void *rfc1042; bool is_first, is_last, is_amsdu; - int bytes_aligned = ar->hw_params.decap_align_bytes; rxd = (void *)msdu->data - sizeof(*rxd); hdr = (void *)rxd->rx_hdr_status; @@ -1196,8 +1195,8 @@ hdr_len = ieee80211_hdrlen(hdr->frame_control); crypto_len = ath10k_htt_rx_crypto_param_len(ar, enctype); - rfc1042 += round_up(hdr_len, bytes_aligned) + - round_up(crypto_len, bytes_aligned); + rfc1042 += round_up(hdr_len, 4) + + round_up(crypto_len, 4); } if (is_amsdu) diff -u linux-lts-xenial-4.4.0/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c linux-lts-xenial-4.4.0/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c --- linux-lts-xenial-4.4.0/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c +++ linux-lts-xenial-4.4.0/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c @@ -6167,7 +6167,7 @@ req->alpha2[0], req->alpha2[1]); /* ignore non-ISO3166 country codes */ - for (i = 0; i < 2; i++) + for (i = 0; i < sizeof(req->alpha2); i++) if (req->alpha2[i] < 'A' || req->alpha2[i] > 'Z') { brcmf_err("not a ISO3166 code\n"); return; reverted: --- linux-lts-xenial-4.4.0/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/rf.c +++ linux-lts-xenial-4.4.0.orig/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/rf.c @@ -304,6 +304,9 @@ writeVal = 0x00000000; if (rtlpriv->dm.dynamic_txhighpower_lvl == TXHIGHPWRLEVEL_BT1) writeVal = writeVal - 0x06060606; + else if (rtlpriv->dm.dynamic_txhighpower_lvl == + TXHIGHPWRLEVEL_BT2) + writeVal = writeVal; *(p_outwriteval + rf) = writeVal; } } diff -u linux-lts-xenial-4.4.0/drivers/nvdimm/bus.c linux-lts-xenial-4.4.0/drivers/nvdimm/bus.c --- linux-lts-xenial-4.4.0/drivers/nvdimm/bus.c +++ linux-lts-xenial-4.4.0/drivers/nvdimm/bus.c @@ -237,18 +237,14 @@ { struct device *dev = disk->driverfs_dev; struct nd_region *nd_region = to_nd_region(dev->parent); - int disk_ro = get_disk_ro(disk); + const char *pol = nd_region->ro ? "only" : "write"; - /* - * Upgrade to read-only if the region is read-only preserve as - * read-only if the disk is already read-only. - */ - if (disk_ro || nd_region->ro == disk_ro) + if (nd_region->ro == get_disk_ro(disk)) return 0; - dev_info(dev, "%s read-only, marking %s read-only\n", - dev_name(&nd_region->dev), disk->disk_name); - set_disk_ro(disk, 1); + dev_info(dev, "%s read-%s, marking %s read-%s\n", + dev_name(&nd_region->dev), pol, disk->disk_name, pol); + set_disk_ro(disk, nd_region->ro); return 0; diff -u linux-lts-xenial-4.4.0/drivers/nvme/host/pci.c linux-lts-xenial-4.4.0/drivers/nvme/host/pci.c --- linux-lts-xenial-4.4.0/drivers/nvme/host/pci.c +++ linux-lts-xenial-4.4.0/drivers/nvme/host/pci.c @@ -1341,11 +1341,11 @@ if (result < 0) goto release_cq; - nvme_init_queue(nvmeq, qid); result = queue_request_irq(dev, nvmeq, nvmeq->irqname); if (result < 0) goto release_sq; + nvme_init_queue(nvmeq, qid); return result; release_sq: @@ -1464,7 +1464,6 @@ goto free_nvmeq; nvmeq->cq_vector = 0; - nvme_init_queue(nvmeq, 0); result = queue_request_irq(dev, nvmeq, nvmeq->irqname); if (result) { nvmeq->cq_vector = -1; @@ -2065,6 +2064,7 @@ if (result) goto unmap; + nvme_init_queue(dev->queues[0], 0); result = nvme_alloc_admin_tags(dev); if (result) goto disable; reverted: --- linux-lts-xenial-4.4.0/drivers/of/unittest.c +++ linux-lts-xenial-4.4.0.orig/drivers/of/unittest.c @@ -156,20 +156,20 @@ /* Add a new property - should pass*/ prop->name = "new-property"; prop->value = "new-property-data"; + prop->length = strlen(prop->value); - prop->length = strlen(prop->value) + 1; unittest(of_add_property(np, prop) == 0, "Adding a new property failed\n"); /* Try to add an existing property - should fail */ prop++; prop->name = "new-property"; prop->value = "new-property-data-should-fail"; + prop->length = strlen(prop->value); - prop->length = strlen(prop->value) + 1; unittest(of_add_property(np, prop) != 0, "Adding an existing property should have failed\n"); /* Try to modify an existing property - should pass */ prop->value = "modify-property-data-should-pass"; + prop->length = strlen(prop->value); - prop->length = strlen(prop->value) + 1; unittest(of_update_property(np, prop) == 0, "Updating an existing property should have passed\n"); @@ -177,7 +177,7 @@ prop++; prop->name = "modify-property"; prop->value = "modify-missing-property-data-should-pass"; + prop->length = strlen(prop->value); - prop->length = strlen(prop->value) + 1; unittest(of_update_property(np, prop) == 0, "Updating a missing property should have passed\n"); diff -u linux-lts-xenial-4.4.0/drivers/pci/host/pci-hyperv.c linux-lts-xenial-4.4.0/drivers/pci/host/pci-hyperv.c --- linux-lts-xenial-4.4.0/drivers/pci/host/pci-hyperv.c +++ linux-lts-xenial-4.4.0/drivers/pci/host/pci-hyperv.c @@ -54,6 +54,7 @@ #include #include #include +#include #include #include #include reverted: --- linux-lts-xenial-4.4.0/drivers/pci/hotplug/pciehp.h +++ linux-lts-xenial-4.4.0.orig/drivers/pci/hotplug/pciehp.h @@ -134,7 +134,7 @@ int pcie_init_notification(struct controller *ctrl); int pciehp_enable_slot(struct slot *p_slot); int pciehp_disable_slot(struct slot *p_slot); +void pcie_enable_notification(struct controller *ctrl); -void pcie_reenable_notification(struct controller *ctrl); int pciehp_power_on_slot(struct slot *slot); void pciehp_power_off_slot(struct slot *slot); void pciehp_get_power_status(struct slot *slot, u8 *status); reverted: --- linux-lts-xenial-4.4.0/drivers/pci/hotplug/pciehp_core.c +++ linux-lts-xenial-4.4.0.orig/drivers/pci/hotplug/pciehp_core.c @@ -295,7 +295,7 @@ ctrl = get_service_data(dev); /* reinitialize the chipset's event detection logic */ + pcie_enable_notification(ctrl); - pcie_reenable_notification(ctrl); slot = ctrl->slot; reverted: --- linux-lts-xenial-4.4.0/drivers/pci/hotplug/pciehp_hpc.c +++ linux-lts-xenial-4.4.0.orig/drivers/pci/hotplug/pciehp_hpc.c @@ -628,7 +628,7 @@ return IRQ_HANDLED; } +void pcie_enable_notification(struct controller *ctrl) -static void pcie_enable_notification(struct controller *ctrl) { u16 cmd, mask; @@ -666,17 +666,6 @@ pci_pcie_cap(ctrl->pcie->port) + PCI_EXP_SLTCTL, cmd); } -void pcie_reenable_notification(struct controller *ctrl) -{ - /* - * Clear both Presence and Data Link Layer Changed to make sure - * those events still fire after we have re-enabled them. - */ - pcie_capability_write_word(ctrl->pcie->port, PCI_EXP_SLTSTA, - PCI_EXP_SLTSTA_PDC | PCI_EXP_SLTSTA_DLLSC); - pcie_enable_notification(ctrl); -} - static void pcie_disable_notification(struct controller *ctrl) { u16 mask; diff -u linux-lts-xenial-4.4.0/drivers/s390/scsi/zfcp_dbf.c linux-lts-xenial-4.4.0/drivers/s390/scsi/zfcp_dbf.c --- linux-lts-xenial-4.4.0/drivers/s390/scsi/zfcp_dbf.c +++ linux-lts-xenial-4.4.0/drivers/s390/scsi/zfcp_dbf.c @@ -628,40 +627,0 @@ -/** - * zfcp_dbf_scsi_eh() - Trace event for special cases of scsi_eh callbacks. - * @tag: Identifier for event. - * @adapter: Pointer to zfcp adapter as context for this event. - * @scsi_id: SCSI ID/target to indicate scope of task management function (TMF). - * @ret: Return value of calling function. - * - * This SCSI trace variant does not depend on any of: - * scsi_cmnd, zfcp_fsf_req, scsi_device. - */ -void zfcp_dbf_scsi_eh(char *tag, struct zfcp_adapter *adapter, - unsigned int scsi_id, int ret) -{ - struct zfcp_dbf *dbf = adapter->dbf; - struct zfcp_dbf_scsi *rec = &dbf->scsi_buf; - unsigned long flags; - static int const level = 1; - - if (unlikely(!debug_level_enabled(adapter->dbf->scsi, level))) - return; - - spin_lock_irqsave(&dbf->scsi_lock, flags); - memset(rec, 0, sizeof(*rec)); - - memcpy(rec->tag, tag, ZFCP_DBF_TAG_LEN); - rec->id = ZFCP_DBF_SCSI_CMND; - rec->scsi_result = ret; /* re-use field, int is 4 bytes and fits */ - rec->scsi_retries = ~0; - rec->scsi_allowed = ~0; - rec->fcp_rsp_info = ~0; - rec->scsi_id = scsi_id; - rec->scsi_lun = (u32)ZFCP_DBF_INVALID_LUN; - rec->scsi_lun_64_hi = (u32)(ZFCP_DBF_INVALID_LUN >> 32); - rec->host_scribble = ~0; - memset(rec->scsi_opcode, 0xff, ZFCP_DBF_SCSI_OPCODE); - - debug_event(dbf->scsi, level, rec, sizeof(*rec)); - spin_unlock_irqrestore(&dbf->scsi_lock, flags); -} - diff -u linux-lts-xenial-4.4.0/drivers/s390/scsi/zfcp_erp.c linux-lts-xenial-4.4.0/drivers/s390/scsi/zfcp_erp.c --- linux-lts-xenial-4.4.0/drivers/s390/scsi/zfcp_erp.c +++ linux-lts-xenial-4.4.0/drivers/s390/scsi/zfcp_erp.c @@ -34,28 +34,11 @@ ZFCP_ERP_STEP_LUN_OPENING = 0x2000, }; -/** - * enum zfcp_erp_act_type - Type of ERP action object. - * @ZFCP_ERP_ACTION_REOPEN_LUN: LUN recovery. - * @ZFCP_ERP_ACTION_REOPEN_PORT: Port recovery. - * @ZFCP_ERP_ACTION_REOPEN_PORT_FORCED: Forced port recovery. - * @ZFCP_ERP_ACTION_REOPEN_ADAPTER: Adapter recovery. - * @ZFCP_ERP_ACTION_NONE: Eyecatcher pseudo flag to bitwise or-combine with - * either of the first four enum values. - * Used to indicate that an ERP action could not be - * set up despite a detected need for some recovery. - * @ZFCP_ERP_ACTION_FAILED: Eyecatcher pseudo flag to bitwise or-combine with - * either of the first four enum values. - * Used to indicate that ERP not needed because - * the object has ZFCP_STATUS_COMMON_ERP_FAILED. - */ enum zfcp_erp_act_type { ZFCP_ERP_ACTION_REOPEN_LUN = 1, ZFCP_ERP_ACTION_REOPEN_PORT = 2, ZFCP_ERP_ACTION_REOPEN_PORT_FORCED = 3, ZFCP_ERP_ACTION_REOPEN_ADAPTER = 4, - ZFCP_ERP_ACTION_NONE = 0xc0, - ZFCP_ERP_ACTION_FAILED = 0xe0, }; enum zfcp_erp_act_state { @@ -142,49 +125,6 @@ } } -static int zfcp_erp_handle_failed(int want, struct zfcp_adapter *adapter, - struct zfcp_port *port, - struct scsi_device *sdev) -{ - int need = want; - struct zfcp_scsi_dev *zsdev; - - switch (want) { - case ZFCP_ERP_ACTION_REOPEN_LUN: - zsdev = sdev_to_zfcp(sdev); - if (atomic_read(&zsdev->status) & ZFCP_STATUS_COMMON_ERP_FAILED) - need = 0; - break; - case ZFCP_ERP_ACTION_REOPEN_PORT_FORCED: - if (atomic_read(&port->status) & ZFCP_STATUS_COMMON_ERP_FAILED) - need = 0; - break; - case ZFCP_ERP_ACTION_REOPEN_PORT: - if (atomic_read(&port->status) & - ZFCP_STATUS_COMMON_ERP_FAILED) { - need = 0; - /* ensure propagation of failed status to new devices */ - zfcp_erp_set_port_status( - port, ZFCP_STATUS_COMMON_ERP_FAILED); - } - break; - case ZFCP_ERP_ACTION_REOPEN_ADAPTER: - if (atomic_read(&adapter->status) & - ZFCP_STATUS_COMMON_ERP_FAILED) { - need = 0; - /* ensure propagation of failed status to new devices */ - zfcp_erp_set_adapter_status( - adapter, ZFCP_STATUS_COMMON_ERP_FAILED); - } - break; - default: - need = 0; - break; - } - - return need; -} - static int zfcp_erp_required_act(int want, struct zfcp_adapter *adapter, struct zfcp_port *port, struct scsi_device *sdev) @@ -308,27 +248,16 @@ int retval = 1, need; struct zfcp_erp_action *act; - need = zfcp_erp_handle_failed(want, adapter, port, sdev); - if (!need) { - need = ZFCP_ERP_ACTION_FAILED; /* marker for trace */ - goto out; - } - - if (!adapter->erp_thread) { - need = ZFCP_ERP_ACTION_NONE; /* marker for trace */ - retval = -EIO; - goto out; - } + if (!adapter->erp_thread) + return -EIO; need = zfcp_erp_required_act(want, adapter, port, sdev); if (!need) goto out; act = zfcp_erp_setup_act(need, act_status, adapter, port, sdev); - if (!act) { - need |= ZFCP_ERP_ACTION_NONE; /* marker for trace */ + if (!act) goto out; - } atomic_or(ZFCP_STATUS_ADAPTER_ERP_PENDING, &adapter->status); ++adapter->erp_total_count; list_add_tail(&act->list, &adapter->erp_ready_head); @@ -339,32 +268,18 @@ return retval; } -void zfcp_erp_port_forced_no_port_dbf(char *id, struct zfcp_adapter *adapter, - u64 port_name, u32 port_id) -{ - unsigned long flags; - static /* don't waste stack */ struct zfcp_port tmpport; - - write_lock_irqsave(&adapter->erp_lock, flags); - /* Stand-in zfcp port with fields just good enough for - * zfcp_dbf_rec_trig() and zfcp_dbf_set_common(). - * Under lock because tmpport is static. - */ - atomic_set(&tmpport.status, -1); /* unknown */ - tmpport.wwpn = port_name; - tmpport.d_id = port_id; - zfcp_dbf_rec_trig(id, adapter, &tmpport, NULL, - ZFCP_ERP_ACTION_REOPEN_PORT_FORCED, - ZFCP_ERP_ACTION_NONE); - write_unlock_irqrestore(&adapter->erp_lock, flags); -} - static int _zfcp_erp_adapter_reopen(struct zfcp_adapter *adapter, int clear_mask, char *id) { zfcp_erp_adapter_block(adapter, clear_mask); zfcp_scsi_schedule_rports_block(adapter); + /* ensure propagation of failed status to new devices */ + if (atomic_read(&adapter->status) & ZFCP_STATUS_COMMON_ERP_FAILED) { + zfcp_erp_set_adapter_status(adapter, + ZFCP_STATUS_COMMON_ERP_FAILED); + return -EIO; + } return zfcp_erp_action_enqueue(ZFCP_ERP_ACTION_REOPEN_ADAPTER, adapter, NULL, NULL, id, 0); } @@ -383,8 +298,12 @@ zfcp_scsi_schedule_rports_block(adapter); write_lock_irqsave(&adapter->erp_lock, flags); - zfcp_erp_action_enqueue(ZFCP_ERP_ACTION_REOPEN_ADAPTER, adapter, - NULL, NULL, id, 0); + if (atomic_read(&adapter->status) & ZFCP_STATUS_COMMON_ERP_FAILED) + zfcp_erp_set_adapter_status(adapter, + ZFCP_STATUS_COMMON_ERP_FAILED); + else + zfcp_erp_action_enqueue(ZFCP_ERP_ACTION_REOPEN_ADAPTER, adapter, + NULL, NULL, id, 0); write_unlock_irqrestore(&adapter->erp_lock, flags); } @@ -425,6 +344,9 @@ zfcp_erp_port_block(port, clear); zfcp_scsi_schedule_rport_block(port); + if (atomic_read(&port->status) & ZFCP_STATUS_COMMON_ERP_FAILED) + return; + zfcp_erp_action_enqueue(ZFCP_ERP_ACTION_REOPEN_PORT_FORCED, port->adapter, port, NULL, id, 0); } @@ -450,6 +372,12 @@ zfcp_erp_port_block(port, clear); zfcp_scsi_schedule_rport_block(port); + if (atomic_read(&port->status) & ZFCP_STATUS_COMMON_ERP_FAILED) { + /* ensure propagation of failed status to new devices */ + zfcp_erp_set_port_status(port, ZFCP_STATUS_COMMON_ERP_FAILED); + return -EIO; + } + return zfcp_erp_action_enqueue(ZFCP_ERP_ACTION_REOPEN_PORT, port->adapter, port, NULL, id, 0); } @@ -489,6 +417,9 @@ zfcp_erp_lun_block(sdev, clear); + if (atomic_read(&zfcp_sdev->status) & ZFCP_STATUS_COMMON_ERP_FAILED) + return; + zfcp_erp_action_enqueue(ZFCP_ERP_ACTION_REOPEN_LUN, adapter, zfcp_sdev->port, sdev, id, act_status); } diff -u linux-lts-xenial-4.4.0/drivers/s390/scsi/zfcp_ext.h linux-lts-xenial-4.4.0/drivers/s390/scsi/zfcp_ext.h --- linux-lts-xenial-4.4.0/drivers/s390/scsi/zfcp_ext.h +++ linux-lts-xenial-4.4.0/drivers/s390/scsi/zfcp_ext.h @@ -52,15 +52,10 @@ extern void zfcp_dbf_san_in_els(char *, struct zfcp_fsf_req *); extern void zfcp_dbf_scsi(char *, int, struct scsi_cmnd *, struct zfcp_fsf_req *); -extern void zfcp_dbf_scsi_eh(char *tag, struct zfcp_adapter *adapter, - unsigned int scsi_id, int ret); /* zfcp_erp.c */ extern void zfcp_erp_set_adapter_status(struct zfcp_adapter *, u32); extern void zfcp_erp_clear_adapter_status(struct zfcp_adapter *, u32); -extern void zfcp_erp_port_forced_no_port_dbf(char *id, - struct zfcp_adapter *adapter, - u64 port_name, u32 port_id); extern void zfcp_erp_adapter_reopen(struct zfcp_adapter *, int, char *); extern void zfcp_erp_adapter_shutdown(struct zfcp_adapter *, int, char *); extern void zfcp_erp_set_port_status(struct zfcp_port *, u32); diff -u linux-lts-xenial-4.4.0/drivers/s390/scsi/zfcp_scsi.c linux-lts-xenial-4.4.0/drivers/s390/scsi/zfcp_scsi.c --- linux-lts-xenial-4.4.0/drivers/s390/scsi/zfcp_scsi.c +++ linux-lts-xenial-4.4.0/drivers/s390/scsi/zfcp_scsi.c @@ -180,7 +180,6 @@ if (abrt_req) break; - zfcp_dbf_scsi_abort("abrt_wt", scpnt, NULL); zfcp_erp_wait(adapter); ret = fc_block_scsi_eh(scpnt); if (ret) { @@ -277,7 +276,6 @@ if (fsf_req) break; - zfcp_dbf_scsi_devreset("wait", scpnt, tm_flags, NULL); zfcp_erp_wait(adapter); ret = fc_block_scsi_eh(scpnt); if (ret) { @@ -324,16 +322,15 @@ { struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(scpnt->device); struct zfcp_adapter *adapter = zfcp_sdev->port->adapter; - int ret = SUCCESS, fc_ret; + int ret; zfcp_erp_adapter_reopen(adapter, 0, "schrh_1"); zfcp_erp_wait(adapter); - fc_ret = fc_block_scsi_eh(scpnt); - if (fc_ret) - ret = fc_ret; + ret = fc_block_scsi_eh(scpnt); + if (ret) + return ret; - zfcp_dbf_scsi_eh("schrh_r", adapter, ~0, ret); - return ret; + return SUCCESS; } struct scsi_transport_template *zfcp_scsi_transport_template; @@ -603,11 +600,6 @@ if (port) { zfcp_erp_port_forced_reopen(port, 0, "sctrpi1"); put_device(&port->dev); - } else { - zfcp_erp_port_forced_no_port_dbf( - "sctrpin", adapter, - rport->port_name /* zfcp_scsi_rport_register */, - rport->port_id /* zfcp_scsi_rport_register */); } } diff -u linux-lts-xenial-4.4.0/drivers/scsi/qla2xxx/qla_init.c linux-lts-xenial-4.4.0/drivers/scsi/qla2xxx/qla_init.c --- linux-lts-xenial-4.4.0/drivers/scsi/qla2xxx/qla_init.c +++ linux-lts-xenial-4.4.0/drivers/scsi/qla2xxx/qla_init.c @@ -3293,8 +3293,7 @@ return; if (fcport->fp_speed == PORT_SPEED_UNKNOWN || - fcport->fp_speed > ha->link_data_rate || - !ha->flags.gpsc_supported) + fcport->fp_speed > ha->link_data_rate) return; rval = qla2x00_set_idma_speed(vha, fcport->loop_id, fcport->fp_speed, reverted: --- linux-lts-xenial-4.4.0/drivers/scsi/scsi_transport_srp.c +++ linux-lts-xenial-4.4.0.orig/drivers/scsi/scsi_transport_srp.c @@ -52,8 +52,6 @@ struct transport_container rport_attr_cont; }; -static int scsi_is_srp_rport(const struct device *dev); - #define to_srp_internal(tmpl) container_of(tmpl, struct srp_internal, t) #define dev_to_rport(d) container_of(d, struct srp_rport, dev) @@ -63,24 +61,9 @@ return dev_to_shost(r->dev.parent); } -static int find_child_rport(struct device *dev, void *data) -{ - struct device **child = data; - - if (scsi_is_srp_rport(dev)) { - WARN_ON_ONCE(*child); - *child = dev; - } - return 0; -} - static inline struct srp_rport *shost_to_rport(struct Scsi_Host *shost) { + return transport_class_to_srp_rport(&shost->shost_gendev); - struct device *child = NULL; - - WARN_ON_ONCE(device_for_each_child(&shost->shost_gendev, &child, - find_child_rport) < 0); - return child ? dev_to_rport(child) : NULL; } /** @@ -654,8 +637,7 @@ struct srp_rport *rport = shost_to_rport(shost); pr_debug("timeout for sdev %s\n", dev_name(&sdev->sdev_gendev)); + return rport->fast_io_fail_tmo < 0 && rport->dev_loss_tmo < 0 && - return rport && rport->fast_io_fail_tmo < 0 && - rport->dev_loss_tmo < 0 && i->f->reset_timer_if_blocked && scsi_device_blocked(sdev) ? BLK_EH_RESET_TIMER : BLK_EH_NOT_HANDLED; } diff -u linux-lts-xenial-4.4.0/drivers/scsi/sg.c linux-lts-xenial-4.4.0/drivers/scsi/sg.c --- linux-lts-xenial-4.4.0/drivers/scsi/sg.c +++ linux-lts-xenial-4.4.0/drivers/scsi/sg.c @@ -51,7 +51,6 @@ #include #include #include -#include /* for sg_check_file_access() */ #include "scsi.h" #include @@ -222,33 +221,6 @@ sdev_prefix_printk(prefix, (sdp)->device, \ (sdp)->disk->disk_name, fmt, ##a) -/* - * The SCSI interfaces that use read() and write() as an asynchronous variant of - * ioctl(..., SG_IO, ...) are fundamentally unsafe, since there are lots of ways - * to trigger read() and write() calls from various contexts with elevated - * privileges. This can lead to kernel memory corruption (e.g. if these - * interfaces are called through splice()) and privilege escalation inside - * userspace (e.g. if a process with access to such a device passes a file - * descriptor to a SUID binary as stdin/stdout/stderr). - * - * This function provides protection for the legacy API by restricting the - * calling context. - */ -static int sg_check_file_access(struct file *filp, const char *caller) -{ - if (filp->f_cred != current_real_cred()) { - pr_err_once("%s: process %d (%s) changed security contexts after opening file descriptor, this is not allowed.\n", - caller, task_tgid_vnr(current), current->comm); - return -EPERM; - } - if (unlikely(segment_eq(get_fs(), KERNEL_DS))) { - pr_err_once("%s: process %d (%s) called from kernel context, this is not allowed.\n", - caller, task_tgid_vnr(current), current->comm); - return -EACCES; - } - return 0; -} - static int sg_allow_access(struct file *filp, unsigned char *cmd) { struct sg_fd *sfp = filp->private_data; @@ -433,14 +405,6 @@ struct sg_header *old_hdr = NULL; int retval = 0; - /* - * This could cause a response to be stranded. Close the associated - * file descriptor to free up any resources being held. - */ - retval = sg_check_file_access(filp, __func__); - if (retval) - return retval; - if ((!(sfp = (Sg_fd *) filp->private_data)) || (!(sdp = sfp->parentdp))) return -ENXIO; SCSI_LOG_TIMEOUT(3, sg_printk(KERN_INFO, sdp, @@ -628,11 +592,9 @@ struct sg_header old_hdr; sg_io_hdr_t *hp; unsigned char cmnd[SG_MAX_CDB_SIZE]; - int retval; - retval = sg_check_file_access(filp, __func__); - if (retval) - return retval; + if (unlikely(segment_eq(get_fs(), KERNEL_DS))) + return -EINVAL; if ((!(sfp = (Sg_fd *) filp->private_data)) || (!(sdp = sfp->parentdp))) return -ENXIO; reverted: --- linux-lts-xenial-4.4.0/drivers/spi/spi.c +++ linux-lts-xenial-4.4.0.orig/drivers/spi/spi.c @@ -707,14 +707,8 @@ for (i = 0; i < sgs; i++) { if (vmalloced_buf) { + min = min_t(size_t, + len, desc_len - offset_in_page(buf)); - /* - * Next scatterlist entry size is the minimum between - * the desc_len and the remaining buffer length that - * fits in a page. - */ - min = min_t(size_t, desc_len, - min_t(size_t, len, - PAGE_SIZE - offset_in_page(buf))); vm_page = vmalloc_to_page(buf); if (!vm_page) { sg_free_table(sgt); reverted: --- linux-lts-xenial-4.4.0/drivers/staging/android/ion/ion_heap.c +++ linux-lts-xenial-4.4.0.orig/drivers/staging/android/ion/ion_heap.c @@ -38,7 +38,7 @@ struct page **tmp = pages; if (!pages) + return NULL; - return ERR_PTR(-ENOMEM); if (buffer->flags & ION_FLAG_CACHED) pgprot = PAGE_KERNEL; reverted: --- linux-lts-xenial-4.4.0/drivers/staging/comedi/drivers/quatech_daqp_cs.c +++ linux-lts-xenial-4.4.0.orig/drivers/staging/comedi/drivers/quatech_daqp_cs.c @@ -642,7 +642,7 @@ /* Make sure D/A update mode is direct update */ outb(0, dev->iobase + DAQP_AUX_REG); + for (i = 0; i > insn->n; i++) { - for (i = 0; i < insn->n; i++) { unsigned val = data[i]; int ret; diff -u linux-lts-xenial-4.4.0/drivers/tty/n_tty.c linux-lts-xenial-4.4.0/drivers/tty/n_tty.c --- linux-lts-xenial-4.4.0/drivers/tty/n_tty.c +++ linux-lts-xenial-4.4.0/drivers/tty/n_tty.c @@ -128,8 +128,6 @@ struct mutex output_lock; }; -#define MASK(x) ((x) & (N_TTY_BUF_SIZE - 1)) - static inline size_t read_cnt(struct n_tty_data *ldata) { return ldata->read_head - ldata->read_tail; @@ -147,7 +145,6 @@ static inline unsigned char echo_buf(struct n_tty_data *ldata, size_t i) { - smp_rmb(); /* Matches smp_wmb() in add_echo_byte(). */ return ldata->echo_buf[i & (N_TTY_BUF_SIZE - 1)]; } @@ -325,7 +322,9 @@ static void reset_buffer_flags(struct n_tty_data *ldata) { ldata->read_head = ldata->canon_head = ldata->read_tail = 0; + ldata->echo_head = ldata->echo_tail = ldata->echo_commit = 0; ldata->commit_head = 0; + ldata->echo_mark = 0; ldata->line_start = 0; ldata->erasing = 0; @@ -646,20 +645,13 @@ old_space = space = tty_write_room(tty); tail = ldata->echo_tail; - while (MASK(ldata->echo_commit) != MASK(tail)) { + while (ldata->echo_commit != tail) { c = echo_buf(ldata, tail); if (c == ECHO_OP_START) { unsigned char op; int no_space_left = 0; /* - * Since add_echo_byte() is called without holding - * output_lock, we might see only portion of multi-byte - * operation. - */ - if (MASK(ldata->echo_commit) == MASK(tail + 1)) - goto not_yet_stored; - /* * If the buffer byte is the start of a multi-byte * operation, get the next byte, which is either the * op code or a control character value. @@ -670,8 +662,6 @@ unsigned int num_chars, num_bs; case ECHO_OP_ERASE_TAB: - if (MASK(ldata->echo_commit) == MASK(tail + 2)) - goto not_yet_stored; num_chars = echo_buf(ldata, tail + 2); /* @@ -766,8 +756,7 @@ /* If the echo buffer is nearly full (so that the possibility exists * of echo overrun before the next commit), then discard enough * data at the tail to prevent a subsequent overrun */ - while (ldata->echo_commit > tail && - ldata->echo_commit - tail >= ECHO_DISCARD_WATERMARK) { + while (ldata->echo_commit - tail >= ECHO_DISCARD_WATERMARK) { if (echo_buf(ldata, tail) == ECHO_OP_START) { if (echo_buf(ldata, tail + 1) == ECHO_OP_ERASE_TAB) tail += 3; @@ -777,7 +766,6 @@ tail++; } - not_yet_stored: ldata->echo_tail = tail; return old_space - space; } @@ -788,7 +776,6 @@ size_t nr, old, echoed; size_t head; - mutex_lock(&ldata->output_lock); head = ldata->echo_head; ldata->echo_mark = head; old = ldata->echo_commit - ldata->echo_tail; @@ -797,12 +784,10 @@ * is over the threshold (and try again each time another * block is accumulated) */ nr = head - ldata->echo_tail; - if (nr < ECHO_COMMIT_WATERMARK || - (nr % ECHO_BLOCK > old % ECHO_BLOCK)) { - mutex_unlock(&ldata->output_lock); + if (nr < ECHO_COMMIT_WATERMARK || (nr % ECHO_BLOCK > old % ECHO_BLOCK)) return; - } + mutex_lock(&ldata->output_lock); ldata->echo_commit = head; echoed = __process_echoes(tty); mutex_unlock(&ldata->output_lock); @@ -853,9 +838,7 @@ static inline void add_echo_byte(unsigned char c, struct n_tty_data *ldata) { - *echo_buf_addr(ldata, ldata->echo_head) = c; - smp_wmb(); /* Matches smp_rmb() in echo_buf(). */ - ldata->echo_head++; + *echo_buf_addr(ldata, ldata->echo_head++) = c; } /** @@ -1023,15 +1006,14 @@ } seen_alnums = 0; - while (MASK(ldata->read_head) != MASK(ldata->canon_head)) { + while (ldata->read_head != ldata->canon_head) { head = ldata->read_head; /* erase a single possibly multibyte character */ do { head--; c = read_buf(ldata, head); - } while (is_continuation(c, tty) && - MASK(head) != MASK(ldata->canon_head)); + } while (is_continuation(c, tty) && head != ldata->canon_head); /* do not partially erase */ if (is_continuation(c, tty)) @@ -1073,7 +1055,7 @@ * This info is used to go back the correct * number of columns. */ - while (MASK(tail) != MASK(ldata->canon_head)) { + while (tail != ldata->canon_head) { tail--; c = read_buf(ldata, tail); if (c == '\t') { @@ -1350,7 +1332,7 @@ finish_erasing(ldata); echo_char(c, tty); echo_char_raw('\n', ldata); - while (MASK(tail) != MASK(ldata->read_head)) { + while (tail != ldata->read_head) { echo_char(read_buf(ldata, tail), tty); tail++; } @@ -1935,22 +1917,31 @@ struct n_tty_data *ldata; /* Currently a malloc failure here can panic */ - ldata = vzalloc(sizeof(*ldata)); + ldata = vmalloc(sizeof(*ldata)); if (!ldata) - return -ENOMEM; + goto err; ldata->overrun_time = jiffies; mutex_init(&ldata->atomic_read_lock); mutex_init(&ldata->output_lock); tty->disc_data = ldata; + reset_buffer_flags(tty->disc_data); + ldata->column = 0; + ldata->canon_column = 0; ldata->minimum_to_wake = 1; + ldata->num_overrun = 0; + ldata->no_room = 0; + ldata->lnext = 0; tty->closing = 0; /* indicate buffer work may resume */ clear_bit(TTY_LDISC_HALTED, &tty->flags); n_tty_set_termios(tty, NULL); tty_unthrottle(tty); + return 0; +err: + return -ENOMEM; } static inline int input_available_p(struct tty_struct *tty, int poll) @@ -2488,7 +2479,7 @@ tail = ldata->read_tail; nr = head - tail; /* Skip EOF-chars.. */ - while (MASK(head) != MASK(tail)) { + while (head != tail) { if (test_bit(tail & (N_TTY_BUF_SIZE - 1), ldata->read_flags) && read_buf(ldata, tail) == __DISABLED_CHAR) nr--; diff -u linux-lts-xenial-4.4.0/drivers/tty/serial/samsung.c linux-lts-xenial-4.4.0/drivers/tty/serial/samsung.c --- linux-lts-xenial-4.4.0/drivers/tty/serial/samsung.c +++ linux-lts-xenial-4.4.0/drivers/tty/serial/samsung.c @@ -860,12 +860,15 @@ dma->rx_conf.direction = DMA_DEV_TO_MEM; dma->rx_conf.src_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE; dma->rx_conf.src_addr = p->port.mapbase + S3C2410_URXH; - dma->rx_conf.src_maxburst = 1; + dma->rx_conf.src_maxburst = 16; dma->tx_conf.direction = DMA_MEM_TO_DEV; dma->tx_conf.dst_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE; dma->tx_conf.dst_addr = p->port.mapbase + S3C2410_UTXH; - dma->tx_conf.dst_maxburst = 1; + if (dma_get_cache_alignment() >= 16) + dma->tx_conf.dst_maxburst = 16; + else + dma->tx_conf.dst_maxburst = 1; dma_cap_zero(mask); dma_cap_set(DMA_SLAVE, mask); diff -u linux-lts-xenial-4.4.0/drivers/tty/serial/sh-sci.c linux-lts-xenial-4.4.0/drivers/tty/serial/sh-sci.c --- linux-lts-xenial-4.4.0/drivers/tty/serial/sh-sci.c +++ linux-lts-xenial-4.4.0/drivers/tty/serial/sh-sci.c @@ -2419,12 +2419,13 @@ unsigned long flags; int locked = 1; + local_irq_save(flags); if (port->sysrq) locked = 0; else if (oops_in_progress) - locked = spin_trylock_irqsave(&port->lock, flags); + locked = spin_trylock(&port->lock); else - spin_lock_irqsave(&port->lock, flags); + spin_lock(&port->lock); /* first save the SCSCR then disable the interrupts */ ctrl = serial_port_in(port, SCSCR); @@ -2441,7 +2442,8 @@ serial_port_out(port, SCSCR, ctrl); if (locked) - spin_unlock_irqrestore(&port->lock, flags); + spin_unlock(&port->lock); + local_irq_restore(flags); } static int serial_console_setup(struct console *co, char *options) diff -u linux-lts-xenial-4.4.0/drivers/usb/class/cdc-acm.c linux-lts-xenial-4.4.0/drivers/usb/class/cdc-acm.c --- linux-lts-xenial-4.4.0/drivers/usb/class/cdc-acm.c +++ linux-lts-xenial-4.4.0/drivers/usb/class/cdc-acm.c @@ -1698,9 +1698,6 @@ { USB_DEVICE(0x11ca, 0x0201), /* VeriFone Mx870 Gadget Serial */ .driver_info = SINGLE_RX_URB, }, - { USB_DEVICE(0x1965, 0x0018), /* Uniden UBC125XLT */ - .driver_info = NO_UNION_NORMAL, /* has no union descriptor */ - }, { USB_DEVICE(0x22b8, 0x7000), /* Motorola Q Phone */ .driver_info = NO_UNION_NORMAL, /* has no union descriptor */ }, diff -u linux-lts-xenial-4.4.0/drivers/usb/core/hub.c linux-lts-xenial-4.4.0/drivers/usb/core/hub.c --- linux-lts-xenial-4.4.0/drivers/usb/core/hub.c +++ linux-lts-xenial-4.4.0/drivers/usb/core/hub.c @@ -4494,9 +4494,7 @@ * reset. But only on the first attempt, * lest we get into a time out/reset loop */ - if (r == 0 || (r == -ETIMEDOUT && - retries == 0 && - udev->speed > USB_SPEED_FULL)) + if (r == 0 || (r == -ETIMEDOUT && retries == 0)) break; } udev->descriptor.bMaxPacketSize0 = diff -u linux-lts-xenial-4.4.0/drivers/usb/musb/musb_host.c linux-lts-xenial-4.4.0/drivers/usb/musb/musb_host.c --- linux-lts-xenial-4.4.0/drivers/usb/musb/musb_host.c +++ linux-lts-xenial-4.4.0/drivers/usb/musb/musb_host.c @@ -2580,11 +2580,8 @@ { struct musb *musb = hcd_to_musb(hcd); u8 devctl; - int ret; - ret = musb_port_suspend(musb, true); - if (ret) - return ret; + musb_port_suspend(musb, true); if (!is_host_active(musb)) return 0; reverted: --- linux-lts-xenial-4.4.0/drivers/usb/musb/musb_host.h +++ linux-lts-xenial-4.4.0.orig/drivers/usb/musb/musb_host.h @@ -92,7 +92,7 @@ extern void musb_root_disconnect(struct musb *musb); extern void musb_host_resume_root_hub(struct musb *musb); extern void musb_host_poke_root_hub(struct musb *musb); +extern void musb_port_suspend(struct musb *musb, bool do_suspend); -extern int musb_port_suspend(struct musb *musb, bool do_suspend); extern void musb_port_reset(struct musb *musb, bool do_reset); extern void musb_host_finish_resume(struct work_struct *work); #else @@ -124,10 +124,7 @@ static inline void musb_host_resume_root_hub(struct musb *musb) {} static inline void musb_host_poll_rh_status(struct musb *musb) {} static inline void musb_host_poke_root_hub(struct musb *musb) {} +static inline void musb_port_suspend(struct musb *musb, bool do_suspend) {} -static inline int musb_port_suspend(struct musb *musb, bool do_suspend) -{ - return 0; -} static inline void musb_port_reset(struct musb *musb, bool do_reset) {} static inline void musb_host_finish_resume(struct work_struct *work) {} #endif reverted: --- linux-lts-xenial-4.4.0/drivers/usb/musb/musb_virthub.c +++ linux-lts-xenial-4.4.0.orig/drivers/usb/musb/musb_virthub.c @@ -74,14 +74,14 @@ spin_unlock_irqrestore(&musb->lock, flags); } +void musb_port_suspend(struct musb *musb, bool do_suspend) -int musb_port_suspend(struct musb *musb, bool do_suspend) { struct usb_otg *otg = musb->xceiv->otg; u8 power; void __iomem *mbase = musb->mregs; if (!is_host_active(musb)) + return; - return 0; /* NOTE: this doesn't necessarily put PHY into low power mode, * turning off its clock; that's a function of PHY integration and @@ -92,20 +92,16 @@ if (do_suspend) { int retries = 10000; + power &= ~MUSB_POWER_RESUME; + power |= MUSB_POWER_SUSPENDM; + musb_writeb(mbase, MUSB_POWER, power); - if (power & MUSB_POWER_RESUME) - return -EBUSY; - - if (!(power & MUSB_POWER_SUSPENDM)) { - power |= MUSB_POWER_SUSPENDM; - musb_writeb(mbase, MUSB_POWER, power); + /* Needed for OPT A tests */ + power = musb_readb(mbase, MUSB_POWER); + while (power & MUSB_POWER_SUSPENDM) { - /* Needed for OPT A tests */ power = musb_readb(mbase, MUSB_POWER); + if (retries-- < 1) + break; - while (power & MUSB_POWER_SUSPENDM) { - power = musb_readb(mbase, MUSB_POWER); - if (retries-- < 1) - break; - } } dev_dbg(musb->controller, "Root port suspended, power %02x\n", power); @@ -142,7 +138,6 @@ schedule_delayed_work(&musb->finish_resume_work, msecs_to_jiffies(USB_RESUME_TIMEOUT)); } - return 0; } void musb_port_reset(struct musb *musb, bool do_reset) diff -u linux-lts-xenial-4.4.0/drivers/usb/serial/cp210x.c linux-lts-xenial-4.4.0/drivers/usb/serial/cp210x.c --- linux-lts-xenial-4.4.0/drivers/usb/serial/cp210x.c +++ linux-lts-xenial-4.4.0/drivers/usb/serial/cp210x.c @@ -33,7 +33,7 @@ static void cp210x_close(struct usb_serial_port *); static void cp210x_get_termios(struct tty_struct *, struct usb_serial_port *); static void cp210x_get_termios_port(struct usb_serial_port *port, - tcflag_t *cflagp, unsigned int *baudp); + unsigned int *cflagp, unsigned int *baudp); static void cp210x_change_speed(struct tty_struct *, struct usb_serial_port *, struct ktermios *); static void cp210x_set_termios(struct tty_struct *, struct usb_serial_port *, @@ -91,9 +91,6 @@ { USB_DEVICE(0x10C4, 0x8156) }, /* B&G H3000 link cable */ { USB_DEVICE(0x10C4, 0x815E) }, /* Helicomm IP-Link 1220-DVM */ { USB_DEVICE(0x10C4, 0x815F) }, /* Timewave HamLinkUSB */ - { USB_DEVICE(0x10C4, 0x817C) }, /* CESINEL MEDCAL N Power Quality Monitor */ - { USB_DEVICE(0x10C4, 0x817D) }, /* CESINEL MEDCAL NT Power Quality Monitor */ - { USB_DEVICE(0x10C4, 0x817E) }, /* CESINEL MEDCAL S Power Quality Monitor */ { USB_DEVICE(0x10C4, 0x818B) }, /* AVIT Research USB to TTL */ { USB_DEVICE(0x10C4, 0x819F) }, /* MJS USB Toslink Switcher */ { USB_DEVICE(0x10C4, 0x81A6) }, /* ThinkOptics WavIt */ @@ -111,9 +108,6 @@ { USB_DEVICE(0x10C4, 0x826B) }, /* Cygnal Integrated Products, Inc., Fasttrax GPS demonstration module */ { USB_DEVICE(0x10C4, 0x8281) }, /* Nanotec Plug & Drive */ { USB_DEVICE(0x10C4, 0x8293) }, /* Telegesis ETRX2USB */ - { USB_DEVICE(0x10C4, 0x82EF) }, /* CESINEL FALCO 6105 AC Power Supply */ - { USB_DEVICE(0x10C4, 0x82F1) }, /* CESINEL MEDCAL EFD Earth Fault Detector */ - { USB_DEVICE(0x10C4, 0x82F2) }, /* CESINEL MEDCAL ST Network Analyzer */ { USB_DEVICE(0x10C4, 0x82F4) }, /* Starizona MicroTouch */ { USB_DEVICE(0x10C4, 0x82F9) }, /* Procyon AVS */ { USB_DEVICE(0x10C4, 0x8341) }, /* Siemens MC35PU GPRS Modem */ @@ -126,9 +120,7 @@ { USB_DEVICE(0x10C4, 0x8470) }, /* Juniper Networks BX Series System Console */ { USB_DEVICE(0x10C4, 0x8477) }, /* Balluff RFID */ { USB_DEVICE(0x10C4, 0x84B6) }, /* Starizona Hyperion */ - { USB_DEVICE(0x10C4, 0x851E) }, /* CESINEL MEDCAL PT Network Analyzer */ { USB_DEVICE(0x10C4, 0x85A7) }, /* LifeScan OneTouch Verio IQ */ - { USB_DEVICE(0x10C4, 0x85B8) }, /* CESINEL ReCon T Energy Logger */ { USB_DEVICE(0x10C4, 0x85EA) }, /* AC-Services IBUS-IF */ { USB_DEVICE(0x10C4, 0x85EB) }, /* AC-Services CIS-IBUS */ { USB_DEVICE(0x10C4, 0x85F8) }, /* Virtenio Preon32 */ @@ -138,23 +130,17 @@ { USB_DEVICE(0x10C4, 0x8857) }, /* CEL EM357 ZigBee USB Stick */ { USB_DEVICE(0x10C4, 0x88A4) }, /* MMB Networks ZigBee USB Device */ { USB_DEVICE(0x10C4, 0x88A5) }, /* Planet Innovation Ingeni ZigBee USB Device */ - { USB_DEVICE(0x10C4, 0x88FB) }, /* CESINEL MEDCAL STII Network Analyzer */ - { USB_DEVICE(0x10C4, 0x8938) }, /* CESINEL MEDCAL S II Network Analyzer */ { USB_DEVICE(0x10C4, 0x8946) }, /* Ketra N1 Wireless Interface */ { USB_DEVICE(0x10C4, 0x8962) }, /* Brim Brothers charging dock */ { USB_DEVICE(0x10C4, 0x8977) }, /* CEL MeshWorks DevKit Device */ { USB_DEVICE(0x10C4, 0x8998) }, /* KCF Technologies PRN */ - { USB_DEVICE(0x10C4, 0x89A4) }, /* CESINEL FTBC Flexible Thyristor Bridge Controller */ { USB_DEVICE(0x10C4, 0x8A2A) }, /* HubZ dual ZigBee and Z-Wave dongle */ { USB_DEVICE(0x10C4, 0x8A5E) }, /* CEL EM3588 ZigBee USB Stick Long Range */ { USB_DEVICE(0x10C4, 0x8B34) }, /* Qivicon ZigBee USB Radio Stick */ { USB_DEVICE(0x10C4, 0xEA60) }, /* Silicon Labs factory default */ { USB_DEVICE(0x10C4, 0xEA61) }, /* Silicon Labs factory default */ - { USB_DEVICE(0x10C4, 0xEA63) }, /* Silicon Labs Windows Update (CP2101-4/CP2102N) */ { USB_DEVICE(0x10C4, 0xEA70) }, /* Silicon Labs factory default */ { USB_DEVICE(0x10C4, 0xEA71) }, /* Infinity GPS-MIC-1 Radio Monophone */ - { USB_DEVICE(0x10C4, 0xEA7A) }, /* Silicon Labs Windows Update (CP2105) */ - { USB_DEVICE(0x10C4, 0xEA7B) }, /* Silicon Labs Windows Update (CP2108) */ { USB_DEVICE(0x10C4, 0xF001) }, /* Elan Digital Systems USBscope50 */ { USB_DEVICE(0x10C4, 0xF002) }, /* Elan Digital Systems USBwave12 */ { USB_DEVICE(0x10C4, 0xF003) }, /* Elan Digital Systems USBpulse100 */ @@ -529,7 +515,7 @@ &tty->termios.c_cflag, &baud); tty_encode_baud_rate(tty, baud, baud); } else { - tcflag_t cflag; + unsigned int cflag; cflag = 0; cp210x_get_termios_port(port, &cflag, &baud); } @@ -540,11 +526,10 @@ * This is the heart of cp210x_get_termios which always uses a &usb_serial_port. */ static void cp210x_get_termios_port(struct usb_serial_port *port, - tcflag_t *cflagp, unsigned int *baudp) + unsigned int *cflagp, unsigned int *baudp) { struct device *dev = &port->dev; - tcflag_t cflag; - unsigned int modem_ctl[4]; + unsigned int cflag, modem_ctl[4]; unsigned int baud; unsigned int bits; diff -u linux-lts-xenial-4.4.0/drivers/vfio/pci/vfio_pci.c linux-lts-xenial-4.4.0/drivers/vfio/pci/vfio_pci.c --- linux-lts-xenial-4.4.0/drivers/vfio/pci/vfio_pci.c +++ linux-lts-xenial-4.4.0/drivers/vfio/pci/vfio_pci.c @@ -112,35 +112,6 @@ static void vfio_pci_try_bus_reset(struct vfio_pci_device *vdev); -/* - * INTx masking requires the ability to disable INTx signaling via PCI_COMMAND - * _and_ the ability detect when the device is asserting INTx via PCI_STATUS. - * If a device implements the former but not the latter we would typically - * expect broken_intx_masking be set and require an exclusive interrupt. - * However since we do have control of the device's ability to assert INTx, - * we can instead pretend that the device does not implement INTx, virtualizing - * the pin register to report zero and maintaining DisINTx set on the host. - */ -static bool vfio_pci_nointx(struct pci_dev *pdev) -{ - switch (pdev->vendor) { - case PCI_VENDOR_ID_INTEL: - switch (pdev->device) { - /* All i40e (XL710/X710) 10/20/40GbE NICs */ - case 0x1572: - case 0x1574: - case 0x1580 ... 0x1581: - case 0x1583 ... 0x1589: - case 0x37d0 ... 0x37d2: - return true; - default: - return false; - } - } - - return false; -} - static int vfio_pci_enable(struct vfio_pci_device *vdev) { struct pci_dev *pdev = vdev->pdev; @@ -164,21 +135,6 @@ pr_debug("%s: Couldn't store %s saved state\n", __func__, dev_name(&pdev->dev)); - if (likely(!nointxmask)) { - if (vfio_pci_nointx(pdev)) { - dev_info(&pdev->dev, "Masking broken INTx support\n"); - vdev->nointx = true; - pci_intx(pdev, 0); - } else - vdev->pci_2_3 = pci_intx_mask_supported(pdev); - } - - pci_read_config_word(pdev, PCI_COMMAND, &cmd); - if (vdev->pci_2_3 && (cmd & PCI_COMMAND_INTX_DISABLE)) { - cmd &= ~PCI_COMMAND_INTX_DISABLE; - pci_write_config_word(pdev, PCI_COMMAND, cmd); - } - ret = vfio_config_init(vdev); if (ret) { kfree(vdev->pci_saved_state); @@ -187,6 +143,15 @@ return ret; } + if (likely(!nointxmask)) + vdev->pci_2_3 = pci_intx_mask_supported(pdev); + + pci_read_config_word(pdev, PCI_COMMAND, &cmd); + if (vdev->pci_2_3 && (cmd & PCI_COMMAND_INTX_DISABLE)) { + cmd &= ~PCI_COMMAND_INTX_DISABLE; + pci_write_config_word(pdev, PCI_COMMAND, cmd); + } + msix_pos = pdev->msix_cap; if (msix_pos) { u16 flags; @@ -318,7 +283,7 @@ if (irq_type == VFIO_PCI_INTX_IRQ_INDEX) { u8 pin; pci_read_config_byte(vdev->pdev, PCI_INTERRUPT_PIN, &pin); - if (IS_ENABLED(CONFIG_VFIO_PCI_INTX) && !vdev->nointx && pin) + if (IS_ENABLED(CONFIG_VFIO_PCI_INTX) && pin) return 1; } else if (irq_type == VFIO_PCI_MSI_IRQ_INDEX) { diff -u linux-lts-xenial-4.4.0/drivers/vfio/pci/vfio_pci_config.c linux-lts-xenial-4.4.0/drivers/vfio/pci/vfio_pci_config.c --- linux-lts-xenial-4.4.0/drivers/vfio/pci/vfio_pci_config.c +++ linux-lts-xenial-4.4.0/drivers/vfio/pci/vfio_pci_config.c @@ -387,7 +387,6 @@ { struct pci_dev *pdev = vdev->pdev; u32 *rbar = vdev->rbar; - u16 cmd; int i; if (pdev->is_virtfn) @@ -400,12 +399,6 @@ pci_user_write_config_dword(pdev, i, *rbar); pci_user_write_config_dword(pdev, PCI_ROM_ADDRESS, *rbar); - - if (vdev->nointx) { - pci_user_read_config_word(pdev, PCI_COMMAND, &cmd); - cmd |= PCI_COMMAND_INTX_DISABLE; - pci_user_write_config_word(pdev, PCI_COMMAND, cmd); - } } static __le32 vfio_generate_bar_flags(struct pci_dev *pdev, int bar) @@ -1621,7 +1614,7 @@ *(__le16 *)&vconfig[PCI_DEVICE_ID] = cpu_to_le16(pdev->device); } - if (!IS_ENABLED(CONFIG_VFIO_PCI_INTX) || vdev->nointx) + if (!IS_ENABLED(CONFIG_VFIO_PCI_INTX)) vconfig[PCI_INTERRUPT_PIN] = 0; ret = vfio_cap_init(vdev); reverted: --- linux-lts-xenial-4.4.0/drivers/vfio/pci/vfio_pci_private.h +++ linux-lts-xenial-4.4.0.orig/drivers/vfio/pci/vfio_pci_private.h @@ -57,7 +57,6 @@ bool bardirty; bool has_vga; bool needs_reset; - bool nointx; struct pci_saved_state *pci_saved_state; int refcnt; struct eventfd_ctx *err_trigger; reverted: --- linux-lts-xenial-4.4.0/drivers/video/backlight/as3711_bl.c +++ linux-lts-xenial-4.4.0.orig/drivers/video/backlight/as3711_bl.c @@ -262,10 +262,10 @@ static int as3711_backlight_parse_dt(struct device *dev) { struct as3711_bl_pdata *pdata = dev_get_platdata(dev); + struct device_node *bl = + of_find_node_by_name(dev->parent->of_node, "backlight"), *fb; - struct device_node *bl, *fb; int ret; - bl = of_get_child_by_name(dev->parent->of_node, "backlight"); if (!bl) { dev_dbg(dev, "backlight node not found\n"); return -ENODEV; @@ -279,7 +279,7 @@ if (pdata->su1_max_uA <= 0) ret = -EINVAL; if (ret < 0) + return ret; - goto err_put_bl; } fb = of_parse_phandle(bl, "su2-dev", 0); @@ -292,7 +292,7 @@ if (pdata->su2_max_uA <= 0) ret = -EINVAL; if (ret < 0) + return ret; - goto err_put_bl; if (of_find_property(bl, "su2-feedback-voltage", NULL)) { pdata->su2_feedback = AS3711_SU2_VOLTAGE; @@ -314,10 +314,8 @@ pdata->su2_feedback = AS3711_SU2_CURR_AUTO; count++; } + if (count != 1) + return -EINVAL; - if (count != 1) { - ret = -EINVAL; - goto err_put_bl; - } count = 0; if (of_find_property(bl, "su2-fbprot-lx-sd4", NULL)) { @@ -336,10 +334,8 @@ pdata->su2_fbprot = AS3711_SU2_GPIO4; count++; } + if (count != 1) + return -EINVAL; - if (count != 1) { - ret = -EINVAL; - goto err_put_bl; - } count = 0; if (of_find_property(bl, "su2-auto-curr1", NULL)) { @@ -359,20 +355,11 @@ * At least one su2-auto-curr* must be specified iff * AS3711_SU2_CURR_AUTO is used */ + if (!count ^ (pdata->su2_feedback != AS3711_SU2_CURR_AUTO)) + return -EINVAL; - if (!count ^ (pdata->su2_feedback != AS3711_SU2_CURR_AUTO)) { - ret = -EINVAL; - goto err_put_bl; - } } - of_node_put(bl); - return 0; - -err_put_bl: - of_node_put(bl); - - return ret; } static int as3711_backlight_probe(struct platform_device *pdev) reverted: --- linux-lts-xenial-4.4.0/drivers/video/backlight/max8925_bl.c +++ linux-lts-xenial-4.4.0.orig/drivers/video/backlight/max8925_bl.c @@ -116,7 +116,7 @@ if (!pdata) return; + np = of_find_node_by_name(nproot, "backlight"); - np = of_get_child_by_name(nproot, "backlight"); if (!np) { dev_err(&pdev->dev, "failed to find backlight node\n"); return; @@ -125,8 +125,6 @@ if (!of_property_read_u32(np, "maxim,max8925-dual-string", &val)) pdata->dual_string = val; - of_node_put(np); - pdev->dev.platform_data = pdata; } reverted: --- linux-lts-xenial-4.4.0/drivers/video/backlight/tps65217_bl.c +++ linux-lts-xenial-4.4.0.orig/drivers/video/backlight/tps65217_bl.c @@ -184,11 +184,11 @@ tps65217_bl_parse_dt(struct platform_device *pdev) { struct tps65217 *tps = dev_get_drvdata(pdev->dev.parent); + struct device_node *node = of_node_get(tps->dev->of_node); - struct device_node *node; struct tps65217_bl_pdata *pdata, *err; u32 val; + node = of_find_node_by_name(node, "backlight"); - node = of_get_child_by_name(tps->dev->of_node, "backlight"); if (!node) return ERR_PTR(-ENODEV); reverted: --- linux-lts-xenial-4.4.0/drivers/video/fbdev/uvesafb.c +++ linux-lts-xenial-4.4.0.orig/drivers/video/fbdev/uvesafb.c @@ -1059,8 +1059,7 @@ info->cmap.len || cmap->start < info->cmap.start) return -EINVAL; + entries = kmalloc(sizeof(*entries) * cmap->len, GFP_KERNEL); - entries = kmalloc_array(cmap->len, sizeof(*entries), - GFP_KERNEL); if (!entries) return -ENOMEM; reverted: --- linux-lts-xenial-4.4.0/drivers/w1/masters/mxc_w1.c +++ linux-lts-xenial-4.4.0.orig/drivers/w1/masters/mxc_w1.c @@ -113,10 +113,6 @@ if (IS_ERR(mdev->clk)) return PTR_ERR(mdev->clk); - err = clk_prepare_enable(mdev->clk); - if (err) - return err; - clkrate = clk_get_rate(mdev->clk); if (clkrate < 10000000) dev_warn(&pdev->dev, @@ -130,10 +126,12 @@ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); mdev->regs = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(mdev->regs)) + return PTR_ERR(mdev->regs); + + err = clk_prepare_enable(mdev->clk); + if (err) + return err; - if (IS_ERR(mdev->regs)) { - err = PTR_ERR(mdev->regs); - goto out_disable_clk; - } /* Software reset 1-Wire module */ writeb(MXC_W1_RESET_RST, mdev->regs + MXC_W1_RESET); @@ -149,12 +147,8 @@ err = w1_add_master_device(&mdev->bus_master); if (err) + clk_disable_unprepare(mdev->clk); - goto out_disable_clk; - - return 0; -out_disable_clk: - clk_disable_unprepare(mdev->clk); return err; } diff -u linux-lts-xenial-4.4.0/drivers/w1/w1.c linux-lts-xenial-4.4.0/drivers/w1/w1.c --- linux-lts-xenial-4.4.0/drivers/w1/w1.c +++ linux-lts-xenial-4.4.0/drivers/w1/w1.c @@ -741,7 +741,7 @@ /* slave modules need to be loaded in a context with unlocked mutex */ mutex_unlock(&dev->mutex); - request_module("w1-family-0x%02X", rn->family); + request_module("w1-family-0x%02x", rn->family); mutex_lock(&dev->mutex); spin_lock(&w1_flock); diff -u linux-lts-xenial-4.4.0/drivers/xen/events/events_base.c linux-lts-xenial-4.4.0/drivers/xen/events/events_base.c --- linux-lts-xenial-4.4.0/drivers/xen/events/events_base.c +++ linux-lts-xenial-4.4.0/drivers/xen/events/events_base.c @@ -637,6 +637,8 @@ xen_irq_info_cleanup(info); } + BUG_ON(info_for_irq(irq)->type == IRQT_UNBOUND); + xen_free_irq(irq); } diff -u linux-lts-xenial-4.4.0/fs/aio.c linux-lts-xenial-4.4.0/fs/aio.c --- linux-lts-xenial-4.4.0/fs/aio.c +++ linux-lts-xenial-4.4.0/fs/aio.c @@ -627,8 +627,9 @@ while (!list_empty(&ctx->active_reqs)) { req = list_first_entry(&ctx->active_reqs, struct aio_kiocb, ki_list); - kiocb_cancel(req); + list_del_init(&req->ki_list); + kiocb_cancel(req); } spin_unlock_irq(&ctx->ctx_lock); diff -u linux-lts-xenial-4.4.0/fs/btrfs/disk-io.c linux-lts-xenial-4.4.0/fs/btrfs/disk-io.c --- linux-lts-xenial-4.4.0/fs/btrfs/disk-io.c +++ linux-lts-xenial-4.4.0/fs/btrfs/disk-io.c @@ -923,7 +923,7 @@ if (bio_flags & EXTENT_BIO_TREE_LOG) return 0; #ifdef CONFIG_X86 - if (static_cpu_has_safe(X86_FEATURE_XMM4_2)) + if (cpu_has_xmm4_2) return 0; #endif return 1; diff -u linux-lts-xenial-4.4.0/fs/btrfs/inode.c linux-lts-xenial-4.4.0/fs/btrfs/inode.c --- linux-lts-xenial-4.4.0/fs/btrfs/inode.c +++ linux-lts-xenial-4.4.0/fs/btrfs/inode.c @@ -1202,8 +1202,6 @@ list_del(&sums->list); kfree(sums); } - if (ret < 0) - return ret; return 1; } @@ -1353,23 +1351,10 @@ goto out_check; if (btrfs_extent_readonly(root, disk_bytenr)) goto out_check; - ret = btrfs_cross_ref_exist(trans, root, ino, + if (btrfs_cross_ref_exist(trans, root, ino, found_key.offset - - extent_offset, disk_bytenr); - if (ret) { - /* - * ret could be -EIO if the above fails to read - * metadata. - */ - if (ret < 0) { - if (cow_start != (u64)-1) - cur_offset = cow_start; - goto error; - } - - WARN_ON_ONCE(nolock); + extent_offset, disk_bytenr)) goto out_check; - } disk_bytenr += extent_offset; disk_bytenr += cur_offset - found_key.offset; num_bytes = min(end + 1, extent_end) - cur_offset; @@ -1387,20 +1372,8 @@ * this ensure that csum for a given extent are * either valid or do not exist. */ - ret = csum_exist_in_range(root, disk_bytenr, num_bytes); - if (ret) { - /* - * ret could be -EIO if the above fails to read - * metadata. - */ - if (ret < 0) { - if (cow_start != (u64)-1) - cur_offset = cow_start; - goto error; - } - WARN_ON_ONCE(nolock); + if (csum_exist_in_range(root, disk_bytenr, num_bytes)) goto out_check; - } nocow = 1; } else if (extent_type == BTRFS_FILE_EXTENT_INLINE) { extent_end = found_key.offset + diff -u linux-lts-xenial-4.4.0/fs/btrfs/ioctl.c linux-lts-xenial-4.4.0/fs/btrfs/ioctl.c --- linux-lts-xenial-4.4.0/fs/btrfs/ioctl.c +++ linux-lts-xenial-4.4.0/fs/btrfs/ioctl.c @@ -3923,6 +3923,11 @@ if (!(src_file.file->f_mode & FMODE_READ)) goto out_fput; + /* don't make the dst file partly checksummed */ + if ((BTRFS_I(src)->flags & BTRFS_INODE_NODATASUM) != + (BTRFS_I(inode)->flags & BTRFS_INODE_NODATASUM)) + goto out_fput; + ret = -EISDIR; if (S_ISDIR(src->i_mode) || S_ISDIR(inode->i_mode)) goto out_fput; @@ -3937,13 +3942,6 @@ mutex_lock(&src->i_mutex); } - /* don't make the dst file partly checksummed */ - if ((BTRFS_I(src)->flags & BTRFS_INODE_NODATASUM) != - (BTRFS_I(inode)->flags & BTRFS_INODE_NODATASUM)) { - ret = -EINVAL; - goto out_unlock; - } - /* determine range to clone */ ret = -EINVAL; if (off + len > src->i_size || off + len < off) reverted: --- linux-lts-xenial-4.4.0/fs/btrfs/scrub.c +++ linux-lts-xenial-4.4.0.orig/fs/btrfs/scrub.c @@ -2513,7 +2513,7 @@ have_csum = scrub_find_csum(sctx, logical, csum); if (have_csum == 0) ++sctx->stat.no_csum; + if (sctx->is_dev_replace && !have_csum) { - if (0 && sctx->is_dev_replace && !have_csum) { ret = copy_nocow_pages(sctx, logical, l, mirror_num, physical_for_dev_replace); diff -u linux-lts-xenial-4.4.0/fs/cifs/cifssmb.c linux-lts-xenial-4.4.0/fs/cifs/cifssmb.c --- linux-lts-xenial-4.4.0/fs/cifs/cifssmb.c +++ linux-lts-xenial-4.4.0/fs/cifs/cifssmb.c @@ -150,14 +150,8 @@ * greater than cifs socket timeout which is 7 seconds */ while (server->tcpStatus == CifsNeedReconnect) { - rc = wait_event_interruptible_timeout(server->response_q, - (server->tcpStatus != CifsNeedReconnect), - 10 * HZ); - if (rc < 0) { - cifs_dbg(FYI, "%s: aborting reconnect due to a received" - " signal by the process\n", __func__); - return -ERESTARTSYS; - } + wait_event_interruptible_timeout(server->response_q, + (server->tcpStatus != CifsNeedReconnect), 10 * HZ); /* are we still trying to reconnect? */ if (server->tcpStatus != CifsNeedReconnect) diff -u linux-lts-xenial-4.4.0/fs/cifs/smb2pdu.c linux-lts-xenial-4.4.0/fs/cifs/smb2pdu.c --- linux-lts-xenial-4.4.0/fs/cifs/smb2pdu.c +++ linux-lts-xenial-4.4.0/fs/cifs/smb2pdu.c @@ -152,7 +152,7 @@ static int smb2_reconnect(__le16 smb2_command, struct cifs_tcon *tcon) { - int rc; + int rc = 0; struct nls_table *nls_codepage; struct cifs_ses *ses; struct TCP_Server_Info *server; @@ -163,10 +163,10 @@ * for those three - in the calling routine. */ if (tcon == NULL) - return 0; + return rc; if (smb2_command == SMB2_TREE_CONNECT) - return 0; + return rc; if (tcon->tidStatus == CifsExiting) { /* @@ -209,14 +209,8 @@ return -EAGAIN; } - rc = wait_event_interruptible_timeout(server->response_q, - (server->tcpStatus != CifsNeedReconnect), - 10 * HZ); - if (rc < 0) { - cifs_dbg(FYI, "%s: aborting reconnect due to a received" - " signal by the process\n", __func__); - return -ERESTARTSYS; - } + wait_event_interruptible_timeout(server->response_q, + (server->tcpStatus != CifsNeedReconnect), 10 * HZ); /* are we still trying to reconnect? */ if (server->tcpStatus != CifsNeedReconnect) @@ -234,7 +228,7 @@ } if (!tcon->ses->need_reconnect && !tcon->need_reconnect) - return 0; + return rc; nls_codepage = load_nls_default(); diff -u linux-lts-xenial-4.4.0/fs/ext4/balloc.c linux-lts-xenial-4.4.0/fs/ext4/balloc.c --- linux-lts-xenial-4.4.0/fs/ext4/balloc.c +++ linux-lts-xenial-4.4.0/fs/ext4/balloc.c @@ -183,6 +183,7 @@ unsigned int bit, bit_max; struct ext4_sb_info *sbi = EXT4_SB(sb); ext4_fsblk_t start, tmp; + int flex_bg = 0; struct ext4_group_info *grp; J_ASSERT_BH(bh, buffer_locked(bh)); @@ -215,19 +216,22 @@ start = ext4_group_first_block_no(sb, block_group); + if (ext4_has_feature_flex_bg(sb)) + flex_bg = 1; + /* Set bits for block and inode bitmaps, and inode table */ tmp = ext4_block_bitmap(sb, gdp); - if (ext4_block_in_group(sb, tmp, block_group)) + if (!flex_bg || ext4_block_in_group(sb, tmp, block_group)) ext4_set_bit(EXT4_B2C(sbi, tmp - start), bh->b_data); tmp = ext4_inode_bitmap(sb, gdp); - if (ext4_block_in_group(sb, tmp, block_group)) + if (!flex_bg || ext4_block_in_group(sb, tmp, block_group)) ext4_set_bit(EXT4_B2C(sbi, tmp - start), bh->b_data); tmp = ext4_inode_table(sb, gdp); for (; tmp < ext4_inode_table(sb, gdp) + sbi->s_itb_per_group; tmp++) { - if (ext4_block_in_group(sb, tmp, block_group)) + if (!flex_bg || ext4_block_in_group(sb, tmp, block_group)) ext4_set_bit(EXT4_B2C(sbi, tmp - start), bh->b_data); } @@ -450,16 +454,7 @@ goto verify; } ext4_lock_group(sb, block_group); - if (ext4_has_group_desc_csum(sb) && - (desc->bg_flags & cpu_to_le16(EXT4_BG_BLOCK_UNINIT))) { - if (block_group == 0) { - ext4_unlock_group(sb, block_group); - unlock_buffer(bh); - ext4_error(sb, "Block bitmap for bg 0 marked " - "uninitialized"); - err = -EFSCORRUPTED; - goto out; - } + if (desc->bg_flags & cpu_to_le16(EXT4_BG_BLOCK_UNINIT)) { err = ext4_init_block_bitmap(sb, bh, block_group, desc); set_bitmap_uptodate(bh); set_buffer_uptodate(bh); diff -u linux-lts-xenial-4.4.0/fs/ext4/ext4.h linux-lts-xenial-4.4.0/fs/ext4/ext4.h --- linux-lts-xenial-4.4.0/fs/ext4/ext4.h +++ linux-lts-xenial-4.4.0/fs/ext4/ext4.h @@ -1468,6 +1468,11 @@ static inline int ext4_valid_inum(struct super_block *sb, unsigned long ino) { return ino == EXT4_ROOT_INO || + ino == EXT4_USR_QUOTA_INO || + ino == EXT4_GRP_QUOTA_INO || + ino == EXT4_BOOT_LOADER_INO || + ino == EXT4_JOURNAL_INO || + ino == EXT4_RESIZE_INO || (ino >= EXT4_FIRST_INO(sb) && ino <= le32_to_cpu(EXT4_SB(sb)->s_es->s_inodes_count)); } reverted: --- linux-lts-xenial-4.4.0/fs/ext4/ext4_extents.h +++ linux-lts-xenial-4.4.0.orig/fs/ext4/ext4_extents.h @@ -103,7 +103,6 @@ }; #define EXT4_EXT_MAGIC cpu_to_le16(0xf30a) -#define EXT4_MAX_EXTENT_DEPTH 5 #define EXT4_EXTENT_TAIL_OFFSET(hdr) \ (sizeof(struct ext4_extent_header) + \ diff -u linux-lts-xenial-4.4.0/fs/ext4/extents.c linux-lts-xenial-4.4.0/fs/ext4/extents.c --- linux-lts-xenial-4.4.0/fs/ext4/extents.c +++ linux-lts-xenial-4.4.0/fs/ext4/extents.c @@ -876,12 +876,6 @@ eh = ext_inode_hdr(inode); depth = ext_depth(inode); - if (depth < 0 || depth > EXT4_MAX_EXTENT_DEPTH) { - EXT4_ERROR_INODE(inode, "inode has invalid extent depth: %d", - depth); - ret = -EFSCORRUPTED; - goto err; - } if (path) { ext4_ext_drop_refs(path); diff -u linux-lts-xenial-4.4.0/fs/ext4/ialloc.c linux-lts-xenial-4.4.0/fs/ext4/ialloc.c --- linux-lts-xenial-4.4.0/fs/ext4/ialloc.c +++ linux-lts-xenial-4.4.0/fs/ext4/ialloc.c @@ -152,16 +152,7 @@ } ext4_lock_group(sb, block_group); - if (ext4_has_group_desc_csum(sb) && - (desc->bg_flags & cpu_to_le16(EXT4_BG_INODE_UNINIT))) { - if (block_group == 0) { - ext4_unlock_group(sb, block_group); - unlock_buffer(bh); - ext4_error(sb, "Inode bitmap for bg 0 marked " - "uninitialized"); - err = -EFSCORRUPTED; - goto out; - } + if (desc->bg_flags & cpu_to_le16(EXT4_BG_INODE_UNINIT)) { memset(bh->b_data, 0, (EXT4_INODES_PER_GROUP(sb) + 7) / 8); ext4_mark_bitmap_end(EXT4_INODES_PER_GROUP(sb), sb->s_blocksize * 8, bh->b_data); @@ -931,8 +922,7 @@ /* recheck and clear flag under lock if we still need to */ ext4_lock_group(sb, group); - if (ext4_has_group_desc_csum(sb) && - (gdp->bg_flags & cpu_to_le16(EXT4_BG_BLOCK_UNINIT))) { + if (gdp->bg_flags & cpu_to_le16(EXT4_BG_BLOCK_UNINIT)) { gdp->bg_flags &= cpu_to_le16(~EXT4_BG_BLOCK_UNINIT); ext4_free_group_clusters_set(sb, gdp, ext4_free_clusters_after_init(sb, group, gdp)); diff -u linux-lts-xenial-4.4.0/fs/ext4/inline.c linux-lts-xenial-4.4.0/fs/ext4/inline.c --- linux-lts-xenial-4.4.0/fs/ext4/inline.c +++ linux-lts-xenial-4.4.0/fs/ext4/inline.c @@ -434,7 +434,6 @@ memset((void *)ext4_raw_inode(&is.iloc)->i_block, 0, EXT4_MIN_INLINE_DATA_SIZE); - memset(ei->i_data, 0, EXT4_MIN_INLINE_DATA_SIZE); if (ext4_has_feature_extents(inode->i_sb)) { if (S_ISDIR(inode->i_mode) || diff -u linux-lts-xenial-4.4.0/fs/ext4/inode.c linux-lts-xenial-4.4.0/fs/ext4/inode.c --- linux-lts-xenial-4.4.0/fs/ext4/inode.c +++ linux-lts-xenial-4.4.0/fs/ext4/inode.c @@ -380,9 +380,9 @@ if (!ext4_data_block_valid(EXT4_SB(inode->i_sb), map->m_pblk, map->m_len)) { ext4_error_inode(inode, func, line, map->m_pblk, - "lblock %lu mapped to illegal pblock %llu " + "lblock %lu mapped to illegal pblock " "(length %d)", (unsigned long) map->m_lblk, - map->m_pblk, map->m_len); + map->m_len); return -EFSCORRUPTED; } return 0; @@ -3792,28 +3792,28 @@ EXT4_BLOCK_SIZE_BITS(sb); stop_block = (offset + length) >> EXT4_BLOCK_SIZE_BITS(sb); - /* If there are blocks to remove, do it */ - if (stop_block > first_block) { - - down_write(&EXT4_I(inode)->i_data_sem); - ext4_discard_preallocations(inode); - - ret = ext4_es_remove_extent(inode, first_block, - stop_block - first_block); - if (ret) { - up_write(&EXT4_I(inode)->i_data_sem); - goto out_stop; - } - - if (ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS)) - ret = ext4_ext_remove_space(inode, first_block, - stop_block - 1); - else - ret = ext4_ind_remove_space(handle, inode, first_block, - stop_block); - + /* If there are no blocks to remove, return now */ + if (first_block >= stop_block) + goto out_stop; + + down_write(&EXT4_I(inode)->i_data_sem); + ext4_discard_preallocations(inode); + + ret = ext4_es_remove_extent(inode, first_block, + stop_block - first_block); + if (ret) { up_write(&EXT4_I(inode)->i_data_sem); + goto out_stop; } + + if (ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS)) + ret = ext4_ext_remove_space(inode, first_block, + stop_block - 1); + else + ret = ext4_ind_remove_space(handle, inode, first_block, + stop_block); + + up_write(&EXT4_I(inode)->i_data_sem); if (IS_SYNC(inode)) ext4_handle_sync(handle); @@ -3996,8 +3996,7 @@ int inodes_per_block, inode_offset; iloc->bh = NULL; - if (inode->i_ino < EXT4_ROOT_INO || - inode->i_ino > le32_to_cpu(EXT4_SB(sb)->s_es->s_inodes_count)) + if (!ext4_valid_inum(sb, inode->i_ino)) return -EFSCORRUPTED; iloc->block_group = (inode->i_ino - 1) / EXT4_INODES_PER_GROUP(sb); diff -u linux-lts-xenial-4.4.0/fs/ext4/mballoc.c linux-lts-xenial-4.4.0/fs/ext4/mballoc.c --- linux-lts-xenial-4.4.0/fs/ext4/mballoc.c +++ linux-lts-xenial-4.4.0/fs/ext4/mballoc.c @@ -2445,8 +2445,7 @@ * initialize bb_free to be able to skip * empty groups without initialization */ - if (ext4_has_group_desc_csum(sb) && - (desc->bg_flags & cpu_to_le16(EXT4_BG_BLOCK_UNINIT))) { + if (desc->bg_flags & cpu_to_le16(EXT4_BG_BLOCK_UNINIT)) { meta_group_info[i]->bb_free = ext4_free_clusters_after_init(sb, group, desc); } else { @@ -2967,8 +2966,7 @@ #endif ext4_set_bits(bitmap_bh->b_data, ac->ac_b_ex.fe_start, ac->ac_b_ex.fe_len); - if (ext4_has_group_desc_csum(sb) && - (gdp->bg_flags & cpu_to_le16(EXT4_BG_BLOCK_UNINIT))) { + if (gdp->bg_flags & cpu_to_le16(EXT4_BG_BLOCK_UNINIT)) { gdp->bg_flags &= cpu_to_le16(~EXT4_BG_BLOCK_UNINIT); ext4_free_group_clusters_set(sb, gdp, ext4_free_clusters_after_init(sb, diff -u linux-lts-xenial-4.4.0/fs/ext4/resize.c linux-lts-xenial-4.4.0/fs/ext4/resize.c --- linux-lts-xenial-4.4.0/fs/ext4/resize.c +++ linux-lts-xenial-4.4.0/fs/ext4/resize.c @@ -1903,7 +1903,7 @@ return 0; n_group = ext4_get_group_number(sb, n_blocks_count - 1); - if (n_group >= (0xFFFFFFFFUL / EXT4_INODES_PER_GROUP(sb))) { + if (n_group > (0xFFFFFFFFUL / EXT4_INODES_PER_GROUP(sb))) { ext4_warning(sb, "resize would cause inodes_count overflow"); return -EINVAL; } diff -u linux-lts-xenial-4.4.0/fs/ext4/super.c linux-lts-xenial-4.4.0/fs/ext4/super.c --- linux-lts-xenial-4.4.0/fs/ext4/super.c +++ linux-lts-xenial-4.4.0/fs/ext4/super.c @@ -2125,7 +2125,6 @@ struct ext4_sb_info *sbi = EXT4_SB(sb); ext4_fsblk_t first_block = le32_to_cpu(sbi->s_es->s_first_data_block); ext4_fsblk_t last_block; - ext4_fsblk_t last_bg_block = sb_block + ext4_bg_num_gdb(sb, 0) + 1; ext4_fsblk_t block_bitmap; ext4_fsblk_t inode_bitmap; ext4_fsblk_t inode_table; @@ -2158,14 +2157,6 @@ if (!(sb->s_flags & MS_RDONLY)) return 0; } - if (block_bitmap >= sb_block + 1 && - block_bitmap <= last_bg_block) { - ext4_msg(sb, KERN_ERR, "ext4_check_descriptors: " - "Block bitmap for group %u overlaps " - "block group descriptors", i); - if (!(sb->s_flags & MS_RDONLY)) - return 0; - } if (block_bitmap < first_block || block_bitmap > last_block) { ext4_msg(sb, KERN_ERR, "ext4_check_descriptors: " "Block bitmap for group %u not in group " @@ -2180,14 +2171,6 @@ if (!(sb->s_flags & MS_RDONLY)) return 0; } - if (inode_bitmap >= sb_block + 1 && - inode_bitmap <= last_bg_block) { - ext4_msg(sb, KERN_ERR, "ext4_check_descriptors: " - "Inode bitmap for group %u overlaps " - "block group descriptors", i); - if (!(sb->s_flags & MS_RDONLY)) - return 0; - } if (inode_bitmap < first_block || inode_bitmap > last_block) { ext4_msg(sb, KERN_ERR, "ext4_check_descriptors: " "Inode bitmap for group %u not in group " @@ -2202,14 +2185,6 @@ if (!(sb->s_flags & MS_RDONLY)) return 0; } - if (inode_table >= sb_block + 1 && - inode_table <= last_bg_block) { - ext4_msg(sb, KERN_ERR, "ext4_check_descriptors: " - "Inode table for group %u overlaps " - "block group descriptors", i); - if (!(sb->s_flags & MS_RDONLY)) - return 0; - } if (inode_table < first_block || inode_table + sbi->s_itb_per_group - 1 > last_block) { ext4_msg(sb, KERN_ERR, "ext4_check_descriptors: " @@ -2890,22 +2865,13 @@ ext4_group_t group, ngroups = EXT4_SB(sb)->s_groups_count; struct ext4_group_desc *gdp = NULL; - if (!ext4_has_group_desc_csum(sb)) - return ngroups; - for (group = 0; group < ngroups; group++) { gdp = ext4_get_group_desc(sb, group, NULL); if (!gdp) continue; - if (gdp->bg_flags & cpu_to_le16(EXT4_BG_INODE_ZEROED)) - continue; - if (group != 0) + if (!(gdp->bg_flags & cpu_to_le16(EXT4_BG_INODE_ZEROED))) break; - ext4_error(sb, "Inode table for bg 0 marked as " - "needing zeroing"); - if (sb->s_flags & MS_RDONLY) - return ngroups; } return group; @@ -3518,13 +3484,6 @@ le32_to_cpu(es->s_log_block_size)); goto failed_mount; } - if (le32_to_cpu(es->s_log_cluster_size) > - (EXT4_MAX_CLUSTER_LOG_SIZE - EXT4_MIN_BLOCK_LOG_SIZE)) { - ext4_msg(sb, KERN_ERR, - "Invalid log cluster size: %u", - le32_to_cpu(es->s_log_cluster_size)); - goto failed_mount; - } if (le16_to_cpu(sbi->s_es->s_reserved_gdt_blocks) > (blocksize / 4)) { ext4_msg(sb, KERN_ERR, @@ -3589,11 +3548,6 @@ } else { sbi->s_inode_size = le16_to_cpu(es->s_inode_size); sbi->s_first_ino = le32_to_cpu(es->s_first_ino); - if (sbi->s_first_ino < EXT4_GOOD_OLD_FIRST_INO) { - ext4_msg(sb, KERN_ERR, "invalid first ino: %u", - sbi->s_first_ino); - goto failed_mount; - } if ((sbi->s_inode_size < EXT4_GOOD_OLD_INODE_SIZE) || (!is_power_of_2(sbi->s_inode_size)) || (sbi->s_inode_size > blocksize)) { @@ -3670,6 +3624,13 @@ "block size (%d)", clustersize, blocksize); goto failed_mount; } + if (le32_to_cpu(es->s_log_cluster_size) > + (EXT4_MAX_CLUSTER_LOG_SIZE - EXT4_MIN_BLOCK_LOG_SIZE)) { + ext4_msg(sb, KERN_ERR, + "Invalid log cluster size: %u", + le32_to_cpu(es->s_log_cluster_size)); + goto failed_mount; + } sbi->s_cluster_bits = le32_to_cpu(es->s_log_cluster_size) - le32_to_cpu(es->s_log_block_size); sbi->s_clusters_per_group = @@ -3690,10 +3651,10 @@ } } else { if (clustersize != blocksize) { - ext4_msg(sb, KERN_ERR, - "fragment/cluster size (%d) != " - "block size (%d)", clustersize, blocksize); - goto failed_mount; + ext4_warning(sb, "fragment/cluster size (%d) != " + "block size (%d)", clustersize, + blocksize); + clustersize = blocksize; } if (sbi->s_blocks_per_group > blocksize * 8) { ext4_msg(sb, KERN_ERR, @@ -3747,13 +3708,6 @@ ext4_blocks_count(es)); goto failed_mount; } - if ((es->s_first_data_block == 0) && (es->s_log_block_size == 0) && - (sbi->s_cluster_ratio == 1)) { - ext4_msg(sb, KERN_WARNING, "bad geometry: first data " - "block is 0 with a 1k block and cluster size"); - goto failed_mount; - } - blocks_count = (ext4_blocks_count(es) - le32_to_cpu(es->s_first_data_block) + EXT4_BLOCKS_PER_GROUP(sb) - 1); @@ -3789,14 +3743,6 @@ ret = -ENOMEM; goto failed_mount; } - if (((u64)sbi->s_groups_count * sbi->s_inodes_per_group) != - le32_to_cpu(es->s_inodes_count)) { - ext4_msg(sb, KERN_ERR, "inodes count not valid: %u vs %llu", - le32_to_cpu(es->s_inodes_count), - ((u64)sbi->s_groups_count * sbi->s_inodes_per_group)); - ret = -EINVAL; - goto failed_mount; - } bgl_lock_init(sbi->s_blockgroup_lock); @@ -4478,14 +4424,6 @@ if (!sbh || block_device_ejected(sb)) return error; - - /* - * The superblock bh should be mapped, but it might not be if the - * device was hot-removed. Not much we can do but fail the I/O. - */ - if (!buffer_mapped(sbh)) - return error; - if (buffer_write_io_error(sbh)) { /* * Oh, dear. A previous attempt to write the reverted: --- linux-lts-xenial-4.4.0/fs/fuse/control.c +++ linux-lts-xenial-4.4.0.orig/fs/fuse/control.c @@ -211,11 +211,10 @@ if (!dentry) return NULL; + fc->ctl_dentry[fc->ctl_ndents++] = dentry; inode = new_inode(fuse_control_sb); + if (!inode) - if (!inode) { - dput(dentry); return NULL; - } inode->i_ino = get_next_ino(); inode->i_mode = mode; @@ -229,9 +228,6 @@ set_nlink(inode, nlink); inode->i_private = fc; d_add(dentry, inode); - - fc->ctl_dentry[fc->ctl_ndents++] = dentry; - return dentry; } @@ -288,10 +284,7 @@ for (i = fc->ctl_ndents - 1; i >= 0; i--) { struct dentry *dentry = fc->ctl_dentry[i]; d_inode(dentry)->i_private = NULL; + d_drop(dentry); - if (!i) { - /* Get rid of submounts: */ - d_invalidate(dentry); - } dput(dentry); } drop_nlink(d_inode(fuse_control_sb->s_root)); diff -u linux-lts-xenial-4.4.0/fs/fuse/dir.c linux-lts-xenial-4.4.0/fs/fuse/dir.c --- linux-lts-xenial-4.4.0/fs/fuse/dir.c +++ linux-lts-xenial-4.4.0/fs/fuse/dir.c @@ -1611,19 +1611,8 @@ return err; if (attr->ia_valid & ATTR_OPEN) { - /* This is coming from open(..., ... | O_TRUNC); */ - WARN_ON(!(attr->ia_valid & ATTR_SIZE)); - WARN_ON(attr->ia_size != 0); - if (fc->atomic_o_trunc) { - /* - * No need to send request to userspace, since actual - * truncation has already been done by OPEN. But still - * need to truncate page cache. - */ - i_size_write(inode, 0); - truncate_pagecache(inode, 0); + if (fc->atomic_o_trunc) return 0; - } file = NULL; } diff -u linux-lts-xenial-4.4.0/fs/fuse/inode.c linux-lts-xenial-4.4.0/fs/fuse/inode.c --- linux-lts-xenial-4.4.0/fs/fuse/inode.c +++ linux-lts-xenial-4.4.0/fs/fuse/inode.c @@ -1177,7 +1177,6 @@ err_put_conn: fuse_bdi_destroy(fc); fuse_conn_put(fc); - sb->s_fs_info = NULL; err_fput: fput(file); err: diff -u linux-lts-xenial-4.4.0/fs/inode.c linux-lts-xenial-4.4.0/fs/inode.c --- linux-lts-xenial-4.4.0/fs/inode.c +++ linux-lts-xenial-4.4.0/fs/inode.c @@ -1946,14 +1946,8 @@ inode->i_uid = current_fsuid(); if (dir && dir->i_mode & S_ISGID) { inode->i_gid = dir->i_gid; - - /* Directories are special, and always inherit S_ISGID */ if (S_ISDIR(mode)) mode |= S_ISGID; - else if ((mode & (S_ISGID | S_IXGRP)) == (S_ISGID | S_IXGRP) && - !in_group_p(inode->i_gid) && - !capable_wrt_inode_uidgid(dir, CAP_FSETID)) - mode &= ~S_ISGID; } else inode->i_gid = current_fsgid(); inode->i_mode = mode; diff -u linux-lts-xenial-4.4.0/fs/jbd2/transaction.c linux-lts-xenial-4.4.0/fs/jbd2/transaction.c --- linux-lts-xenial-4.4.0/fs/jbd2/transaction.c +++ linux-lts-xenial-4.4.0/fs/jbd2/transaction.c @@ -1363,13 +1363,6 @@ if (jh->b_transaction == transaction && jh->b_jlist != BJ_Metadata) { jbd_lock_bh_state(bh); - if (jh->b_transaction == transaction && - jh->b_jlist != BJ_Metadata) - pr_err("JBD2: assertion failure: h_type=%u " - "h_line_no=%u block_no=%llu jlist=%u\n", - handle->h_type, handle->h_line_no, - (unsigned long long) bh->b_blocknr, - jh->b_jlist); J_ASSERT_JH(jh, jh->b_transaction != transaction || jh->b_jlist == BJ_Metadata); jbd_unlock_bh_state(bh); @@ -1389,11 +1382,11 @@ * of the transaction. This needs to be done * once a transaction -bzzz */ + jh->b_modified = 1; if (handle->h_buffer_credits <= 0) { ret = -ENOSPC; goto out_unlock_bh; } - jh->b_modified = 1; handle->h_buffer_credits--; } reverted: --- linux-lts-xenial-4.4.0/fs/jfs/xattr.c +++ linux-lts-xenial-4.4.0.orig/fs/jfs/xattr.c @@ -493,17 +493,15 @@ if (size > PSIZE) { /* * To keep the rest of the code simple. Allocate a + * contiguous buffer to work with - * contiguous buffer to work with. Make the buffer large - * enough to make use of the whole extent. */ + ea_buf->xattr = kmalloc(size, GFP_KERNEL); - ea_buf->max_size = (size + sb->s_blocksize - 1) & - ~(sb->s_blocksize - 1); - - ea_buf->xattr = kmalloc(ea_buf->max_size, GFP_KERNEL); if (ea_buf->xattr == NULL) return -ENOMEM; ea_buf->flag = EA_MALLOC; + ea_buf->max_size = (size + sb->s_blocksize - 1) & + ~(sb->s_blocksize - 1); if (ea_size == 0) return 0; diff -u linux-lts-xenial-4.4.0/fs/nfs/nfs4idmap.c linux-lts-xenial-4.4.0/fs/nfs/nfs4idmap.c --- linux-lts-xenial-4.4.0/fs/nfs/nfs4idmap.c +++ linux-lts-xenial-4.4.0/fs/nfs/nfs4idmap.c @@ -343,7 +343,7 @@ int id_len; ssize_t ret; - id_len = nfs_map_numeric_to_string(id, id_str, sizeof(id_str)); + id_len = snprintf(id_str, sizeof(id_str), "%u", id); ret = nfs_idmap_get_key(id_str, id_len, type, buf, buflen, idmap); if (ret < 0) return -EINVAL; @@ -626,8 +626,7 @@ if (strcmp(upcall->im_name, im->im_name) != 0) break; /* Note: here we store the NUL terminator too */ - len = 1 + nfs_map_numeric_to_string(im->im_id, id_str, - sizeof(id_str)); + len = sprintf(id_str, "%d", im->im_id) + 1; ret = nfs_idmap_instantiate(key, authkey, id_str, len); break; case IDMAP_CONV_IDTONAME: diff -u linux-lts-xenial-4.4.0/fs/nfsd/nfs4xdr.c linux-lts-xenial-4.4.0/fs/nfsd/nfs4xdr.c --- linux-lts-xenial-4.4.0/fs/nfsd/nfs4xdr.c +++ linux-lts-xenial-4.4.0/fs/nfsd/nfs4xdr.c @@ -3595,8 +3595,7 @@ nfserr = nfserr_resource; goto err_no_verf; } - maxcount = svc_max_payload(resp->rqstp); - maxcount = min_t(u32, readdir->rd_maxcount, maxcount); + maxcount = min_t(u32, readdir->rd_maxcount, INT_MAX); /* * Note the rfc defines rd_maxcount as the size of the * READDIR4resok structure, which includes the verifier above @@ -3610,7 +3609,7 @@ /* RFC 3530 14.2.24 allows us to ignore dircount when it's 0: */ if (!readdir->rd_dircount) - readdir->rd_dircount = svc_max_payload(resp->rqstp); + readdir->rd_dircount = INT_MAX; readdir->xdr = xdr; readdir->rd_maxcount = maxcount; reverted: --- linux-lts-xenial-4.4.0/fs/ubifs/journal.c +++ linux-lts-xenial-4.4.0.orig/fs/ubifs/journal.c @@ -1107,7 +1107,7 @@ int err, len, compr_type, out_len; out_len = le32_to_cpu(dn->size); + buf = kmalloc(out_len * WORST_COMPR_FACTOR, GFP_NOFS); - buf = kmalloc_array(out_len, WORST_COMPR_FACTOR, GFP_NOFS); if (!buf) return -ENOMEM; reverted: --- linux-lts-xenial-4.4.0/fs/udf/directory.c +++ linux-lts-xenial-4.4.0.orig/fs/udf/directory.c @@ -150,9 +150,6 @@ sizeof(struct fileIdentDesc)); } } - /* Got last entry outside of dir size - fs is corrupted! */ - if (*nf_pos > dir->i_size) - return NULL; return fi; } diff -u linux-lts-xenial-4.4.0/fs/xattr.c linux-lts-xenial-4.4.0/fs/xattr.c --- linux-lts-xenial-4.4.0/fs/xattr.c +++ linux-lts-xenial-4.4.0/fs/xattr.c @@ -361,12 +361,6 @@ if ((strcmp(kname, XATTR_NAME_POSIX_ACL_ACCESS) == 0) || (strcmp(kname, XATTR_NAME_POSIX_ACL_DEFAULT) == 0)) posix_acl_fix_xattr_from_user(kvalue, size); - else if (strcmp(kname, XATTR_NAME_CAPS) == 0) { - error = cap_convert_nscap(d, &kvalue, size); - if (error < 0) - goto out; - size = error; - } } error = vfs_setxattr(d, kname, kvalue, size, flags); diff -u linux-lts-xenial-4.4.0/fs/xfs/libxfs/xfs_alloc.c linux-lts-xenial-4.4.0/fs/xfs/libxfs/xfs_alloc.c --- linux-lts-xenial-4.4.0/fs/xfs/libxfs/xfs_alloc.c +++ linux-lts-xenial-4.4.0/fs/xfs/libxfs/xfs_alloc.c @@ -1924,93 +1924,6 @@ } /* - * Check the agfl fields of the agf for inconsistency or corruption. The purpose - * is to detect an agfl header padding mismatch between current and early v5 - * kernels. This problem manifests as a 1-slot size difference between the - * on-disk flcount and the active [first, last] range of a wrapped agfl. This - * may also catch variants of agfl count corruption unrelated to padding. Either - * way, we'll reset the agfl and warn the user. - * - * Return true if a reset is required before the agfl can be used, false - * otherwise. - */ -static bool -xfs_agfl_needs_reset( - struct xfs_mount *mp, - struct xfs_agf *agf) -{ - uint32_t f = be32_to_cpu(agf->agf_flfirst); - uint32_t l = be32_to_cpu(agf->agf_fllast); - uint32_t c = be32_to_cpu(agf->agf_flcount); - int agfl_size = XFS_AGFL_SIZE(mp); - int active; - - /* no agfl header on v4 supers */ - if (!xfs_sb_version_hascrc(&mp->m_sb)) - return false; - - /* - * The agf read verifier catches severe corruption of these fields. - * Repeat some sanity checks to cover a packed -> unpacked mismatch if - * the verifier allows it. - */ - if (f >= agfl_size || l >= agfl_size) - return true; - if (c > agfl_size) - return true; - - /* - * Check consistency between the on-disk count and the active range. An - * agfl padding mismatch manifests as an inconsistent flcount. - */ - if (c && l >= f) - active = l - f + 1; - else if (c) - active = agfl_size - f + l + 1; - else - active = 0; - - return active != c; -} - -/* - * Reset the agfl to an empty state. Ignore/drop any existing blocks since the - * agfl content cannot be trusted. Warn the user that a repair is required to - * recover leaked blocks. - * - * The purpose of this mechanism is to handle filesystems affected by the agfl - * header padding mismatch problem. A reset keeps the filesystem online with a - * relatively minor free space accounting inconsistency rather than suffer the - * inevitable crash from use of an invalid agfl block. - */ -static void -xfs_agfl_reset( - struct xfs_trans *tp, - struct xfs_buf *agbp, - struct xfs_perag *pag) -{ - struct xfs_mount *mp = tp->t_mountp; - struct xfs_agf *agf = XFS_BUF_TO_AGF(agbp); - - ASSERT(pag->pagf_agflreset); - trace_xfs_agfl_reset(mp, agf, 0, _RET_IP_); - - xfs_warn(mp, - "WARNING: Reset corrupted AGFL on AG %u. %d blocks leaked. " - "Please unmount and run xfs_repair.", - pag->pag_agno, pag->pagf_flcount); - - agf->agf_flfirst = 0; - agf->agf_fllast = cpu_to_be32(XFS_AGFL_SIZE(mp) - 1); - agf->agf_flcount = 0; - xfs_alloc_log_agf(tp, agbp, XFS_AGF_FLFIRST | XFS_AGF_FLLAST | - XFS_AGF_FLCOUNT); - - pag->pagf_flcount = 0; - pag->pagf_agflreset = false; -} - -/* * Decide whether to use this allocation group for this allocation. * If so, fix up the btree freelist's size. */ @@ -2070,10 +1983,6 @@ } } - /* reset a padding mismatched agfl before final free space check */ - if (pag->pagf_agflreset) - xfs_agfl_reset(tp, agbp, pag); - /* If there isn't enough total space or single-extent, reject it. */ need = xfs_alloc_min_freelist(mp, pag); if (!xfs_alloc_space_available(args, need, flags)) @@ -2212,7 +2121,6 @@ agf->agf_flfirst = 0; pag = xfs_perag_get(mp, be32_to_cpu(agf->agf_seqno)); - ASSERT(!pag->pagf_agflreset); be32_add_cpu(&agf->agf_flcount, -1); xfs_trans_agflist_delta(tp, -1); pag->pagf_flcount--; @@ -2318,7 +2226,6 @@ agf->agf_fllast = 0; pag = xfs_perag_get(mp, be32_to_cpu(agf->agf_seqno)); - ASSERT(!pag->pagf_agflreset); be32_add_cpu(&agf->agf_flcount, 1); xfs_trans_agflist_delta(tp, 1); pag->pagf_flcount++; @@ -2510,7 +2417,6 @@ pag->pagb_count = 0; pag->pagb_tree = RB_ROOT; pag->pagf_init = 1; - pag->pagf_agflreset = xfs_agfl_needs_reset(mp, agf); } #ifdef DEBUG else if (!XFS_FORCED_SHUTDOWN(mp)) { diff -u linux-lts-xenial-4.4.0/fs/xfs/libxfs/xfs_attr_leaf.c linux-lts-xenial-4.4.0/fs/xfs/libxfs/xfs_attr_leaf.c --- linux-lts-xenial-4.4.0/fs/xfs/libxfs/xfs_attr_leaf.c +++ linux-lts-xenial-4.4.0/fs/xfs/libxfs/xfs_attr_leaf.c @@ -779,8 +779,9 @@ ASSERT(blkno == 0); error = xfs_attr3_leaf_create(args, blkno, &bp); if (error) { - /* xfs_attr3_leaf_create may not have instantiated a block */ - if (bp && (xfs_da_shrink_inode(args, 0, bp) != 0)) + error = xfs_da_shrink_inode(args, 0, bp); + bp = NULL; + if (error) goto out; xfs_idata_realloc(dp, size, XFS_ATTR_FORK); /* try to put */ memcpy(ifp->if_u1.if_data, tmpbuffer, size); /* it back */ reverted: --- linux-lts-xenial-4.4.0/fs/xfs/xfs_log.c +++ linux-lts-xenial-4.4.0.orig/fs/xfs/xfs_log.c @@ -3323,6 +3323,8 @@ */ if (iclog->ic_state & XLOG_STATE_IOERROR) return -EIO; + if (log_flushed) + *log_flushed = 1; } else { no_sleep: @@ -3430,6 +3432,8 @@ xlog_wait(&iclog->ic_prev->ic_write_wait, &log->l_icloglock); + if (log_flushed) + *log_flushed = 1; already_slept = 1; goto try_again; } @@ -3463,6 +3467,9 @@ */ if (iclog->ic_state & XLOG_STATE_IOERROR) return -EIO; + + if (log_flushed) + *log_flushed = 1; } else { /* just return */ spin_unlock(&log->l_icloglock); } reverted: --- linux-lts-xenial-4.4.0/fs/xfs/xfs_mount.h +++ linux-lts-xenial-4.4.0.orig/fs/xfs/xfs_mount.h @@ -278,7 +278,6 @@ char pagi_inodeok; /* The agi is ok for inodes */ __uint8_t pagf_levels[XFS_BTNUM_AGF]; /* # of levels in bno & cnt btree */ - bool pagf_agflreset; /* agfl requires reset before use */ __uint32_t pagf_flcount; /* count of blocks in freelist */ xfs_extlen_t pagf_freeblks; /* total free blocks */ xfs_extlen_t pagf_longest; /* longest free space */ reverted: --- linux-lts-xenial-4.4.0/fs/xfs/xfs_trace.h +++ linux-lts-xenial-4.4.0.orig/fs/xfs/xfs_trace.h @@ -1485,7 +1485,7 @@ __entry->lsn) ); +TRACE_EVENT(xfs_agf, -DECLARE_EVENT_CLASS(xfs_agf_class, TP_PROTO(struct xfs_mount *mp, struct xfs_agf *agf, int flags, unsigned long caller_ip), TP_ARGS(mp, agf, flags, caller_ip), @@ -1541,13 +1541,6 @@ __entry->longest, (void *)__entry->caller_ip) ); -#define DEFINE_AGF_EVENT(name) \ -DEFINE_EVENT(xfs_agf_class, name, \ - TP_PROTO(struct xfs_mount *mp, struct xfs_agf *agf, int flags, \ - unsigned long caller_ip), \ - TP_ARGS(mp, agf, flags, caller_ip)) -DEFINE_AGF_EVENT(xfs_agf); -DEFINE_AGF_EVENT(xfs_agfl_reset); TRACE_EVENT(xfs_free_extent, TP_PROTO(struct xfs_mount *mp, xfs_agnumber_t agno, xfs_agblock_t agbno, diff -u linux-lts-xenial-4.4.0/include/asm-generic/pgtable.h linux-lts-xenial-4.4.0/include/asm-generic/pgtable.h --- linux-lts-xenial-4.4.0/include/asm-generic/pgtable.h +++ linux-lts-xenial-4.4.0/include/asm-generic/pgtable.h @@ -799,6 +799,18 @@ } #endif /* CONFIG_HAVE_ARCH_HUGE_VMAP */ +#ifndef __HAVE_ARCH_PFN_MODIFY_ALLOWED +static inline bool pfn_modify_allowed(unsigned long pfn, pgprot_t prot) +{ + return true; +} + +static inline bool arch_has_pfn_modify_check(void) +{ + return false; +} +#endif /* !_HAVE_ARCH_PFN_MODIFY_ALLOWED */ + #endif /* !__ASSEMBLY__ */ #ifndef io_remap_pfn_range diff -u linux-lts-xenial-4.4.0/include/linux/blkdev.h linux-lts-xenial-4.4.0/include/linux/blkdev.h --- linux-lts-xenial-4.4.0/include/linux/blkdev.h +++ linux-lts-xenial-4.4.0/include/linux/blkdev.h @@ -883,8 +883,8 @@ if (!q->limits.chunk_sectors) return q->limits.max_sectors; - return min(q->limits.max_sectors, (unsigned int)(q->limits.chunk_sectors - - (offset & (q->limits.chunk_sectors - 1)))); + return q->limits.chunk_sectors - + (offset & (q->limits.chunk_sectors - 1)); } static inline unsigned int blk_rq_get_max_sectors(struct request *rq) diff -u linux-lts-xenial-4.4.0/include/linux/capability.h linux-lts-xenial-4.4.0/include/linux/capability.h --- linux-lts-xenial-4.4.0/include/linux/capability.h +++ linux-lts-xenial-4.4.0/include/linux/capability.h @@ -255,4 +255,2 @@ -extern int cap_convert_nscap(struct dentry *dentry, void **ivalue, size_t size); - #endif /* !_LINUX_CAPABILITY_H */ diff -u linux-lts-xenial-4.4.0/include/linux/compiler.h linux-lts-xenial-4.4.0/include/linux/compiler.h --- linux-lts-xenial-4.4.0/include/linux/compiler.h +++ linux-lts-xenial-4.4.0/include/linux/compiler.h @@ -111,7 +111,7 @@ #define unlikely_notrace(x) __builtin_expect(!!(x), 0) #define __branch_check__(x, expect) ({ \ - long ______r; \ + int ______r; \ static struct ftrace_branch_data \ __attribute__((__aligned__(4))) \ __attribute__((section("_ftrace_annotated_branch"))) \ diff -u linux-lts-xenial-4.4.0/include/linux/cpu.h linux-lts-xenial-4.4.0/include/linux/cpu.h --- linux-lts-xenial-4.4.0/include/linux/cpu.h +++ linux-lts-xenial-4.4.0/include/linux/cpu.h @@ -48,6 +48,8 @@ struct device_attribute *attr, char *buf); extern ssize_t cpu_show_spec_store_bypass(struct device *dev, struct device_attribute *attr, char *buf); +extern ssize_t cpu_show_l1tf(struct device *dev, + struct device_attribute *attr, char *buf); extern __printf(4, 5) struct device *cpu_device_create(struct device *parent, void *drvdata, @@ -241,6 +243,7 @@ #define __unregister_hotcpu_notifier(nb) __unregister_cpu_notifier(nb) void clear_tasks_mm_cpumask(int cpu); int cpu_down(unsigned int cpu); +int cpu_down_maps_locked(unsigned int cpu); #else /* CONFIG_HOTPLUG_CPU */ @@ -294,2 +297,21 @@ +enum cpuhp_smt_control { + CPU_SMT_ENABLED, + CPU_SMT_DISABLED, + CPU_SMT_FORCE_DISABLED, + CPU_SMT_NOT_SUPPORTED, +}; + +#if defined(CONFIG_SMP) && defined(CONFIG_HOTPLUG_SMT) +extern enum cpuhp_smt_control cpu_smt_control; +extern void cpu_smt_disable(bool force); +extern void cpu_smt_check_topology_early(void); +extern void cpu_smt_check_topology(void); +#else +# define cpu_smt_control (CPU_SMT_ENABLED) +static inline void cpu_smt_disable(bool force) { } +static inline void cpu_smt_check_topology_early(void) { } +static inline void cpu_smt_check_topology(void) { } +#endif + #endif /* _LINUX_CPU_H_ */ diff -u linux-lts-xenial-4.4.0/include/linux/fs.h linux-lts-xenial-4.4.0/include/linux/fs.h --- linux-lts-xenial-4.4.0/include/linux/fs.h +++ linux-lts-xenial-4.4.0/include/linux/fs.h @@ -902,9 +902,9 @@ /* Page cache limit. The filesystems should put that into their s_maxbytes limits, otherwise bad things can happen in VM. */ #if BITS_PER_LONG==32 -#define MAX_LFS_FILESIZE ((loff_t)ULONG_MAX << PAGE_SHIFT) +#define MAX_LFS_FILESIZE (((loff_t)PAGE_CACHE_SIZE << (BITS_PER_LONG-1))-1) #elif BITS_PER_LONG==64 -#define MAX_LFS_FILESIZE ((loff_t)LLONG_MAX) +#define MAX_LFS_FILESIZE ((loff_t)0x7fffffffffffffffLL) #endif #define FL_POSIX 1 reverted: --- linux-lts-xenial-4.4.0/include/linux/iio/buffer.h +++ linux-lts-xenial-4.4.0.orig/include/linux/iio/buffer.h @@ -49,7 +49,7 @@ int (*request_update)(struct iio_buffer *buffer); int (*set_bytes_per_datum)(struct iio_buffer *buffer, size_t bpd); + int (*set_length)(struct iio_buffer *buffer, int length); - int (*set_length)(struct iio_buffer *buffer, unsigned int length); void (*release)(struct iio_buffer *buffer); @@ -78,8 +78,8 @@ * @watermark: [INTERN] number of datums to wait for poll/read. */ struct iio_buffer { + int length; + int bytes_per_datum; - unsigned int length; - size_t bytes_per_datum; struct attribute_group *scan_el_attrs; long *scan_mask; bool scan_timestamp; diff -u linux-lts-xenial-4.4.0/include/linux/security.h linux-lts-xenial-4.4.0/include/linux/security.h --- linux-lts-xenial-4.4.0/include/linux/security.h +++ linux-lts-xenial-4.4.0/include/linux/security.h @@ -85,8 +85,6 @@ extern int cap_inode_removexattr(struct dentry *dentry, const char *name); extern int cap_inode_need_killpriv(struct dentry *dentry); extern int cap_inode_killpriv(struct dentry *dentry); -extern int cap_inode_getsecurity(const struct inode *inode, const char *name, - void **buffer, bool alloc); extern int cap_mmap_addr(unsigned long addr); extern int cap_mmap_file(struct file *file, unsigned long reqprot, unsigned long prot, unsigned long flags); diff -u linux-lts-xenial-4.4.0/include/linux/tcp.h linux-lts-xenial-4.4.0/include/linux/tcp.h --- linux-lts-xenial-4.4.0/include/linux/tcp.h +++ linux-lts-xenial-4.4.0/include/linux/tcp.h @@ -324,7 +324,7 @@ /* Receiver queue space */ struct { - u32 space; + int space; u32 seq; u32 time; } rcvq_space; diff -u linux-lts-xenial-4.4.0/include/net/bluetooth/hci_core.h linux-lts-xenial-4.4.0/include/net/bluetooth/hci_core.h --- linux-lts-xenial-4.4.0/include/net/bluetooth/hci_core.h +++ linux-lts-xenial-4.4.0/include/net/bluetooth/hci_core.h @@ -879,7 +879,7 @@ u16 conn_timeout, u8 role); struct hci_conn *hci_connect_le(struct hci_dev *hdev, bdaddr_t *dst, u8 dst_type, u8 sec_level, u16 conn_timeout, - u8 role, bdaddr_t *direct_rpa); + u8 role); struct hci_conn *hci_connect_acl(struct hci_dev *hdev, bdaddr_t *dst, u8 sec_level, u8 auth_type); struct hci_conn *hci_connect_sco(struct hci_dev *hdev, int type, bdaddr_t *dst, diff -u linux-lts-xenial-4.4.0/include/net/ipv6.h linux-lts-xenial-4.4.0/include/net/ipv6.h --- linux-lts-xenial-4.4.0/include/net/ipv6.h +++ linux-lts-xenial-4.4.0/include/net/ipv6.h @@ -327,8 +327,8 @@ } #endif -#define IPV6_FRAG_HIGH_THRESH (4 * 1024*1024) /* 4194304 */ -#define IPV6_FRAG_LOW_THRESH (3 * 1024*1024) /* 3145728 */ +#define IPV6_FRAG_HIGH_THRESH (256 * 1024) /* 262144 */ +#define IPV6_FRAG_LOW_THRESH (192 * 1024) /* 196608 */ #define IPV6_FRAG_TIMEOUT (60 * HZ) /* 60 seconds */ int __ipv6_addr_type(const struct in6_addr *addr); reverted: --- linux-lts-xenial-4.4.0/include/uapi/linux/capability.h +++ linux-lts-xenial-4.4.0.orig/include/uapi/linux/capability.h @@ -62,13 +62,9 @@ #define VFS_CAP_U32_2 2 #define XATTR_CAPS_SZ_2 (sizeof(__le32)*(1 + 2*VFS_CAP_U32_2)) +#define XATTR_CAPS_SZ XATTR_CAPS_SZ_2 +#define VFS_CAP_U32 VFS_CAP_U32_2 +#define VFS_CAP_REVISION VFS_CAP_REVISION_2 -#define VFS_CAP_REVISION_3 0x03000000 -#define VFS_CAP_U32_3 2 -#define XATTR_CAPS_SZ_3 (sizeof(__le32)*(2 + 2*VFS_CAP_U32_3)) - -#define XATTR_CAPS_SZ XATTR_CAPS_SZ_3 -#define VFS_CAP_U32 VFS_CAP_U32_3 -#define VFS_CAP_REVISION VFS_CAP_REVISION_3 struct vfs_cap_data { __le32 magic_etc; /* Little endian */ @@ -78,18 +74,6 @@ } data[VFS_CAP_U32]; }; -/* - * same as vfs_cap_data but with a rootid at the end - */ -struct vfs_ns_cap_data { - __le32 magic_etc; - struct { - __le32 permitted; /* Little endian */ - __le32 inheritable; /* Little endian */ - } data[VFS_CAP_U32]; - __le32 rootid; -}; - #ifndef __KERNEL__ /* diff -u linux-lts-xenial-4.4.0/include/uapi/linux/kvm.h linux-lts-xenial-4.4.0/include/uapi/linux/kvm.h --- linux-lts-xenial-4.4.0/include/uapi/linux/kvm.h +++ linux-lts-xenial-4.4.0/include/uapi/linux/kvm.h @@ -705,6 +705,7 @@ #define KVM_TRACE_PAUSE __KVM_DEPRECATED_MAIN_0x07 #define KVM_TRACE_DISABLE __KVM_DEPRECATED_MAIN_0x08 #define KVM_GET_EMULATED_CPUID _IOWR(KVMIO, 0x09, struct kvm_cpuid2) +#define KVM_GET_MSR_FEATURE_INDEX_LIST _IOWR(KVMIO, 0x0a, struct kvm_msr_list) /* * Extension capability list. @@ -850,6 +851,7 @@ #define KVM_CAP_IOEVENTFD_ANY_LENGTH 122 #define KVM_CAP_HYPERV_SYNIC 123 #define KVM_CAP_S390_BPB 152 +#define KVM_CAP_GET_MSR_FEATURES 153 #ifdef KVM_CAP_IRQ_ROUTING diff -u linux-lts-xenial-4.4.0/include/uapi/linux/nl80211.h linux-lts-xenial-4.4.0/include/uapi/linux/nl80211.h --- linux-lts-xenial-4.4.0/include/uapi/linux/nl80211.h +++ linux-lts-xenial-4.4.0/include/uapi/linux/nl80211.h @@ -2195,7 +2195,7 @@ #define NL80211_ATTR_KEYS NL80211_ATTR_KEYS #define NL80211_ATTR_FEATURE_FLAGS NL80211_ATTR_FEATURE_FLAGS -#define NL80211_WIPHY_NAME_MAXLEN 64 +#define NL80211_WIPHY_NAME_MAXLEN 128 #define NL80211_MAX_SUPP_RATES 32 #define NL80211_MAX_SUPP_HT_RATES 77 diff -u linux-lts-xenial-4.4.0/init/Kconfig linux-lts-xenial-4.4.0/init/Kconfig --- linux-lts-xenial-4.4.0/init/Kconfig +++ linux-lts-xenial-4.4.0/init/Kconfig @@ -1317,17 +1317,6 @@ endif -choice - prompt "Compiler optimization level" - default CONFIG_CC_OPTIMIZE_FOR_PERFORMANCE - -config CC_OPTIMIZE_FOR_PERFORMANCE - bool "Optimize for performance" - help - This is the default optimization level for the kernel, building - with the "-O2" compiler flag for best performance and most - helpful compile-time warnings. - config CC_OPTIMIZE_FOR_SIZE bool "Optimize for size" help @@ -1336,8 +1325,6 @@ If unsure, say N. -endchoice - config SYSCTL bool diff -u linux-lts-xenial-4.4.0/kernel/cpu.c linux-lts-xenial-4.4.0/kernel/cpu.c --- linux-lts-xenial-4.4.0/kernel/cpu.c +++ linux-lts-xenial-4.4.0/kernel/cpu.c @@ -30,6 +30,11 @@ /* Serializes the updates to cpu_online_mask, cpu_present_mask */ static DEFINE_MUTEX(cpu_add_remove_lock); +#ifdef CONFIG_HOTPLUG_SMT +static DECLARE_BITMAP(cpu_bootonce_bits, CONFIG_NR_CPUS) __read_mostly; +const struct cpumask *const cpu_bootonce_mask = to_cpumask(cpu_bootonce_bits); +#endif + /* * The following two APIs (cpu_maps_update_begin/done) must be used when * attempting to serialize the updates to cpu_online_mask & cpu_present_mask. @@ -192,6 +197,77 @@ EXPORT_SYMBOL_GPL(cpu_hotplug_enable); #endif /* CONFIG_HOTPLUG_CPU */ +#ifdef CONFIG_HOTPLUG_SMT +enum cpuhp_smt_control cpu_smt_control __read_mostly = CPU_SMT_ENABLED; +EXPORT_SYMBOL_GPL(cpu_smt_control); + +static bool cpu_smt_available __read_mostly; + +void __init cpu_smt_disable(bool force) +{ + if (cpu_smt_control == CPU_SMT_FORCE_DISABLED || + cpu_smt_control == CPU_SMT_NOT_SUPPORTED) + return; + + if (force) { + pr_info("SMT: Force disabled\n"); + cpu_smt_control = CPU_SMT_FORCE_DISABLED; + } else { + cpu_smt_control = CPU_SMT_DISABLED; + } +} + +/* + * The decision whether SMT is supported can only be done after the full + * CPU identification. Called from architecture code before non boot CPUs + * are brought up. + */ +void __init cpu_smt_check_topology_early(void) +{ + if (!topology_smt_supported()) + cpu_smt_control = CPU_SMT_NOT_SUPPORTED; +} + +/* + * If SMT was disabled by BIOS, detect it here, after the CPUs have been + * brought online. This ensures the smt/l1tf sysfs entries are consistent + * with reality. cpu_smt_available is set to true during the bringup of non + * boot CPUs when a SMT sibling is detected. Note, this may overwrite + * cpu_smt_control's previous setting. + */ +void __init cpu_smt_check_topology(void) +{ + if (!cpu_smt_available) + cpu_smt_control = CPU_SMT_NOT_SUPPORTED; +} + +static int __init smt_cmdline_disable(char *str) +{ + cpu_smt_disable(str && !strcmp(str, "force")); + return 0; +} +early_param("nosmt", smt_cmdline_disable); + +static inline bool cpu_smt_allowed(unsigned int cpu) +{ + if (topology_is_primary_thread(cpu)) + return true; + + if (cpu_smt_control == CPU_SMT_ENABLED) + return true; + + /* + * On x86 it's required to boot all logical CPUs at least once so + * that the init code can get a chance to set CR4.MCE on each + * CPU. Otherwise, a broadacasted MCE observing CR4.MCE=0b on any + * core will shutdown the machine. + */ + return !cpumask_test_cpu(cpu, cpu_bootonce_mask); +} +#else +static inline bool cpu_smt_allowed(unsigned int cpu) { return true; } +#endif + /* Need to know about CPUs going up/down? */ int register_cpu_notifier(struct notifier_block *nb) { @@ -353,7 +429,6 @@ return -EINVAL; cpu_hotplug_begin(); - err = __cpu_notify(CPU_DOWN_PREPARE | mod, hcpu, -1, &nr_calls); if (err) { nr_calls--; @@ -430,20 +505,20 @@ return err; } +int cpu_down_maps_locked(unsigned int cpu) +{ + if (cpu_hotplug_disabled) + return -EBUSY; + return _cpu_down(cpu, 0); +} +EXPORT_SYMBOL(cpu_down_maps_locked); + int cpu_down(unsigned int cpu) { int err; cpu_maps_update_begin(); - - if (cpu_hotplug_disabled) { - err = -EBUSY; - goto out; - } - - err = _cpu_down(cpu, 0); - -out: + err = cpu_down_maps_locked(cpu); cpu_maps_update_done(); return err; } @@ -517,9 +592,24 @@ /* Arch-specific enabling code. */ ret = __cpu_up(cpu, idle); - if (ret != 0) goto out_notify; + +#ifdef CONFIG_HOTPLUG_SMT + cpumask_set_cpu(cpu, to_cpumask(cpu_bootonce_bits)); + /* + * If the CPU is not a 'primary' thread and the booted_once bit is + * set then the processor has SMT support. Store this information + * for the late check of SMT support in cpu_smt_check_topology(). + * + * Backport notice, since without the hotplug state machine there + * is no additional cpu_smt_allowed() check in the callback. There + * are no callbacks at all. So make the change here when the bit + * for booted once was just set for a non primary thread. + */ + if (!topology_is_primary_thread(cpu)) + cpu_smt_available = true; +#endif BUG_ON(!cpu_online(cpu)); /* Now call notifier in preparation. */ @@ -557,6 +647,10 @@ err = -EBUSY; goto out; } + if (!cpu_smt_allowed(cpu)) { + err = -EPERM; + goto out; + } err = _cpu_up(cpu, 0); @@ -728,6 +822,169 @@ cpu_notify(val, (void *)(long)cpu); } +#ifdef CONFIG_HOTPLUG_SMT + +static const char *smt_states[] = { + [CPU_SMT_ENABLED] = "on", + [CPU_SMT_DISABLED] = "off", + [CPU_SMT_FORCE_DISABLED] = "forceoff", + [CPU_SMT_NOT_SUPPORTED] = "notsupported", +}; + +static ssize_t +show_smt_control(struct device *dev, struct device_attribute *attr, char *buf) +{ + return snprintf(buf, PAGE_SIZE - 2, "%s\n", smt_states[cpu_smt_control]); +} + +static void cpuhp_offline_cpu_device(unsigned int cpu) +{ + struct device *dev = get_cpu_device(cpu); + + dev->offline = true; + /* Tell user space about the state change */ + kobject_uevent(&dev->kobj, KOBJ_OFFLINE); +} + +static void cpuhp_online_cpu_device(unsigned int cpu) +{ + struct device *dev = get_cpu_device(cpu); + + dev->offline = false; + /* Tell user space about the state change */ + kobject_uevent(&dev->kobj, KOBJ_ONLINE); +} + +static int cpuhp_smt_disable(enum cpuhp_smt_control ctrlval) +{ + int cpu, ret = 0; + + cpu_maps_update_begin(); + for_each_online_cpu(cpu) { + if (topology_is_primary_thread(cpu)) + continue; + ret = cpu_down_maps_locked(cpu); + if (ret) + break; + /* + * As this needs to hold the cpu maps lock it's impossible + * to call device_offline() because that ends up calling + * cpu_down() which takes cpu maps lock. cpu maps lock + * needs to be held as this might race against in kernel + * abusers of the hotplug machinery (thermal management). + * + * So nothing would update device:offline state. That would + * leave the sysfs entry stale and prevent onlining after + * smt control has been changed to 'off' again. This is + * called under the sysfs hotplug lock, so it is properly + * serialized against the regular offline usage. + */ + cpuhp_offline_cpu_device(cpu); + } + if (!ret) + cpu_smt_control = ctrlval; + cpu_maps_update_done(); + return ret; +} + +static int cpuhp_smt_enable(void) +{ + int cpu, ret = 0; + + cpu_maps_update_begin(); + cpu_smt_control = CPU_SMT_ENABLED; + for_each_present_cpu(cpu) { + /* Skip online CPUs and CPUs on offline nodes */ + if (cpu_online(cpu) || !node_online(cpu_to_node(cpu))) + continue; + ret = _cpu_up(cpu, 0); + if (ret) + break; + /* See comment in cpuhp_smt_disable() */ + cpuhp_online_cpu_device(cpu); + } + cpu_maps_update_done(); + return ret; +} + +static ssize_t +store_smt_control(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + int ctrlval, ret; + + if (sysfs_streq(buf, "on")) + ctrlval = CPU_SMT_ENABLED; + else if (sysfs_streq(buf, "off")) + ctrlval = CPU_SMT_DISABLED; + else if (sysfs_streq(buf, "forceoff")) + ctrlval = CPU_SMT_FORCE_DISABLED; + else + return -EINVAL; + + if (cpu_smt_control == CPU_SMT_FORCE_DISABLED) + return -EPERM; + + if (cpu_smt_control == CPU_SMT_NOT_SUPPORTED) + return -ENODEV; + + ret = lock_device_hotplug_sysfs(); + if (ret) + return ret; + + if (ctrlval != cpu_smt_control) { + switch (ctrlval) { + case CPU_SMT_ENABLED: + ret = cpuhp_smt_enable(); + break; + case CPU_SMT_DISABLED: + case CPU_SMT_FORCE_DISABLED: + ret = cpuhp_smt_disable(ctrlval); + break; + } + } + + unlock_device_hotplug(); + return ret ? ret : count; +} +static DEVICE_ATTR(control, 0644, show_smt_control, store_smt_control); + +static ssize_t +show_smt_active(struct device *dev, struct device_attribute *attr, char *buf) +{ + bool active = topology_max_smt_threads() > 1; + + return snprintf(buf, PAGE_SIZE - 2, "%d\n", active); +} +static DEVICE_ATTR(active, 0444, show_smt_active, NULL); + +static struct attribute *cpuhp_smt_attrs[] = { + &dev_attr_control.attr, + &dev_attr_active.attr, + NULL +}; + +static const struct attribute_group cpuhp_smt_attr_group = { + .attrs = cpuhp_smt_attrs, + .name = "smt", + NULL +}; + +static int __init cpu_smt_state_init(void) +{ + return sysfs_create_group(&cpu_subsys.dev_root->kobj, + &cpuhp_smt_attr_group); +} + +#else +static inline int cpu_smt_state_init(void) { return 0; } +#endif /* CONFIG_HOTPLUG_SMT */ + +static int __init cpuhp_sysfs_init(void) +{ + return cpu_smt_state_init(); +} +device_initcall(cpuhp_sysfs_init); #endif /* CONFIG_SMP */ /* diff -u linux-lts-xenial-4.4.0/kernel/smp.c linux-lts-xenial-4.4.0/kernel/smp.c --- linux-lts-xenial-4.4.0/kernel/smp.c +++ linux-lts-xenial-4.4.0/kernel/smp.c @@ -623,6 +623,26 @@ cpu_up(cpu); } +#ifdef CONFIG_HOTPLUG_SMT + /* Handle nosmt[=force] here */ + if (cpu_smt_control == CPU_SMT_DISABLED || + cpu_smt_control == CPU_SMT_FORCE_DISABLED) { + int ret; + + cpu_maps_update_begin(); + for_each_online_cpu(cpu) { + if (topology_is_primary_thread(cpu)) + continue; + ret = cpu_down_maps_locked(cpu); + if (ret) + break; + } + cpu_maps_update_done(); + } +#endif + + /* Final decision about SMT support */ + cpu_smt_check_topology(); /* Any cleanup work */ smp_announce(); smp_cpus_done(setup_max_cpus); reverted: --- linux-lts-xenial-4.4.0/kernel/time/time.c +++ linux-lts-xenial-4.4.0.orig/kernel/time/time.c @@ -28,7 +28,6 @@ */ #include -#include #include #include #include @@ -259,10 +258,9 @@ return (j + (HZ / MSEC_PER_SEC) - 1)/(HZ / MSEC_PER_SEC); #else # if BITS_PER_LONG == 32 + return (HZ_TO_MSEC_MUL32 * j) >> HZ_TO_MSEC_SHR32; - return (HZ_TO_MSEC_MUL32 * j + (1ULL << HZ_TO_MSEC_SHR32) - 1) >> - HZ_TO_MSEC_SHR32; # else + return (j * HZ_TO_MSEC_NUM) / HZ_TO_MSEC_DEN; - return DIV_ROUND_UP(j * HZ_TO_MSEC_NUM, HZ_TO_MSEC_DEN); # endif #endif } reverted: --- linux-lts-xenial-4.4.0/kernel/trace/trace_events_trigger.c +++ linux-lts-xenial-4.4.0.orig/kernel/trace/trace_events_trigger.c @@ -469,10 +469,9 @@ struct trace_event_file *file; list_for_each_entry(file, &tr->events, list) { + struct event_trigger_data *data; + list_for_each_entry_rcu(data, &file->triggers, list) { - struct event_trigger_data *data, *n; - list_for_each_entry_safe(data, n, &file->triggers, list) { trace_event_trigger_enable_disable(file, 0); - list_del_rcu(&data->list); if (data->ops->free) data->ops->free(data->ops, data); } diff -u linux-lts-xenial-4.4.0/kernel/trace/trace_functions_graph.c linux-lts-xenial-4.4.0/kernel/trace/trace_functions_graph.c --- linux-lts-xenial-4.4.0/kernel/trace/trace_functions_graph.c +++ linux-lts-xenial-4.4.0/kernel/trace/trace_functions_graph.c @@ -768,7 +768,6 @@ struct ftrace_graph_ret *graph_ret; struct ftrace_graph_ent *call; unsigned long long duration; - int cpu = iter->cpu; int i; graph_ret = &ret_entry->ret; @@ -777,6 +776,7 @@ if (data) { struct fgraph_cpu_data *cpu_data; + int cpu = iter->cpu; cpu_data = per_cpu_ptr(data->cpu_data, cpu); @@ -806,9 +806,6 @@ trace_seq_printf(s, "%ps();\n", (void *)call->func); - print_graph_irq(iter, graph_ret->func, TRACE_GRAPH_RET, - cpu, iter->ent->pid, flags); - return trace_handle_return(s); } reverted: --- linux-lts-xenial-4.4.0/lib/vsprintf.c +++ linux-lts-xenial-4.4.0.orig/lib/vsprintf.c @@ -1345,6 +1345,9 @@ return string(buf, end, NULL, spec); switch (fmt[1]) { + case 'r': + return number(buf, end, clk_get_rate(clk), spec); + case 'n': default: #ifdef CONFIG_COMMON_CLK diff -u linux-lts-xenial-4.4.0/mm/hugetlb.c linux-lts-xenial-4.4.0/mm/hugetlb.c --- linux-lts-xenial-4.4.0/mm/hugetlb.c +++ linux-lts-xenial-4.4.0/mm/hugetlb.c @@ -2038,7 +2038,6 @@ */ if (hstate_is_gigantic(h)) adjust_managed_page_count(page, 1 << h->order); - cond_resched(); } } diff -u linux-lts-xenial-4.4.0/mm/memory.c linux-lts-xenial-4.4.0/mm/memory.c --- linux-lts-xenial-4.4.0/mm/memory.c +++ linux-lts-xenial-4.4.0/mm/memory.c @@ -1621,6 +1621,9 @@ if (addr < vma->vm_start || addr >= vma->vm_end) return -EFAULT; + if (!pfn_modify_allowed(pfn, pgprot)) + return -EACCES; + if (track_pfn_insert(vma, &pgprot, pfn)) return -EINVAL; @@ -1638,6 +1641,9 @@ if (addr < vma->vm_start || addr >= vma->vm_end) return -EFAULT; + if (!pfn_modify_allowed(pfn, vma->vm_page_prot)) + return -EACCES; + /* * If we don't have pte special, then we have to use the pfn_valid() * based VM_MIXEDMAP scheme (see vm_normal_page), and thus we *must* @@ -1651,6 +1657,7 @@ page = pfn_to_page(pfn); return insert_page(vma, addr, page, vma->vm_page_prot); } + return insert_pfn(vma, addr, pfn, vma->vm_page_prot); } EXPORT_SYMBOL(vm_insert_mixed); @@ -1666,6 +1673,7 @@ { pte_t *pte; spinlock_t *ptl; + int err = 0; pte = pte_alloc_map_lock(mm, pmd, addr, &ptl); if (!pte) @@ -1673,12 +1681,16 @@ arch_enter_lazy_mmu_mode(); do { BUG_ON(!pte_none(*pte)); + if (!pfn_modify_allowed(pfn, prot)) { + err = -EACCES; + break; + } set_pte_at(mm, addr, pte, pte_mkspecial(pfn_pte(pfn, prot))); pfn++; } while (pte++, addr += PAGE_SIZE, addr != end); arch_leave_lazy_mmu_mode(); pte_unmap_unlock(pte - 1, ptl); - return 0; + return err; } static inline int remap_pmd_range(struct mm_struct *mm, pud_t *pud, @@ -1687,6 +1699,7 @@ { pmd_t *pmd; unsigned long next; + int err; pfn -= addr >> PAGE_SHIFT; pmd = pmd_alloc(mm, pud, addr); @@ -1695,9 +1708,10 @@ VM_BUG_ON(pmd_trans_huge(*pmd)); do { next = pmd_addr_end(addr, end); - if (remap_pte_range(mm, pmd, addr, next, - pfn + (addr >> PAGE_SHIFT), prot)) - return -ENOMEM; + err = remap_pte_range(mm, pmd, addr, next, + pfn + (addr >> PAGE_SHIFT), prot); + if (err) + return err; } while (pmd++, addr = next, addr != end); return 0; } @@ -1708,6 +1722,7 @@ { pud_t *pud; unsigned long next; + int err; pfn -= addr >> PAGE_SHIFT; pud = pud_alloc(mm, pgd, addr); @@ -1715,9 +1730,10 @@ return -ENOMEM; do { next = pud_addr_end(addr, end); - if (remap_pmd_range(mm, pud, addr, next, - pfn + (addr >> PAGE_SHIFT), prot)) - return -ENOMEM; + err = remap_pmd_range(mm, pud, addr, next, + pfn + (addr >> PAGE_SHIFT), prot); + if (err) + return err; } while (pud++, addr = next, addr != end); return 0; } diff -u linux-lts-xenial-4.4.0/mm/mmap.c linux-lts-xenial-4.4.0/mm/mmap.c --- linux-lts-xenial-4.4.0/mm/mmap.c +++ linux-lts-xenial-4.4.0/mm/mmap.c @@ -1295,35 +1295,6 @@ return 0; } -static inline u64 file_mmap_size_max(struct file *file, struct inode *inode) -{ - if (S_ISREG(inode->i_mode)) - return MAX_LFS_FILESIZE; - - if (S_ISBLK(inode->i_mode)) - return MAX_LFS_FILESIZE; - - /* Special "we do even unsigned file positions" case */ - if (file->f_mode & FMODE_UNSIGNED_OFFSET) - return 0; - - /* Yes, random drivers might want more. But I'm tired of buggy drivers */ - return ULONG_MAX; -} - -static inline bool file_mmap_ok(struct file *file, struct inode *inode, - unsigned long pgoff, unsigned long len) -{ - u64 maxsize = file_mmap_size_max(file, inode); - - if (maxsize && len > maxsize) - return false; - maxsize -= len; - if (pgoff > maxsize >> PAGE_SHIFT) - return false; - return true; -} - /* * The caller must hold down_write(¤t->mm->mmap_sem). */ @@ -1389,9 +1360,6 @@ if (file) { struct inode *inode = file_inode(file); - if (!file_mmap_ok(file, inode, pgoff, len)) - return -EOVERFLOW; - switch (flags & MAP_TYPE) { case MAP_SHARED: if ((prot&PROT_WRITE) && !(file->f_mode&FMODE_WRITE)) diff -u linux-lts-xenial-4.4.0/mm/mprotect.c linux-lts-xenial-4.4.0/mm/mprotect.c --- linux-lts-xenial-4.4.0/mm/mprotect.c +++ linux-lts-xenial-4.4.0/mm/mprotect.c @@ -255,6 +255,42 @@ return pages; } +static int prot_none_pte_entry(pte_t *pte, unsigned long addr, + unsigned long next, struct mm_walk *walk) +{ + return pfn_modify_allowed(pte_pfn(*pte), *(pgprot_t *)(walk->private)) ? + 0 : -EACCES; +} + +static int prot_none_hugetlb_entry(pte_t *pte, unsigned long hmask, + unsigned long addr, unsigned long next, + struct mm_walk *walk) +{ + return pfn_modify_allowed(pte_pfn(*pte), *(pgprot_t *)(walk->private)) ? + 0 : -EACCES; +} + +static int prot_none_test(unsigned long addr, unsigned long next, + struct mm_walk *walk) +{ + return 0; +} + +static int prot_none_walk(struct vm_area_struct *vma, unsigned long start, + unsigned long end, unsigned long newflags) +{ + pgprot_t new_pgprot = vm_get_page_prot(newflags); + struct mm_walk prot_none_walk = { + .pte_entry = prot_none_pte_entry, + .hugetlb_entry = prot_none_hugetlb_entry, + .test_walk = prot_none_test, + .mm = current->mm, + .private = &new_pgprot, + }; + + return walk_page_range(start, end, &prot_none_walk); +} + int mprotect_fixup(struct vm_area_struct *vma, struct vm_area_struct **pprev, unsigned long start, unsigned long end, unsigned long newflags) @@ -273,6 +309,19 @@ } /* + * Do PROT_NONE PFN permission checks here when we can still + * bail out without undoing a lot of state. This is a rather + * uncommon case, so doesn't need to be very optimized. + */ + if (arch_has_pfn_modify_check() && + (vma->vm_flags & (VM_PFNMAP|VM_MIXEDMAP)) && + (newflags & (VM_READ|VM_WRITE|VM_EXEC)) == 0) { + error = prot_none_walk(vma, start, end, newflags); + if (error) + return error; + } + + /* * If we make a private mapping writable we increase our commit; * but (without finer accounting) cannot reduce our commit if we * make it unwritable again. hugetlb mapping were accounted for diff -u linux-lts-xenial-4.4.0/mm/page_alloc.c linux-lts-xenial-4.4.0/mm/page_alloc.c --- linux-lts-xenial-4.4.0/mm/page_alloc.c +++ linux-lts-xenial-4.4.0/mm/page_alloc.c @@ -3250,6 +3250,8 @@ * the allocation is high priority and these type of * allocations are system rather than user orientated */ + ac->zonelist = node_zonelist(numa_node_id(), gfp_mask); + page = __alloc_pages_high_priority(gfp_mask, order, ac); if (page) { diff -u linux-lts-xenial-4.4.0/mm/swapfile.c linux-lts-xenial-4.4.0/mm/swapfile.c --- linux-lts-xenial-4.4.0/mm/swapfile.c +++ linux-lts-xenial-4.4.0/mm/swapfile.c @@ -2212,6 +2212,35 @@ return 0; } + +/* + * Find out how many pages are allowed for a single swap device. There + * are two limiting factors: + * 1) the number of bits for the swap offset in the swp_entry_t type, and + * 2) the number of bits in the swap pte, as defined by the different + * architectures. + * + * In order to find the largest possible bit mask, a swap entry with + * swap type 0 and swap offset ~0UL is created, encoded to a swap pte, + * decoded to a swp_entry_t again, and finally the swap offset is + * extracted. + * + * This will mask all the bits from the initial ~0UL mask that can't + * be encoded in either the swp_entry_t or the architecture definition + * of a swap pte. + */ +unsigned long generic_max_swapfile_size(void) +{ + return swp_offset(pte_to_swp_entry( + swp_entry_to_pte(swp_entry(0, ~0UL)))) + 1; +} + +/* Can be overridden by an architecture for additional checks. */ +__weak unsigned long max_swapfile_size(void) +{ + return generic_max_swapfile_size(); +} + static unsigned long read_swap_header(struct swap_info_struct *p, union swap_header *swap_header, struct inode *inode) @@ -2247,22 +2276,7 @@ p->cluster_next = 1; p->cluster_nr = 0; - /* - * Find out how many pages are allowed for a single swap - * device. There are two limiting factors: 1) the number - * of bits for the swap offset in the swp_entry_t type, and - * 2) the number of bits in the swap pte as defined by the - * different architectures. In order to find the - * largest possible bit mask, a swap entry with swap type 0 - * and swap offset ~0UL is created, encoded to a swap pte, - * decoded to a swp_entry_t again, and finally the swap - * offset is extracted. This will mask all the bits from - * the initial ~0UL mask that can't be encoded in either - * the swp_entry_t or the architecture definition of a - * swap pte. - */ - maxpages = swp_offset(pte_to_swp_entry( - swp_entry_to_pte(swp_entry(0, ~0UL)))) + 1; + maxpages = max_swapfile_size(); last_page = swap_header->info.last_page; if (!last_page) { pr_warn("Empty swap-file\n"); diff -u linux-lts-xenial-4.4.0/mm/vmscan.c linux-lts-xenial-4.4.0/mm/vmscan.c --- linux-lts-xenial-4.4.0/mm/vmscan.c +++ linux-lts-xenial-4.4.0/mm/vmscan.c @@ -1331,7 +1331,7 @@ return ret; mapping = page_mapping(page); - migrate_dirty = !mapping || mapping->a_ops->migratepage; + migrate_dirty = mapping && mapping->a_ops->migratepage; unlock_page(page); if (!migrate_dirty) return ret; diff -u linux-lts-xenial-4.4.0/net/bluetooth/hci_conn.c linux-lts-xenial-4.4.0/net/bluetooth/hci_conn.c --- linux-lts-xenial-4.4.0/net/bluetooth/hci_conn.c +++ linux-lts-xenial-4.4.0/net/bluetooth/hci_conn.c @@ -708,8 +708,7 @@ } static void hci_req_add_le_create_conn(struct hci_request *req, - struct hci_conn *conn, - bdaddr_t *direct_rpa) + struct hci_conn *conn) { struct hci_cp_le_create_conn cp; struct hci_dev *hdev = conn->hdev; @@ -717,23 +716,11 @@ memset(&cp, 0, sizeof(cp)); - /* If direct address was provided we use it instead of current - * address. + /* Update random address, but set require_privacy to false so + * that we never connect with an non-resolvable address. */ - if (direct_rpa) { - if (bacmp(&req->hdev->random_addr, direct_rpa)) - hci_req_add(req, HCI_OP_LE_SET_RANDOM_ADDR, 6, - direct_rpa); - - /* direct address is always RPA */ - own_addr_type = ADDR_LE_DEV_RANDOM; - } else { - /* Update random address, but set require_privacy to false so - * that we never connect with an non-resolvable address. - */ - if (hci_update_random_address(req, false, &own_addr_type)) - return; - } + if (hci_update_random_address(req, false, &own_addr_type)) + return; /* Set window to be the same value as the interval to enable * continuous scanning. @@ -795,7 +782,7 @@ struct hci_conn *hci_connect_le(struct hci_dev *hdev, bdaddr_t *dst, u8 dst_type, u8 sec_level, u16 conn_timeout, - u8 role, bdaddr_t *direct_rpa) + u8 role) { struct hci_conn_params *params; struct hci_conn *conn, *conn_unfinished; @@ -926,7 +913,7 @@ hci_dev_set_flag(hdev, HCI_LE_SCAN_INTERRUPTED); } - hci_req_add_le_create_conn(&req, conn, direct_rpa); + hci_req_add_le_create_conn(&req, conn); create_conn: err = hci_req_run(&req, create_le_conn_complete); reverted: --- linux-lts-xenial-4.4.0/net/bluetooth/hci_event.c +++ linux-lts-xenial-4.4.0.orig/net/bluetooth/hci_event.c @@ -4632,8 +4632,7 @@ /* This function requires the caller holds hdev->lock */ static struct hci_conn *check_pending_le_conn(struct hci_dev *hdev, bdaddr_t *addr, + u8 addr_type, u8 adv_type) - u8 addr_type, u8 adv_type, - bdaddr_t *direct_rpa) { struct hci_conn *conn; struct hci_conn_params *params; @@ -4684,8 +4683,7 @@ } conn = hci_connect_le(hdev, addr, addr_type, BT_SECURITY_LOW, + HCI_LE_AUTOCONN_TIMEOUT, HCI_ROLE_MASTER); - HCI_LE_AUTOCONN_TIMEOUT, HCI_ROLE_MASTER, - direct_rpa); if (!IS_ERR(conn)) { /* If HCI_AUTO_CONN_EXPLICIT is set, conn is already owned * by higher layer that tried to connect, if no then @@ -4782,13 +4780,8 @@ bdaddr_type = irk->addr_type; } + /* Check if we have been requested to connect to this device */ + conn = check_pending_le_conn(hdev, bdaddr, bdaddr_type, type); - /* Check if we have been requested to connect to this device. - * - * direct_addr is set only for directed advertising reports (it is NULL - * for advertising reports) and is already verified to be RPA above. - */ - conn = check_pending_le_conn(hdev, bdaddr, bdaddr_type, type, - direct_addr); if (conn && type == LE_ADV_IND) { /* Store report for later inclusion by * mgmt_device_connected diff -u linux-lts-xenial-4.4.0/net/bridge/netfilter/ebtables.c linux-lts-xenial-4.4.0/net/bridge/netfilter/ebtables.c --- linux-lts-xenial-4.4.0/net/bridge/netfilter/ebtables.c +++ linux-lts-xenial-4.4.0/net/bridge/netfilter/ebtables.c @@ -1912,8 +1912,7 @@ int off, pad = 0; unsigned int size_kern, match_size = mwt->match_size; - if (strscpy(name, mwt->u.name, sizeof(name)) < 0) - return -EINVAL; + strlcpy(name, mwt->u.name, sizeof(name)); if (state->buf_kern_start) dst = state->buf_kern_start + state->buf_kern_offset; diff -u linux-lts-xenial-4.4.0/net/core/rtnetlink.c linux-lts-xenial-4.4.0/net/core/rtnetlink.c --- linux-lts-xenial-4.4.0/net/core/rtnetlink.c +++ linux-lts-xenial-4.4.0/net/core/rtnetlink.c @@ -1691,10 +1691,6 @@ const struct net_device_ops *ops = dev->netdev_ops; int err; - err = validate_linkmsg(dev, tb); - if (err < 0) - return err; - if (tb[IFLA_NET_NS_PID] || tb[IFLA_NET_NS_FD]) { struct net *net = rtnl_link_get_net(dev_net(dev), tb); if (IS_ERR(net)) { @@ -1986,6 +1982,10 @@ goto errout; } + err = validate_linkmsg(dev, tb); + if (err < 0) + goto errout; + err = do_setlink(skb, dev, ifm, tb, ifname, 0); errout: return err; diff -u linux-lts-xenial-4.4.0/net/dccp/proto.c linux-lts-xenial-4.4.0/net/dccp/proto.c --- linux-lts-xenial-4.4.0/net/dccp/proto.c +++ linux-lts-xenial-4.4.0/net/dccp/proto.c @@ -280,7 +280,9 @@ dccp_clear_xmit_timers(sk); ccid_hc_rx_delete(dp->dccps_hc_rx_ccid, sk); + ccid_hc_tx_delete(dp->dccps_hc_tx_ccid, sk); dp->dccps_hc_rx_ccid = NULL; + dp->dccps_hc_tx_ccid = NULL; __skb_queue_purge(&sk->sk_receive_queue); __skb_queue_purge(&sk->sk_write_queue); diff -u linux-lts-xenial-4.4.0/net/ipv4/fib_semantics.c linux-lts-xenial-4.4.0/net/ipv4/fib_semantics.c --- linux-lts-xenial-4.4.0/net/ipv4/fib_semantics.c +++ linux-lts-xenial-4.4.0/net/ipv4/fib_semantics.c @@ -979,8 +979,6 @@ if (val == TCP_CA_UNSPEC) return -EINVAL; } else { - if (nla_len(nla) != sizeof(u32)) - return -EINVAL; val = nla_get_u32(nla); } if (type == RTAX_ADVMSS && val > 65535 - 40) diff -u linux-lts-xenial-4.4.0/net/ipv4/ip_fragment.c linux-lts-xenial-4.4.0/net/ipv4/ip_fragment.c --- linux-lts-xenial-4.4.0/net/ipv4/ip_fragment.c +++ linux-lts-xenial-4.4.0/net/ipv4/ip_fragment.c @@ -849,22 +849,14 @@ static int __net_init ipv4_frags_init_net(struct net *net) { - /* Fragment cache limits. - * - * The fragment memory accounting code, (tries to) account for - * the real memory usage, by measuring both the size of frag - * queue struct (inet_frag_queue (ipv4:ipq/ipv6:frag_queue)) - * and the SKB's truesize. - * - * A 64K fragment consumes 129736 bytes (44*2944)+200 - * (1500 truesize == 2944, sizeof(struct ipq) == 200) - * - * We will commit 4MB at one time. Should we cross that limit - * we will prune down to 3MB, making room for approx 8 big 64K - * fragments 8x128k. + /* + * Fragment cache limits. We will commit 256K at one time. Should we + * cross that limit we will prune down to 192K. This should cope with + * even the most extreme cases without allowing an attacker to + * measurably harm machine performance. */ - net->ipv4.frags.high_thresh = 4 * 1024 * 1024; - net->ipv4.frags.low_thresh = 3 * 1024 * 1024; + net->ipv4.frags.high_thresh = 256 * 1024; + net->ipv4.frags.low_thresh = 192 * 1024; /* * Important NOTE! Fragment queue must be destroyed before MSL expires. * RFC791 is wrong proposing to prolongate timer each fragment arrival diff -u linux-lts-xenial-4.4.0/net/ipv4/ip_sockglue.c linux-lts-xenial-4.4.0/net/ipv4/ip_sockglue.c --- linux-lts-xenial-4.4.0/net/ipv4/ip_sockglue.c +++ linux-lts-xenial-4.4.0/net/ipv4/ip_sockglue.c @@ -493,6 +493,8 @@ int err; int copied; + WARN_ON_ONCE(sk->sk_family == AF_INET6); + err = -EAGAIN; skb = sock_dequeue_err_skb(sk); if (!skb) diff -u linux-lts-xenial-4.4.0/net/ipv4/ip_vti.c linux-lts-xenial-4.4.0/net/ipv4/ip_vti.c --- linux-lts-xenial-4.4.0/net/ipv4/ip_vti.c +++ linux-lts-xenial-4.4.0/net/ipv4/ip_vti.c @@ -366,7 +366,6 @@ memcpy(dev->dev_addr, &iph->saddr, 4); memcpy(dev->broadcast, &iph->daddr, 4); - dev->mtu = ETH_DATA_LEN; dev->flags = IFF_NOARP; dev->addr_len = 4; dev->features |= NETIF_F_LLTX; diff -u linux-lts-xenial-4.4.0/net/ipv4/tcp_input.c linux-lts-xenial-4.4.0/net/ipv4/tcp_input.c --- linux-lts-xenial-4.4.0/net/ipv4/tcp_input.c +++ linux-lts-xenial-4.4.0/net/ipv4/tcp_input.c @@ -557,8 +557,8 @@ void tcp_rcv_space_adjust(struct sock *sk) { struct tcp_sock *tp = tcp_sk(sk); - u32 copied; int time; + int copied; time = tcp_time_stamp - tp->rcvq_space.time; if (time < (tp->rcv_rtt_est.rtt >> 3) || tp->rcv_rtt_est.rtt == 0) @@ -580,13 +580,12 @@ if (sysctl_tcp_moderate_rcvbuf && !(sk->sk_userlocks & SOCK_RCVBUF_LOCK)) { - int rcvmem, rcvbuf; - u64 rcvwin; + int rcvwin, rcvmem, rcvbuf; /* minimal window to cope with packet losses, assuming * steady state. Add some cushion because of small variations. */ - rcvwin = ((u64)copied << 1) + 16 * tp->advmss; + rcvwin = (copied << 1) + 16 * tp->advmss; /* If rate increased by 25%, * assume slow start, rcvwin = 3 * copied @@ -606,13 +605,12 @@ while (tcp_win_from_space(rcvmem) < tp->advmss) rcvmem += 128; - do_div(rcvwin, tp->advmss); - rcvbuf = min_t(u64, rcvwin * rcvmem, sysctl_tcp_rmem[2]); + rcvbuf = min(rcvwin / tp->advmss * rcvmem, sysctl_tcp_rmem[2]); if (rcvbuf > sk->sk_rcvbuf) { sk->sk_rcvbuf = rcvbuf; /* Make the window clamp follow along. */ - tp->window_clamp = tcp_win_from_space(rcvbuf); + tp->window_clamp = rcvwin; } } tp->rcvq_space.space = copied; @@ -4776,6 +4774,7 @@ static void tcp_collapse_ofo_queue(struct sock *sk) { struct tcp_sock *tp = tcp_sk(sk); + u32 range_truesize, sum_tiny = 0; struct sk_buff *skb = skb_peek(&tp->out_of_order_queue); struct sk_buff *head; u32 start, end; @@ -4785,6 +4784,7 @@ start = TCP_SKB_CB(skb)->seq; end = TCP_SKB_CB(skb)->end_seq; + range_truesize = skb->truesize; head = skb; for (;;) { @@ -4799,14 +4799,24 @@ if (!skb || after(TCP_SKB_CB(skb)->seq, end) || before(TCP_SKB_CB(skb)->end_seq, start)) { - tcp_collapse(sk, &tp->out_of_order_queue, - head, skb, start, end); + /* Do not attempt collapsing tiny skbs */ + if (range_truesize != head->truesize || + end - start >= SKB_WITH_OVERHEAD(SK_MEM_QUANTUM)) { + tcp_collapse(sk, &tp->out_of_order_queue, + head, skb, start, end); + } else { + sum_tiny += range_truesize; + if (sum_tiny > sk->sk_rcvbuf >> 3) + return; + } + head = skb; if (!skb) break; /* Start new segment */ start = TCP_SKB_CB(skb)->seq; end = TCP_SKB_CB(skb)->end_seq; + range_truesize += skb->truesize; } else { if (before(TCP_SKB_CB(skb)->seq, start)) start = TCP_SKB_CB(skb)->seq; @@ -4862,6 +4872,9 @@ else if (tcp_under_memory_pressure(sk)) tp->rcv_ssthresh = min(tp->rcv_ssthresh, 4U * tp->advmss); + if (atomic_read(&sk->sk_rmem_alloc) <= sk->sk_rcvbuf) + return 0; + tcp_collapse_ofo_queue(sk); if (!skb_queue_empty(&sk->sk_receive_queue)) tcp_collapse(sk, &sk->sk_receive_queue, diff -u linux-lts-xenial-4.4.0/net/ipv4/tcp_ipv4.c linux-lts-xenial-4.4.0/net/ipv4/tcp_ipv4.c --- linux-lts-xenial-4.4.0/net/ipv4/tcp_ipv4.c +++ linux-lts-xenial-4.4.0/net/ipv4/tcp_ipv4.c @@ -1627,10 +1627,6 @@ reqsk_put(req); goto discard_it; } - if (tcp_checksum_complete(skb)) { - reqsk_put(req); - goto csum_error; - } if (unlikely(sk->sk_state != TCP_LISTEN)) { inet_csk_reqsk_queue_drop_and_put(sk, req); goto lookup; diff -u linux-lts-xenial-4.4.0/net/ipv6/ip6mr.c linux-lts-xenial-4.4.0/net/ipv6/ip6mr.c --- linux-lts-xenial-4.4.0/net/ipv6/ip6mr.c +++ linux-lts-xenial-4.4.0/net/ipv6/ip6mr.c @@ -1787,8 +1787,7 @@ ret = 0; if (!ip6mr_new_table(net, v)) ret = -ENOMEM; - else - raw6_sk(sk)->ip6mr_table = v; + raw6_sk(sk)->ip6mr_table = v; rtnl_unlock(); return ret; } diff -u linux-lts-xenial-4.4.0/net/ipv6/tcp_ipv6.c linux-lts-xenial-4.4.0/net/ipv6/tcp_ipv6.c --- linux-lts-xenial-4.4.0/net/ipv6/tcp_ipv6.c +++ linux-lts-xenial-4.4.0/net/ipv6/tcp_ipv6.c @@ -1415,10 +1415,6 @@ reqsk_put(req); goto discard_it; } - if (tcp_checksum_complete(skb)) { - reqsk_put(req); - goto csum_error; - } if (unlikely(sk->sk_state != TCP_LISTEN)) { inet_csk_reqsk_queue_drop_and_put(sk, req); goto lookup; diff -u linux-lts-xenial-4.4.0/net/ipv6/xfrm6_policy.c linux-lts-xenial-4.4.0/net/ipv6/xfrm6_policy.c --- linux-lts-xenial-4.4.0/net/ipv6/xfrm6_policy.c +++ linux-lts-xenial-4.4.0/net/ipv6/xfrm6_policy.c @@ -121,7 +121,7 @@ struct flowi6 *fl6 = &fl->u.ip6; int onlyproto = 0; const struct ipv6hdr *hdr = ipv6_hdr(skb); - u32 offset = sizeof(*hdr); + u16 offset = sizeof(*hdr); struct ipv6_opt_hdr *exthdr; const unsigned char *nh = skb_network_header(skb); u16 nhoff = IP6CB(skb)->nhoff; diff -u linux-lts-xenial-4.4.0/net/key/af_key.c linux-lts-xenial-4.4.0/net/key/af_key.c --- linux-lts-xenial-4.4.0/net/key/af_key.c +++ linux-lts-xenial-4.4.0/net/key/af_key.c @@ -437,24 +437,6 @@ return 0; } -static inline int sadb_key_len(const struct sadb_key *key) -{ - int key_bytes = DIV_ROUND_UP(key->sadb_key_bits, 8); - - return DIV_ROUND_UP(sizeof(struct sadb_key) + key_bytes, - sizeof(uint64_t)); -} - -static int verify_key_len(const void *p) -{ - const struct sadb_key *key = p; - - if (sadb_key_len(key) > key->sadb_key_len) - return -EINVAL; - - return 0; -} - static inline int pfkey_sec_ctx_len(const struct sadb_x_sec_ctx *sec_ctx) { return DIV_ROUND_UP(sizeof(struct sadb_x_sec_ctx) + @@ -551,25 +533,16 @@ return -EINVAL; if (ext_hdrs[ext_type-1] != NULL) return -EINVAL; - switch (ext_type) { - case SADB_EXT_ADDRESS_SRC: - case SADB_EXT_ADDRESS_DST: - case SADB_EXT_ADDRESS_PROXY: - case SADB_X_EXT_NAT_T_OA: + if (ext_type == SADB_EXT_ADDRESS_SRC || + ext_type == SADB_EXT_ADDRESS_DST || + ext_type == SADB_EXT_ADDRESS_PROXY || + ext_type == SADB_X_EXT_NAT_T_OA) { if (verify_address_len(p)) return -EINVAL; - break; - case SADB_X_EXT_SEC_CTX: + } + if (ext_type == SADB_X_EXT_SEC_CTX) { if (verify_sec_ctx_len(p)) return -EINVAL; - break; - case SADB_EXT_KEY_AUTH: - case SADB_EXT_KEY_ENCRYPT: - if (verify_key_len(p)) - return -EINVAL; - break; - default: - break; } ext_hdrs[ext_type-1] = (void *) p; } @@ -1138,12 +1111,14 @@ key = ext_hdrs[SADB_EXT_KEY_AUTH - 1]; if (key != NULL && sa->sadb_sa_auth != SADB_X_AALG_NULL && - key->sadb_key_bits == 0) + ((key->sadb_key_bits+7) / 8 == 0 || + (key->sadb_key_bits+7) / 8 > key->sadb_key_len * sizeof(uint64_t))) return ERR_PTR(-EINVAL); key = ext_hdrs[SADB_EXT_KEY_ENCRYPT-1]; if (key != NULL && sa->sadb_sa_encrypt != SADB_EALG_NULL && - key->sadb_key_bits == 0) + ((key->sadb_key_bits+7) / 8 == 0 || + (key->sadb_key_bits+7) / 8 > key->sadb_key_len * sizeof(uint64_t))) return ERR_PTR(-EINVAL); x = xfrm_state_alloc(net); diff -u linux-lts-xenial-4.4.0/net/netfilter/ipvs/ip_vs_ctl.c linux-lts-xenial-4.4.0/net/netfilter/ipvs/ip_vs_ctl.c --- linux-lts-xenial-4.4.0/net/netfilter/ipvs/ip_vs_ctl.c +++ linux-lts-xenial-4.4.0/net/netfilter/ipvs/ip_vs_ctl.c @@ -2349,10 +2349,8 @@ struct ipvs_sync_daemon_cfg cfg; memset(&cfg, 0, sizeof(cfg)); - ret = -EINVAL; - if (strscpy(cfg.mcast_ifn, dm->mcast_ifn, - sizeof(cfg.mcast_ifn)) <= 0) - goto out_dec; + strlcpy(cfg.mcast_ifn, dm->mcast_ifn, + sizeof(cfg.mcast_ifn)); cfg.syncid = dm->syncid; ret = start_sync_thread(ipvs, &cfg, dm->state); } else { @@ -2390,19 +2388,12 @@ } } - if ((cmd == IP_VS_SO_SET_ADD || cmd == IP_VS_SO_SET_EDIT) && - strnlen(usvc.sched_name, IP_VS_SCHEDNAME_MAXLEN) == - IP_VS_SCHEDNAME_MAXLEN) { - ret = -EINVAL; - goto out_unlock; - } - /* Check for valid protocol: TCP or UDP or SCTP, even for fwmark!=0 */ if (usvc.protocol != IPPROTO_TCP && usvc.protocol != IPPROTO_UDP && usvc.protocol != IPPROTO_SCTP) { - pr_err("set_ctl: invalid protocol: %d %pI4:%d\n", + pr_err("set_ctl: invalid protocol: %d %pI4:%d %s\n", usvc.protocol, &usvc.addr.ip, - ntohs(usvc.port)); + ntohs(usvc.port), usvc.sched_name); ret = -EFAULT; goto out_unlock; } @@ -2831,7 +2822,7 @@ static const struct nla_policy ip_vs_daemon_policy[IPVS_DAEMON_ATTR_MAX + 1] = { [IPVS_DAEMON_ATTR_STATE] = { .type = NLA_U32 }, [IPVS_DAEMON_ATTR_MCAST_IFN] = { .type = NLA_NUL_STRING, - .len = IP_VS_IFNAME_MAXLEN - 1 }, + .len = IP_VS_IFNAME_MAXLEN }, [IPVS_DAEMON_ATTR_SYNC_ID] = { .type = NLA_U32 }, [IPVS_DAEMON_ATTR_SYNC_MAXLEN] = { .type = NLA_U16 }, [IPVS_DAEMON_ATTR_MCAST_GROUP] = { .type = NLA_U32 }, @@ -2849,7 +2840,7 @@ [IPVS_SVC_ATTR_PORT] = { .type = NLA_U16 }, [IPVS_SVC_ATTR_FWMARK] = { .type = NLA_U32 }, [IPVS_SVC_ATTR_SCHED_NAME] = { .type = NLA_NUL_STRING, - .len = IP_VS_SCHEDNAME_MAXLEN - 1 }, + .len = IP_VS_SCHEDNAME_MAXLEN }, [IPVS_SVC_ATTR_PE_NAME] = { .type = NLA_NUL_STRING, .len = IP_VS_PENAME_MAXLEN }, [IPVS_SVC_ATTR_FLAGS] = { .type = NLA_BINARY, diff -u linux-lts-xenial-4.4.0/net/netfilter/nf_log.c linux-lts-xenial-4.4.0/net/netfilter/nf_log.c --- linux-lts-xenial-4.4.0/net/netfilter/nf_log.c +++ linux-lts-xenial-4.4.0/net/netfilter/nf_log.c @@ -437,17 +437,14 @@ rcu_assign_pointer(net->nf.nf_loggers[tindex], logger); mutex_unlock(&nf_log_mutex); } else { - struct ctl_table tmp = *table; - - tmp.data = buf; mutex_lock(&nf_log_mutex); logger = nft_log_dereference(net->nf.nf_loggers[tindex]); if (!logger) - strlcpy(buf, "NONE", sizeof(buf)); + table->data = "NONE"; else - strlcpy(buf, logger->name, sizeof(buf)); + table->data = logger->name; + r = proc_dostring(table, write, buffer, lenp, ppos); mutex_unlock(&nf_log_mutex); - r = proc_dostring(&tmp, write, buffer, lenp, ppos); } return r; reverted: --- linux-lts-xenial-4.4.0/net/netfilter/nf_tables_core.c +++ linux-lts-xenial-4.4.0.orig/net/netfilter/nf_tables_core.c @@ -167,8 +167,7 @@ switch (regs.verdict.code) { case NFT_JUMP: + BUG_ON(stackptr >= NFT_JUMP_STACK_SIZE); - if (WARN_ON_ONCE(stackptr >= NFT_JUMP_STACK_SIZE)) - return NF_DROP; jumpstack[stackptr].chain = chain; jumpstack[stackptr].rule = rule; jumpstack[stackptr].rulenum = rulenum; diff -u linux-lts-xenial-4.4.0/net/packet/af_packet.c linux-lts-xenial-4.4.0/net/packet/af_packet.c --- linux-lts-xenial-4.4.0/net/packet/af_packet.c +++ linux-lts-xenial-4.4.0/net/packet/af_packet.c @@ -2779,7 +2779,7 @@ if (unlikely(offset < 0)) goto out_free; } else if (reserve) { - skb_reserve(skb, -reserve); + skb_push(skb, reserve); } /* Returns -EFAULT on error */ @@ -4198,7 +4198,7 @@ goto out; if (po->tp_version >= TPACKET_V3 && req->tp_block_size <= - BLK_PLUS_PRIV((u64)req_u->req3.tp_sizeof_priv) + sizeof(struct tpacket3_hdr)) + BLK_PLUS_PRIV((u64)req_u->req3.tp_sizeof_priv)) goto out; if (unlikely(req->tp_frame_size < po->tp_hdrlen + po->tp_reserve)) diff -u linux-lts-xenial-4.4.0/net/xfrm/xfrm_policy.c linux-lts-xenial-4.4.0/net/xfrm/xfrm_policy.c --- linux-lts-xenial-4.4.0/net/xfrm/xfrm_policy.c +++ linux-lts-xenial-4.4.0/net/xfrm/xfrm_policy.c @@ -626,8 +626,7 @@ /* re-insert all policies by order of creation */ list_for_each_entry_reverse(policy, &net->xfrm.policy_all, walk.all) { - if (policy->walk.dead || - xfrm_policy_id2dir(policy->index) >= XFRM_POLICY_MAX) { + if (xfrm_policy_id2dir(policy->index) >= XFRM_POLICY_MAX) { /* skip socket policies */ continue; } diff -u linux-lts-xenial-4.4.0/scripts/kconfig/confdata.c linux-lts-xenial-4.4.0/scripts/kconfig/confdata.c --- linux-lts-xenial-4.4.0/scripts/kconfig/confdata.c +++ linux-lts-xenial-4.4.0/scripts/kconfig/confdata.c @@ -743,7 +743,7 @@ struct menu *menu; const char *basename; const char *str; - char dirname[PATH_MAX+1], tmpname[PATH_MAX+22], newname[PATH_MAX+8]; + char dirname[PATH_MAX+1], tmpname[PATH_MAX+1], newname[PATH_MAX+1]; char *env; dirname[0] = 0; diff -u linux-lts-xenial-4.4.0/security/apparmor/lib.c linux-lts-xenial-4.4.0/security/apparmor/lib.c --- linux-lts-xenial-4.4.0/security/apparmor/lib.c +++ linux-lts-xenial-4.4.0/security/apparmor/lib.c @@ -354,7 +354,7 @@ /* for v5 perm mapping in the policydb, the other set is used * to extend the general perm set */ - perms->allow |= map_other(dfa_other_allow(dfa, state)) | AA_MAY_LOCK; + perms->allow |= map_other(dfa_other_allow(dfa, state)); perms->audit |= map_other(dfa_other_audit(dfa, state)); perms->quiet |= map_other(dfa_other_quiet(dfa, state)); // perms->xindex = dfa_user_xindex(dfa, state); diff -u linux-lts-xenial-4.4.0/security/commoncap.c linux-lts-xenial-4.4.0/security/commoncap.c --- linux-lts-xenial-4.4.0/security/commoncap.c +++ linux-lts-xenial-4.4.0/security/commoncap.c @@ -337,208 +337,6 @@ return inode->i_op->removexattr(dentry, XATTR_NAME_CAPS); } -static bool rootid_owns_currentns(kuid_t kroot) -{ - struct user_namespace *ns; - - if (!uid_valid(kroot)) - return false; - - for (ns = current_user_ns(); ; ns = ns->parent) { - if (from_kuid(ns, kroot) == 0) - return true; - if (ns == &init_user_ns) - break; - } - - return false; -} - -static __u32 sansflags(__u32 m) -{ - return m & ~VFS_CAP_FLAGS_EFFECTIVE; -} - -static bool is_v2header(size_t size, const struct vfs_cap_data *cap) -{ - if (size != XATTR_CAPS_SZ_2) - return false; - return sansflags(le32_to_cpu(cap->magic_etc)) == VFS_CAP_REVISION_2; -} - -static bool is_v3header(size_t size, const struct vfs_cap_data *cap) -{ - if (size != XATTR_CAPS_SZ_3) - return false; - return sansflags(le32_to_cpu(cap->magic_etc)) == VFS_CAP_REVISION_3; -} - -/* - * getsecurity: We are called for security.* before any attempt to read the - * xattr from the inode itself. - * - * This gives us a chance to read the on-disk value and convert it. If we - * return -EOPNOTSUPP, then vfs_getxattr() will call the i_op handler. - * - * Note we are not called by vfs_getxattr_alloc(), but that is only called - * by the integrity subsystem, which really wants the unconverted values - - * so that's good. - */ -int cap_inode_getsecurity(const struct inode *inode, const char *name, - void **buffer, bool alloc) -{ - int size, ret; - kuid_t kroot; - uid_t root, mappedroot; - char *tmpbuf = NULL; - struct vfs_cap_data *cap; - struct vfs_ns_cap_data *nscap; - struct dentry *dentry; - struct user_namespace *fs_ns; - - if (strcmp(name, "capability") != 0) - return -EOPNOTSUPP; - - dentry = d_find_alias((struct inode *)inode); - if (!dentry) - return -EINVAL; - - size = sizeof(struct vfs_ns_cap_data); - ret = (int) vfs_getxattr_alloc(dentry, XATTR_NAME_CAPS, - &tmpbuf, size, GFP_NOFS); - dput(dentry); - - if (ret < 0) - return ret; - - fs_ns = inode->i_sb->s_user_ns; - cap = (struct vfs_cap_data *) tmpbuf; - if (is_v2header((size_t) ret, cap)) { - /* If this is sizeof(vfs_cap_data) then we're ok with the - * on-disk value, so return that. */ - if (alloc) - *buffer = tmpbuf; - else - kfree(tmpbuf); - return ret; - } else if (!is_v3header((size_t) ret, cap)) { - kfree(tmpbuf); - return -EINVAL; - } - - nscap = (struct vfs_ns_cap_data *) tmpbuf; - root = le32_to_cpu(nscap->rootid); - kroot = make_kuid(fs_ns, root); - - /* If the root kuid maps to a valid uid in current ns, then return - * this as a nscap. */ - mappedroot = from_kuid(current_user_ns(), kroot); - if (mappedroot != (uid_t)-1 && mappedroot != (uid_t)0) { - if (alloc) { - *buffer = tmpbuf; - nscap->rootid = cpu_to_le32(mappedroot); - } else - kfree(tmpbuf); - return size; - } - - if (!rootid_owns_currentns(kroot)) { - kfree(tmpbuf); - return -EOPNOTSUPP; - } - - /* This comes from a parent namespace. Return as a v2 capability */ - size = sizeof(struct vfs_cap_data); - if (alloc) { - *buffer = kmalloc(size, GFP_ATOMIC); - if (*buffer) { - struct vfs_cap_data *cap = *buffer; - __le32 nsmagic, magic; - magic = VFS_CAP_REVISION_2; - nsmagic = le32_to_cpu(nscap->magic_etc); - if (nsmagic & VFS_CAP_FLAGS_EFFECTIVE) - magic |= VFS_CAP_FLAGS_EFFECTIVE; - memcpy(&cap->data, &nscap->data, sizeof(__le32) * 2 * VFS_CAP_U32); - cap->magic_etc = cpu_to_le32(magic); - } else { - size = -ENOMEM; - } - } - kfree(tmpbuf); - return size; -} - -static kuid_t rootid_from_xattr(const void *value, size_t size, - struct user_namespace *task_ns) -{ - const struct vfs_ns_cap_data *nscap = value; - uid_t rootid = 0; - - if (size == XATTR_CAPS_SZ_3) - rootid = le32_to_cpu(nscap->rootid); - - return make_kuid(task_ns, rootid); -} - -static bool validheader(size_t size, const struct vfs_cap_data *cap) -{ - return is_v2header(size, cap) || is_v3header(size, cap); -} - -/* - * User requested a write of security.capability. If needed, update the - * xattr to change from v2 to v3, or to fixup the v3 rootid. - * - * If all is ok, we return the new size, on error return < 0. - */ -int cap_convert_nscap(struct dentry *dentry, void **ivalue, size_t size) -{ - struct vfs_ns_cap_data *nscap; - uid_t nsrootid; - const struct vfs_cap_data *cap = *ivalue; - __u32 magic, nsmagic; - struct inode *inode = d_backing_inode(dentry); - struct user_namespace *task_ns = current_user_ns(), - *fs_ns = inode->i_sb->s_user_ns; - kuid_t rootid; - size_t newsize; - - if (!*ivalue) - return -EINVAL; - if (!validheader(size, cap)) - return -EINVAL; - if (!capable_wrt_inode_uidgid(inode, CAP_SETFCAP)) - return -EPERM; - if (size == XATTR_CAPS_SZ_2) - if (ns_capable(inode->i_sb->s_user_ns, CAP_SETFCAP)) - /* user is privileged, just write the v2 */ - return size; - - rootid = rootid_from_xattr(*ivalue, size, task_ns); - if (!uid_valid(rootid)) - return -EINVAL; - - nsrootid = from_kuid(fs_ns, rootid); - if (nsrootid == -1) - return -EINVAL; - - newsize = sizeof(struct vfs_ns_cap_data); - nscap = kmalloc(newsize, GFP_ATOMIC); - if (!nscap) - return -ENOMEM; - nscap->rootid = cpu_to_le32(nsrootid); - nsmagic = VFS_CAP_REVISION_3; - magic = le32_to_cpu(cap->magic_etc); - if (magic & VFS_CAP_FLAGS_EFFECTIVE) - nsmagic |= VFS_CAP_FLAGS_EFFECTIVE; - nscap->magic_etc = cpu_to_le32(nsmagic); - memcpy(&nscap->data, &cap->data, sizeof(__le32) * 2 * VFS_CAP_U32); - - kvfree(*ivalue); - *ivalue = nscap; - return newsize; -} - /* * Calculate the new process capability sets from the capability sets attached * to a file. @@ -592,32 +390,26 @@ __u32 magic_etc; unsigned tocopy, i; int size; - struct vfs_ns_cap_data data, *nscaps = &data; - struct vfs_cap_data *caps = (struct vfs_cap_data *) &data; - kuid_t rootkuid; - struct user_namespace *fs_ns; + struct vfs_cap_data caps; memset(cpu_caps, 0, sizeof(struct cpu_vfs_cap_data)); if (!inode || !inode->i_op->getxattr) return -ENODATA; - fs_ns = inode->i_sb->s_user_ns; - size = inode->i_op->getxattr((struct dentry *)dentry, XATTR_NAME_CAPS, &data, + size = inode->i_op->getxattr((struct dentry *)dentry, XATTR_NAME_CAPS, &caps, XATTR_CAPS_SZ); if (size == -ENODATA || size == -EOPNOTSUPP) /* no data, that's ok */ return -ENODATA; - if (size < 0) return size; if (size < sizeof(magic_etc)) return -EINVAL; - cpu_caps->magic_etc = magic_etc = le32_to_cpu(caps->magic_etc); + cpu_caps->magic_etc = magic_etc = le32_to_cpu(caps.magic_etc); - rootkuid = make_kuid(fs_ns, 0); switch (magic_etc & VFS_CAP_REVISION_MASK) { case VFS_CAP_REVISION_1: if (size != XATTR_CAPS_SZ_1) @@ -629,27 +421,15 @@ return -EINVAL; tocopy = VFS_CAP_U32_2; break; - case VFS_CAP_REVISION_3: - if (size != XATTR_CAPS_SZ_3) - return -EINVAL; - tocopy = VFS_CAP_U32_3; - rootkuid = make_kuid(fs_ns, le32_to_cpu(nscaps->rootid)); - break; - default: return -EINVAL; } - /* Limit the caps to the mounter of the filesystem - * or the more limited uid specified in the xattr. - */ - if (!rootid_owns_currentns(rootkuid)) - return -ENODATA; CAP_FOR_EACH_U32(i) { if (i >= tocopy) break; - cpu_caps->permitted.cap[i] = le32_to_cpu(caps->data[i].permitted); - cpu_caps->inheritable.cap[i] = le32_to_cpu(caps->data[i].inheritable); + cpu_caps->permitted.cap[i] = le32_to_cpu(caps.data[i].permitted); + cpu_caps->inheritable.cap[i] = le32_to_cpu(caps.data[i].inheritable); } cpu_caps->permitted.cap[CAP_LAST_U32] &= CAP_LAST_U32_VALID_MASK; @@ -681,8 +461,8 @@ rc = get_vfs_caps_from_disk(bprm->file->f_path.dentry, &vcaps); if (rc < 0) { if (rc == -EINVAL) - printk(KERN_NOTICE "Invalid argument reading file caps for %s\n", - bprm->filename); + printk(KERN_NOTICE "%s: get_vfs_caps_from_disk returned %d for %s\n", + __func__, rc, bprm->filename); else if (rc == -ENODATA) rc = 0; goto out; @@ -880,19 +660,15 @@ { struct user_namespace *user_ns = dentry->d_sb->s_user_ns; - /* Ignore non-security xattrs */ - if (strncmp(name, XATTR_SECURITY_PREFIX, - sizeof(XATTR_SECURITY_PREFIX) - 1) != 0) - return 0; - - /* - * For XATTR_NAME_CAPS the check will be done in - * cap_convert_nscap(), called by setxattr() - */ - if (strcmp(name, XATTR_NAME_CAPS) == 0) + if (!strcmp(name, XATTR_NAME_CAPS)) { + if (!ns_capable(user_ns, CAP_SETFCAP)) + return -EPERM; return 0; + } - if (!ns_capable(user_ns, CAP_SYS_ADMIN)) + if (!strncmp(name, XATTR_SECURITY_PREFIX, + sizeof(XATTR_SECURITY_PREFIX) - 1) && + !ns_capable(user_ns, CAP_SYS_ADMIN)) return -EPERM; return 0; } @@ -912,22 +688,15 @@ { struct user_namespace *user_ns = dentry->d_sb->s_user_ns; - /* Ignore non-security xattrs */ - if (strncmp(name, XATTR_SECURITY_PREFIX, - sizeof(XATTR_SECURITY_PREFIX) - 1) != 0) - return 0; - - if (strcmp(name, XATTR_NAME_CAPS) == 0) { - /* security.capability gets namespaced */ - struct inode *inode = d_backing_inode(dentry); - if (!inode) - return -EINVAL; - if (!capable_wrt_inode_uidgid(inode, CAP_SETFCAP)) + if (!strcmp(name, XATTR_NAME_CAPS)) { + if (!ns_capable(user_ns, CAP_SETFCAP)) return -EPERM; return 0; } - if (!ns_capable(user_ns, CAP_SYS_ADMIN)) + if (!strncmp(name, XATTR_SECURITY_PREFIX, + sizeof(XATTR_SECURITY_PREFIX) - 1) && + !ns_capable(user_ns, CAP_SYS_ADMIN)) return -EPERM; return 0; } @@ -1317,7 +1086,6 @@ LSM_HOOK_INIT(bprm_secureexec, cap_bprm_secureexec), LSM_HOOK_INIT(inode_need_killpriv, cap_inode_need_killpriv), LSM_HOOK_INIT(inode_killpriv, cap_inode_killpriv), - LSM_HOOK_INIT(inode_getsecurity, cap_inode_getsecurity), LSM_HOOK_INIT(mmap_addr, cap_mmap_addr), LSM_HOOK_INIT(mmap_file, cap_mmap_file), LSM_HOOK_INIT(task_fix_setuid, cap_task_fix_setuid), diff -u linux-lts-xenial-4.4.0/security/selinux/ss/services.c linux-lts-xenial-4.4.0/security/selinux/ss/services.c --- linux-lts-xenial-4.4.0/security/selinux/ss/services.c +++ linux-lts-xenial-4.4.0/security/selinux/ss/services.c @@ -1441,7 +1441,7 @@ scontext_len, &context, def_sid); if (rc == -EINVAL && force) { context.str = str; - context.len = strlen(str) + 1; + context.len = scontext_len; str = NULL; } else if (rc) goto out_unlock; diff -u linux-lts-xenial-4.4.0/snapcraft.yaml linux-lts-xenial-4.4.0/snapcraft.yaml --- linux-lts-xenial-4.4.0/snapcraft.yaml +++ linux-lts-xenial-4.4.0/snapcraft.yaml @@ -17,10 +17,6 @@ kconfigflavour: generic kconfigs: - CONFIG_DEBUG_INFO=n - override-build: | - cp debian/scripts/retpoline-extract-one \ - $SNAPCRAFT_PART_BUILD/scripts/ubuntu-retpoline-extract-one - snapcraftctl build firmware: plugin: nil stage-packages: diff -u linux-lts-xenial-4.4.0/sound/pci/hda/hda_controller.c linux-lts-xenial-4.4.0/sound/pci/hda/hda_controller.c --- linux-lts-xenial-4.4.0/sound/pci/hda/hda_controller.c +++ linux-lts-xenial-4.4.0/sound/pci/hda/hda_controller.c @@ -547,10 +547,8 @@ return err; strlcpy(pcm->name, cpcm->name, sizeof(pcm->name)); apcm = kzalloc(sizeof(*apcm), GFP_KERNEL); - if (apcm == NULL) { - snd_device_free(chip->card, pcm); + if (apcm == NULL) return -ENOMEM; - } apcm->chip = chip; apcm->pcm = pcm; apcm->codec = codec; diff -u linux-lts-xenial-4.4.0/sound/pci/hda/patch_conexant.c linux-lts-xenial-4.4.0/sound/pci/hda/patch_conexant.c --- linux-lts-xenial-4.4.0/sound/pci/hda/patch_conexant.c +++ linux-lts-xenial-4.4.0/sound/pci/hda/patch_conexant.c @@ -851,8 +851,6 @@ SND_PCI_QUIRK(0x103c, 0x8079, "HP EliteBook 840 G3", CXT_FIXUP_HP_DOCK), SND_PCI_QUIRK(0x103c, 0x807C, "HP EliteBook 820 G3", CXT_FIXUP_HP_DOCK), SND_PCI_QUIRK(0x103c, 0x80FD, "HP ProBook 640 G2", CXT_FIXUP_HP_DOCK), - SND_PCI_QUIRK(0x103c, 0x83b3, "HP EliteBook 830 G5", CXT_FIXUP_HP_DOCK), - SND_PCI_QUIRK(0x103c, 0x83d3, "HP ProBook 640 G4", CXT_FIXUP_HP_DOCK), SND_PCI_QUIRK(0x103c, 0x8174, "HP Spectre x360", CXT_FIXUP_HP_SPECTRE), SND_PCI_QUIRK(0x103c, 0x8115, "HP Z1 Gen3", CXT_FIXUP_HP_GATE_MIC), SND_PCI_QUIRK(0x1043, 0x138d, "Asus", CXT_FIXUP_HEADPHONE_MIC_PIN), diff -u linux-lts-xenial-4.4.0/sound/pci/hda/patch_realtek.c linux-lts-xenial-4.4.0/sound/pci/hda/patch_realtek.c --- linux-lts-xenial-4.4.0/sound/pci/hda/patch_realtek.c +++ linux-lts-xenial-4.4.0/sound/pci/hda/patch_realtek.c @@ -2447,7 +2447,6 @@ SND_PCI_QUIRK(0x10cf, 0x1397, "Fujitsu Lifebook S7110", ALC262_FIXUP_FSC_S7110), SND_PCI_QUIRK(0x10cf, 0x142d, "Fujitsu Lifebook E8410", ALC262_FIXUP_BENQ), SND_PCI_QUIRK(0x10f1, 0x2915, "Tyan Thunder n6650W", ALC262_FIXUP_TYAN), - SND_PCI_QUIRK(0x1734, 0x1141, "FSC ESPRIMO U9210", ALC262_FIXUP_FSC_H270), SND_PCI_QUIRK(0x1734, 0x1147, "FSC Celsius H270", ALC262_FIXUP_FSC_H270), SND_PCI_QUIRK(0x17aa, 0x384e, "Lenovo 3000", ALC262_FIXUP_LENOVO_3000), SND_PCI_QUIRK(0x17ff, 0x0560, "Benq ED8", ALC262_FIXUP_BENQ), reverted: --- linux-lts-xenial-4.4.0/sound/soc/cirrus/edb93xx.c +++ linux-lts-xenial-4.4.0.orig/sound/soc/cirrus/edb93xx.c @@ -67,7 +67,7 @@ .cpu_dai_name = "ep93xx-i2s", .codec_name = "spi0.0", .codec_dai_name = "cs4271-hifi", + .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_IF | - .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS, .ops = &edb93xx_ops, }; reverted: --- linux-lts-xenial-4.4.0/sound/soc/cirrus/ep93xx-i2s.c +++ linux-lts-xenial-4.4.0.orig/sound/soc/cirrus/ep93xx-i2s.c @@ -51,9 +51,7 @@ #define EP93XX_I2S_WRDLEN_24 (1 << 0) #define EP93XX_I2S_WRDLEN_32 (2 << 0) +#define EP93XX_I2S_LINCTRLDATA_R_JUST (1 << 2) /* Right justify */ -#define EP93XX_I2S_RXLINCTRLDATA_R_JUST BIT(1) /* Right justify */ - -#define EP93XX_I2S_TXLINCTRLDATA_R_JUST BIT(2) /* Right justify */ #define EP93XX_I2S_CLKCFG_LRS (1 << 0) /* lrclk polarity */ #define EP93XX_I2S_CLKCFG_CKP (1 << 1) /* Bit clock polarity */ @@ -172,25 +170,25 @@ unsigned int fmt) { struct ep93xx_i2s_info *info = snd_soc_dai_get_drvdata(cpu_dai); + unsigned int clk_cfg, lin_ctrl; - unsigned int clk_cfg; - unsigned int txlin_ctrl = 0; - unsigned int rxlin_ctrl = 0; clk_cfg = ep93xx_i2s_read_reg(info, EP93XX_I2S_RXCLKCFG); + lin_ctrl = ep93xx_i2s_read_reg(info, EP93XX_I2S_RXLINCTRLDATA); switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { case SND_SOC_DAIFMT_I2S: clk_cfg |= EP93XX_I2S_CLKCFG_REL; + lin_ctrl &= ~EP93XX_I2S_LINCTRLDATA_R_JUST; break; case SND_SOC_DAIFMT_LEFT_J: clk_cfg &= ~EP93XX_I2S_CLKCFG_REL; + lin_ctrl &= ~EP93XX_I2S_LINCTRLDATA_R_JUST; break; case SND_SOC_DAIFMT_RIGHT_J: clk_cfg &= ~EP93XX_I2S_CLKCFG_REL; + lin_ctrl |= EP93XX_I2S_LINCTRLDATA_R_JUST; - rxlin_ctrl |= EP93XX_I2S_RXLINCTRLDATA_R_JUST; - txlin_ctrl |= EP93XX_I2S_TXLINCTRLDATA_R_JUST; break; default: @@ -215,32 +213,32 @@ switch (fmt & SND_SOC_DAIFMT_INV_MASK) { case SND_SOC_DAIFMT_NB_NF: /* Negative bit clock, lrclk low on left word */ + clk_cfg &= ~(EP93XX_I2S_CLKCFG_CKP | EP93XX_I2S_CLKCFG_REL); - clk_cfg &= ~(EP93XX_I2S_CLKCFG_CKP | EP93XX_I2S_CLKCFG_LRS); break; case SND_SOC_DAIFMT_NB_IF: /* Negative bit clock, lrclk low on right word */ clk_cfg &= ~EP93XX_I2S_CLKCFG_CKP; + clk_cfg |= EP93XX_I2S_CLKCFG_REL; - clk_cfg |= EP93XX_I2S_CLKCFG_LRS; break; case SND_SOC_DAIFMT_IB_NF: /* Positive bit clock, lrclk low on left word */ clk_cfg |= EP93XX_I2S_CLKCFG_CKP; + clk_cfg &= ~EP93XX_I2S_CLKCFG_REL; - clk_cfg &= ~EP93XX_I2S_CLKCFG_LRS; break; case SND_SOC_DAIFMT_IB_IF: /* Positive bit clock, lrclk low on right word */ + clk_cfg |= EP93XX_I2S_CLKCFG_CKP | EP93XX_I2S_CLKCFG_REL; - clk_cfg |= EP93XX_I2S_CLKCFG_CKP | EP93XX_I2S_CLKCFG_LRS; break; } /* Write new register values */ ep93xx_i2s_write_reg(info, EP93XX_I2S_RXCLKCFG, clk_cfg); ep93xx_i2s_write_reg(info, EP93XX_I2S_TXCLKCFG, clk_cfg); + ep93xx_i2s_write_reg(info, EP93XX_I2S_RXLINCTRLDATA, lin_ctrl); + ep93xx_i2s_write_reg(info, EP93XX_I2S_TXLINCTRLDATA, lin_ctrl); - ep93xx_i2s_write_reg(info, EP93XX_I2S_RXLINCTRLDATA, rxlin_ctrl); - ep93xx_i2s_write_reg(info, EP93XX_I2S_TXLINCTRLDATA, txlin_ctrl); return 0; } reverted: --- linux-lts-xenial-4.4.0/sound/soc/cirrus/snappercl15.c +++ linux-lts-xenial-4.4.0.orig/sound/soc/cirrus/snappercl15.c @@ -72,7 +72,7 @@ .codec_dai_name = "tlv320aic23-hifi", .codec_name = "tlv320aic23-codec.0-001a", .platform_name = "ep93xx-i2s", + .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_IF | - .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS, .ops = &snappercl15_ops, }; reverted: --- linux-lts-xenial-4.4.0/sound/soc/intel/common/sst-firmware.c +++ linux-lts-xenial-4.4.0.orig/sound/soc/intel/common/sst-firmware.c @@ -260,6 +260,7 @@ struct sst_pdata *sst_pdata = sst->pdata; struct sst_dma *dma; struct resource mem; + const char *dma_dev_name; int ret = 0; if (sst->pdata->resindex_dma_base == -1) @@ -270,6 +271,7 @@ * is attached to the ADSP IP. */ switch (sst->pdata->dma_engine) { case SST_DMA_TYPE_DW: + dma_dev_name = "dw_dmac"; break; default: dev_err(sst->dev, "error: invalid DMA engine %d\n", diff -u linux-lts-xenial-4.4.0/sound/soc/soc-dapm.c linux-lts-xenial-4.4.0/sound/soc/soc-dapm.c --- linux-lts-xenial-4.4.0/sound/soc/soc-dapm.c +++ linux-lts-xenial-4.4.0/sound/soc/soc-dapm.c @@ -425,8 +425,6 @@ static void dapm_kcontrol_free(struct snd_kcontrol *kctl) { struct dapm_kcontrol_data *data = snd_kcontrol_chip(kctl); - - list_del(&data->paths); kfree(data->wlist); kfree(data); } reverted: --- linux-lts-xenial-4.4.0/tools/perf/util/dso.c +++ linux-lts-xenial-4.4.0.orig/tools/perf/util/dso.c @@ -249,8 +249,6 @@ if ((strncmp(name, "[kernel.kallsyms]", 17) == 0) || (strncmp(name, "[guest.kernel.kallsyms", 22) == 0) || (strncmp(name, "[vdso]", 6) == 0) || - (strncmp(name, "[vdso32]", 8) == 0) || - (strncmp(name, "[vdsox32]", 9) == 0) || (strncmp(name, "[vsyscall]", 10) == 0)) { m->kmod = false; diff -u linux-lts-xenial-4.4.0/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c linux-lts-xenial-4.4.0/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c --- linux-lts-xenial-4.4.0/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c +++ linux-lts-xenial-4.4.0/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c @@ -111,7 +111,6 @@ bool have_cyc; bool fixup_last_mtc; bool have_last_ip; - enum intel_pt_param_flags flags; uint64_t pos; uint64_t last_ip; uint64_t ip; @@ -214,8 +213,6 @@ decoder->data = params->data; decoder->return_compression = params->return_compression; - decoder->flags = params->flags; - decoder->period = params->period; decoder->period_type = params->period_type; @@ -1013,15 +1010,6 @@ return err; } -static inline bool intel_pt_fup_with_nlip(struct intel_pt_decoder *decoder, - struct intel_pt_insn *intel_pt_insn, - uint64_t ip, int err) -{ - return decoder->flags & INTEL_PT_FUP_WITH_NLIP && !err && - intel_pt_insn->branch == INTEL_PT_BR_INDIRECT && - ip == decoder->ip + intel_pt_insn->length; -} - static int intel_pt_walk_fup(struct intel_pt_decoder *decoder) { struct intel_pt_insn intel_pt_insn; @@ -1034,8 +1022,7 @@ err = intel_pt_walk_insn(decoder, &intel_pt_insn, ip); if (err == INTEL_PT_RETURN) return 0; - if (err == -EAGAIN || - intel_pt_fup_with_nlip(decoder, &intel_pt_insn, ip, err)) { + if (err == -EAGAIN) { if (decoder->set_fup_tx_flags) { decoder->set_fup_tx_flags = false; decoder->tx_flags = decoder->fup_tx_flags; @@ -1045,7 +1032,7 @@ decoder->state.flags = decoder->fup_tx_flags; return 0; } - return -EAGAIN; + return err; } decoder->set_fup_tx_flags = false; if (err) @@ -1281,6 +1268,7 @@ { intel_pt_log("ERROR: Buffer overflow\n"); intel_pt_clear_tx_flags(decoder); + decoder->have_tma = false; decoder->cbr = 0; decoder->timestamp_insn_cnt = 0; decoder->pkt_state = INTEL_PT_STATE_ERR_RESYNC; @@ -1499,6 +1487,7 @@ case INTEL_PT_PSB: case INTEL_PT_TSC: case INTEL_PT_TMA: + case INTEL_PT_CBR: case INTEL_PT_MODE_TSX: case INTEL_PT_BAD: case INTEL_PT_PSBEND: @@ -1507,10 +1496,6 @@ decoder->pkt_step = 0; return -ENOENT; - case INTEL_PT_CBR: - intel_pt_calc_cbr(decoder); - break; - case INTEL_PT_OVF: return intel_pt_overflow(decoder); diff -u linux-lts-xenial-4.4.0/tools/perf/util/intel-pt-decoder/intel-pt-decoder.h linux-lts-xenial-4.4.0/tools/perf/util/intel-pt-decoder/intel-pt-decoder.h --- linux-lts-xenial-4.4.0/tools/perf/util/intel-pt-decoder/intel-pt-decoder.h +++ linux-lts-xenial-4.4.0/tools/perf/util/intel-pt-decoder/intel-pt-decoder.h @@ -53,14 +53,6 @@ INTEL_PT_ERR_MAX, }; -enum intel_pt_param_flags { - /* - * FUP packet can contain next linear instruction pointer instead of - * current linear instruction pointer. - */ - INTEL_PT_FUP_WITH_NLIP = 1 << 0, -}; - struct intel_pt_state { enum intel_pt_sample_type type; int err; @@ -99,7 +91,6 @@ unsigned int mtc_period; uint32_t tsc_ctc_ratio_n; uint32_t tsc_ctc_ratio_d; - enum intel_pt_param_flags flags; }; struct intel_pt_decoder; diff -u linux-lts-xenial-4.4.0/tools/perf/util/intel-pt-decoder/intel-pt-pkt-decoder.c linux-lts-xenial-4.4.0/tools/perf/util/intel-pt-decoder/intel-pt-pkt-decoder.c --- linux-lts-xenial-4.4.0/tools/perf/util/intel-pt-decoder/intel-pt-pkt-decoder.c +++ linux-lts-xenial-4.4.0/tools/perf/util/intel-pt-decoder/intel-pt-pkt-decoder.c @@ -281,7 +281,7 @@ if (len < offs) return INTEL_PT_NEED_MORE_BYTES; byte = buf[offs++]; - payload |= ((uint64_t)byte >> 1) << shift; + payload |= (byte >> 1) << shift; } packet->type = INTEL_PT_CYC; diff -u linux-lts-xenial-4.4.0/tools/perf/util/intel-pt.c linux-lts-xenial-4.4.0/tools/perf/util/intel-pt.c --- linux-lts-xenial-4.4.0/tools/perf/util/intel-pt.c +++ linux-lts-xenial-4.4.0/tools/perf/util/intel-pt.c @@ -676,7 +676,6 @@ unsigned int queue_nr) { struct intel_pt_params params = { .get_trace = 0, }; - struct perf_env *env = pt->machine->env; struct intel_pt_queue *ptq; ptq = zalloc(sizeof(struct intel_pt_queue)); @@ -754,9 +753,6 @@ } } - if (env->cpuid && !strncmp(env->cpuid, "GenuineIntel,6,92,", 18)) - params.flags |= INTEL_PT_FUP_WITH_NLIP; - ptq->decoder = intel_pt_decoder_new(¶ms); if (!ptq->decoder) goto out_free; @@ -1250,7 +1246,6 @@ if (intel_pt_is_switch_ip(ptq, state->to_ip)) { switch (ptq->switch_state) { - case INTEL_PT_SS_NOT_TRACING: case INTEL_PT_SS_UNKNOWN: case INTEL_PT_SS_EXPECTING_SWITCH_IP: err = intel_pt_next_tid(pt, ptq); diff -u linux-lts-xenial-4.4.0/ubuntu/ixxat/Makefile linux-lts-xenial-4.4.0/ubuntu/ixxat/Makefile --- linux-lts-xenial-4.4.0/ubuntu/ixxat/Makefile +++ linux-lts-xenial-4.4.0/ubuntu/ixxat/Makefile @@ -2,3 +2,3 @@ obj-m += ixx_usb.o -ixx_usb-objs := ixx_usb_cl1.o ixx_usb_cl2.o ixx_usb_core.o +ixx_usb-objs := ixx_usb_v2.o ixx_usb_fd.o ixx_usb_core.o reverted: --- linux-lts-xenial-4.4.0/ubuntu/ixxat/ixx_usb_cl1.c +++ linux-lts-xenial-4.4.0.orig/ubuntu/ixxat/ixx_usb_cl1.c @@ -1,139 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 - -/* CAN driver adapter for IXXAT USB-to-CAN CL1 - * - * Copyright (C) 2018 HMS Industrial Networks - * - * 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; version 2 of the License. - * - * 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 "ixx_usb_core.h" - -#define IXXAT_USB_CLOCK 8000000 - -#define IXXAT_USB_BUFFER_SIZE_RX 512 -#define IXXAT_USB_BUFFER_SIZE_TX 256 - -#define IXXAT_USB_MODES (CAN_CTRLMODE_3_SAMPLES | \ - CAN_CTRLMODE_BERR_REPORTING | \ - CAN_CTRLMODE_LISTENONLY) \ - -#define IXXAT_USB_BTMODE_TSM_CL1 0x80 - -/* bittiming parameters */ -#define IXXAT_USB2CAN_NAME "ixxat_usb" - -#define IXXAT_USB2CAN_TSEG1_MIN 1 -#define IXXAT_USB2CAN_TSEG1_MAX 16 -#define IXXAT_USB2CAN_TSEG2_MIN 1 -#define IXXAT_USB2CAN_TSEG2_MAX 8 -#define IXXAT_USB2CAN_SJW_MAX 4 -#define IXXAT_USB2CAN_BRP_MIN 1 -#define IXXAT_USB2CAN_BRP_MAX 64 -#define IXXAT_USB2CAN_BRP_INC 1 - -/* USB endpoint mapping for CL1 */ -#define IXXAT_USB2CAN_EP1_IN (1 | USB_DIR_IN) -#define IXXAT_USB2CAN_EP2_IN (2 | USB_DIR_IN) -#define IXXAT_USB2CAN_EP3_IN (3 | USB_DIR_IN) -#define IXXAT_USB2CAN_EP4_IN (4 | USB_DIR_IN) -#define IXXAT_USB2CAN_EP5_IN (5 | USB_DIR_IN) - -#define IXXAT_USB2CAN_EP1_OUT (1 | USB_DIR_OUT) -#define IXXAT_USB2CAN_EP2_OUT (2 | USB_DIR_OUT) -#define IXXAT_USB2CAN_EP3_OUT (3 | USB_DIR_OUT) -#define IXXAT_USB2CAN_EP4_OUT (4 | USB_DIR_OUT) -#define IXXAT_USB2CAN_EP5_OUT (5 | USB_DIR_OUT) - -#define IXXAT_USB_CAN_CMD_INIT 0x325 - -static const struct can_bittiming_const usb2can_bt = { - .name = IXXAT_USB2CAN_NAME, - .tseg1_min = IXXAT_USB2CAN_TSEG1_MIN, - .tseg1_max = IXXAT_USB2CAN_TSEG1_MAX, - .tseg2_min = IXXAT_USB2CAN_TSEG2_MIN, - .tseg2_max = IXXAT_USB2CAN_TSEG2_MAX, - .sjw_max = IXXAT_USB2CAN_SJW_MAX, - .brp_min = IXXAT_USB2CAN_BRP_MIN, - .brp_max = IXXAT_USB2CAN_BRP_MAX, - .brp_inc = IXXAT_USB2CAN_BRP_INC, -}; - -static int ixxat_usb_init_ctrl(struct ixxat_usb_device *dev) -{ - int ret; - u8 data[IXXAT_USB_CMD_BUFFER_SIZE] = { 0 }; - struct ixxat_usb_init_cmd *cmd = (struct ixxat_usb_init_cmd *)data; - struct ixxat_usb_init_cl1_req *req = &cmd->req_cl1; - struct ixxat_usb_init_res *res = &cmd->res; - u8 opmode = IXXAT_USB_OPMODE_EXTENDED | IXXAT_USB_OPMODE_STANDARD; - const struct can_bittiming *bt = &dev->can.bittiming; - - /* Bittiming calculation from kernel - * (see can-utils/can-calc-bit-timing.c) - */ - u8 btr0 = ((bt->brp - 1) & 0x3f) | (((bt->sjw - 1) & 0x3) << 6); - u8 btr1 = ((bt->prop_seg + bt->phase_seg1 - 1) & 0xf) | - (((bt->phase_seg2 - 1) & 0x7) << 4); - - if (dev->can.ctrlmode & CAN_CTRLMODE_3_SAMPLES) - btr1 |= IXXAT_USB_BTMODE_TSM_CL1; - if (dev->can.ctrlmode & CAN_CTRLMODE_BERR_REPORTING) - opmode |= IXXAT_USB_OPMODE_ERRFRAME; - if (dev->can.ctrlmode & CAN_CTRLMODE_LISTENONLY) - opmode |= IXXAT_USB_OPMODE_LISTONLY; - - ixxat_usb_setup_cmd(&req->dal_req, &res->dal_res); - req->dal_req.req_size = cpu_to_le32(sizeof(*req)); - req->dal_req.req_code = cpu_to_le32(IXXAT_USB_CAN_CMD_INIT); - req->dal_req.req_port = cpu_to_le16(dev->ctrl_index); - req->mode = opmode; - req->btr0 = btr0; - req->btr1 = btr1; - - ret = ixxat_usb_send_cmd(dev->udev, &req->dal_req); - if (ret < 0) - return ret; - - ret = ixxat_usb_rcv_cmd(dev->udev, &res->dal_res, dev->ctrl_index); - if (ret < 0) - return ret; - - return le32_to_cpu(res->dal_res.ret_code); -} - -const struct ixxat_usb_adapter usb2can_cl1 = { - .clock = IXXAT_USB_CLOCK, - .bt = &usb2can_bt, - .btd = NULL, - .modes = IXXAT_USB_MODES, - .buffer_size_rx = IXXAT_USB_BUFFER_SIZE_RX, - .buffer_size_tx = IXXAT_USB_BUFFER_SIZE_TX, - .ep_msg_in = { - IXXAT_USB2CAN_EP1_IN, - IXXAT_USB2CAN_EP2_IN, - IXXAT_USB2CAN_EP3_IN, - IXXAT_USB2CAN_EP4_IN, - IXXAT_USB2CAN_EP5_IN - }, - .ep_msg_out = { - IXXAT_USB2CAN_EP1_OUT, - IXXAT_USB2CAN_EP2_OUT, - IXXAT_USB2CAN_EP3_OUT, - IXXAT_USB2CAN_EP4_OUT, - IXXAT_USB2CAN_EP5_OUT - }, - .ep_offs = 0, - .init_ctrl = ixxat_usb_init_ctrl -}; reverted: --- linux-lts-xenial-4.4.0/ubuntu/ixxat/ixx_usb_cl2.c +++ linux-lts-xenial-4.4.0.orig/ubuntu/ixxat/ixx_usb_cl2.c @@ -1,331 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 - -/* CAN driver adapter for IXXAT USB-to-CAN CL2 - * - * Copyright (C) 2018 HMS Industrial Networks - * - * 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; version 2 of the License. - * - * 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 "ixx_usb_core.h" - -#define IXXAT_USB_CLOCK 80000000 - -#define IXXAT_USB_BUFFER_SIZE_RX 512 -#define IXXAT_USB_BUFFER_SIZE_TX 512 - -#define IXXAT_USB_MODES (CAN_CTRLMODE_3_SAMPLES | \ - CAN_CTRLMODE_LISTENONLY | \ - CAN_CTRLMODE_BERR_REPORTING) - -#define IXXAT_USB_MODES_FD (IXXAT_USB_MODES | \ - CAN_CTRLMODE_FD | \ - CAN_CTRLMODE_FD_NON_ISO) - -/* bittiming parameters CL2 */ -#define IXXAT_USB2CAN_NAME "ifi_can" - -#define IXXAT_USB2CAN_TSEG1_MIN 1 -#define IXXAT_USB2CAN_TSEG1_MAX 256 -#define IXXAT_USB2CAN_TSEG2_MIN 1 -#define IXXAT_USB2CAN_TSEG2_MAX 256 -#define IXXAT_USB2CAN_SJW_MAX 128 -#define IXXAT_USB2CAN_BRP_MIN 2 -#define IXXAT_USB2CAN_BRP_MAX 513 -#define IXXAT_USB2CAN_BRP_INC 1 - -#define IXXAT_USB2CAN_TSEG1_MIN_DATA 1 -#define IXXAT_USB2CAN_TSEG1_MAX_DATA 256 -#define IXXAT_USB2CAN_TSEG2_MIN_DATA 1 -#define IXXAT_USB2CAN_TSEG2_MAX_DATA 256 -#define IXXAT_USB2CAN_SJW_MAX_DATA 128 -#define IXXAT_USB2CAN_BRP_MIN_DATA 2 -#define IXXAT_USB2CAN_BRP_MAX_DATA 513 -#define IXXAT_USB2CAN_BRP_INC_DATA 1 - -/* bittiming parameters CAN IDM100 */ -#define IXXAT_CANIDM_NAME "mcan" - -#define IXXAT_CANIDM100_TSEG1_MIN 1 -#define IXXAT_CANIDM100_TSEG1_MAX 64 -#define IXXAT_CANIDM100_TSEG2_MIN 1 -#define IXXAT_CANIDM100_TSEG2_MAX 16 -#define IXXAT_CANIDM100_SJW_MAX 16 -#define IXXAT_CANIDM100_BRP_MIN 1 -#define IXXAT_CANIDM100_BRP_MAX 1024 -#define IXXAT_CANIDM100_BRP_INC 1 - -#define IXXAT_CANIDM100_TSEG1_MIN_DATA 1 -#define IXXAT_CANIDM100_TSEG1_MAX_DATA 16 -#define IXXAT_CANIDM100_TSEG2_MIN_DATA 1 -#define IXXAT_CANIDM100_TSEG2_MAX_DATA 8 -#define IXXAT_CANIDM100_SJW_MAX_DATA 4 -#define IXXAT_CANIDM100_BRP_MIN_DATA 1 -#define IXXAT_CANIDM100_BRP_MAX_DATA 32 -#define IXXAT_CANIDM100_BRP_INC_DATA 1 - -/* bittiming parameters CAN IDM101 */ -#define IXXAT_CANIDM_NAME "mcan" - -#define IXXAT_CANIDM101_TSEG1_MIN 1 -#define IXXAT_CANIDM101_TSEG1_MAX 256 -#define IXXAT_CANIDM101_TSEG2_MIN 1 -#define IXXAT_CANIDM101_TSEG2_MAX 128 -#define IXXAT_CANIDM101_SJW_MAX 128 -#define IXXAT_CANIDM101_BRP_MIN 1 -#define IXXAT_CANIDM101_BRP_MAX 512 -#define IXXAT_CANIDM101_BRP_INC 1 - -#define IXXAT_CANIDM101_TSEG1_MIN_DATA 1 -#define IXXAT_CANIDM101_TSEG1_MAX_DATA 32 -#define IXXAT_CANIDM101_TSEG2_MIN_DATA 1 -#define IXXAT_CANIDM101_TSEG2_MAX_DATA 16 -#define IXXAT_CANIDM101_SJW_MAX_DATA 8 -#define IXXAT_CANIDM101_BRP_MIN_DATA 1 -#define IXXAT_CANIDM101_BRP_MAX_DATA 32 -#define IXXAT_CANIDM101_BRP_INC_DATA 1 - -/* USB endpoint mapping for CL2 */ -#define IXXAT_USB2CAN_EP1_IN (1 | USB_DIR_IN) -#define IXXAT_USB2CAN_EP2_IN (2 | USB_DIR_IN) -#define IXXAT_USB2CAN_EP3_IN (3 | USB_DIR_IN) -#define IXXAT_USB2CAN_EP4_IN (4 | USB_DIR_IN) -#define IXXAT_USB2CAN_EP5_IN (5 | USB_DIR_IN) - -#define IXXAT_USB2CAN_EP1_OUT (1 | USB_DIR_OUT) -#define IXXAT_USB2CAN_EP2_OUT (2 | USB_DIR_OUT) -#define IXXAT_USB2CAN_EP3_OUT (3 | USB_DIR_OUT) -#define IXXAT_USB2CAN_EP4_OUT (4 | USB_DIR_OUT) -#define IXXAT_USB2CAN_EP5_OUT (5 | USB_DIR_OUT) - -/* USB endpoint mapping for CAN IDM */ -#define IXXAT_CANIDM_EP1_IN (2 | USB_DIR_IN) -#define IXXAT_CANIDM_EP2_IN (4 | USB_DIR_IN) -#define IXXAT_CANIDM_EP3_IN (6 | USB_DIR_IN) -#define IXXAT_CANIDM_EP4_IN (8 | USB_DIR_IN) -#define IXXAT_CANIDM_EP5_IN (10 | USB_DIR_IN) - -#define IXXAT_CANIDM_EP1_OUT (1 | USB_DIR_OUT) -#define IXXAT_CANIDM_EP2_OUT (3 | USB_DIR_OUT) -#define IXXAT_CANIDM_EP3_OUT (5 | USB_DIR_OUT) -#define IXXAT_CANIDM_EP4_OUT (7 | USB_DIR_OUT) -#define IXXAT_CANIDM_EP5_OUT (9 | USB_DIR_OUT) - -#define IXXAT_USB_CAN_CMD_INIT 0x337 - -static const struct can_bittiming_const usb2can_bt = { - .name = IXXAT_USB2CAN_NAME, - .tseg1_min = IXXAT_USB2CAN_TSEG1_MIN, - .tseg1_max = IXXAT_USB2CAN_TSEG1_MAX, - .tseg2_min = IXXAT_USB2CAN_TSEG2_MIN, - .tseg2_max = IXXAT_USB2CAN_TSEG2_MAX, - .sjw_max = IXXAT_USB2CAN_SJW_MAX, - .brp_min = IXXAT_USB2CAN_BRP_MIN, - .brp_max = IXXAT_USB2CAN_BRP_MAX, - .brp_inc = IXXAT_USB2CAN_BRP_INC, -}; - -static const struct can_bittiming_const usb2can_btd = { - .name = IXXAT_USB2CAN_NAME, - .tseg1_min = IXXAT_USB2CAN_TSEG1_MIN_DATA, - .tseg1_max = IXXAT_USB2CAN_TSEG1_MAX_DATA, - .tseg2_min = IXXAT_USB2CAN_TSEG2_MIN_DATA, - .tseg2_max = IXXAT_USB2CAN_TSEG2_MAX_DATA, - .sjw_max = IXXAT_USB2CAN_SJW_MAX_DATA, - .brp_min = IXXAT_USB2CAN_BRP_MIN_DATA, - .brp_max = IXXAT_USB2CAN_BRP_MAX_DATA, - .brp_inc = IXXAT_USB2CAN_BRP_INC_DATA, -}; - -static const struct can_bittiming_const canidm100_bt = { - .name = IXXAT_CANIDM_NAME, - .tseg1_min = IXXAT_CANIDM100_TSEG1_MIN, - .tseg1_max = IXXAT_CANIDM100_TSEG1_MAX, - .tseg2_min = IXXAT_CANIDM100_TSEG2_MIN, - .tseg2_max = IXXAT_CANIDM100_TSEG2_MAX, - .sjw_max = IXXAT_CANIDM100_SJW_MAX, - .brp_min = IXXAT_CANIDM100_BRP_MIN, - .brp_max = IXXAT_CANIDM100_BRP_MAX, - .brp_inc = IXXAT_CANIDM100_BRP_INC -}; - -static const struct can_bittiming_const canidm100_btd = { - .name = IXXAT_CANIDM_NAME, - .tseg1_min = IXXAT_CANIDM100_TSEG1_MIN_DATA, - .tseg1_max = IXXAT_CANIDM100_TSEG1_MAX_DATA, - .tseg2_min = IXXAT_CANIDM100_TSEG2_MIN_DATA, - .tseg2_max = IXXAT_CANIDM100_TSEG2_MAX_DATA, - .sjw_max = IXXAT_CANIDM100_SJW_MAX_DATA, - .brp_min = IXXAT_CANIDM100_BRP_MIN_DATA, - .brp_max = IXXAT_CANIDM100_BRP_MAX_DATA, - .brp_inc = IXXAT_CANIDM100_BRP_INC_DATA -}; - -static const struct can_bittiming_const canidm101_bt = { - .name = IXXAT_CANIDM_NAME, - .tseg1_min = IXXAT_CANIDM101_TSEG1_MIN, - .tseg1_max = IXXAT_CANIDM101_TSEG1_MAX, - .tseg2_min = IXXAT_CANIDM101_TSEG2_MIN, - .tseg2_max = IXXAT_CANIDM101_TSEG2_MAX, - .sjw_max = IXXAT_CANIDM101_SJW_MAX, - .brp_min = IXXAT_CANIDM101_BRP_MIN, - .brp_max = IXXAT_CANIDM101_BRP_MAX, - .brp_inc = IXXAT_CANIDM101_BRP_INC -}; - -static const struct can_bittiming_const canidm101_btd = { - .name = IXXAT_CANIDM_NAME, - .tseg1_min = IXXAT_CANIDM101_TSEG1_MIN_DATA, - .tseg1_max = IXXAT_CANIDM101_TSEG1_MAX_DATA, - .tseg2_min = IXXAT_CANIDM101_TSEG2_MIN_DATA, - .tseg2_max = IXXAT_CANIDM101_TSEG2_MAX_DATA, - .sjw_max = IXXAT_CANIDM101_SJW_MAX_DATA, - .brp_min = IXXAT_CANIDM101_BRP_MIN_DATA, - .brp_max = IXXAT_CANIDM101_BRP_MAX_DATA, - .brp_inc = IXXAT_CANIDM101_BRP_INC_DATA -}; - -static int ixxat_usb_init_ctrl(struct ixxat_usb_device *dev) -{ - int ret; - u8 data[IXXAT_USB_CMD_BUFFER_SIZE] = { 0 }; - struct ixxat_usb_init_cmd *cmd = (struct ixxat_usb_init_cmd *)data; - struct ixxat_usb_init_cl2_req *req = &cmd->req_cl2; - struct ixxat_usb_init_res *res = &cmd->res; - u8 opmode = IXXAT_USB_OPMODE_EXTENDED | IXXAT_USB_OPMODE_STANDARD; - u8 exmode = 0; - u32 btmode = IXXAT_USB_BTMODE_NAT; - const struct can_bittiming *bt = &dev->can.bittiming; - const struct can_bittiming *btd = &dev->can.data_bittiming; - - if (dev->can.ctrlmode & CAN_CTRLMODE_3_SAMPLES) - btmode = IXXAT_USB_BTMODE_TSM; - if (dev->can.ctrlmode & CAN_CTRLMODE_BERR_REPORTING) - opmode |= IXXAT_USB_OPMODE_ERRFRAME; - if (dev->can.ctrlmode & CAN_CTRLMODE_LISTENONLY) - opmode |= IXXAT_USB_OPMODE_LISTONLY; - if ((CAN_CTRLMODE_FD | CAN_CTRLMODE_FD_NON_ISO) & dev->can.ctrlmode) - exmode |= IXXAT_USB_EXMODE_EXTDATA | IXXAT_USB_EXMODE_FASTDATA; - if (!(CAN_CTRLMODE_FD_NON_ISO & dev->can.ctrlmode) && exmode) - exmode |= IXXAT_USB_EXMODE_ISOFD; - - ixxat_usb_setup_cmd(&req->dal_req, &res->dal_res); - - req->dal_req.req_size = cpu_to_le32(sizeof(*req)); - req->dal_req.req_code = cpu_to_le32(IXXAT_USB_CAN_CMD_INIT); - req->dal_req.req_port = cpu_to_le16(dev->ctrl_index); - req->opmode = opmode; - req->exmode = exmode; - req->sdr.mode = cpu_to_le32(btmode); - req->sdr.bps = cpu_to_le32(bt->brp); - req->sdr.ts1 = cpu_to_le16(bt->prop_seg + bt->phase_seg1); - req->sdr.ts2 = cpu_to_le16(bt->phase_seg2); - req->sdr.sjw = cpu_to_le16(bt->sjw); - req->sdr.tdo = 0; - - if (exmode) { - req->fdr.mode = cpu_to_le32(btmode); - req->fdr.bps = cpu_to_le32(btd->brp); - req->fdr.ts1 = cpu_to_le16(btd->prop_seg + btd->phase_seg1); - req->fdr.ts2 = cpu_to_le16(btd->phase_seg2); - req->fdr.sjw = cpu_to_le16(btd->sjw); - req->fdr.tdo = cpu_to_le16(btd->brp * (btd->phase_seg1 + 1 + - btd->prop_seg)); - } - - ret = ixxat_usb_send_cmd(dev->udev, &req->dal_req); - if (ret < 0) - return ret; - - ret = ixxat_usb_rcv_cmd(dev->udev, &res->dal_res, dev->ctrl_index); - if (ret < 0) - return ret; - - return le32_to_cpu(res->dal_res.ret_code); -} - -const struct ixxat_usb_adapter usb2can_cl2 = { - .clock = IXXAT_USB_CLOCK, - .bt = &usb2can_bt, - .btd = &usb2can_btd, - .modes = IXXAT_USB_MODES_FD, - .buffer_size_rx = IXXAT_USB_BUFFER_SIZE_RX, - .buffer_size_tx = IXXAT_USB_BUFFER_SIZE_TX, - .ep_msg_in = { - IXXAT_USB2CAN_EP1_IN, - IXXAT_USB2CAN_EP2_IN, - IXXAT_USB2CAN_EP3_IN, - IXXAT_USB2CAN_EP4_IN, - IXXAT_USB2CAN_EP5_IN - }, - .ep_msg_out = { - IXXAT_USB2CAN_EP1_OUT, - IXXAT_USB2CAN_EP2_OUT, - IXXAT_USB2CAN_EP3_OUT, - IXXAT_USB2CAN_EP4_OUT, - IXXAT_USB2CAN_EP5_OUT - }, - .ep_offs = 1, - .init_ctrl = ixxat_usb_init_ctrl -}; - -const struct ixxat_usb_adapter can_idm100 = { - .clock = IXXAT_USB_CLOCK, - .bt = &canidm100_bt, - .btd = &canidm100_btd, - .modes = IXXAT_USB_MODES, - .buffer_size_rx = IXXAT_USB_BUFFER_SIZE_RX, - .buffer_size_tx = IXXAT_USB_BUFFER_SIZE_TX, - .ep_msg_in = { - IXXAT_CANIDM_EP1_IN, - IXXAT_CANIDM_EP2_IN, - IXXAT_CANIDM_EP3_IN, - IXXAT_CANIDM_EP4_IN, - IXXAT_CANIDM_EP5_IN - }, - .ep_msg_out = { - IXXAT_CANIDM_EP1_OUT, - IXXAT_CANIDM_EP2_OUT, - IXXAT_CANIDM_EP3_OUT, - IXXAT_CANIDM_EP4_OUT, - IXXAT_CANIDM_EP5_OUT - }, - .ep_offs = 0, - .init_ctrl = ixxat_usb_init_ctrl -}; - -const struct ixxat_usb_adapter can_idm101 = { - .clock = IXXAT_USB_CLOCK, - .bt = &canidm101_bt, - .btd = &canidm101_btd, - .modes = IXXAT_USB_MODES_FD, - .buffer_size_rx = IXXAT_USB_BUFFER_SIZE_RX, - .buffer_size_tx = IXXAT_USB_BUFFER_SIZE_TX, - .ep_msg_in = { - IXXAT_CANIDM_EP1_IN, - IXXAT_CANIDM_EP2_IN, - IXXAT_CANIDM_EP3_IN, - IXXAT_CANIDM_EP4_IN, - IXXAT_CANIDM_EP5_IN - }, - .ep_msg_out = { - IXXAT_CANIDM_EP1_OUT, - IXXAT_CANIDM_EP2_OUT, - IXXAT_CANIDM_EP3_OUT, - IXXAT_CANIDM_EP4_OUT, - IXXAT_CANIDM_EP5_OUT - }, - .ep_offs = 0, - .init_ctrl = ixxat_usb_init_ctrl -}; diff -u linux-lts-xenial-4.4.0/ubuntu/ixxat/ixx_usb_core.c linux-lts-xenial-4.4.0/ubuntu/ixxat/ixx_usb_core.c --- linux-lts-xenial-4.4.0/ubuntu/ixxat/ixx_usb_core.c +++ linux-lts-xenial-4.4.0/ubuntu/ixxat/ixx_usb_core.c @@ -1,8 +1,9 @@ -// SPDX-License-Identifier: GPL-2.0 - -/* CAN driver for IXXAT USB-to-CAN +/* + * CAN driver for IXXAT USB-to-CAN V2 adapters + * + * Copyright (C) 2003-2014 Michael Hengler IXXAT Automation GmbH * - * Copyright (C) 2018 HMS Industrial Networks + * Based on code originally by pcan_usb_core * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published @@ -13,775 +14,265 @@ * 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 +#include +#include +#include +#include #include "ixx_usb_core.h" -MODULE_AUTHOR("Marcel Schmidt "); -MODULE_DESCRIPTION("CAN driver for IXXAT USB-to-CAN FD adapters"); +MODULE_AUTHOR("Michael Hengler "); +MODULE_DESCRIPTION("CAN driver for IXXAT USB-to-CAN V2 adapters"); MODULE_LICENSE("GPL v2"); -/* Table of devices that work with this driver */ -static const struct usb_device_id ixxat_usb_table[] = { - { USB_DEVICE(IXXAT_USB_VENDOR_ID, USB2CAN_COMPACT_PRODUCT_ID) }, - { USB_DEVICE(IXXAT_USB_VENDOR_ID, USB2CAN_EMBEDDED_PRODUCT_ID) }, - { USB_DEVICE(IXXAT_USB_VENDOR_ID, USB2CAN_PROFESSIONAL_PRODUCT_ID) }, - { USB_DEVICE(IXXAT_USB_VENDOR_ID, USB2CAN_AUTOMOTIVE_PRODUCT_ID) }, - { USB_DEVICE(IXXAT_USB_VENDOR_ID, USB2CAN_FD_COMPACT_PRODUCT_ID) }, - { USB_DEVICE(IXXAT_USB_VENDOR_ID, USB2CAN_FD_PROFESSIONAL_PRODUCT_ID) }, - { USB_DEVICE(IXXAT_USB_VENDOR_ID, USB2CAN_FD_AUTOMOTIVE_PRODUCT_ID) }, - { USB_DEVICE(IXXAT_USB_VENDOR_ID, USB2CAN_FD_PCIE_MINI_PRODUCT_ID) }, - { USB_DEVICE(IXXAT_USB_VENDOR_ID, USB2CAR_PRODUCT_ID) }, - { USB_DEVICE(IXXAT_USB_VENDOR_ID, CAN_IDM100_PRODUCT_ID) }, - { USB_DEVICE(IXXAT_USB_VENDOR_ID, CAN_IDM101_PRODUCT_ID) }, - { } /* Terminating entry */ -}; - -MODULE_DEVICE_TABLE(usb, ixxat_usb_table); - -void ixxat_usb_setup_cmd(struct ixxat_usb_dal_req *req, - struct ixxat_usb_dal_res *res) -{ - req->req_size = sizeof(*req); - req->req_port = 0xffff; - req->req_socket = 0xffff; - req->req_code = 0; - - res->res_size = sizeof(*res); - res->ret_size = 0; - res->ret_code = 0xffffffff; -} - -int ixxat_usb_send_cmd(struct usb_device *dev, - struct ixxat_usb_dal_req *dal_req) -{ - int ret = 0; - int i; - u16 size = le32_to_cpu(dal_req->req_size) + - sizeof(struct ixxat_usb_dal_res); - u16 value = le16_to_cpu(dal_req->req_port); - u8 request = 0xff; - u8 requesttype = USB_TYPE_VENDOR | USB_DIR_OUT; - u8 *buf = kmalloc(size, GFP_KERNEL); - - if (!buf) - return -ENOMEM; - - memcpy(buf, dal_req, size); - - for (i = 0; i < IXXAT_USB_MAX_COM_REQ; ++i) { - const int to = msecs_to_jiffies(IXXAT_USB_MSG_TIMEOUT); - - ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), request, - requesttype, value, 0, buf, size, to); - - if (ret < 0) - msleep(IXXAT_USB_MSG_CYCLE); - else - break; - } - - kfree(buf); +#define IXXAT_USB_DRIVER_NAME "ixx_usb" - if (ret < 0) - dev_err(&dev->dev, "Error %d: Sending command failure\n", ret); - - return ret; -} - -int ixxat_usb_rcv_cmd(struct usb_device *dev, - struct ixxat_usb_dal_res *dal_res, int value) -{ - int ret; - int res_size = 0; - int i; - int size_to_read = le32_to_cpu(dal_res->res_size); - u8 req = 0xff; - u8 req_type = USB_TYPE_VENDOR | USB_DIR_IN; - u8 *buf = kmalloc(size_to_read, GFP_KERNEL); - - if (!buf) - return -ENOMEM; - - for (i = 0; i < IXXAT_USB_MAX_COM_REQ; ++i) { - const int to = msecs_to_jiffies(IXXAT_USB_MSG_TIMEOUT); - void *data = buf + (u8)res_size; - const int size = size_to_read - res_size; - - ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), - req, req_type, value, 0, - data, size, to); - - if (ret < 0) { - msleep(IXXAT_USB_MSG_CYCLE); - continue; - } - - res_size += ret; - if (res_size < size_to_read) - msleep(IXXAT_USB_MSG_CYCLE); - else - break; - } - - if (res_size != size_to_read) - ret = -EBADMSG; - - if (ret < 0) { - dev_err(&dev->dev, "Error %d: Receiving command failure\n", - ret); - kfree(buf); - return ret; - } - - memcpy(dal_res, buf, size_to_read); - kfree(buf); - - return ret; -} - -static void ixxat_usb_update_ts_now(struct ixxat_usb_device *dev, u32 ts_now) -{ - u32 *ts_dev = &dev->time_ref.ts_dev_0; - ktime_t *kt_host = &dev->time_ref.kt_host_0; - u64 timebase = (u64)0x00000000FFFFFFFF - (u64)(*ts_dev) + (u64)ts_now; - - *kt_host = ktime_add_us(*kt_host, timebase); - *ts_dev = ts_now; -} +#define IXXAT_USB_BUS_CAN 1 // CAN +#define IXXAT_USB_BUS_TYPE(BusCtrl) (u8) ( ((BusCtrl) >> 8) & 0x00FF ) +#define IXXAT_USB_VENDOR_ID 0x08d8 -static void ixxat_usb_get_ts_tv(struct ixxat_usb_device *dev, u32 ts, - ktime_t *k_time) -{ - ktime_t tmp_time = dev->time_ref.kt_host_0; +#define IXXAT_USB_STATE_CONNECTED 0x00000001 +#define IXXAT_USB_STATE_STARTED 0x00000002 - if (ts < dev->time_ref.ts_dev_last) - ixxat_usb_update_ts_now(dev, ts); - dev->time_ref.ts_dev_last = ts; - tmp_time = ktime_add_us(tmp_time, ts - dev->time_ref.ts_dev_0); +/* Table of devices that work with this driver */ +static struct usb_device_id ixxat_usb_table[] = { + {USB_DEVICE(IXXAT_USB_VENDOR_ID, USB_TO_CAN_V2_COMPACT_PRODUCT_ID)}, + {USB_DEVICE(IXXAT_USB_VENDOR_ID, USB_TO_CAN_V2_EMBEDDED_PRODUCT_ID)}, + {USB_DEVICE(IXXAT_USB_VENDOR_ID, USB_TO_CAN_V2_PROFESSIONAL_PRODUCT_ID)}, + {USB_DEVICE(IXXAT_USB_VENDOR_ID, USB_TO_CAN_V2_AUTOMOTIVE_PRODUCT_ID)}, + {USB_DEVICE(IXXAT_USB_VENDOR_ID, USB_TO_LIN_V2_PRODUCT_ID)}, + {USB_DEVICE(IXXAT_USB_VENDOR_ID, USB_TO_KLINE_V2_PRODUCT_ID)}, +#ifdef CANFD_CAPABLE + {USB_DEVICE(IXXAT_USB_VENDOR_ID, USB_TO_CAN_FD_AUTOMOTIVE_PRODUCT_ID)}, + {USB_DEVICE(IXXAT_USB_VENDOR_ID, USB_TO_CAN_FD_COMPACT_PRODUCT_ID)}, + {USB_DEVICE(IXXAT_USB_VENDOR_ID, USB_TO_CAN_FD_PROFESSIONAL_PRODUCT_ID)}, + {USB_DEVICE(IXXAT_USB_VENDOR_ID, USB_TO_CAN_FD_PCIE_MINI_PRODUCT_ID)}, + {USB_DEVICE(IXXAT_USB_VENDOR_ID, USB_TO_CAR_ID)}, + {USB_DEVICE(IXXAT_USB_VENDOR_ID, DELL_EDGE_GW3002_PRODUCT_ID)}, +#endif + {} /* Terminating entry */ +}; - if (k_time) - *k_time = tmp_time; -} +MODULE_DEVICE_TABLE(usb, ixxat_usb_table); -static void ixxat_usb_set_ts_now(struct ixxat_usb_device *dev, u32 ts_now) -{ - dev->time_ref.ts_dev_0 = ts_now; - dev->time_ref.kt_host_0 = ktime_get_real(); - dev->time_ref.ts_dev_last = ts_now; -} +/* List of supported IXX-USB adapters (NULL terminated list) */ +static struct ixx_usb_adapter *ixx_usb_adapters_list[] = { + &usb_to_can_v2_compact, + &usb_to_can_v2_automotive, + &usb_to_can_v2_embedded, + &usb_to_can_v2_professional, + &usb_to_can_v2_low_speed, + &usb_to_can_v2_extended, +#ifdef CANFD_CAPABLE + &usb_to_can_fd_automotive, + &usb_to_can_fd_compact, + &usb_to_can_fd_professional, + &usb_to_can_fd_pcie_mini, + &usb_to_car, + &dell_edge_gw3002, +#endif + NULL, +}; -static int ixxat_usb_get_dev_caps(struct usb_device *dev, - struct ixxat_dev_caps *dev_caps) +/* + * dump memory + */ +#define DUMP_WIDTH 16 +void ixxat_dump_mem(char *prompt, void *p, int l) { - int i; - int ret; - u8 data[IXXAT_USB_CMD_BUFFER_SIZE] = { 0 }; - struct ixxat_usb_caps_cmd *cmd = (struct ixxat_usb_caps_cmd *)data; - struct ixxat_usb_caps_req *req = &cmd->req; - struct ixxat_usb_caps_res *res = &cmd->res; - - ixxat_usb_setup_cmd(&req->dal_req, &res->dal_res); - req->dal_req.req_code = cpu_to_le32(IXXAT_USB_BRD_CMD_GET_DEVCAPS); - res->dal_res.res_size = cpu_to_le32(sizeof(*res)); - - ret = ixxat_usb_send_cmd(dev, &req->dal_req); - if (ret < 0) - return ret; - - ret = ixxat_usb_rcv_cmd(dev, &res->dal_res, 0xffff); - if (ret < 0) - return ret; - - dev_caps->bus_ctrl_count = le16_to_cpu(res->dev_caps.bus_ctrl_count); - for (i = 0; i < dev_caps->bus_ctrl_count; ++i) { - u16 type = le16_to_cpu(res->dev_caps.bus_ctrl_types[i]); - - dev_caps->bus_ctrl_types[i] = type; - } - - return 0; + pr_info("%s dumping %s (%d bytes):\n", + IXXAT_USB_DRIVER_NAME, prompt ? prompt : "memory", l); + print_hex_dump(KERN_INFO, IXXAT_USB_DRIVER_NAME " ", DUMP_PREFIX_NONE, + DUMP_WIDTH, 1, p, l, false); } -static int ixxat_usb_get_dev_info(struct ixxat_usb_device *dev, - struct ixxat_dev_info *dev_info) +static void ixxat_usb_add_us(struct timeval *tv, u64 delta_us) { - int ret; - u8 data[IXXAT_USB_CMD_BUFFER_SIZE] = { 0 }; - struct ixxat_usb_info_cmd *cmd = (struct ixxat_usb_info_cmd *)data; - struct ixxat_usb_info_req *req = &cmd->req; - struct ixxat_usb_info_res *res = &cmd->res; - - ixxat_usb_setup_cmd(&req->dal_req, &res->dal_res); - req->dal_req.req_code = cpu_to_le32(IXXAT_USB_BRD_CMD_GET_DEVINFO); - res->dal_res.res_size = cpu_to_le32(sizeof(*res)); - - ret = ixxat_usb_send_cmd(dev->udev, &req->dal_req); - if (ret < 0) - return ret; - - ret = ixxat_usb_rcv_cmd(dev->udev, &res->dal_res, 0xffff); - if (ret < 0) - return ret; + /* number of s. to add to final time */ + u32 delta_s = div_u64(delta_us, 1000000); - if (dev_info) { - const size_t id_size = sizeof(res->info.device_id); - const size_t nm_size = sizeof(res->info.device_name); - const u32 fpgav = le32_to_cpu(res->info.device_fpga_version); - const u16 devv = le16_to_cpu(res->info.device_version); + delta_us -= delta_s * 1000000; - memcpy(dev_info->device_id, &res->info.device_id, id_size); - memcpy(dev_info->device_name, &res->info.device_name, nm_size); - dev_info->device_fpga_version = fpgav; - dev_info->device_version = devv; + tv->tv_usec += delta_us; + if (tv->tv_usec >= 1000000) { + tv->tv_usec -= 1000000; + delta_s++; } - - return le32_to_cpu(res->dal_res.ret_code); + tv->tv_sec += delta_s; } -static int ixxat_usb_start_ctrl(struct ixxat_usb_device *dev, u32 *time_ref) +void ixxat_usb_get_ts_tv(struct ixx_usb_device *dev, u32 ts, ktime_t *k_time) { - int ret; - u8 data[IXXAT_USB_CMD_BUFFER_SIZE] = { 0 }; - struct ixxat_usb_start_cmd *cmd = (struct ixxat_usb_start_cmd *)data; - struct ixxat_usb_start_req *req = &cmd->req; - struct ixxat_usb_start_res *res = &cmd->res; - - ixxat_usb_setup_cmd(&req->dal_req, &res->dal_res); - req->dal_req.req_code = cpu_to_le32(IXXAT_USB_CAN_CMD_START); - req->dal_req.req_port = cpu_to_le16(dev->ctrl_index); - res->dal_res.res_size = cpu_to_le32(sizeof(*res)); - res->start_time = 0; - - ret = ixxat_usb_send_cmd(dev->udev, &req->dal_req); - if (ret < 0) - return ret; + struct timeval tv = dev->time_ref.tv_host_0; - ret = ixxat_usb_rcv_cmd(dev->udev, &res->dal_res, dev->ctrl_index); - if (ret < 0) - return ret; - - if (time_ref) - *time_ref = le32_to_cpu(res->start_time); - - return le32_to_cpu(res->dal_res.ret_code); -} - -static int ixxat_usb_stop_ctrl(struct ixxat_usb_device *dev) -{ - int ret; - u8 data[IXXAT_USB_CMD_BUFFER_SIZE] = { 0 }; - struct ixxat_usb_stop_cmd *cmd = (struct ixxat_usb_stop_cmd *)data; - struct ixxat_usb_stop_req *req = &cmd->req; - struct ixxat_usb_stop_res *res = &cmd->res; - - ixxat_usb_setup_cmd(&req->dal_req, &res->dal_res); - req->dal_req.req_size = cpu_to_le32(sizeof(*req)); - req->dal_req.req_code = cpu_to_le32(IXXAT_USB_CAN_CMD_STOP); - req->dal_req.req_port = cpu_to_le16(dev->ctrl_index); - req->action = cpu_to_le32(IXXAT_USB_STOP_ACTION_CLEARALL); - - ret = ixxat_usb_send_cmd(dev->udev, &req->dal_req); - if (ret < 0) - return ret; - - ret = ixxat_usb_rcv_cmd(dev->udev, &res->dal_res, dev->ctrl_index); - if (ret < 0) - return ret; - - ret = le32_to_cpu(res->dal_res.ret_code); - if (!ret) - dev->can.state = CAN_STATE_STOPPED; - - return ret; -} - -static int ixxat_usb_power_ctrl(struct usb_device *dev, u8 mode) -{ - int ret; - u8 data[IXXAT_USB_CMD_BUFFER_SIZE] = { 0 }; - struct ixxat_usb_power_cmd *cmd = (struct ixxat_usb_power_cmd *)data; - struct ixxat_usb_power_req *req = &cmd->req; - struct ixxat_usb_power_res *res = &cmd->res; - - ixxat_usb_setup_cmd(&req->dal_req, &res->dal_res); - req->dal_req.req_size = cpu_to_le32(sizeof(*req)); - req->dal_req.req_code = cpu_to_le32(IXXAT_USB_BRD_CMD_POWER); - req->mode = mode; - - ret = ixxat_usb_send_cmd(dev, &req->dal_req); - if (ret < 0) - return ret; - - ret = ixxat_usb_rcv_cmd(dev, &res->dal_res, 0xffff); - if (ret < 0) - return ret; - - return le32_to_cpu(res->dal_res.ret_code); -} - -static int ixxat_usb_reset_ctrl(struct ixxat_usb_device *dev) -{ - int ret; - u8 data[IXXAT_USB_CMD_BUFFER_SIZE] = { 0 }; - struct ixxat_usb_dal_cmd *cmd = (struct ixxat_usb_dal_cmd *)data; - struct ixxat_usb_dal_req *req = &cmd->req; - struct ixxat_usb_dal_res *res = &cmd->res; - - ixxat_usb_setup_cmd(req, res); - req->req_code = cpu_to_le32(IXXAT_USB_CAN_CMD_RESET); - req->req_port = cpu_to_le16(dev->ctrl_index); - - ret = ixxat_usb_send_cmd(dev->udev, req); - if (ret < 0) - return ret; - - ret = ixxat_usb_rcv_cmd(dev->udev, res, dev->ctrl_index); - if (ret < 0) - return ret; - - return le32_to_cpu(res->ret_code); -} - -static void ixxat_usb_unlink_all_urbs(struct ixxat_usb_device *dev) -{ - usb_kill_anchored_urbs(&dev->rx_submitted); - usb_kill_anchored_urbs(&dev->tx_submitted); - atomic_set(&dev->active_tx_urbs, 0); -} - -static int ixxat_usb_set_mode(struct net_device *netdev, enum can_mode mode) -{ - struct ixxat_usb_device *dev = netdev_priv(netdev); - u32 time_ref; - - switch (mode) { - case CAN_MODE_START: - ixxat_usb_stop_ctrl(dev); - ixxat_usb_start_ctrl(dev, &time_ref); - break; - case CAN_MODE_STOP: - case CAN_MODE_SLEEP: - default: - return -EOPNOTSUPP; + if (ts < dev->time_ref.ts_dev_last) { + ixxat_usb_update_ts_now(dev, ts); } - return 0; -} - -static int ixxat_usb_get_berr_counter(const struct net_device *netdev, - struct can_berr_counter *bec) -{ - struct ixxat_usb_device *dev = netdev_priv(netdev); + dev->time_ref.ts_dev_last = ts; + ixxat_usb_add_us(&tv, ts - dev->time_ref.ts_dev_0); - *bec = dev->bec; - return 0; + if(k_time) + *k_time = timeval_to_ktime(tv); } -static int ixxat_usb_handle_canmsg(struct ixxat_usb_device *dev, - struct ixxat_can_msg *rx) +void ixxat_usb_update_ts_now(struct ixx_usb_device *dev, u32 hw_time_base) { - struct net_device *netdev = dev->netdev; - union can_frame_union cfu; - struct sk_buff *skb; - const u32 flags = le32_to_cpu(rx->base.flags); - const u8 dlc = IXXAT_USB_DECODE_DLC(flags); - - if (flags & IXXAT_USB_FDMSG_FLAGS_EDL) - skb = alloc_canfd_skb(netdev, &cfu.cfd); - else - skb = alloc_can_skb(netdev, &cfu.cf); + u64 timebase; - if (!skb) - return -ENOMEM; - - if (flags & IXXAT_USB_FDMSG_FLAGS_EDL) { - if (flags & IXXAT_USB_FDMSG_FLAGS_FDR) - cfu.cfd->flags |= CANFD_BRS; - - if (flags & IXXAT_USB_FDMSG_FLAGS_ESI) - cfu.cfd->flags |= CANFD_ESI; + timebase = (u64)0x00000000FFFFFFFF - (u64)dev->time_ref.ts_dev_0 + (u64)hw_time_base; - cfu.cfd->len = can_dlc2len(get_canfd_dlc(dlc)); - } else { - cfu.cf->can_dlc = get_can_dlc(dlc); - } + ixxat_usb_add_us(&dev->time_ref.tv_host_0, timebase); - if (flags & IXXAT_USB_MSG_FLAGS_OVR) { - netdev->stats.rx_over_errors++; - netdev->stats.rx_errors++; - netdev_err(netdev, "Error: Message overflow\n"); - } - - cfu.cf->can_id = le32_to_cpu(rx->base.msg_id); - - if (flags & IXXAT_USB_MSG_FLAGS_EXT) - cfu.cf->can_id |= CAN_EFF_FLAG; - - if (flags & IXXAT_USB_MSG_FLAGS_RTR) { - cfu.cf->can_id |= CAN_RTR_FLAG; - } else { - if (dev->adapter == &usb2can_cl1) - memcpy(cfu.cfd->data, rx->cl1.data, cfu.cfd->len); - else - memcpy(cfu.cfd->data, rx->cl2.data, cfu.cfd->len); - } - - ixxat_usb_get_ts_tv(dev, le32_to_cpu(rx->base.time), &skb->tstamp); - - netdev->stats.rx_packets++; - netdev->stats.rx_bytes += cfu.cfd->len; - netif_rx(skb); - - return 0; + dev->time_ref.ts_dev_0 = hw_time_base; } -static int ixxat_usb_handle_status(struct ixxat_usb_device *dev, - struct ixxat_can_msg *rx) +void ixxat_usb_set_ts_now(struct ixx_usb_device *dev, u32 hw_time_base) { - struct net_device *netdev = dev->netdev; - struct can_frame *can_frame; - struct sk_buff *skb = alloc_can_err_skb(netdev, &can_frame); - enum can_state new_state = CAN_STATE_ERROR_ACTIVE; - u32 raw_status; - - if (dev->adapter == &usb2can_cl1) - raw_status = le32_to_cpu(*(__le32 *)(rx->cl1.data)); - else - raw_status = le32_to_cpu(*(__le32 *)(rx->cl2.data)); - - if (!skb) - return -ENOMEM; - - if (raw_status == IXXAT_USB_CAN_STATUS_OK) { - dev->can.state = CAN_STATE_ERROR_ACTIVE; - can_frame->can_id |= CAN_ERR_CRTL; - can_frame->data[1] |= CAN_ERR_CRTL_ACTIVE; - } else if (raw_status & IXXAT_USB_CAN_STATUS_BUSOFF) { - can_frame->can_id |= CAN_ERR_BUSOFF; - dev->can.can_stats.bus_off++; - new_state = CAN_STATE_BUS_OFF; - can_bus_off(netdev); - } else { - if (raw_status & IXXAT_USB_CAN_STATUS_ERRLIM) { - can_frame->can_id |= CAN_ERR_CRTL; - can_frame->data[1] |= CAN_ERR_CRTL_TX_WARNING; - can_frame->data[1] |= CAN_ERR_CRTL_RX_WARNING; - dev->can.can_stats.error_warning++; - new_state = CAN_STATE_ERROR_WARNING; - } - - if (raw_status & IXXAT_USB_CAN_STATUS_ERR_PAS) { - can_frame->can_id |= CAN_ERR_CRTL; - can_frame->data[1] |= CAN_ERR_CRTL_TX_PASSIVE; - can_frame->data[1] |= CAN_ERR_CRTL_RX_PASSIVE; - dev->can.can_stats.error_passive++; - new_state = CAN_STATE_ERROR_PASSIVE; - } - - if (raw_status & IXXAT_USB_CAN_STATUS_OVERRUN) { - can_frame->can_id |= CAN_ERR_CRTL; - can_frame->data[1] |= CAN_ERR_CRTL_RX_OVERFLOW; - new_state = CAN_STATE_MAX; - } - } - - if (new_state == CAN_STATE_ERROR_ACTIVE) { - dev->bec.txerr = 0; - dev->bec.rxerr = 0; - } - - if (new_state != CAN_STATE_MAX) - dev->can.state = new_state; - - netdev->stats.rx_packets++; - netdev->stats.rx_bytes += can_frame->can_dlc; - netif_rx(skb); - - return 0; + dev->time_ref.ts_dev_0 = hw_time_base; + do_gettimeofday(&dev->time_ref.tv_host_0); + dev->time_ref.ts_dev_last = hw_time_base; } -static int ixxat_usb_handle_error(struct ixxat_usb_device *dev, - struct ixxat_can_msg *rx) +/* + * callback for bulk Rx urb + */ +static void ixxat_usb_read_bulk_callback(struct urb *urb) { - struct net_device *netdev = dev->netdev; - struct can_frame *can_frame; - struct sk_buff *skb = alloc_can_err_skb(netdev, &can_frame); - u8 raw_error; - - if (dev->adapter == &usb2can_cl1) { - raw_error = rx->cl1.data[0]; - dev->bec.rxerr = rx->cl1.data[3]; - dev->bec.txerr = rx->cl1.data[4]; - } else { - raw_error = rx->cl2.data[0]; - dev->bec.rxerr = rx->cl2.data[3]; - dev->bec.txerr = rx->cl2.data[4]; - } - - if (dev->can.state == CAN_STATE_BUS_OFF) - return 0; - - if (!skb) - return -ENOMEM; - - switch (raw_error) { - case IXXAT_USB_CAN_ERROR_ACK: - can_frame->can_id |= CAN_ERR_ACK; - netdev->stats.tx_errors++; - break; - case IXXAT_USB_CAN_ERROR_BIT: - can_frame->can_id |= CAN_ERR_PROT; - can_frame->data[2] |= CAN_ERR_PROT_BIT; - netdev->stats.rx_errors++; - break; - case IXXAT_USB_CAN_ERROR_CRC: - can_frame->can_id |= CAN_ERR_PROT; - can_frame->data[3] |= CAN_ERR_PROT_LOC_CRC_SEQ; - netdev->stats.rx_errors++; - break; - case IXXAT_USB_CAN_ERROR_FORM: - can_frame->can_id |= CAN_ERR_PROT; - can_frame->data[2] |= CAN_ERR_PROT_FORM; - netdev->stats.rx_errors++; - break; - case IXXAT_USB_CAN_ERROR_STUFF: - can_frame->can_id |= CAN_ERR_PROT; - can_frame->data[2] |= CAN_ERR_PROT_STUFF; - netdev->stats.rx_errors++; - break; - default: - can_frame->can_id |= CAN_ERR_PROT; - can_frame->data[2] |= CAN_ERR_PROT_UNSPEC; - netdev->stats.rx_errors++; - break; - } - - netdev->stats.rx_packets++; - netdev->stats.rx_bytes += can_frame->can_dlc; - netif_rx(skb); + struct ixx_usb_device *dev = urb->context; + struct net_device *netdev; + int err; - return 0; -} + netdev = dev->netdev; -static int ixxat_usb_decode_buf(struct urb *urb) -{ - struct ixxat_usb_device *dev = urb->context; - struct net_device *netdev = dev->netdev; - struct ixxat_can_msg *can_msg; - int ret = 0; - u32 msg_end = urb->actual_length; - u32 read_size = 0; - u8 *data = urb->transfer_buffer; - - while (msg_end > 0) { - u8 msg_type; - - can_msg = (struct ixxat_can_msg *)&data[read_size]; - - if (!can_msg || !can_msg->base.size) { - ret = -ENOTSUPP; - netdev_err(netdev, "Error %d: Unsupported usb msg\n", - ret); - break; - } + if (!netif_device_present(netdev)) + return; - if ((read_size + can_msg->base.size + 1) > urb->actual_length) { - ret = -EBADMSG; - netdev_err(netdev, - "Error %d: Usb rx-buffer size unknown\n", - ret); + /* check reception status */ + switch (urb->status) { + case 0: + /* success */ break; - } - msg_type = le32_to_cpu(can_msg->base.flags); - msg_type &= IXXAT_USB_MSG_FLAGS_TYPE; + case -EILSEQ: + case -ENOENT: + case -ECONNRESET: + case -ESHUTDOWN: + return; - switch (msg_type) { - case IXXAT_USB_CAN_DATA: - ret = ixxat_usb_handle_canmsg(dev, can_msg); - if (ret < 0) - goto fail; - break; - case IXXAT_USB_CAN_STATUS: - ret = ixxat_usb_handle_status(dev, can_msg); - if (ret < 0) - goto fail; - break; - case IXXAT_USB_CAN_ERROR: - ret = ixxat_usb_handle_error(dev, can_msg); - if (ret < 0) - goto fail; - break; - case IXXAT_USB_CAN_TIMEOVR: - ixxat_usb_get_ts_tv(dev, can_msg->base.time, NULL); - break; - case IXXAT_USB_CAN_INFO: - case IXXAT_USB_CAN_WAKEUP: - case IXXAT_USB_CAN_TIMERST: - break; default: - netdev_err(netdev, - "Unhandled rec type 0x%02x (%d): ignored\n", - msg_type, msg_type); - break; - } - - read_size += (can_msg->base.size + 1); - msg_end -= (can_msg->base.size + 1); + if (net_ratelimit()) + netdev_err(netdev, "Rx urb aborted (%d)\n", + urb->status); + goto resubmit_urb; } -fail: - if (ret < 0) - netdev_err(netdev, "Error %d: Buffer decoding failed\n", ret); - - return ret; -} - -static void ixxat_usb_read_bulk(struct urb *urb) -{ - struct ixxat_usb_device *dev = urb->context; - const struct ixxat_usb_adapter *adapter = dev->adapter; - struct net_device *netdev = dev->netdev; - struct usb_device *udev = dev->udev; - int ret; - - if (!netif_device_present(netdev)) - return; - - switch (urb->status) { - case 0: /* success */ - break; - case -EPROTO: - case -EILSEQ: - case -ENOENT: - case -ECONNRESET: - case -ESHUTDOWN: - return; - default: - netdev_err(netdev, "Rx urb aborted /(%d)\n", urb->status); - goto resubmit_urb; + /* protect from any incoming empty msgs */ + if ((urb->actual_length > 0) && (dev->adapter->dev_decode_buf)) { + /* handle these kinds of msgs only if _start callback called */ + if (dev->state & IXXAT_USB_STATE_STARTED) + err = dev->adapter->dev_decode_buf(dev, urb); } - if (urb->actual_length > 0) - if (dev->state & IXXAT_USB_STATE_STARTED) - ret = ixxat_usb_decode_buf(urb); +resubmit_urb: usb_fill_bulk_urb(urb, dev->udev, + usb_rcvbulkpipe(dev->udev, dev->ep_msg_in), + urb->transfer_buffer, dev->adapter->rx_buffer_size, + ixxat_usb_read_bulk_callback, dev); -resubmit_urb: - usb_fill_bulk_urb(urb, udev, usb_rcvbulkpipe(udev, dev->ep_msg_in), - urb->transfer_buffer, adapter->buffer_size_rx, - ixxat_usb_read_bulk, dev); - - usb_anchor_urb(urb, &dev->rx_submitted); - ret = usb_submit_urb(urb, GFP_ATOMIC); - if (ret == 0) - return; + usb_anchor_urb(urb, &dev->rx_submitted); + err = usb_submit_urb(urb, GFP_ATOMIC); + if (!err) + return; - usb_unanchor_urb(urb); + usb_unanchor_urb(urb); - if (ret == -ENODEV) - netif_device_detach(netdev); - else - netdev_err(netdev, - "Error %d: Failed to resubmit read bulk urb\n", ret); + if (err == -ENODEV) + netif_device_detach(netdev); + else + netdev_err(netdev, "failed resubmitting read bulk urb: %d\n", + err); } -static void ixxat_usb_write_bulk(struct urb *urb) +/* + * callback for bulk Tx urb + */ +static void ixxat_usb_write_bulk_callback(struct urb *urb) { - struct ixxat_tx_urb_context *context = urb->context; - struct ixxat_usb_device *dev; + struct ixx_tx_urb_context *context = urb->context; + struct ixx_usb_device *dev; struct net_device *netdev; - if (WARN_ON(!context)) - return; + BUG_ON(!context); dev = context->dev; netdev = dev->netdev; + atomic_dec(&dev->active_tx_urbs); if (!netif_device_present(netdev)) return; - if (!urb->status) { - netdev->stats.tx_packets += context->count; - netdev->stats.tx_bytes += context->dlc; - } else { - netdev_err(netdev, "Error %d: Tx urb aborted\n", urb->status); + /* check tx status */ + switch (urb->status) { + case 0: + /* transmission complete */ + netdev->stats.tx_packets += context->count; + netdev->stats.tx_bytes += context->dlc; + + /* prevent tx timeout */ +#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 7, 0) + netif_trans_update(netdev); +#else + netdev->trans_start = jiffies; +#endif + break; + + + case -EPROTO: + case -ENOENT: + case -ECONNRESET: + case -ESHUTDOWN: + break; + default: + if (net_ratelimit()) + netdev_err(netdev, "Tx urb aborted (%d)\n", + urb->status); + break; } + /* should always release echo skb and corresponding context */ can_get_echo_skb(netdev, context->echo_index); context->echo_index = IXXAT_USB_MAX_TX_URBS; + /* do wakeup tx queue in case of success only */ if (!urb->status) netif_wake_queue(netdev); } -static void ixxat_usb_encode_msg(struct ixxat_usb_device *dev, - struct sk_buff *skb, u8 *obuf, - size_t *size) -{ - struct canfd_frame *cf = (struct canfd_frame *)skb->data; - struct ixxat_can_msg can_msg = {0}; - struct ixxat_can_msg_base *msg_base = &can_msg.base; - - if (cf->can_id & CAN_RTR_FLAG) - msg_base->flags |= IXXAT_USB_MSG_FLAGS_RTR; - - if (cf->can_id & CAN_EFF_FLAG) { - msg_base->flags |= IXXAT_USB_MSG_FLAGS_EXT; - msg_base->msg_id = cf->can_id & CAN_EFF_MASK; - } else { - msg_base->msg_id = cf->can_id & CAN_SFF_MASK; - } - - if (can_is_canfd_skb(skb)) { - msg_base->flags |= IXXAT_USB_FDMSG_FLAGS_EDL; - - if (!(cf->can_id & CAN_RTR_FLAG) && (cf->flags & CANFD_BRS)) - msg_base->flags |= IXXAT_USB_FDMSG_FLAGS_FDR; - - msg_base->flags |= IXXAT_USB_ENCODE_DLC(can_len2dlc(cf->len)); - } else { - msg_base->flags |= IXXAT_USB_ENCODE_DLC(cf->len); - } - - le32_to_cpus(&msg_base->flags); - le32_to_cpus(&msg_base->msg_id); - - msg_base->size = (u8)(sizeof(*msg_base) - 1); - if (dev->adapter == &usb2can_cl1) { - msg_base->size += (u8)(sizeof(can_msg.cl1) - CAN_MAX_DLEN); - msg_base->size += cf->len; - memcpy(can_msg.cl1.data, cf->data, cf->len); - } else { - msg_base->size += (u8)(sizeof(can_msg.cl2) - CANFD_MAX_DLEN); - msg_base->size += cf->len; - memcpy(can_msg.cl2.data, cf->data, cf->len); - } - - *size = msg_base->size + 1; - memcpy(obuf, &can_msg, *size); - skb->data_len = *size; -} - -static netdev_tx_t ixxat_usb_start_xmit(struct sk_buff *skb, - struct net_device *netdev) +/* + * called by netdev to send one skb on the CAN interface. + */ +static netdev_tx_t ixxat_usb_ndo_start_xmit(struct sk_buff *skb, + struct net_device *netdev) { - struct ixxat_usb_device *dev = netdev_priv(netdev); - struct ixxat_tx_urb_context *context = NULL; + struct ixx_usb_device *dev = netdev_priv(netdev); + struct ixx_tx_urb_context *context = NULL; struct net_device_stats *stats = &netdev->stats; - struct canfd_frame *cf = (struct canfd_frame *)skb->data; + struct canfd_frame *cf = (struct canfd_frame *) skb->data; struct urb *urb; u8 *obuf; - int i; - int ret; - size_t size = dev->adapter->buffer_size_tx; + int i, err; + size_t size = dev->adapter->tx_buffer_size; if (can_dropped_invalid_skb(netdev, skb)) return NETDEV_TX_OK; @@ -793,39 +284,68 @@ } } - if (WARN_ON_ONCE(!context)) + if (!context) { + /* should not occur except during restart */ return NETDEV_TX_BUSY; + } urb = context->urb; obuf = urb->transfer_buffer; - ixxat_usb_encode_msg(dev, skb, obuf, &size); + err = dev->adapter->dev_encode_msg(dev, skb, obuf, &size); context->echo_index = i; context->dlc = cf->len; context->count = 1; urb->transfer_buffer_length = size; + + if (err) { + if (net_ratelimit()) + netdev_err(netdev, "packet dropped\n"); + dev_kfree_skb(skb); + stats->tx_dropped++; + return NETDEV_TX_OK; + } + usb_anchor_urb(urb, &dev->tx_submitted); + can_put_echo_skb(skb, netdev, context->echo_index); + atomic_inc(&dev->active_tx_urbs); - ret = usb_submit_urb(urb, GFP_ATOMIC); - if (unlikely(ret)) { + err = usb_submit_urb(urb, GFP_ATOMIC); + if (err) { can_free_echo_skb(netdev, context->echo_index); + usb_unanchor_urb(urb); - atomic_dec(&dev->active_tx_urbs); + /* this context is not used in fact */ context->echo_index = IXXAT_USB_MAX_TX_URBS; - if (ret == -ENODEV) { - netif_device_detach(netdev); - } else { - stats->tx_dropped++; - netdev_err(netdev, - "Error %d: Submitting tx-urb failed\n", ret); + atomic_dec(&dev->active_tx_urbs); + + switch (err) { + case -ENODEV: + netif_device_detach(netdev); + break; + case -ENOENT: + /* cable unplugged */ + stats->tx_dropped++; + break; + default: + stats->tx_dropped++; + netdev_warn(netdev, "tx urb submitting failed err=%d\n", + err); } } else { +#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 7, 0) + netif_trans_update(netdev); +#else + netdev->trans_start = jiffies; +#endif + + /* slow down tx path */ if (atomic_read(&dev->active_tx_urbs) >= IXXAT_USB_MAX_TX_URBS) netif_stop_queue(netdev); } @@ -833,91 +353,86 @@ return NETDEV_TX_OK; } -static int ixxat_usb_setup_rx_urbs(struct ixxat_usb_device *dev) +/* + * start the CAN interface. + * Rx and Tx urbs are allocated here. Rx urbs are submitted here. + */ +static int ixxat_usb_start(struct ixx_usb_device *dev) { - int i; - int ret = 0; - const struct ixxat_usb_adapter *adapter = dev->adapter; struct net_device *netdev = dev->netdev; - struct usb_device *udev = dev->udev; + int err, i; for (i = 0; i < IXXAT_USB_MAX_RX_URBS; i++) { struct urb *urb; u8 *buf; + /* create a URB, and a buffer for it, to receive usb messages */ urb = usb_alloc_urb(0, GFP_KERNEL); if (!urb) { - ret = -ENOMEM; - netdev_err(netdev, "Error %d: No memory for URBs\n", - ret); + netdev_err(netdev, "No memory left for URBs\n"); + err = -ENOMEM; break; } - buf = kmalloc(adapter->buffer_size_rx, GFP_KERNEL); + buf = kmalloc(dev->adapter->rx_buffer_size, GFP_KERNEL); if (!buf) { usb_free_urb(urb); - ret = -ENOMEM; - netdev_err(netdev, - "Error %d: No memory for USB-buffer\n", ret); + err = -ENOMEM; break; } - usb_fill_bulk_urb(urb, udev, - usb_rcvbulkpipe(udev, dev->ep_msg_in), buf, - adapter->buffer_size_rx, ixxat_usb_read_bulk, - dev); + usb_fill_bulk_urb(urb, dev->udev, + usb_rcvbulkpipe(dev->udev, dev->ep_msg_in), buf, + dev->adapter->rx_buffer_size, + ixxat_usb_read_bulk_callback, dev); + /* ask last usb_free_urb() to also kfree() transfer_buffer */ urb->transfer_flags |= URB_FREE_BUFFER; usb_anchor_urb(urb, &dev->rx_submitted); - ret = usb_submit_urb(urb, GFP_KERNEL); - if (ret < 0) { + err = usb_submit_urb(urb, GFP_KERNEL); + if (err) { + if (err == -ENODEV) + netif_device_detach(dev->netdev); + usb_unanchor_urb(urb); kfree(buf); usb_free_urb(urb); - - if (ret == -ENODEV) - netif_device_detach(netdev); - break; } + /* drop reference, USB core will take care of freeing it */ usb_free_urb(urb); } - if (i == 0) - netdev_err(netdev, "Error: Couldn't setup any rx-URBs\n"); - - return ret; -} + /* did we submit any URBs? Warn if we was not able to submit all urbs */ + if (i < IXXAT_USB_MAX_RX_URBS) { + if (i == 0) { + netdev_err(netdev, "couldn't setup any rx URB\n"); + return err; + } -static int ixxat_usb_setup_tx_urbs(struct ixxat_usb_device *dev) -{ - int i; - int ret = 0; - const struct ixxat_usb_adapter *adapter = dev->adapter; - struct net_device *netdev = dev->netdev; - struct usb_device *udev = dev->udev; + netdev_warn(netdev, "rx performance may be slow\n"); + } + /* pre-alloc tx buffers and corresponding urbs */ for (i = 0; i < IXXAT_USB_MAX_TX_URBS; i++) { - struct ixxat_tx_urb_context *context; - struct urb *urb = NULL; - u8 *buf = NULL; + struct ixx_tx_urb_context *context; + struct urb *urb; + u8 *buf; + /* create a URB and a buffer for it, to transmit usb messages */ urb = usb_alloc_urb(0, GFP_KERNEL); if (!urb) { - ret = -ENOMEM; - netdev_err(netdev, "Error %d: No memory for URBs\n", - ret); + netdev_err(netdev, "No memory left for URBs\n"); + err = -ENOMEM; break; } - buf = kmalloc(adapter->buffer_size_tx, GFP_KERNEL); + buf = kmalloc(dev->adapter->tx_buffer_size, GFP_KERNEL); if (!buf) { usb_free_urb(urb); - ret = -ENOMEM; - netdev_err(netdev, - "Error %d: No memory for USB-buffer\n", ret); + err = -ENOMEM; break; } @@ -925,111 +440,70 @@ context->dev = dev; context->urb = urb; - usb_fill_bulk_urb(urb, udev, - usb_sndbulkpipe(udev, dev->ep_msg_out), buf, - adapter->buffer_size_tx, ixxat_usb_write_bulk, - context); + usb_fill_bulk_urb(urb, dev->udev, + usb_sndbulkpipe(dev->udev, dev->ep_msg_out), + buf, dev->adapter->tx_buffer_size, + ixxat_usb_write_bulk_callback, context); + /* ask last usb_free_urb() to also kfree() transfer_buffer */ urb->transfer_flags |= URB_FREE_BUFFER; } - if (i == 0) { - netdev_err(netdev, "Error: Couldn't setup any tx-URBs\n"); - usb_kill_anchored_urbs(&dev->rx_submitted); - } - - return ret; -} - -static void ixxat_usb_disconnect(struct usb_interface *intf) -{ - struct ixxat_usb_device *dev; - struct ixxat_usb_device *prev_dev; - - /* unregister the given device and all previous devices */ - for (dev = usb_get_intfdata(intf); dev; dev = prev_dev) { - prev_dev = dev->prev_dev; - unregister_netdev(dev->netdev); - free_candev(dev->netdev); - } - - usb_set_intfdata(intf, NULL); -} - -static int ixxat_usb_start(struct ixxat_usb_device *dev) -{ - int ret; - int i; - u32 time_ref = 0; - const struct ixxat_usb_adapter *adapter = dev->adapter; - - ret = ixxat_usb_setup_rx_urbs(dev); - if (ret < 0) - return ret; - - ret = ixxat_usb_setup_tx_urbs(dev); - if (ret < 0) - return ret; - - /* Try to reset the controller, in case it is already initialized - * from a previous unclean shutdown - */ - ixxat_usb_reset_ctrl(dev); + /* warn if we were not able to allocate enough tx contexts */ + if (i < IXXAT_USB_MAX_TX_URBS) { + if (i == 0) { + netdev_err(netdev, "couldn't setup any tx URB\n"); + goto err_tx; + } - if (adapter->init_ctrl) { - ret = adapter->init_ctrl(dev); - if (ret < 0) - goto fail; + netdev_warn(netdev, "tx performance may be slow\n"); } - if (dev->ctrl_opened_count == 0) { - ret = ixxat_usb_start_ctrl(dev, &time_ref); - if (ret < 0) - goto fail; - - ixxat_usb_set_ts_now(dev, time_ref); + if (dev->adapter->dev_start) { + err = dev->adapter->dev_start(dev); + if (err) + goto err_adapter; } - dev->ctrl_opened_count++; - - dev->bec.txerr = 0; - dev->bec.rxerr = 0; - dev->state |= IXXAT_USB_STATE_STARTED; + dev->can.state = CAN_STATE_ERROR_ACTIVE; return 0; -fail: - if (ret == -ENODEV) - netif_device_detach(dev->netdev); +err_adapter: if (err == -ENODEV) + netif_device_detach(dev->netdev); - netdev_err(dev->netdev, "Error %d: Couldn't submit control\n", ret); + netdev_warn(netdev, "couldn't submit control: %d\n", err); - for (i = 0; i < IXXAT_USB_MAX_TX_URBS; i++) { - usb_free_urb(dev->tx_contexts[i].urb); - dev->tx_contexts[i].urb = NULL; - } + for (i = 0; i < IXXAT_USB_MAX_TX_URBS; i++) { + usb_free_urb(dev->tx_contexts[i].urb); + dev->tx_contexts[i].urb = NULL; + } +err_tx: usb_kill_anchored_urbs(&dev->rx_submitted); - return ret; + return err; } -static int ixxat_usb_open(struct net_device *netdev) +/* + * called by netdev to open the corresponding CAN interface. + */ +static int ixxat_usb_ndo_open(struct net_device *netdev) { - struct ixxat_usb_device *dev = netdev_priv(netdev); - int ret; + struct ixx_usb_device *dev = netdev_priv(netdev); + int err; /* common open */ - ret = open_candev(netdev); - if (ret < 0) - return ret; + err = open_candev(netdev); + if (err) + return err; /* finally start device */ - ret = ixxat_usb_start(dev); - if (ret < 0) { - netdev_err(netdev, "Error %d: Couldn't start device.\n", ret); + err = ixxat_usb_start(dev); + if (err) { + netdev_err(netdev, "couldn't start device: %d\n", err); close_candev(netdev); - return ret; + return err; } netif_start_queue(netdev); @@ -1037,20 +511,54 @@ return 0; } -static int ixxat_usb_stop(struct net_device *netdev) +/* + * unlink in-flight Rx and Tx urbs and free their memory. + */ +static void ixxat_usb_unlink_all_urbs(struct ixx_usb_device *dev) { - int ret = 0; - struct ixxat_usb_device *dev = netdev_priv(netdev); + int i; + + /* free all Rx (submitted) urbs */ + usb_kill_anchored_urbs(&dev->rx_submitted); + + /* free unsubmitted Tx urbs first */ + for (i = 0; i < IXXAT_USB_MAX_TX_URBS; i++) { + struct urb *urb = dev->tx_contexts[i].urb; + + if (!urb + || dev->tx_contexts[i].echo_index + != IXXAT_USB_MAX_TX_URBS) { + /* + * this urb is already released or always submitted, + * let usb core free by itself + */ + continue; + } + + usb_free_urb(urb); + dev->tx_contexts[i].urb = NULL; + } + /* then free all submitted Tx urbs */ + usb_kill_anchored_urbs(&dev->tx_submitted); + atomic_set(&dev->active_tx_urbs, 0); +} + +/* + * called by netdev to close the corresponding CAN interface. + */ +static int ixxat_usb_ndo_stop(struct net_device *netdev) +{ + struct ixx_usb_device *dev = netdev_priv(netdev); + + dev->state &= ~IXXAT_USB_STATE_STARTED; netif_stop_queue(netdev); + + /* unlink all pending urbs and free used memory */ ixxat_usb_unlink_all_urbs(dev); - if (dev->ctrl_opened_count == 1) { - ret = ixxat_usb_stop_ctrl(dev); - if (ret < 0) - return ret; - } - dev->ctrl_opened_count--; + if (dev->adapter->dev_stop) + dev->adapter->dev_stop(dev); close_candev(netdev); @@ -1062,190 +570,354 @@ -static const struct net_device_ops ixxat_usb_netdev_ops = { - .ndo_open = ixxat_usb_open, - .ndo_stop = ixxat_usb_stop, - .ndo_start_xmit = ixxat_usb_start_xmit -}; +/* + * handle end of waiting for the device to reset + */ +void ixxat_usb_restart_complete(struct ixx_usb_device *dev) +{ + /* finally MUST update can state */ + dev->can.state = CAN_STATE_ERROR_ACTIVE; -static const struct ixxat_usb_adapter *ixxat_usb_get_adapter(const u16 id) + /* netdev queue can be awaken now */ + netif_wake_queue(dev->netdev); +} + +void ixxat_usb_async_complete(struct urb *urb) { - switch (id) { - case USB2CAN_COMPACT_PRODUCT_ID: - case USB2CAN_EMBEDDED_PRODUCT_ID: - case USB2CAN_PROFESSIONAL_PRODUCT_ID: - case USB2CAN_AUTOMOTIVE_PRODUCT_ID: - return &usb2can_cl1; - case USB2CAN_FD_COMPACT_PRODUCT_ID: - case USB2CAN_FD_PROFESSIONAL_PRODUCT_ID: - case USB2CAN_FD_AUTOMOTIVE_PRODUCT_ID: - case USB2CAN_FD_PCIE_MINI_PRODUCT_ID: - case USB2CAR_PRODUCT_ID: - return &usb2can_cl2; - case CAN_IDM100_PRODUCT_ID: - return &can_idm100; - case CAN_IDM101_PRODUCT_ID: - return &can_idm101; - default: - return NULL; + kfree(urb->transfer_buffer); + usb_free_urb(urb); +} + +/* + * candev callback used to change CAN mode. + * Warning: this is called from a timer context! + */ +static int ixxat_usb_set_mode(struct net_device *netdev, enum can_mode mode) +{ + struct ixx_usb_device *dev = netdev_priv(netdev); + int err = 0; + + switch (mode) { + case CAN_MODE_START: + dev->restart_flag = 1; + wake_up_interruptible(&dev->wait_queue); + break; + default: + return -EOPNOTSUPP; } + + return err; } -static int ixxat_usb_create_dev(struct usb_interface *intf, - const struct ixxat_usb_adapter *adapter, - u16 ctrl_index) +/* + * candev callback used to set device bitrate. + */ +static int ixxat_usb_set_bittiming(struct net_device *netdev) +{ + struct ixx_usb_device* dev = (struct ixx_usb_device*) netdev_priv( + netdev); + struct can_bittiming *bt = &dev->can.bittiming; + + if (dev->adapter->dev_set_bittiming) { + int err = dev->adapter->dev_set_bittiming(dev, bt); + + if (err) + netdev_info(netdev, "couldn't set bitrate (err %d)\n", + err); + return err; + } + + return 0; +} + +/* + * candev callback used to set error counters. + */ +static int ixxat_usb_get_berr_counter(const struct net_device *netdev, + struct can_berr_counter *bec) +{ + struct ixx_usb_device* dev = (struct ixx_usb_device*) netdev_priv( + netdev); + + *bec = dev->bec; + + return 0; +} + +static const struct net_device_ops ixx_usb_netdev_ops = { .ndo_open = + ixxat_usb_ndo_open, .ndo_stop = ixxat_usb_ndo_stop, + .ndo_start_xmit = ixxat_usb_ndo_start_xmit, +#ifdef CANFD_CAPABLE + .ndo_change_mtu = can_change_mtu, +#endif +}; + +/* + * create one device which is attached to CAN controller #ctrl_idx of the + * usb adapter. + */ +static int ixxat_usb_create_dev(struct ixx_usb_adapter *ixx_usb_adapter, + struct usb_interface *intf, int ctrl_idx) { struct usb_device *usb_dev = interface_to_usbdev(intf); - struct ixxat_usb_device *dev; + int sizeof_candev = ixx_usb_adapter->sizeof_dev_private; + struct ixx_usb_device *dev; struct net_device *netdev; - int ret; - int i; + int i, err = 0, ep_off = 0; + u16 tmp16; + + if (sizeof_candev < sizeof(struct ixx_usb_device)) + sizeof_candev = sizeof(struct ixx_usb_device); - netdev = alloc_candev(sizeof(*dev), IXXAT_USB_MAX_TX_URBS); + netdev = alloc_candev(sizeof_candev, IXXAT_USB_MAX_TX_URBS); if (!netdev) { - dev_err(&intf->dev, "Cannot allocate candev\n"); + dev_err(&intf->dev, "%s: couldn't alloc candev\n", + IXXAT_USB_DRIVER_NAME); return -ENOMEM; } dev = netdev_priv(netdev); + dev->transmit_ptr = 0; + dev->transmit_dlc = 0; + dev->transmit_count = 0; + + dev->restart_flag = 0; + dev->restart_task = 0; + dev->must_quit = 0; + init_waitqueue_head(&dev->wait_queue); + dev->ctrl_opened_count = 0; + dev->udev = usb_dev; dev->netdev = netdev; - dev->adapter = adapter; - dev->ctrl_index = ctrl_index; + dev->adapter = ixx_usb_adapter; + dev->ctrl_idx = ctrl_idx; dev->state = IXXAT_USB_STATE_CONNECTED; - i = ctrl_index + adapter->ep_offs; - dev->ep_msg_in = adapter->ep_msg_in[i]; - dev->ep_msg_out = adapter->ep_msg_out[i]; - - dev->can.clock.freq = adapter->clock; - dev->can.bittiming_const = adapter->bt; - dev->can.data_bittiming_const = adapter->btd; + ep_off = ixx_usb_adapter->has_bgi_ep ? 1 : 0; + + /* Add +1 because of the bgi endpoint */ + dev->ep_msg_in = ixx_usb_adapter->ep_msg_in[ctrl_idx+ep_off]; + dev->ep_msg_out = ixx_usb_adapter->ep_msg_out[ctrl_idx+ep_off]; + + dev->can.clock = ixx_usb_adapter->clock; + dev->can.bittiming_const = &ixx_usb_adapter->bittiming_const; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 19, 3) + dev->can.data_bittiming_const = &ixx_usb_adapter->data_bittiming_const; +#endif + dev->can.do_set_bittiming = ixxat_usb_set_bittiming; dev->can.do_set_mode = ixxat_usb_set_mode; dev->can.do_get_berr_counter = ixxat_usb_get_berr_counter; - dev->can.ctrlmode_supported = adapter->modes; + dev->can.ctrlmode_supported = ixx_usb_adapter->ctrlmode_supported; - netdev->netdev_ops = &ixxat_usb_netdev_ops; + netdev->netdev_ops = &ixx_usb_netdev_ops; - netdev->flags |= IFF_ECHO; + netdev->flags |= IFF_ECHO; /* we support local echo */ init_usb_anchor(&dev->rx_submitted); - init_usb_anchor(&dev->tx_submitted); + init_usb_anchor(&dev->tx_submitted); atomic_set(&dev->active_tx_urbs, 0); for (i = 0; i < IXXAT_USB_MAX_TX_URBS; i++) dev->tx_contexts[i].echo_index = IXXAT_USB_MAX_TX_URBS; - dev->prev_dev = usb_get_intfdata(intf); + dev->prev_siblings = usb_get_intfdata(intf); usb_set_intfdata(intf, dev); SET_NETDEV_DEV(netdev, &intf->dev); - ret = register_candev(netdev); - if (ret < 0) { - dev_err(&intf->dev, "Error %d: Failed to register can device\n", - ret); - goto free_candev; - } - - if (dev->prev_dev) - (dev->prev_dev)->next_dev = dev; - - ret = ixxat_usb_get_dev_info(dev, &dev->dev_info); - if (ret < 0) { - dev_err(&intf->dev, - "Error %d: Failed to get device information\n", ret); - goto unreg_candev; - } - - netdev_info(netdev, "%s: Connected Channel %u (device %s)\n", - dev->dev_info.device_name, ctrl_index, - dev->dev_info.device_id); + + err = register_candev(netdev); + if (err) { + dev_err(&intf->dev, "couldn't register CAN device: %d\n", err); + goto lbl_set_intf_data; + } + + if (dev->prev_siblings) + (dev->prev_siblings)->next_siblings = dev; + + /* keep hw revision into the netdevice */ + tmp16 = le16_to_cpu(usb_dev->descriptor.bcdDevice); + dev->device_rev = tmp16 >> 8; + + if (dev->adapter->dev_init) { + err = dev->adapter->dev_init(dev); + if (err) + goto lbl_set_intf_data; + } + + if (dev->adapter->intf_get_info) + dev->adapter->intf_get_info(dev, + &dev->dev_info); + + netdev_info(netdev, "attached to %s channel %u (device %s)\n", + dev->dev_info.device_name, ctrl_idx, + dev->dev_info.device_id); return 0; -unreg_candev: - unregister_candev(netdev); -free_candev: - usb_set_intfdata(intf, dev->prev_dev); - free_candev(netdev); - return ret; +lbl_set_intf_data: usb_set_intfdata(intf, dev->prev_siblings); + free_candev(netdev); + + return err; } -static int ixxat_usb_probe(struct usb_interface *intf, - const struct usb_device_id *id) +/* + * called by the usb core when the device is unplugged from the system + */ +static void ixxat_usb_disconnect(struct usb_interface *intf) { - struct usb_device *udev = interface_to_usbdev(intf); - struct usb_host_interface *host_intf = intf->altsetting; - const struct ixxat_usb_adapter *adapter; - struct ixxat_dev_caps dev_caps; - u16 i; - int ret; - - usb_reset_configuration(udev); - - adapter = ixxat_usb_get_adapter(id->idProduct); - if (!adapter) { - dev_err(&intf->dev, "%s: Unknown device id %d\n", - IXXAT_USB_DRIVER_NAME, id->idProduct); - return -ENODEV; - } - - for (i = 0; i < host_intf->desc.bNumEndpoints; i++) { - const u8 epaddr = host_intf->endpoint[i].desc.bEndpointAddress; - int match; - u8 j; - - /* Check if usb-endpoint address matches known usb-endpoints */ - for (j = 0; j < IXXAT_USB_MAX_CHANNEL; j++) { - u8 ep_msg_in = adapter->ep_msg_in[j]; - u8 ep_msg_out = adapter->ep_msg_in[j]; + struct ixx_usb_device *dev; + struct ixx_usb_device *dev_prev_siblings; - if (epaddr == ep_msg_in || epaddr == ep_msg_out) { - match = 1; - break; - } - } + /* unregister as many netdev devices as siblings */ + for (dev = usb_get_intfdata(intf); dev; dev = dev_prev_siblings) { + struct net_device *netdev = dev->netdev; + char name[IFNAMSIZ]; + + dev_prev_siblings = dev->prev_siblings; + dev->state &= ~IXXAT_USB_STATE_CONNECTED; + strncpy(name, netdev->name, IFNAMSIZ); + + unregister_netdev(netdev); + + dev->next_siblings = NULL; + if (dev->adapter->dev_free) + dev->adapter->dev_free(dev); - if (!match) - return -ENODEV; + free_candev(netdev); + dev_dbg(&intf->dev, "%s removed\n", name); } - ret = ixxat_usb_power_ctrl(udev, IXXAT_USB_POWER_WAKEUP); - if (ret < 0) - return ret; + usb_set_intfdata(intf, NULL); +} + +/* + * probe function for new ixxat-usb devices + */ +static int ixxat_usb_probe(struct usb_interface *intf, + const struct usb_device_id *id) +{ + struct usb_device *usb_dev = interface_to_usbdev(intf); + struct ixx_usb_adapter *ixx_usb_adapter, **pp; + int i, err = -ENOMEM; + struct ixx_dev_caps dev_caps; - msleep(IXXAT_USB_POWER_WAKEUP_TIME); + usb_dev = interface_to_usbdev(intf); - ret = ixxat_usb_get_dev_caps(udev, &dev_caps); - if (ret < 0) { - dev_err(&intf->dev, "Failed to get device capabilities\n"); - return ret; - } + usb_reset_configuration(usb_dev); - ret = -ENODEV; - for (i = 0; i < dev_caps.bus_ctrl_count; i++) { - u8 bustype = IXXAT_USB_BUS_TYPE(dev_caps.bus_ctrl_types[i]); + /* get corresponding IXX-USB adapter */ + for (pp = ixx_usb_adapters_list; *pp; pp++) + if ((*pp)->device_id == le16_to_cpu(usb_dev->descriptor.idProduct)) + break; - if (bustype == IXXAT_USB_BUS_CAN) - ret = ixxat_usb_create_dev(intf, adapter, i); + ixx_usb_adapter = *pp; + if (!ixx_usb_adapter) { + /* should never come except device_id bad usage in this file */ + pr_err("%s: didn't find device id. 0x%x in devices list\n", + IXXAT_USB_DRIVER_NAME, le16_to_cpu(usb_dev->descriptor.idProduct)); + return -ENODEV; + } - if (ret < 0) { - /* deregister already created devices */ - ixxat_usb_disconnect(intf); - return ret; + /* got corresponding adapter: check if it handles current interface */ + if (ixx_usb_adapter->intf_probe) { + err = ixx_usb_adapter->intf_probe(intf); + if (err) + return err; + } + + if (ixx_usb_adapter->dev_power) { + err = ixx_usb_adapter->dev_power(usb_dev, IXXAT_USB_POWER_WAKEUP); + if (err) + return err; + + /* Give usb device some time to start its can controllers */ + msleep(500); + } + + /* got corresponding adapter: check the available controllers */ + if (ixx_usb_adapter->dev_get_dev_caps) { + err = ixx_usb_adapter->dev_get_dev_caps(usb_dev, &dev_caps); + if (err) + return err; + + for (i = 0; i < dev_caps.bus_ctrl_count; i++) { + if ( IXXAT_USB_BUS_CAN + == IXXAT_USB_BUS_TYPE(dev_caps.bus_ctrl_types[i])) + ixx_usb_adapter->ctrl_count++; + } + + for (i = 0; i < dev_caps.bus_ctrl_count; i++) { + if ( IXXAT_USB_BUS_CAN == IXXAT_USB_BUS_TYPE(dev_caps.bus_ctrl_types[i])) + err = ixxat_usb_create_dev(ixx_usb_adapter, intf, i); + if (err) { + /* deregister already created devices */ + ixxat_usb_disconnect(intf); + break; + } } } - return ret; + return err; } -static struct usb_driver ixxat_usb_driver = { +/* usb specific object needed to register this driver with the usb subsystem */ +static struct usb_driver ixx_usb_driver = { .name = IXXAT_USB_DRIVER_NAME, - .probe = ixxat_usb_probe, .disconnect = ixxat_usb_disconnect, + .probe = ixxat_usb_probe, .id_table = ixxat_usb_table, }; -module_usb_driver(ixxat_usb_driver); +static int __init ixx_usb_init(void) +{ + int err; + + /* register this driver with the USB subsystem */ + err = usb_register(&ixx_usb_driver); + if (err) + pr_err("%s: usb_register failed (err %d)\n", + IXXAT_USB_DRIVER_NAME, err); + + return err; +} + +static int ixxat_usb_do_device_exit(struct device *d, void *arg) +{ + struct usb_interface + *intf = (struct usb_interface*)to_usb_interface(d); + struct ixx_usb_device *dev; + + /* stop as many netdev devices as siblings */ + for (dev = usb_get_intfdata(intf); dev; dev = dev->prev_siblings) { + struct net_device *netdev = dev->netdev; + + if (netif_device_present(netdev)) + if (dev->adapter->dev_exit) + dev->adapter->dev_exit(dev); + } + + return 0; +} + +static void __exit ixx_usb_exit(void) +{ + int err; + + /* last chance do send any synchronous commands here */ + err = driver_for_each_device(&ixx_usb_driver.drvwrap.driver, NULL, + NULL, ixxat_usb_do_device_exit); + if (err) + pr_err("%s: failed to stop all can devices (err %d)\n", + IXXAT_USB_DRIVER_NAME, err); + + /* deregister this driver with the USB subsystem */ + usb_deregister(&ixx_usb_driver); + + pr_info("%s: IXX-USB interfaces driver unloaded\n", + IXXAT_USB_DRIVER_NAME); +} + +module_init(ixx_usb_init); +module_exit(ixx_usb_exit); diff -u linux-lts-xenial-4.4.0/ubuntu/ixxat/ixx_usb_core.h linux-lts-xenial-4.4.0/ubuntu/ixxat/ixx_usb_core.h --- linux-lts-xenial-4.4.0/ubuntu/ixxat/ixx_usb_core.h +++ linux-lts-xenial-4.4.0/ubuntu/ixxat/ixx_usb_core.h @@ -1,8 +1,9 @@ -/* SPDX-License-Identifier: GPL-2.0 */ - -/* CAN driver base for IXXAT USB-to-CAN +/* + * CAN driver for IXXAT USB-to-CAN V2 adapters + * + * Copyright (C) 2003-2014 Michael Hengler IXXAT Automation GmbH * - * Copyright (C) 2018 HMS Industrial Networks + * Based on code originally by pcan_usb_core * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published @@ -16,645 +17,273 @@ +#ifndef IXX_USB_CORE_H +#define IXX_USB_CORE_H -#ifndef IXXAT_USB_CORE_H -#define IXXAT_USB_CORE_H +#include -#define IXXAT_USB_DRIVER_NAME "ixx_usb" +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 19, 3) +#define CANFD_CAPABLE 1 +#endif + +extern struct ixx_usb_adapter usb_to_can_v2_compact; +extern struct ixx_usb_adapter usb_to_can_v2_automotive; +extern struct ixx_usb_adapter usb_to_can_v2_embedded; +extern struct ixx_usb_adapter usb_to_can_v2_professional; +extern struct ixx_usb_adapter usb_to_can_v2_low_speed; +extern struct ixx_usb_adapter usb_to_can_v2_extended; + +#ifdef CANFD_CAPABLE +extern struct ixx_usb_adapter usb_to_can_fd_automotive; +extern struct ixx_usb_adapter usb_to_can_fd_compact; +extern struct ixx_usb_adapter usb_to_can_fd_professional; +extern struct ixx_usb_adapter usb_to_can_fd_pcie_mini; +extern struct ixx_usb_adapter usb_to_car; +extern struct ixx_usb_adapter dell_edge_gw3002; +#endif + +#ifndef CAN_MAX_DLEN +#define CAN_MAX_DLEN 8 +#endif + +#ifndef CANFD_MAX_DLEN +#define CANFD_MAX_DLEN 64 +#endif + + +/* supported device ids. */ +#define USB_TO_CAN_V2_COMPACT_PRODUCT_ID 0x0008 +#define USB_TO_CAN_V2_EMBEDDED_PRODUCT_ID 0x0009 +#define USB_TO_CAN_V2_PROFESSIONAL_PRODUCT_ID 0x000A +#define USB_TO_CAN_V2_AUTOMOTIVE_PRODUCT_ID 0x000B +#define USB_TO_LIN_V2_PRODUCT_ID 0x000C +#define USB_TO_KLINE_V2_PRODUCT_ID 0x000D +#define USB_TO_CAN_V2_LOW_SPEED_PRODUCT_ID 0xFFFF +#define USB_TO_CAN_V2_EXTENDED_PRODUCT_ID 0x000E + +#define USB_TO_CAN_FD_COMPACT_PRODUCT_ID 0x0014 +#define USB_TO_CAN_FD_PROFESSIONAL_PRODUCT_ID 0x0016 +#define USB_TO_CAN_FD_AUTOMOTIVE_PRODUCT_ID 0x0017 +#define USB_TO_CAN_FD_PCIE_MINI_PRODUCT_ID 0x001B +#define USB_TO_CAR_ID 0x001C +#define DELL_EDGE_GW3002_PRODUCT_ID 0xFF11 + +#define IXXAT_USB_MAX_CHANNEL 5 + +/* number of urbs that are submitted for rx/tx per channel */ +#define IXXAT_USB_MAX_RX_URBS 4 +#define IXXAT_USB_MAX_TX_URBS 10 + +#define IXX_BTMODE_NAT 0x01 + +#define IXXAT_USB_POWER_WAKEUP 0 +#define IXXAT_USB_POWER_SLEEP 1 + +struct ixx_usb_device; + +struct ixx_dev_caps +{ + u16 bus_ctrl_count; + u16 bus_ctrl_types[32]; +} __packed; + +struct ixx_ctrl_caps +{ + u16 ctrl_type; + u16 bus_coupling; + u32 features; + u32 clock_freq; + u32 tsc_divisor; + u32 cms_divisor; + u32 cms_max_ticks; + u32 dtx_divisor; + u32 dtx_max_ticks; +} __packed; + +struct canbtp +{ + u32 mode; // timing mode (see CAN_BTMODE_ const) + u32 bps; // bits per second or prescaler (see CAN_BTMODE_) + u16 ts1; // length of time segment 1 in quantas + u16 ts2; // length of time segment 2 in quantas + u16 sjw; // re-synchronisation jump width in quantas + u16 tdo; // transceiver delay compensation offset in quantas + // (0 = disabled) +} __packed; + +struct ixx_ctrl_caps_v2 +{ + u16 ctrl_type; + u16 bus_coupling; + u32 features; + + u32 clock_freq; + struct canbtp sdr_range_min; + struct canbtp sdr_range_max; + struct canbtp fdr_range_min; + struct canbtp fdr_range_max; + + u32 tsc_freq; + u32 tsc_divisor; + + u32 cms_freq; + u32 cms_divisor; + u32 cms_max_ticks; + + u32 dtx_freq; + u32 dtx_divisor; + u32 dtx_max_ticks; +} __packed; + +struct ixx_intf_info +{ + char device_name[16]; // device name + char device_id[16]; // device identification ( unique device id) + u16 device_version; // device version ( 0, 1, ...) + u32 device_fpga_version; // device version of FPGA design +} __packed; + +struct ixx_intf_fw_info +{ + u32 firmware_type; // type of currently running firmware + u16 reserved; // reserved + u16 major_version; // major firmware version number + u16 minor_version; // minor firmware version number + u16 build_version; // build firmware version number +} __packed; + +struct ixx_usb_adapter { + char *name; + u32 device_id; + struct can_clock clock; + const struct can_bittiming_const bittiming_const; + const struct can_bittiming_const data_bittiming_const; + + unsigned int ctrl_count; + + u32 ctrlmode_supported; + + int (*intf_probe)(struct usb_interface *intf); + + int (*dev_get_dev_caps)(struct usb_device *usb_dev, struct ixx_dev_caps* dev_caps); + int (*dev_get_ctrl_caps)(struct usb_device *usb_dev, struct ixx_ctrl_caps* ctrl_caps, int index); + + int (*intf_get_info)(struct ixx_usb_device *dev, struct ixx_intf_info* intf_info); + int (*intf_get_fw_info)(struct ixx_usb_device *dev, struct ixx_intf_fw_info* fw_info); + + int (*dev_init)(struct ixx_usb_device *dev); + void (*dev_exit)(struct ixx_usb_device *dev); + void (*dev_free)(struct ixx_usb_device *dev); + int (*dev_open)(struct ixx_usb_device *dev); + int (*dev_close)(struct ixx_usb_device *dev); + int (*dev_set_bittiming)(struct ixx_usb_device *dev, struct can_bittiming *bt); + int (*dev_set_bus)(struct ixx_usb_device *dev, u8 onoff); + int (*dev_decode_buf)(struct ixx_usb_device *dev, struct urb *urb); + int (*dev_encode_msg)(struct ixx_usb_device *dev, struct sk_buff *skb, + u8 *obuf, size_t *size); + int (*dev_start)(struct ixx_usb_device *dev); + int (*dev_stop)(struct ixx_usb_device *dev); + int (*dev_restart_async)(struct ixx_usb_device *dev, struct urb *urb, + u8 *buf); + int (*dev_power)(struct usb_device *usb_dev, u8 mode); + u8 ep_msg_in[IXXAT_USB_MAX_CHANNEL]; + u8 ep_msg_out[IXXAT_USB_MAX_CHANNEL]; + + int rx_buffer_size; + int tx_buffer_size; + int sizeof_dev_private; -#define IXXAT_USB_VENDOR_ID 0x08d8 + int has_bgi_ep; -/* supported device ids: CL1 */ -#define USB2CAN_COMPACT_PRODUCT_ID 0x0008 -#define USB2CAN_EMBEDDED_PRODUCT_ID 0x0009 -#define USB2CAN_PROFESSIONAL_PRODUCT_ID 0x000A -#define USB2CAN_AUTOMOTIVE_PRODUCT_ID 0x000B - -/* supported device ids: CL2 */ -#define USB2CAN_FD_COMPACT_PRODUCT_ID 0x0014 -#define USB2CAN_FD_PROFESSIONAL_PRODUCT_ID 0x0016 -#define USB2CAN_FD_AUTOMOTIVE_PRODUCT_ID 0x0017 -#define USB2CAN_FD_PCIE_MINI_PRODUCT_ID 0x001B -#define USB2CAR_PRODUCT_ID 0x001C -#define CAN_IDM100_PRODUCT_ID 0xFF11 -#define CAN_IDM101_PRODUCT_ID 0xFF12 - -#define IXXAT_USB_BUS_CAN 1 - -#define IXXAT_USB_BUS_TYPE(type) ((u8)(((type) >> 8) & 0x00FF)) - -#define IXXAT_USB_STATE_CONNECTED 0x00000001 -#define IXXAT_USB_STATE_STARTED 0x00000002 - -#define IXXAT_USB_MAX_CHANNEL 5 -#define IXXAT_USB_MAX_TYPES 32 -#define IXXAT_USB_MAX_RX_URBS 4 -#define IXXAT_USB_MAX_TX_URBS 10 -#define IXXAT_USB_MAX_COM_REQ 10 - -#define IXXAT_USB_MSG_TIMEOUT 50 -#define IXXAT_USB_MSG_CYCLE 20 - -#define IXXAT_USB_POWER_WAKEUP 0 -#define IXXAT_USB_POWER_WAKEUP_TIME 500 - -#define IXXAT_USB_CMD_BUFFER_SIZE 256 - -#define IXXAT_USB_OPMODE_STANDARD 0x01 -#define IXXAT_USB_OPMODE_EXTENDED 0x02 -#define IXXAT_USB_OPMODE_ERRFRAME 0x04 -#define IXXAT_USB_OPMODE_LISTONLY 0x08 - -#define IXXAT_USB_EXMODE_EXTDATA 0x01 -#define IXXAT_USB_EXMODE_FASTDATA 0x02 -#define IXXAT_USB_EXMODE_ISOFD 0x04 - -#define IXXAT_USB_BTMODE_NAT 0x00000001 -#define IXXAT_USB_BTMODE_TSM 0x00000002 - -#define IXXAT_USB_STOP_ACTION_CLEARALL 3 - -#define IXXAT_RESTART_TASK_CYCLE_TIME 20 - -#define IXXAT_USB_CAN_DATA 0x00 -#define IXXAT_USB_CAN_INFO 0x01 -#define IXXAT_USB_CAN_ERROR 0x02 -#define IXXAT_USB_CAN_STATUS 0x03 -#define IXXAT_USB_CAN_WAKEUP 0x04 -#define IXXAT_USB_CAN_TIMEOVR 0x05 -#define IXXAT_USB_CAN_TIMERST 0x06 - -#define IXXAT_USB_CAN_STATUS_OK 0x00000000 -#define IXXAT_USB_CAN_STATUS_OVERRUN 0x00000002 -#define IXXAT_USB_CAN_STATUS_ERRLIM 0x00000004 -#define IXXAT_USB_CAN_STATUS_BUSOFF 0x00000008 -#define IXXAT_USB_CAN_STATUS_ERR_PAS 0x00002000 - -#define IXXAT_USB_CAN_ERROR_STUFF 1 -#define IXXAT_USB_CAN_ERROR_FORM 2 -#define IXXAT_USB_CAN_ERROR_ACK 3 -#define IXXAT_USB_CAN_ERROR_BIT 4 -#define IXXAT_USB_CAN_ERROR_CRC 6 - -#define IXXAT_USB_MSG_FLAGS_TYPE 0x000000FF -#define IXXAT_USB_MSG_FLAGS_DLC 0x000F0000 -#define IXXAT_USB_MSG_FLAGS_OVR 0x00100000 -#define IXXAT_USB_MSG_FLAGS_RTR 0x00400000 -#define IXXAT_USB_MSG_FLAGS_EXT 0x00800000 - -#define IXXAT_USB_DECODE_DLC(flags) (((flags) & IXXAT_USB_MSG_FLAGS_DLC) >> 16) -#define IXXAT_USB_ENCODE_DLC(len) (((len) << 16) & IXXAT_USB_MSG_FLAGS_DLC) - -#define IXXAT_USB_FDMSG_FLAGS_EDL 0x00000400 -#define IXXAT_USB_FDMSG_FLAGS_FDR 0x00000800 -#define IXXAT_USB_FDMSG_FLAGS_ESI 0x00001000 - -#define IXXAT_USB_CAN_CMD_START 0x326 -#define IXXAT_USB_CAN_CMD_STOP 0x327 -#define IXXAT_USB_CAN_CMD_RESET 0x328 - -#define IXXAT_USB_BRD_CMD_GET_DEVCAPS 0x401 -#define IXXAT_USB_BRD_CMD_GET_DEVINFO 0x402 -#define IXXAT_USB_BRD_CMD_POWER 0x421 - -/** - * union can_frame_union - Union for standard CAN / CAN FD pointers - * @cf: Pointer to standard CAN frame - * @cfd: Pointer to CAN FD frame - * - * Contains either a pointer to a standard CAN frame or a CAN FD frame - */ -union can_frame_union { - struct can_frame *cf; - struct canfd_frame *cfd; }; -/** - * struct ixxat_can_msg_base - IXXAT CAN message base (CL1/CL2) - * @size: Message size (this field excluded) - * @time: Message timestamp - * @msg_id: Message ID - * @flags: Message flags - * - * Contains the common fields of an IXXAT CAN message on both CL1 and CL2 - * devices - */ -struct ixxat_can_msg_base { - u8 size; - __le32 time; - __le32 msg_id; - __le32 flags; -} __packed; - -/** - * struct ixxat_can_msg_cl1 - IXXAT CAN message (CL1) - * @data: Message data (standard CAN frame) - * - * Contains the fields of an IXXAT CAN message on CL1 devices - */ -struct ixxat_can_msg_cl1 { - u8 data[CAN_MAX_DLEN]; -} __packed; - -/** - * struct ixxat_can_msg_cl2 - IXXAT CAN message (CL2) - * @client_id: Client ID - * @data: Message data (CAN FD frame) - * - * Contains the fields of an IXXAT CAN message on CL2 devices - */ -struct ixxat_can_msg_cl2 { - __le32 client_id; - u8 data[CANFD_MAX_DLEN]; -} __packed; - -/** - * struct ixxat_can_msg - IXXAT CAN message - * @base: Base message - * @cl1: Cl1 message - * @cl2: Cl2 message - * - * Contains an IXXAT CAN message - */ -struct ixxat_can_msg { - struct ixxat_can_msg_base base; - union { - struct ixxat_can_msg_cl1 cl1; - struct ixxat_can_msg_cl2 cl2; - }; -} __packed; - -/** - * struct ixxat_dev_caps - Device capabilities - * @bus_ctrl_count: Stores the bus controller counter - * @bus_ctrl_types: Stores the bus controller types - * - * Contains the device capabilities - */ -struct ixxat_dev_caps { - __le16 bus_ctrl_count; - __le16 bus_ctrl_types[IXXAT_USB_MAX_TYPES]; -} __packed; - -/** - * struct ixxat_canbtp Bittiming parameters (CL2) - * @mode: Operation mode - * @bps: Bits per second - * @ts1: TSEG 1 - * @ts2: TSEG 2 - * @sjw: Synchronization jump width - * @tdo: TDO - * - * Bittiming parameters of a CL2 initialization request - */ -struct ixxat_canbtp { - __le32 mode; - __le32 bps; - __le16 ts1; - __le16 ts2; - __le16 sjw; - __le16 tdo; -} __packed; - -/** - * struct ixxat_dev_info IXXAT usb device information - * @device_name: Name of the device - * @device_id: Device identification ( unique device id) - * @device_version: Device version ( 0, 1, ...) - * @device_fpga_version: Version of FPGA design - * - * Contains device information of IXXAT USB devices - */ -struct ixxat_dev_info { - char device_name[16]; - char device_id[16]; - __le16 device_version; - __le32 device_fpga_version; -} __packed; - -/** - * struct ixxat_time_ref Time reference - * @kt_host_0: Latest time on the host - * @ts_dev_0: Latest time stamp on the device - * @ts_dev_last: Last device time stamp - * - * Contains time references of the device and the host - */ -struct ixxat_time_ref { - ktime_t kt_host_0; +struct ixx_time_ref { + struct timeval tv_host_0; u32 ts_dev_0; u32 ts_dev_last; }; -/** - * struct ixxat_tx_urb_context URB content for transmission - * @dev: IXXAT USB device - * echo_index: Echo index - * @dlc: Data length code - * @count: Counter - * @urb: USB request block - * - * Contains content for USB request block transmissions - */ -struct ixxat_tx_urb_context { - struct ixxat_usb_device *dev; +struct ixx_tx_urb_context { + struct ixx_usb_device *dev; u32 echo_index; u8 dlc; u8 count; struct urb *urb; }; -/** - * struct ixxat_usb_device IXXAT USB device - * @can: CAN common private data - * @adapter: USB network descriptor - * @udev: USB device - * @netdev: Net_device - * @active_tx_urbs: Active tx urbs - * @tx_submitted: Submitted tx usb anchor - * @tx_contexts: Buffer for tx contexts - * @rx_submitted: Submitted rx usb anchor - * @state: Device state - * @ctrl_opened_count: Counter for opened controllers - * @ctrl_index: Controller index - * @ep_msg_in: USB endpoint for incoming messages - * @ep_msg_out: USB endpoint for outgoing messages - * @prev_dev: Previous opened device - * @next_dev: Next opened device in list - * @time_ref: Time reference - * @dev_info: Device information - * @bec: CAN error counter - * - * IXXAT USB-to-CAN device - */ -struct ixxat_usb_device { +/*IXXAT USB device */ +struct ixx_usb_device { struct can_priv can; - const struct ixxat_usb_adapter *adapter; + struct ixx_usb_adapter *adapter; + unsigned int ctrl_idx; + u32 state; + + struct sk_buff *echo_skb[IXXAT_USB_MAX_TX_URBS]; + struct usb_device *udev; struct net_device *netdev; atomic_t active_tx_urbs; struct usb_anchor tx_submitted; - struct ixxat_tx_urb_context tx_contexts[IXXAT_USB_MAX_TX_URBS]; - struct usb_anchor rx_submitted; + struct ixx_tx_urb_context tx_contexts[IXXAT_USB_MAX_TX_URBS]; - u32 state; + struct usb_anchor rx_submitted; - u32 ctrl_opened_count; - u16 ctrl_index; + u32 device_number; + u8 device_rev; u8 ep_msg_in; u8 ep_msg_out; - struct ixxat_usb_device *prev_dev; - struct ixxat_usb_device *next_dev; - - struct ixxat_time_ref time_ref; - struct ixxat_dev_info dev_info; - - struct can_berr_counter bec; -}; - -/** - * struct ixxat_usb_dal_req IXXAT device request block - * @req_size: Size of the request - * @req_port: Port of the request - * @req_socket: Socket of the request - * @req_code: Code of the request - * - * IXXAT device request block - */ -struct ixxat_usb_dal_req { - __le32 req_size; - __le16 req_port; - __le16 req_socket; - __le32 req_code; -} __packed; - -/** - * struct ixxat_usb_dal_res IXXAT device response block - * @res_size: Size of the respond - * @ret_size: Size of the return - * @ret_code: Return code - * - * IXXAT device response block - */ -struct ixxat_usb_dal_res { - __le32 res_size; - __le32 ret_size; - __le32 ret_code; -} __packed; - -/** - * struct ixxat_usb_dal_cmd IXXAT device command - * @req: Request block - * @req: Response block - * - * IXXAT device command - */ -struct ixxat_usb_dal_cmd { - struct ixxat_usb_dal_req req; - struct ixxat_usb_dal_res res; -} __packed; - -/** - * struct ixxat_usb_caps_req Device capabilities request block - * @dal_req: Request block - * - * Device capabilities request block - */ -struct ixxat_usb_caps_req { - struct ixxat_usb_dal_req dal_req; -} __packed; - -/** - * struct ixxat_usb_caps_res Device capabilities response block - * @dal_res: Response block - * @dev_caps: Device capabilities - * - * Device capabilities response block - */ -struct ixxat_usb_caps_res { - struct ixxat_usb_dal_res dal_res; - struct ixxat_dev_caps dev_caps; -} __packed; + u8 transmit_buffer[256]; + u8 transmit_ptr; + u8 transmit_count; + u8 transmit_dlc; + + struct task_struct *restart_task; + u8 restart_flag; + u8 must_quit; + wait_queue_head_t wait_queue; -/** - * struct ixxat_usb_caps_cmd Device capabilities command - * @req: Request block - * @res: Response block - * - * Can be sent to a device to request its capabilities - */ -struct ixxat_usb_caps_cmd { - struct ixxat_usb_caps_req req; - struct ixxat_usb_caps_res res; -} __packed; + struct ixx_usb_device *prev_siblings; + struct ixx_usb_device *next_siblings; -/** - * struct ixxat_usb_init_cl1_req Initialization request block (CL1) - * @dal_req: Request block - * @mode: Operation mode - * @btr0: Bittiming register 0 - * @btr1: Bittiming register 1 - * - * Initialization request block for CL1 devices - */ -struct ixxat_usb_init_cl1_req { - struct ixxat_usb_dal_req dal_req; - u8 mode; u8 btr0; u8 btr1; - u8 padding; -} __packed; - -/** - * struct ixxat_usb_init_cl2_req Initialization request block (CL2) - * @dal_req: Request block - * @opmode: Operation mode - * @exmode: Extended mode - * @sdr: Stadard bittiming parameters - * @fdr: Fast data bittiming parameters - * @_padding: 2 bytes padding - * - * Initialization request block for CL2 devices - */ -struct ixxat_usb_init_cl2_req { - struct ixxat_usb_dal_req dal_req; - u8 opmode; - u8 exmode; - struct ixxat_canbtp sdr; - struct ixxat_canbtp fdr; - __le16 _padding; -} __packed; - -/** - * struct ixxat_usb_init_res Initialization response block - * @dal_res: Response block - * - * Initialization response block - */ -struct ixxat_usb_init_res { - struct ixxat_usb_dal_res dal_res; -} __packed; - -/** - * struct ixxat_usb_init_cmd Initialization command - * @req_cl1: Request block for CL1 devices - * @req_cl2: Request block for CL2 devices - * - * Can be sent to a device to initialize it - */ -struct ixxat_usb_init_cmd { - union { - struct ixxat_usb_init_cl1_req req_cl1; - struct ixxat_usb_init_cl2_req req_cl2; - }; - struct ixxat_usb_init_res res; -} __packed; - -/** - * struct ixxat_usb_start_req Controller start request block - * @dal_req: Request block - * - * Controller start request block - */ -struct ixxat_usb_start_req { - struct ixxat_usb_dal_req dal_req; -} __packed; - -/** - * struct ixxat_usb_start_res Controller start response block - * @dal_res: Response block - * @start_time: Device starting point - * - * Controller start response block - */ -struct ixxat_usb_start_res { - struct ixxat_usb_dal_res dal_res; - __le32 start_time; -} __packed; - -/** - * struct ixxat_usb_start_cmd Controller start command - * @req: Request block - * @res: Response block - * - * Can be sent to a device to start its controller - */ -struct ixxat_usb_start_cmd { - struct ixxat_usb_start_req req; - struct ixxat_usb_start_res res; -} __packed; - -/** - * struct ixxat_usb_stop_req Controller stop request block - * @dal_req: Request block - * @action: Requested action - * - * Controller stop request block - */ -struct ixxat_usb_stop_req { - struct ixxat_usb_dal_req dal_req; - __le32 action; -} __packed; - -/** - * struct ixxat_usb_stop_res Controller stop response block - * @dal_res: Response block - * - * Controller stop response block - */ -struct ixxat_usb_stop_res { - struct ixxat_usb_dal_res dal_res; -} __packed; - -/** - * struct ixxat_usb_stop_cmd Controller stop command - * @req: Request block - * @res: Response block - * - * Can be sent to a device to start its controller - */ -struct ixxat_usb_stop_cmd { - struct ixxat_usb_stop_req req; - struct ixxat_usb_stop_res res; -} __packed; - -/** - * struct ixxat_usb_power_req Power request block - * @dal_req: Request block - * @mode: Power mode - * @_padding1: 1 byte padding - * @_padding2: 2 bytes padding - * - * Power request block - */ -struct ixxat_usb_power_req { - struct ixxat_usb_dal_req dal_req; - u8 mode; - u8 _padding1; - __le16 _padding2; -} __packed; - -/** - * struct ixxat_usb_power_res Power response block - * @dal_res: Response block - * - * Power response block - */ -struct ixxat_usb_power_res { - struct ixxat_usb_dal_res dal_res; -} __packed; -/** - * struct ixxat_usb_power_cmd Power command - * @req: Request block - * @res: Response block - * - * Can be sent to a device to set its power mode - */ -struct ixxat_usb_power_cmd { - struct ixxat_usb_power_req req; - struct ixxat_usb_power_res res; -} __packed; + int ctrl_opened_count; -/** - * struct ixxat_usb_info_req Device information request block - * @dal_req: Request block - * - * Device information request block - */ -struct ixxat_usb_info_req { - struct ixxat_usb_dal_req dal_req; -} __packed; - -/** - * struct ixxat_usb_info_res Device information response block - * @dal_res: Response block - * @info: Device information - * - * Device information response block - */ -struct ixxat_usb_info_res { - struct ixxat_usb_dal_res dal_res; - struct ixxat_dev_info info; -} __packed; + struct ixx_time_ref time_ref; -/** - * struct ixxat_usb_info_cmd Device information command - * @req: Request block - * @res: Response block - * - * Can be sent to a device to request its device information - */ -struct ixxat_usb_info_cmd { - struct ixxat_usb_info_req req; - struct ixxat_usb_info_res res; -} __packed; + struct ixx_intf_info dev_info; + struct ixx_intf_fw_info fw_info; -/** - * struct ixxat_usb_adapter IXXAT USB device adapter - * @clock: Clock frequency - * @bt: Bittiming constants - * @btd: Data bittiming constants - * @modes: Supported modes - * @buffer_size_rx: Buffer size for receiving - * @buffer_size_tx: Buffer size for transfer - * @ep_msg_in: USB endpoint buffer for incoming messages - * @ep_msg_out: USB endpoint buffer for outgoing messages - * @ep_offs: Endpoint offset (device depended) - * - * Device Adapter for IXXAT USB devices - */ -struct ixxat_usb_adapter { - const u32 clock; - const struct can_bittiming_const *bt; - const struct can_bittiming_const *btd; - const u32 modes; - const u16 buffer_size_rx; - const u16 buffer_size_tx; - const u8 ep_msg_in[IXXAT_USB_MAX_CHANNEL]; - const u8 ep_msg_out[IXXAT_USB_MAX_CHANNEL]; - const u8 ep_offs; - int (*init_ctrl)(struct ixxat_usb_device *dev); + struct can_berr_counter bec; }; -extern const struct ixxat_usb_adapter usb2can_cl1; -extern const struct ixxat_usb_adapter usb2can_cl2; -extern const struct ixxat_usb_adapter can_idm100; -extern const struct ixxat_usb_adapter can_idm101; - -/** - * ixxat_usb_setup_cmd() - Setup a device command - * @req: Request block - * @res: Response block - * - * This function sets the default values in the request and the response block - * of a device command - */ -void ixxat_usb_setup_cmd(struct ixxat_usb_dal_req *req, - struct ixxat_usb_dal_res *res); - -/** - * ixxat_usb_send_cmd() - Send a command to the device - * @dev: USB device - * @dal_req: Requested command - * - * This function sends a specific command to the device. - * - * Return: Error, if one occurred else 0 - */ -int ixxat_usb_send_cmd(struct usb_device *dev, struct ixxat_usb_dal_req *req); - -/** - * ixxat_usb_rcv_cmd() - Receive a command from the device - * @dev: USB device - * @dal_req: Responded command - * @value: Requested values - * - * This function receives a response to a device request - * - * Return: Error, if one occurred else 0 - */ -int ixxat_usb_rcv_cmd(struct usb_device *dev, struct ixxat_usb_dal_res *res, - int value); - -#endif /* IXXAT_USB_CORE_H */ +struct ixx_can_msg +{ + u8 size; + u32 time; + u32 msg_id; + u32 flags; + u8 data[CAN_MAX_DLEN]; +} __packed; + +struct ixx_can_msg_v2 +{ + u8 size; + u32 time; + u32 msg_id; + u32 flags; + u32 client_id; + u8 data[CANFD_MAX_DLEN]; +} __packed; + +void ixxat_dump_mem(char *prompt, void *p, int l); + +void ixxat_usb_update_ts_now(struct ixx_usb_device *dev, u32 ts_now); +void ixxat_usb_set_ts_now(struct ixx_usb_device *dev, u32 ts_now); +void ixxat_usb_get_ts_tv(struct ixx_usb_device *dev, u32 ts, + ktime_t* k_time); + +void ixxat_usb_async_complete(struct urb *urb); +void ixxat_usb_restart_complete(struct ixx_usb_device *dev); +#endif diff -u linux-lts-xenial-4.4.0/ubuntu/rsi/rsi_91x_mac80211.c linux-lts-xenial-4.4.0/ubuntu/rsi/rsi_91x_mac80211.c --- linux-lts-xenial-4.4.0/ubuntu/rsi/rsi_91x_mac80211.c +++ linux-lts-xenial-4.4.0/ubuntu/rsi/rsi_91x_mac80211.c @@ -376,7 +376,6 @@ if (common->bgscan_en || common->scan_in_prog) return -EBUSY; - cancel_work_sync(&common->scan_work); mutex_lock(&common->mutex); if (!bss->assoc) { @@ -565,7 +564,8 @@ return; } if ((!bss->assoc) && - (adapter->ps_state == PS_ENABLED)) + (adapter->ps_state == PS_ENABLED) && + (vif->type == NL80211_IFTYPE_STATION)) rsi_disable_ps(adapter); if (ieee80211_is_auth(wlh->frame_control)) common->mac_ops_resumed = false; @@ -630,7 +630,6 @@ ven_rsi_dbg(ERR_ZONE, "===> Interface DOWN <===\n"); - cancel_work_sync(&common->scan_work); mutex_lock(&common->mutex); common->iface_down = true; @@ -860,7 +859,6 @@ switch (newtype) { case NL80211_IFTYPE_AP: - rsi_disable_ps(adapter); ven_rsi_dbg(INFO_ZONE, "Change to AP Mode\n"); intf_mode = AP_OPMODE; break; @@ -2349,10 +2347,14 @@ struct rsi_hw *adapter = hw->priv; struct rsi_common *common = adapter->priv; + mutex_lock(&common->mutex); + if (common->fsm_state != FSM_MAC_INIT_DONE) wiphy_rfkill_set_hw_state(hw->wiphy, true); else wiphy_rfkill_set_hw_state(hw->wiphy, false); + + mutex_unlock(&common->mutex); } #ifdef CONFIG_VEN_RSI_WOW diff -u linux-lts-xenial-4.4.0/ubuntu/rsi/rsi_common.h linux-lts-xenial-4.4.0/ubuntu/rsi/rsi_common.h --- linux-lts-xenial-4.4.0/ubuntu/rsi/rsi_common.h +++ linux-lts-xenial-4.4.0/ubuntu/rsi/rsi_common.h @@ -90,6 +90,7 @@ atomic_inc(&handle->thread_done); rsi_set_event(&handle->event); + wait_for_completion(&handle->completion); return kthread_stop(handle->task); } diff -u linux-lts-xenial-4.4.0/zfs/META linux-lts-xenial-4.4.0/zfs/META --- linux-lts-xenial-4.4.0/zfs/META +++ linux-lts-xenial-4.4.0/zfs/META @@ -2,7 +2,7 @@ Name: zfs Branch: 1.0 Version: 0.6.5.6 -Release: 0ubuntu25 +Release: 0ubuntu20 Release-Tags: relext License: CDDL Author: OpenZFS on Linux diff -u linux-lts-xenial-4.4.0/zfs/Makefile.in linux-lts-xenial-4.4.0/zfs/Makefile.in --- linux-lts-xenial-4.4.0/zfs/Makefile.in +++ linux-lts-xenial-4.4.0/zfs/Makefile.in @@ -140,7 +140,6 @@ $(top_srcdir)/config/kernel-file-inode.m4 \ $(top_srcdir)/config/kernel-fmode-t.m4 \ $(top_srcdir)/config/kernel-follow-down-one.m4 \ - $(top_srcdir)/config/kernel-fst-mount.m4 \ $(top_srcdir)/config/kernel-fsync.m4 \ $(top_srcdir)/config/kernel-generic_io_acct.m4 \ $(top_srcdir)/config/kernel-get-disk-ro.m4 \ @@ -156,6 +155,7 @@ $(top_srcdir)/config/kernel-lseek-execute.m4 \ $(top_srcdir)/config/kernel-mk-request-fn.m4 \ $(top_srcdir)/config/kernel-mkdir-umode-t.m4 \ + $(top_srcdir)/config/kernel-mount-nodev.m4 \ $(top_srcdir)/config/kernel-open-bdev-exclusive.m4 \ $(top_srcdir)/config/kernel-put-link.m4 \ $(top_srcdir)/config/kernel-security-inode-init.m4 \ diff -u linux-lts-xenial-4.4.0/zfs/aclocal.m4 linux-lts-xenial-4.4.0/zfs/aclocal.m4 --- linux-lts-xenial-4.4.0/zfs/aclocal.m4 +++ linux-lts-xenial-4.4.0/zfs/aclocal.m4 @@ -1245,7 +1245,6 @@ m4_include([config/kernel-file-inode.m4]) m4_include([config/kernel-fmode-t.m4]) m4_include([config/kernel-follow-down-one.m4]) -m4_include([config/kernel-fst-mount.m4]) m4_include([config/kernel-fsync.m4]) m4_include([config/kernel-generic_io_acct.m4]) m4_include([config/kernel-get-disk-ro.m4]) @@ -1261,6 +1260,7 @@ m4_include([config/kernel-lseek-execute.m4]) m4_include([config/kernel-mk-request-fn.m4]) m4_include([config/kernel-mkdir-umode-t.m4]) +m4_include([config/kernel-mount-nodev.m4]) m4_include([config/kernel-open-bdev-exclusive.m4]) m4_include([config/kernel-put-link.m4]) m4_include([config/kernel-security-inode-init.m4]) reverted: --- linux-lts-xenial-4.4.0/zfs/config/kernel-fst-mount.m4 +++ linux-lts-xenial-4.4.0.orig/zfs/config/kernel-fst-mount.m4 @@ -1,28 +0,0 @@ -dnl # -dnl # 2.6.38 API change -dnl # The .get_sb callback has been replaced by a .mount callback -dnl # in the file_system_type structure. -dnl # -AC_DEFUN([ZFS_AC_KERNEL_FST_MOUNT], [ - AC_MSG_CHECKING([whether fst->mount() exists]) - ZFS_LINUX_TRY_COMPILE([ - #include - - static struct dentry * - mount(struct file_system_type *fs_type, int flags, - const char *osname, void *data) { - struct dentry *d = NULL; - return (d); - } - - static struct file_system_type fst __attribute__ ((unused)) = { - .mount = mount, - }; - ],[ - ],[ - AC_MSG_RESULT(yes) - AC_DEFINE(HAVE_FST_MOUNT, 1, [fst->mount() exists]) - ],[ - AC_MSG_RESULT(no) - ]) -]) diff -u linux-lts-xenial-4.4.0/zfs/config/kernel.m4 linux-lts-xenial-4.4.0/zfs/config/kernel.m4 --- linux-lts-xenial-4.4.0/zfs/config/kernel.m4 +++ linux-lts-xenial-4.4.0/zfs/config/kernel.m4 @@ -77,7 +77,7 @@ ZFS_AC_KERNEL_TRUNCATE_SETSIZE ZFS_AC_KERNEL_6ARGS_SECURITY_INODE_INIT_SECURITY ZFS_AC_KERNEL_CALLBACK_SECURITY_INODE_INIT_SECURITY - ZFS_AC_KERNEL_FST_MOUNT + ZFS_AC_KERNEL_MOUNT_NODEV ZFS_AC_KERNEL_SHRINK ZFS_AC_KERNEL_SHRINK_CONTROL_HAS_NID ZFS_AC_KERNEL_S_INSTANCES_LIST_HEAD diff -u linux-lts-xenial-4.4.0/zfs/configure linux-lts-xenial-4.4.0/zfs/configure --- linux-lts-xenial-4.4.0/zfs/configure +++ linux-lts-xenial-4.4.0/zfs/configure @@ -21202,31 +21202,21 @@ + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether mount_nodev() is available" >&5 +$as_echo_n "checking whether mount_nodev() is available... " >&6; } - { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether fst->mount() exists" >&5 -$as_echo_n "checking whether fst->mount() exists... " >&6; } cat confdefs.h - <<_ACEOF >conftest.c - #include - - static struct dentry * - mount(struct file_system_type *fs_type, int flags, - const char *osname, void *data) { - struct dentry *d = NULL; - return (d); - } - - static struct file_system_type fst __attribute__ ((unused)) = { - .mount = mount, - }; + #include int main (void) { + mount_nodev(NULL, 0, NULL, NULL); ; return 0; @@ -21256,25 +21246,64 @@ ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; }; then : + rc=0 +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + rc=1 - { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -$as_echo "yes" >&6; } -$as_echo "#define HAVE_FST_MOUNT 1" >>confdefs.h +fi + rm -Rf build -else - $as_echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 + if test $rc -ne 0; then : - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } + else + if test "x$enable_linux_builtin" != xyes; then + grep -q -E '[[:space:]]mount_nodev[[:space:]]' \ + $LINUX_OBJ/$LINUX_SYMBOLS 2>/dev/null + rc=$? + if test $rc -ne 0; then + export=0 + for file in fs/super.c; do + grep -q -E "EXPORT_SYMBOL.*(mount_nodev)" \ + "$LINUX/$file" 2>/dev/null + rc=$? + if test $rc -eq 0; then + export=1 + break; + fi + done + if test $export -eq 0; then : + rc=1 + else : + rc=0 + fi + else : + rc=0 + fi -fi - rm -Rf build + fi + if test $rc -ne 0; then : + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + else : + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + +$as_echo "#define HAVE_MOUNT_NODEV 1" >>confdefs.h + + + fi + fi @@ -30567,31 +30596,21 @@ + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether mount_nodev() is available" >&5 +$as_echo_n "checking whether mount_nodev() is available... " >&6; } - { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether fst->mount() exists" >&5 -$as_echo_n "checking whether fst->mount() exists... " >&6; } cat confdefs.h - <<_ACEOF >conftest.c - #include - - static struct dentry * - mount(struct file_system_type *fs_type, int flags, - const char *osname, void *data) { - struct dentry *d = NULL; - return (d); - } - - static struct file_system_type fst __attribute__ ((unused)) = { - .mount = mount, - }; + #include int main (void) { + mount_nodev(NULL, 0, NULL, NULL); ; return 0; @@ -30621,25 +30640,64 @@ ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; }; then : + rc=0 +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + rc=1 - { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -$as_echo "yes" >&6; } -$as_echo "#define HAVE_FST_MOUNT 1" >>confdefs.h +fi + rm -Rf build -else - $as_echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 + if test $rc -ne 0; then : - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } + else + if test "x$enable_linux_builtin" != xyes; then + grep -q -E '[[:space:]]mount_nodev[[:space:]]' \ + $LINUX_OBJ/$LINUX_SYMBOLS 2>/dev/null + rc=$? + if test $rc -ne 0; then + export=0 + for file in fs/super.c; do + grep -q -E "EXPORT_SYMBOL.*(mount_nodev)" \ + "$LINUX/$file" 2>/dev/null + rc=$? + if test $rc -eq 0; then + export=1 + break; + fi + done + if test $export -eq 0; then : + rc=1 + else : + rc=0 + fi + else : + rc=0 + fi -fi - rm -Rf build + fi + if test $rc -ne 0; then : + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + else : + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + +$as_echo "#define HAVE_MOUNT_NODEV 1" >>confdefs.h + + + fi + fi diff -u linux-lts-xenial-4.4.0/zfs/contrib/Makefile.in linux-lts-xenial-4.4.0/zfs/contrib/Makefile.in --- linux-lts-xenial-4.4.0/zfs/contrib/Makefile.in +++ linux-lts-xenial-4.4.0/zfs/contrib/Makefile.in @@ -129,7 +129,6 @@ $(top_srcdir)/config/kernel-file-inode.m4 \ $(top_srcdir)/config/kernel-fmode-t.m4 \ $(top_srcdir)/config/kernel-follow-down-one.m4 \ - $(top_srcdir)/config/kernel-fst-mount.m4 \ $(top_srcdir)/config/kernel-fsync.m4 \ $(top_srcdir)/config/kernel-generic_io_acct.m4 \ $(top_srcdir)/config/kernel-get-disk-ro.m4 \ @@ -145,6 +144,7 @@ $(top_srcdir)/config/kernel-lseek-execute.m4 \ $(top_srcdir)/config/kernel-mk-request-fn.m4 \ $(top_srcdir)/config/kernel-mkdir-umode-t.m4 \ + $(top_srcdir)/config/kernel-mount-nodev.m4 \ $(top_srcdir)/config/kernel-open-bdev-exclusive.m4 \ $(top_srcdir)/config/kernel-put-link.m4 \ $(top_srcdir)/config/kernel-security-inode-init.m4 \ diff -u linux-lts-xenial-4.4.0/zfs/contrib/bash_completion.d/Makefile.in linux-lts-xenial-4.4.0/zfs/contrib/bash_completion.d/Makefile.in --- linux-lts-xenial-4.4.0/zfs/contrib/bash_completion.d/Makefile.in +++ linux-lts-xenial-4.4.0/zfs/contrib/bash_completion.d/Makefile.in @@ -130,7 +130,6 @@ $(top_srcdir)/config/kernel-file-inode.m4 \ $(top_srcdir)/config/kernel-fmode-t.m4 \ $(top_srcdir)/config/kernel-follow-down-one.m4 \ - $(top_srcdir)/config/kernel-fst-mount.m4 \ $(top_srcdir)/config/kernel-fsync.m4 \ $(top_srcdir)/config/kernel-generic_io_acct.m4 \ $(top_srcdir)/config/kernel-get-disk-ro.m4 \ @@ -146,6 +145,7 @@ $(top_srcdir)/config/kernel-lseek-execute.m4 \ $(top_srcdir)/config/kernel-mk-request-fn.m4 \ $(top_srcdir)/config/kernel-mkdir-umode-t.m4 \ + $(top_srcdir)/config/kernel-mount-nodev.m4 \ $(top_srcdir)/config/kernel-open-bdev-exclusive.m4 \ $(top_srcdir)/config/kernel-put-link.m4 \ $(top_srcdir)/config/kernel-security-inode-init.m4 \ diff -u linux-lts-xenial-4.4.0/zfs/contrib/dracut/90zfs/Makefile.in linux-lts-xenial-4.4.0/zfs/contrib/dracut/90zfs/Makefile.in --- linux-lts-xenial-4.4.0/zfs/contrib/dracut/90zfs/Makefile.in +++ linux-lts-xenial-4.4.0/zfs/contrib/dracut/90zfs/Makefile.in @@ -130,7 +130,6 @@ $(top_srcdir)/config/kernel-file-inode.m4 \ $(top_srcdir)/config/kernel-fmode-t.m4 \ $(top_srcdir)/config/kernel-follow-down-one.m4 \ - $(top_srcdir)/config/kernel-fst-mount.m4 \ $(top_srcdir)/config/kernel-fsync.m4 \ $(top_srcdir)/config/kernel-generic_io_acct.m4 \ $(top_srcdir)/config/kernel-get-disk-ro.m4 \ @@ -146,6 +145,7 @@ $(top_srcdir)/config/kernel-lseek-execute.m4 \ $(top_srcdir)/config/kernel-mk-request-fn.m4 \ $(top_srcdir)/config/kernel-mkdir-umode-t.m4 \ + $(top_srcdir)/config/kernel-mount-nodev.m4 \ $(top_srcdir)/config/kernel-open-bdev-exclusive.m4 \ $(top_srcdir)/config/kernel-put-link.m4 \ $(top_srcdir)/config/kernel-security-inode-init.m4 \ diff -u linux-lts-xenial-4.4.0/zfs/contrib/dracut/Makefile.in linux-lts-xenial-4.4.0/zfs/contrib/dracut/Makefile.in --- linux-lts-xenial-4.4.0/zfs/contrib/dracut/Makefile.in +++ linux-lts-xenial-4.4.0/zfs/contrib/dracut/Makefile.in @@ -129,7 +129,6 @@ $(top_srcdir)/config/kernel-file-inode.m4 \ $(top_srcdir)/config/kernel-fmode-t.m4 \ $(top_srcdir)/config/kernel-follow-down-one.m4 \ - $(top_srcdir)/config/kernel-fst-mount.m4 \ $(top_srcdir)/config/kernel-fsync.m4 \ $(top_srcdir)/config/kernel-generic_io_acct.m4 \ $(top_srcdir)/config/kernel-get-disk-ro.m4 \ @@ -145,6 +144,7 @@ $(top_srcdir)/config/kernel-lseek-execute.m4 \ $(top_srcdir)/config/kernel-mk-request-fn.m4 \ $(top_srcdir)/config/kernel-mkdir-umode-t.m4 \ + $(top_srcdir)/config/kernel-mount-nodev.m4 \ $(top_srcdir)/config/kernel-open-bdev-exclusive.m4 \ $(top_srcdir)/config/kernel-put-link.m4 \ $(top_srcdir)/config/kernel-security-inode-init.m4 \ diff -u linux-lts-xenial-4.4.0/zfs/contrib/initramfs/Makefile.in linux-lts-xenial-4.4.0/zfs/contrib/initramfs/Makefile.in --- linux-lts-xenial-4.4.0/zfs/contrib/initramfs/Makefile.in +++ linux-lts-xenial-4.4.0/zfs/contrib/initramfs/Makefile.in @@ -130,7 +130,6 @@ $(top_srcdir)/config/kernel-file-inode.m4 \ $(top_srcdir)/config/kernel-fmode-t.m4 \ $(top_srcdir)/config/kernel-follow-down-one.m4 \ - $(top_srcdir)/config/kernel-fst-mount.m4 \ $(top_srcdir)/config/kernel-fsync.m4 \ $(top_srcdir)/config/kernel-generic_io_acct.m4 \ $(top_srcdir)/config/kernel-get-disk-ro.m4 \ @@ -146,6 +145,7 @@ $(top_srcdir)/config/kernel-lseek-execute.m4 \ $(top_srcdir)/config/kernel-mk-request-fn.m4 \ $(top_srcdir)/config/kernel-mkdir-umode-t.m4 \ + $(top_srcdir)/config/kernel-mount-nodev.m4 \ $(top_srcdir)/config/kernel-open-bdev-exclusive.m4 \ $(top_srcdir)/config/kernel-put-link.m4 \ $(top_srcdir)/config/kernel-security-inode-init.m4 \ diff -u linux-lts-xenial-4.4.0/zfs/include/Makefile.in linux-lts-xenial-4.4.0/zfs/include/Makefile.in --- linux-lts-xenial-4.4.0/zfs/include/Makefile.in +++ linux-lts-xenial-4.4.0/zfs/include/Makefile.in @@ -130,7 +130,6 @@ $(top_srcdir)/config/kernel-file-inode.m4 \ $(top_srcdir)/config/kernel-fmode-t.m4 \ $(top_srcdir)/config/kernel-follow-down-one.m4 \ - $(top_srcdir)/config/kernel-fst-mount.m4 \ $(top_srcdir)/config/kernel-fsync.m4 \ $(top_srcdir)/config/kernel-generic_io_acct.m4 \ $(top_srcdir)/config/kernel-get-disk-ro.m4 \ @@ -146,6 +145,7 @@ $(top_srcdir)/config/kernel-lseek-execute.m4 \ $(top_srcdir)/config/kernel-mk-request-fn.m4 \ $(top_srcdir)/config/kernel-mkdir-umode-t.m4 \ + $(top_srcdir)/config/kernel-mount-nodev.m4 \ $(top_srcdir)/config/kernel-open-bdev-exclusive.m4 \ $(top_srcdir)/config/kernel-put-link.m4 \ $(top_srcdir)/config/kernel-security-inode-init.m4 \ diff -u linux-lts-xenial-4.4.0/zfs/include/linux/Makefile.in linux-lts-xenial-4.4.0/zfs/include/linux/Makefile.in --- linux-lts-xenial-4.4.0/zfs/include/linux/Makefile.in +++ linux-lts-xenial-4.4.0/zfs/include/linux/Makefile.in @@ -130,7 +130,6 @@ $(top_srcdir)/config/kernel-file-inode.m4 \ $(top_srcdir)/config/kernel-fmode-t.m4 \ $(top_srcdir)/config/kernel-follow-down-one.m4 \ - $(top_srcdir)/config/kernel-fst-mount.m4 \ $(top_srcdir)/config/kernel-fsync.m4 \ $(top_srcdir)/config/kernel-generic_io_acct.m4 \ $(top_srcdir)/config/kernel-get-disk-ro.m4 \ @@ -146,6 +145,7 @@ $(top_srcdir)/config/kernel-lseek-execute.m4 \ $(top_srcdir)/config/kernel-mk-request-fn.m4 \ $(top_srcdir)/config/kernel-mkdir-umode-t.m4 \ + $(top_srcdir)/config/kernel-mount-nodev.m4 \ $(top_srcdir)/config/kernel-open-bdev-exclusive.m4 \ $(top_srcdir)/config/kernel-put-link.m4 \ $(top_srcdir)/config/kernel-security-inode-init.m4 \ diff -u linux-lts-xenial-4.4.0/zfs/include/linux/vfs_compat.h linux-lts-xenial-4.4.0/zfs/include/linux/vfs_compat.h --- linux-lts-xenial-4.4.0/zfs/include/linux/vfs_compat.h +++ linux-lts-xenial-4.4.0/zfs/include/linux/vfs_compat.h @@ -112,30 +112,6 @@ #endif /* - * 4.14 adds SB_* flag definitions, define them to MS_* equivalents - * if not set. - */ -#ifndef SB_RDONLY -#define SB_RDONLY MS_RDONLY -#endif - -#ifndef SB_SILENT -#define SB_SILENT MS_SILENT -#endif - -#ifndef SB_ACTIVE -#define SB_ACTIVE MS_ACTIVE -#endif - -#ifndef SB_POSIXACL -#define SB_POSIXACL MS_POSIXACL -#endif - -#ifndef SB_MANDLOCK -#define SB_MANDLOCK MS_MANDLOCK -#endif - -/* * 2.6.38 API change, * LOOKUP_RCU flag introduced to distinguish rcu-walk from ref-walk cases. */ diff -u linux-lts-xenial-4.4.0/zfs/include/sys/Makefile.in linux-lts-xenial-4.4.0/zfs/include/sys/Makefile.in --- linux-lts-xenial-4.4.0/zfs/include/sys/Makefile.in +++ linux-lts-xenial-4.4.0/zfs/include/sys/Makefile.in @@ -130,7 +130,6 @@ $(top_srcdir)/config/kernel-file-inode.m4 \ $(top_srcdir)/config/kernel-fmode-t.m4 \ $(top_srcdir)/config/kernel-follow-down-one.m4 \ - $(top_srcdir)/config/kernel-fst-mount.m4 \ $(top_srcdir)/config/kernel-fsync.m4 \ $(top_srcdir)/config/kernel-generic_io_acct.m4 \ $(top_srcdir)/config/kernel-get-disk-ro.m4 \ @@ -146,6 +145,7 @@ $(top_srcdir)/config/kernel-lseek-execute.m4 \ $(top_srcdir)/config/kernel-mk-request-fn.m4 \ $(top_srcdir)/config/kernel-mkdir-umode-t.m4 \ + $(top_srcdir)/config/kernel-mount-nodev.m4 \ $(top_srcdir)/config/kernel-open-bdev-exclusive.m4 \ $(top_srcdir)/config/kernel-put-link.m4 \ $(top_srcdir)/config/kernel-security-inode-init.m4 \ diff -u linux-lts-xenial-4.4.0/zfs/include/sys/fm/Makefile.in linux-lts-xenial-4.4.0/zfs/include/sys/fm/Makefile.in --- linux-lts-xenial-4.4.0/zfs/include/sys/fm/Makefile.in +++ linux-lts-xenial-4.4.0/zfs/include/sys/fm/Makefile.in @@ -130,7 +130,6 @@ $(top_srcdir)/config/kernel-file-inode.m4 \ $(top_srcdir)/config/kernel-fmode-t.m4 \ $(top_srcdir)/config/kernel-follow-down-one.m4 \ - $(top_srcdir)/config/kernel-fst-mount.m4 \ $(top_srcdir)/config/kernel-fsync.m4 \ $(top_srcdir)/config/kernel-generic_io_acct.m4 \ $(top_srcdir)/config/kernel-get-disk-ro.m4 \ @@ -146,6 +145,7 @@ $(top_srcdir)/config/kernel-lseek-execute.m4 \ $(top_srcdir)/config/kernel-mk-request-fn.m4 \ $(top_srcdir)/config/kernel-mkdir-umode-t.m4 \ + $(top_srcdir)/config/kernel-mount-nodev.m4 \ $(top_srcdir)/config/kernel-open-bdev-exclusive.m4 \ $(top_srcdir)/config/kernel-put-link.m4 \ $(top_srcdir)/config/kernel-security-inode-init.m4 \ diff -u linux-lts-xenial-4.4.0/zfs/include/sys/fm/fs/Makefile.in linux-lts-xenial-4.4.0/zfs/include/sys/fm/fs/Makefile.in --- linux-lts-xenial-4.4.0/zfs/include/sys/fm/fs/Makefile.in +++ linux-lts-xenial-4.4.0/zfs/include/sys/fm/fs/Makefile.in @@ -130,7 +130,6 @@ $(top_srcdir)/config/kernel-file-inode.m4 \ $(top_srcdir)/config/kernel-fmode-t.m4 \ $(top_srcdir)/config/kernel-follow-down-one.m4 \ - $(top_srcdir)/config/kernel-fst-mount.m4 \ $(top_srcdir)/config/kernel-fsync.m4 \ $(top_srcdir)/config/kernel-generic_io_acct.m4 \ $(top_srcdir)/config/kernel-get-disk-ro.m4 \ @@ -146,6 +145,7 @@ $(top_srcdir)/config/kernel-lseek-execute.m4 \ $(top_srcdir)/config/kernel-mk-request-fn.m4 \ $(top_srcdir)/config/kernel-mkdir-umode-t.m4 \ + $(top_srcdir)/config/kernel-mount-nodev.m4 \ $(top_srcdir)/config/kernel-open-bdev-exclusive.m4 \ $(top_srcdir)/config/kernel-put-link.m4 \ $(top_srcdir)/config/kernel-security-inode-init.m4 \ diff -u linux-lts-xenial-4.4.0/zfs/include/sys/fs/Makefile.in linux-lts-xenial-4.4.0/zfs/include/sys/fs/Makefile.in --- linux-lts-xenial-4.4.0/zfs/include/sys/fs/Makefile.in +++ linux-lts-xenial-4.4.0/zfs/include/sys/fs/Makefile.in @@ -130,7 +130,6 @@ $(top_srcdir)/config/kernel-file-inode.m4 \ $(top_srcdir)/config/kernel-fmode-t.m4 \ $(top_srcdir)/config/kernel-follow-down-one.m4 \ - $(top_srcdir)/config/kernel-fst-mount.m4 \ $(top_srcdir)/config/kernel-fsync.m4 \ $(top_srcdir)/config/kernel-generic_io_acct.m4 \ $(top_srcdir)/config/kernel-get-disk-ro.m4 \ @@ -146,6 +145,7 @@ $(top_srcdir)/config/kernel-lseek-execute.m4 \ $(top_srcdir)/config/kernel-mk-request-fn.m4 \ $(top_srcdir)/config/kernel-mkdir-umode-t.m4 \ + $(top_srcdir)/config/kernel-mount-nodev.m4 \ $(top_srcdir)/config/kernel-open-bdev-exclusive.m4 \ $(top_srcdir)/config/kernel-put-link.m4 \ $(top_srcdir)/config/kernel-security-inode-init.m4 \ diff -u linux-lts-xenial-4.4.0/zfs/include/sys/zfs_vfsops.h linux-lts-xenial-4.4.0/zfs/include/sys/zfs_vfsops.h --- linux-lts-xenial-4.4.0/zfs/include/sys/zfs_vfsops.h +++ linux-lts-xenial-4.4.0/zfs/include/sys/zfs_vfsops.h @@ -32,7 +32,6 @@ #include #include #include -#include #include #ifdef __cplusplus diff -u linux-lts-xenial-4.4.0/zfs/module/zfs/zpl_super.c linux-lts-xenial-4.4.0/zfs/module/zfs/zpl_super.c --- linux-lts-xenial-4.4.0/zfs/module/zfs/zpl_super.c +++ linux-lts-xenial-4.4.0/zfs/module/zfs/zpl_super.c @@ -443,65 +443,12 @@ return (error); } -static int -zpl_test_super(struct super_block *s, void *data) -{ - zfs_sb_t *zsb = s->s_fs_info; - - objset_t *os = data; - - if (zsb == NULL) - return (0); - - return (os == zsb->z_os); -} - -static struct super_block * -zpl_mount_impl(struct file_system_type *fs_type, int flags, zfs_mntopts_t *zmo) -{ - struct super_block *s; - objset_t *os; - int err; - - err = dmu_objset_hold(zmo->z_osname, FTAG, &os); - if (err) - return (ERR_PTR(-err)); - - /* - * The dsl pool lock must be released prior to calling sget(). - * It is possible sget() may block on the lock in grab_super() - * while deactivate_super() holds that same lock and waits for - * a txg sync. If the dsl_pool lock is held over over sget() - * this can prevent the pool sync and cause a deadlock. - */ - dsl_pool_rele(dmu_objset_pool(os), FTAG); - s = zpl_sget(fs_type, zpl_test_super, set_anon_super, flags, os); - dsl_dataset_rele(dmu_objset_ds(os), FTAG); - - if (IS_ERR(s)) - return (ERR_CAST(s)); - - if (s->s_root == NULL) { - err = zpl_fill_super(s, zmo, flags & SB_SILENT ? 1 : 0); - if (err) { - deactivate_locked_super(s); - return (ERR_PTR(err)); - } - s->s_flags |= SB_ACTIVE; - } else if ((flags ^ s->s_flags) & SB_RDONLY) { - deactivate_locked_super(s); - return (ERR_PTR(-EBUSY)); - } - - return (s); -} -#ifdef HAVE_FST_MOUNT +#ifdef HAVE_MOUNT_NODEV static struct dentry * zpl_mount(struct file_system_type *fs_type, int flags, const char *osname, void *data) { zfs_mntopts_t *zmo = zfs_mntopts_alloc(); - struct super_block *sb; int error; error = zpl_parse_options((char *)osname, (char *)data, zmo, B_FALSE); @@ -509,11 +456,8 @@ zfs_mntopts_free(zmo); return (ERR_PTR(error)); } - sb = zpl_mount_impl(fs_type, flags, zmo); - if (IS_ERR(sb)) - return (ERR_CAST(sb)); - return (dget(sb->s_root)); + return (mount_nodev(fs_type, flags, zmo, zpl_fill_super)); } #else static int @@ -521,7 +465,6 @@ const char *osname, void *data, struct vfsmount *mnt) { zfs_mntopts_t *zmo = zfs_mntopts_alloc(); - struct super_block *sb; int error; error = zpl_parse_options((char *)osname, (char *)data, zmo, B_FALSE); @@ -529,15 +472,10 @@ zfs_mntopts_free(zmo); return (error); } - sb = zpl_mount_impl(fs_type, flags, zmo); - if (IS_ERR(sb)) - return (ERR_CAST(sb)); - (void) simple_set_mnt(mnt, sb); - - return (0); + return (get_sb_nodev(fs_type, flags, zmo, zpl_fill_super, mnt)); } -#endif /* HAVE_FST_MOUNT */ +#endif /* HAVE_MOUNT_NODEV */ static void zpl_kill_sb(struct super_block *sb) @@ -605,9 +543,9 @@ .owner = THIS_MODULE, .name = ZFS_DRIVER, -#ifdef HAVE_FST_MOUNT +#ifdef HAVE_MOUNT_NODEV .mount = zpl_mount, #else .get_sb = zpl_get_sb, -#endif /* HAVE_FST_MOUNT */ +#endif /* HAVE_MOUNT_NODEV */ .kill_sb = zpl_kill_sb, }; diff -u linux-lts-xenial-4.4.0/zfs/zfs_config.h.in linux-lts-xenial-4.4.0/zfs/zfs_config.h.in --- linux-lts-xenial-4.4.0/zfs/zfs_config.h.in +++ linux-lts-xenial-4.4.0/zfs/zfs_config.h.in @@ -162,9 +162,6 @@ /* sops->free_cached_objects() exists */ #undef HAVE_FREE_CACHED_OBJECTS -/* fst->mount() exists */ -#undef HAVE_FST_MOUNT - /* fops->fsync() with range */ #undef HAVE_FSYNC_RANGE @@ -255,6 +252,9 @@ /* Define to 1 if you have the `mlockall' function. */ #undef HAVE_MLOCKALL +/* mount_nodev() is available */ +#undef HAVE_MOUNT_NODEV + /* sops->nr_cached_objects() exists */ #undef HAVE_NR_CACHED_OBJECTS only in patch2: unchanged: --- linux-lts-xenial-4.4.0.orig/Documentation/security/00-INDEX +++ linux-lts-xenial-4.4.0/Documentation/security/00-INDEX @@ -24,3 +24,7 @@ - documentation on the TOMOYO Linux Security Module. IMA-templates.txt - documentation on the template management mechanism for IMA. +l1tf.txt + - Describes CPU vulnerabilities and provides an overview of the + possible mitigations along with guidiance for selecting miti- + gations if they are configurable at compile, boot or run time. only in patch2: unchanged: --- linux-lts-xenial-4.4.0.orig/Documentation/security/l1tf.txt +++ linux-lts-xenial-4.4.0/Documentation/security/l1tf.txt @@ -0,0 +1,610 @@ +L1TF - L1 Terminal Fault +======================== + +L1 Terminal Fault is a hardware vulnerability which allows unprivileged +speculative access to data which is available in the Level 1 Data Cache +when the page table entry controlling the virtual address, which is used +for the access, has the Present bit cleared or other reserved bits set. + +Affected processors +------------------- + +This vulnerability affects a wide range of Intel processors. The +vulnerability is not present on: + + - Processors from AMD, Centaur and other non Intel vendors + + - Older processor models, where the CPU family is < 6 + + - A range of Intel ATOM processors (Cedarview, Cloverview, Lincroft, + Penwell, Pineview, Silvermont, Airmont, Merrifield) + + - The Intel XEON PHI family + + - Intel processors which have the ARCH_CAP_RDCL_NO bit set in the + IA32_ARCH_CAPABILITIES MSR. If the bit is set the CPU is not affected + by the Meltdown vulnerability either. These CPUs should become + available by end of 2018. + +Whether a processor is affected or not can be read out from the L1TF +vulnerability file in sysfs. See :ref:`l1tf_sys_info`. + +Related CVEs +------------ + +The following CVE entries are related to the L1TF vulnerability: + + ============= ================= ============================== + CVE-2018-3615 L1 Terminal Fault SGX related aspects + CVE-2018-3620 L1 Terminal Fault OS, SMM related aspects + CVE-2018-3646 L1 Terminal Fault Virtualization related aspects + ============= ================= ============================== + +Problem +------- + +If an instruction accesses a virtual address for which the relevant page +table entry (PTE) has the Present bit cleared or other reserved bits set, +then speculative execution ignores the invalid PTE and loads the referenced +data if it is present in the Level 1 Data Cache, as if the page referenced +by the address bits in the PTE was still present and accessible. + +While this is a purely speculative mechanism and the instruction will raise +a page fault when it is retired eventually, the pure act of loading the +data and making it available to other speculative instructions opens up the +opportunity for side channel attacks to unprivileged malicious code, +similar to the Meltdown attack. + +While Meltdown breaks the user space to kernel space protection, L1TF +allows to attack any physical memory address in the system and the attack +works across all protection domains. It allows an attack of SGX and also +works from inside virtual machines because the speculation bypasses the +extended page table (EPT) protection mechanism. + + +Attack scenarios +---------------- + +1. Malicious user space +^^^^^^^^^^^^^^^^^^^^^^^ + + Operating Systems store arbitrary information in the address bits of a + PTE which is marked non present. This allows a malicious user space + application to attack the physical memory to which these PTEs resolve. + In some cases user-space can maliciously influence the information + encoded in the address bits of the PTE, thus making attacks more + deterministic and more practical. + + The Linux kernel contains a mitigation for this attack vector, PTE + inversion, which is permanently enabled and has no performance + impact. The kernel ensures that the address bits of PTEs, which are not + marked present, never point to cacheable physical memory space. + + A system with an up to date kernel is protected against attacks from + malicious user space applications. + +2. Malicious guest in a virtual machine +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + The fact that L1TF breaks all domain protections allows malicious guest + OSes, which can control the PTEs directly, and malicious guest user + space applications, which run on an unprotected guest kernel lacking the + PTE inversion mitigation for L1TF, to attack physical host memory. + + A special aspect of L1TF in the context of virtualization is symmetric + multi threading (SMT). The Intel implementation of SMT is called + HyperThreading. The fact that Hyperthreads on the affected processors + share the L1 Data Cache (L1D) is important for this. As the flaw allows + only to attack data which is present in L1D, a malicious guest running + on one Hyperthread can attack the data which is brought into the L1D by + the context which runs on the sibling Hyperthread of the same physical + core. This context can be host OS, host user space or a different guest. + + If the processor does not support Extended Page Tables, the attack is + only possible, when the hypervisor does not sanitize the content of the + effective (shadow) page tables. + + While solutions exist to mitigate these attack vectors fully, these + mitigations are not enabled by default in the Linux kernel because they + can affect performance significantly. The kernel provides several + mechanisms which can be utilized to address the problem depending on the + deployment scenario. The mitigations, their protection scope and impact + are described in the next sections. + + The default mitigations and the rationale for choosing them are explained + at the end of this document. See :ref:`default_mitigations`. + +.. _l1tf_sys_info: + +L1TF system information +----------------------- + +The Linux kernel provides a sysfs interface to enumerate the current L1TF +status of the system: whether the system is vulnerable, and which +mitigations are active. The relevant sysfs file is: + +/sys/devices/system/cpu/vulnerabilities/l1tf + +The possible values in this file are: + + =========================== =============================== + 'Not affected' The processor is not vulnerable + 'Mitigation: PTE Inversion' The host protection is active + =========================== =============================== + +If KVM/VMX is enabled and the processor is vulnerable then the following +information is appended to the 'Mitigation: PTE Inversion' part: + + - SMT status: + + ===================== ================ + 'VMX: SMT vulnerable' SMT is enabled + 'VMX: SMT disabled' SMT is disabled + ===================== ================ + + - L1D Flush mode: + + ================================ ==================================== + 'L1D vulnerable' L1D flushing is disabled + + 'L1D conditional cache flushes' L1D flush is conditionally enabled + + 'L1D cache flushes' L1D flush is unconditionally enabled + ================================ ==================================== + +The resulting grade of protection is discussed in the following sections. + + +Host mitigation mechanism +------------------------- + +The kernel is unconditionally protected against L1TF attacks from malicious +user space running on the host. + + +Guest mitigation mechanisms +--------------------------- + +.. _l1d_flush: + +1. L1D flush on VMENTER +^^^^^^^^^^^^^^^^^^^^^^^ + + To make sure that a guest cannot attack data which is present in the L1D + the hypervisor flushes the L1D before entering the guest. + + Flushing the L1D evicts not only the data which should not be accessed + by a potentially malicious guest, it also flushes the guest + data. Flushing the L1D has a performance impact as the processor has to + bring the flushed guest data back into the L1D. Depending on the + frequency of VMEXIT/VMENTER and the type of computations in the guest + performance degradation in the range of 1% to 50% has been observed. For + scenarios where guest VMEXIT/VMENTER are rare the performance impact is + minimal. Virtio and mechanisms like posted interrupts are designed to + confine the VMEXITs to a bare minimum, but specific configurations and + application scenarios might still suffer from a high VMEXIT rate. + + The kernel provides two L1D flush modes: + - conditional ('cond') + - unconditional ('always') + + The conditional mode avoids L1D flushing after VMEXITs which execute + only audited code paths before the corresponding VMENTER. These code + paths have been verified that they cannot expose secrets or other + interesting data to an attacker, but they can leak information about the + address space layout of the hypervisor. + + Unconditional mode flushes L1D on all VMENTER invocations and provides + maximum protection. It has a higher overhead than the conditional + mode. The overhead cannot be quantified correctly as it depends on the + workload scenario and the resulting number of VMEXITs. + + The general recommendation is to enable L1D flush on VMENTER. The kernel + defaults to conditional mode on affected processors. + + **Note**, that L1D flush does not prevent the SMT problem because the + sibling thread will also bring back its data into the L1D which makes it + attackable again. + + L1D flush can be controlled by the administrator via the kernel command + line and sysfs control files. See :ref:`mitigation_control_command_line` + and :ref:`mitigation_control_kvm`. + +.. _guest_confinement: + +2. Guest VCPU confinement to dedicated physical cores +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + To address the SMT problem, it is possible to make a guest or a group of + guests affine to one or more physical cores. The proper mechanism for + that is to utilize exclusive cpusets to ensure that no other guest or + host tasks can run on these cores. + + If only a single guest or related guests run on sibling SMT threads on + the same physical core then they can only attack their own memory and + restricted parts of the host memory. + + Host memory is attackable, when one of the sibling SMT threads runs in + host OS (hypervisor) context and the other in guest context. The amount + of valuable information from the host OS context depends on the context + which the host OS executes, i.e. interrupts, soft interrupts and kernel + threads. The amount of valuable data from these contexts cannot be + declared as non-interesting for an attacker without deep inspection of + the code. + + **Note**, that assigning guests to a fixed set of physical cores affects + the ability of the scheduler to do load balancing and might have + negative effects on CPU utilization depending on the hosting + scenario. Disabling SMT might be a viable alternative for particular + scenarios. + + For further information about confining guests to a single or to a group + of cores consult the cpusets documentation: + + https://www.kernel.org/doc/Documentation/cgroup-v1/cpusets.txt + +.. _interrupt_isolation: + +3. Interrupt affinity +^^^^^^^^^^^^^^^^^^^^^ + + Interrupts can be made affine to logical CPUs. This is not universally + true because there are types of interrupts which are truly per CPU + interrupts, e.g. the local timer interrupt. Aside of that multi queue + devices affine their interrupts to single CPUs or groups of CPUs per + queue without allowing the administrator to control the affinities. + + Moving the interrupts, which can be affinity controlled, away from CPUs + which run untrusted guests, reduces the attack vector space. + + Whether the interrupts with are affine to CPUs, which run untrusted + guests, provide interesting data for an attacker depends on the system + configuration and the scenarios which run on the system. While for some + of the interrupts it can be assumed that they won't expose interesting + information beyond exposing hints about the host OS memory layout, there + is no way to make general assumptions. + + Interrupt affinity can be controlled by the administrator via the + /proc/irq/$NR/smp_affinity[_list] files. Limited documentation is + available at: + + https://www.kernel.org/doc/Documentation/IRQ-affinity.txt + +.. _smt_control: + +4. SMT control +^^^^^^^^^^^^^^ + + To prevent the SMT issues of L1TF it might be necessary to disable SMT + completely. Disabling SMT can have a significant performance impact, but + the impact depends on the hosting scenario and the type of workloads. + The impact of disabling SMT needs also to be weighted against the impact + of other mitigation solutions like confining guests to dedicated cores. + + The kernel provides a sysfs interface to retrieve the status of SMT and + to control it. It also provides a kernel command line interface to + control SMT. + + The kernel command line interface consists of the following options: + + =========== ========================================================== + nosmt Affects the bring up of the secondary CPUs during boot. The + kernel tries to bring all present CPUs online during the + boot process. "nosmt" makes sure that from each physical + core only one - the so called primary (hyper) thread is + activated. Due to a design flaw of Intel processors related + to Machine Check Exceptions the non primary siblings have + to be brought up at least partially and are then shut down + again. "nosmt" can be undone via the sysfs interface. + + nosmt=force Has the same effect as "nosmt" but it does not allow to + undo the SMT disable via the sysfs interface. + =========== ========================================================== + + The sysfs interface provides two files: + + - /sys/devices/system/cpu/smt/control + - /sys/devices/system/cpu/smt/active + + /sys/devices/system/cpu/smt/control: + + This file allows to read out the SMT control state and provides the + ability to disable or (re)enable SMT. The possible states are: + + ============== =================================================== + on SMT is supported by the CPU and enabled. All + logical CPUs can be onlined and offlined without + restrictions. + + off SMT is supported by the CPU and disabled. Only + the so called primary SMT threads can be onlined + and offlined without restrictions. An attempt to + online a non-primary sibling is rejected + + forceoff Same as 'off' but the state cannot be controlled. + Attempts to write to the control file are rejected. + + notsupported The processor does not support SMT. It's therefore + not affected by the SMT implications of L1TF. + Attempts to write to the control file are rejected. + ============== =================================================== + + The possible states which can be written into this file to control SMT + state are: + + - on + - off + - forceoff + + /sys/devices/system/cpu/smt/active: + + This file reports whether SMT is enabled and active, i.e. if on any + physical core two or more sibling threads are online. + + SMT control is also possible at boot time via the l1tf kernel command + line parameter in combination with L1D flush control. See + :ref:`mitigation_control_command_line`. + +5. Disabling EPT +^^^^^^^^^^^^^^^^ + + Disabling EPT for virtual machines provides full mitigation for L1TF even + with SMT enabled, because the effective page tables for guests are + managed and sanitized by the hypervisor. Though disabling EPT has a + significant performance impact especially when the Meltdown mitigation + KPTI is enabled. + + EPT can be disabled in the hypervisor via the 'kvm-intel.ept' parameter. + +There is ongoing research and development for new mitigation mechanisms to +address the performance impact of disabling SMT or EPT. + +.. _mitigation_control_command_line: + +Mitigation control on the kernel command line +--------------------------------------------- + +The kernel command line allows to control the L1TF mitigations at boot +time with the option "l1tf=". The valid arguments for this option are: + + ============ ============================================================= + full Provides all available mitigations for the L1TF + vulnerability. Disables SMT and enables all mitigations in + the hypervisors, i.e. unconditional L1D flushing + + SMT control and L1D flush control via the sysfs interface + is still possible after boot. Hypervisors will issue a + warning when the first VM is started in a potentially + insecure configuration, i.e. SMT enabled or L1D flush + disabled. + + full,force Same as 'full', but disables SMT and L1D flush runtime + control. Implies the 'nosmt=force' command line option. + (i.e. sysfs control of SMT is disabled.) + + flush Leaves SMT enabled and enables the default hypervisor + mitigation, i.e. conditional L1D flushing + + SMT control and L1D flush control via the sysfs interface + is still possible after boot. Hypervisors will issue a + warning when the first VM is started in a potentially + insecure configuration, i.e. SMT enabled or L1D flush + disabled. + + flush,nosmt Disables SMT and enables the default hypervisor mitigation, + i.e. conditional L1D flushing. + + SMT control and L1D flush control via the sysfs interface + is still possible after boot. Hypervisors will issue a + warning when the first VM is started in a potentially + insecure configuration, i.e. SMT enabled or L1D flush + disabled. + + flush,nowarn Same as 'flush', but hypervisors will not warn when a VM is + started in a potentially insecure configuration. + + off Disables hypervisor mitigations and doesn't emit any + warnings. + ============ ============================================================= + +The default is 'flush'. For details about L1D flushing see :ref:`l1d_flush`. + + +.. _mitigation_control_kvm: + +Mitigation control for KVM - module parameter +------------------------------------------------------------- + +The KVM hypervisor mitigation mechanism, flushing the L1D cache when +entering a guest, can be controlled with a module parameter. + +The option/parameter is "kvm-intel.vmentry_l1d_flush=". It takes the +following arguments: + + ============ ============================================================== + always L1D cache flush on every VMENTER. + + cond Flush L1D on VMENTER only when the code between VMEXIT and + VMENTER can leak host memory which is considered + interesting for an attacker. This still can leak host memory + which allows e.g. to determine the hosts address space layout. + + never Disables the mitigation + ============ ============================================================== + +The parameter can be provided on the kernel command line, as a module +parameter when loading the modules and at runtime modified via the sysfs +file: + +/sys/module/kvm_intel/parameters/vmentry_l1d_flush + +The default is 'cond'. If 'l1tf=full,force' is given on the kernel command +line, then 'always' is enforced and the kvm-intel.vmentry_l1d_flush +module parameter is ignored and writes to the sysfs file are rejected. + + +Mitigation selection guide +-------------------------- + +1. No virtualization in use +^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + The system is protected by the kernel unconditionally and no further + action is required. + +2. Virtualization with trusted guests +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + If the guest comes from a trusted source and the guest OS kernel is + guaranteed to have the L1TF mitigations in place the system is fully + protected against L1TF and no further action is required. + + To avoid the overhead of the default L1D flushing on VMENTER the + administrator can disable the flushing via the kernel command line and + sysfs control files. See :ref:`mitigation_control_command_line` and + :ref:`mitigation_control_kvm`. + + +3. Virtualization with untrusted guests +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +3.1. SMT not supported or disabled +"""""""""""""""""""""""""""""""""" + + If SMT is not supported by the processor or disabled in the BIOS or by + the kernel, it's only required to enforce L1D flushing on VMENTER. + + Conditional L1D flushing is the default behaviour and can be tuned. See + :ref:`mitigation_control_command_line` and :ref:`mitigation_control_kvm`. + +3.2. EPT not supported or disabled +"""""""""""""""""""""""""""""""""" + + If EPT is not supported by the processor or disabled in the hypervisor, + the system is fully protected. SMT can stay enabled and L1D flushing on + VMENTER is not required. + + EPT can be disabled in the hypervisor via the 'kvm-intel.ept' parameter. + +3.3. SMT and EPT supported and active +""""""""""""""""""""""""""""""""""""" + + If SMT and EPT are supported and active then various degrees of + mitigations can be employed: + + - L1D flushing on VMENTER: + + L1D flushing on VMENTER is the minimal protection requirement, but it + is only potent in combination with other mitigation methods. + + Conditional L1D flushing is the default behaviour and can be tuned. See + :ref:`mitigation_control_command_line` and :ref:`mitigation_control_kvm`. + + - Guest confinement: + + Confinement of guests to a single or a group of physical cores which + are not running any other processes, can reduce the attack surface + significantly, but interrupts, soft interrupts and kernel threads can + still expose valuable data to a potential attacker. See + :ref:`guest_confinement`. + + - Interrupt isolation: + + Isolating the guest CPUs from interrupts can reduce the attack surface + further, but still allows a malicious guest to explore a limited amount + of host physical memory. This can at least be used to gain knowledge + about the host address space layout. The interrupts which have a fixed + affinity to the CPUs which run the untrusted guests can depending on + the scenario still trigger soft interrupts and schedule kernel threads + which might expose valuable information. See + :ref:`interrupt_isolation`. + +The above three mitigation methods combined can provide protection to a +certain degree, but the risk of the remaining attack surface has to be +carefully analyzed. For full protection the following methods are +available: + + - Disabling SMT: + + Disabling SMT and enforcing the L1D flushing provides the maximum + amount of protection. This mitigation is not depending on any of the + above mitigation methods. + + SMT control and L1D flushing can be tuned by the command line + parameters 'nosmt', 'l1tf', 'kvm-intel.vmentry_l1d_flush' and at run + time with the matching sysfs control files. See :ref:`smt_control`, + :ref:`mitigation_control_command_line` and + :ref:`mitigation_control_kvm`. + + - Disabling EPT: + + Disabling EPT provides the maximum amount of protection as well. It is + not depending on any of the above mitigation methods. SMT can stay + enabled and L1D flushing is not required, but the performance impact is + significant. + + EPT can be disabled in the hypervisor via the 'kvm-intel.ept' + parameter. + +3.4. Nested virtual machines +"""""""""""""""""""""""""""" + +When nested virtualization is in use, three operating systems are involved: +the bare metal hypervisor, the nested hypervisor and the nested virtual +machine. VMENTER operations from the nested hypervisor into the nested +guest will always be processed by the bare metal hypervisor. If KVM is the +bare metal hypervisor it wiil: + + - Flush the L1D cache on every switch from the nested hypervisor to the + nested virtual machine, so that the nested hypervisor's secrets are not + exposed to the nested virtual machine; + + - Flush the L1D cache on every switch from the nested virtual machine to + the nested hypervisor; this is a complex operation, and flushing the L1D + cache avoids that the bare metal hypervisor's secrets are exposed to the + nested virtual machine; + + - Instruct the nested hypervisor to not perform any L1D cache flush. This + is an optimization to avoid double L1D flushing. + + +.. _default_mitigations: + +Default mitigations +------------------- + + The kernel default mitigations for vulnerable processors are: + + - PTE inversion to protect against malicious user space. This is done + unconditionally and cannot be controlled. + + - L1D conditional flushing on VMENTER when EPT is enabled for + a guest. + + The kernel does not by default enforce the disabling of SMT, which leaves + SMT systems vulnerable when running untrusted guests with EPT enabled. + + The rationale for this choice is: + + - Force disabling SMT can break existing setups, especially with + unattended updates. + + - If regular users run untrusted guests on their machine, then L1TF is + just an add on to other malware which might be embedded in an untrusted + guest, e.g. spam-bots or attacks on the local network. + + There is no technical way to prevent a user from running untrusted code + on their machines blindly. + + - It's technically extremely unlikely and from today's knowledge even + impossible that L1TF can be exploited via the most popular attack + mechanisms like JavaScript because these mechanisms have no way to + control PTEs. If this would be possible and not other mitigation would + be possible, then the default might be different. + + - The administrators of cloud and hosting setups have to carefully + analyze the risk for their scenarios and make the appropriate + mitigation choices, which might even vary across their deployed + machines and also result in other changes of their overall setup. + There is no way for the kernel to provide a sensible default for this + kind of scenarios. only in patch2: unchanged: --- linux-lts-xenial-4.4.0.orig/arch/Kconfig +++ linux-lts-xenial-4.4.0/arch/Kconfig @@ -5,6 +5,9 @@ config KEXEC_CORE bool +config HOTPLUG_SMT + bool + config OPROFILE tristate "OProfile system profiling" depends on PROFILING only in patch2: unchanged: --- linux-lts-xenial-4.4.0.orig/arch/x86/include/asm/dmi.h +++ linux-lts-xenial-4.4.0/arch/x86/include/asm/dmi.h @@ -3,8 +3,8 @@ #include #include +#include -#include #include static __always_inline __init void *dmi_alloc(unsigned len) only in patch2: unchanged: --- linux-lts-xenial-4.4.0.orig/arch/x86/include/asm/page_32_types.h +++ linux-lts-xenial-4.4.0/arch/x86/include/asm/page_32_types.h @@ -27,8 +27,13 @@ #define N_EXCEPTION_STACKS 1 #ifdef CONFIG_X86_PAE -/* 44=32+12, the limit we can fit into an unsigned long pfn */ -#define __PHYSICAL_MASK_SHIFT 44 +/* + * This is beyond the 44 bit limit imposed by the 32bit long pfns, + * but we need the full mask to make sure inverted PROT_NONE + * entries have all the host bits set in a guest. + * The real limit is still 44 bits. + */ +#define __PHYSICAL_MASK_SHIFT 52 #define __VIRTUAL_MASK_SHIFT 32 #else /* !CONFIG_X86_PAE */ only in patch2: unchanged: --- linux-lts-xenial-4.4.0.orig/arch/x86/include/asm/pgtable-2level.h +++ linux-lts-xenial-4.4.0/arch/x86/include/asm/pgtable-2level.h @@ -77,4 +77,21 @@ #define __pte_to_swp_entry(pte) ((swp_entry_t) { (pte).pte_low }) #define __swp_entry_to_pte(x) ((pte_t) { .pte = (x).val }) +/* No inverted PFNs on 2 level page tables */ + +static inline u64 protnone_mask(u64 val) +{ + return 0; +} + +static inline u64 flip_protnone_guard(u64 oldval, u64 val, u64 mask) +{ + return val; +} + +static inline bool __pte_needs_invert(u64 val) +{ + return false; +} + #endif /* _ASM_X86_PGTABLE_2LEVEL_H */ only in patch2: unchanged: --- linux-lts-xenial-4.4.0.orig/arch/x86/include/asm/pgtable-3level.h +++ linux-lts-xenial-4.4.0/arch/x86/include/asm/pgtable-3level.h @@ -177,11 +177,46 @@ #endif /* Encode and de-code a swap entry */ +#define SWP_TYPE_BITS 5 + +#define SWP_OFFSET_FIRST_BIT (_PAGE_BIT_PROTNONE + 1) + +/* We always extract/encode the offset by shifting it all the way up, + * and then down again + */ +#define SWP_OFFSET_SHIFT (SWP_OFFSET_FIRST_BIT + SWP_TYPE_BITS) + #define MAX_SWAPFILES_CHECK() BUILD_BUG_ON(MAX_SWAPFILES_SHIFT > 5) #define __swp_type(x) (((x).val) & 0x1f) #define __swp_offset(x) ((x).val >> 5) #define __swp_entry(type, offset) ((swp_entry_t){(type) | (offset) << 5}) -#define __pte_to_swp_entry(pte) ((swp_entry_t){ (pte).pte_high }) -#define __swp_entry_to_pte(x) ((pte_t){ { .pte_high = (x).val } }) + +/* + * Normally, __swp_entry() converts from arch-independent swp_entry_t to + * arch-dependent swp_entry_t, and __swp_entry_to_pte() just stores the result + * to pte. But here we have 32bit swp_entry_t and 64bit pte, and need to use the + * whole 64 bits. Thus, we shift the "real" arch-dependent conversion to + * __swp_entry_to_pte() through the following helper macro based on 64bit + * __swp_entry(). + */ +#define __swp_pteval_entry(type, offset) ((pteval_t) { \ + (~(pteval_t)(offset) << SWP_OFFSET_SHIFT >> SWP_TYPE_BITS) \ + | ((pteval_t)(type) << (64 - SWP_TYPE_BITS)) }) + +#define __swp_entry_to_pte(x) ((pte_t){ .pte = \ + __swp_pteval_entry(__swp_type(x), __swp_offset(x)) }) +/* + * Analogically, __pte_to_swp_entry() doesn't just extract the arch-dependent + * swp_entry_t, but also has to convert it from 64bit to the 32bit + * intermediate representation, using the following macros based on 64bit + * __swp_type() and __swp_offset(). + */ +#define __pteval_swp_type(x) ((unsigned long)((x).pte >> (64 - SWP_TYPE_BITS))) +#define __pteval_swp_offset(x) ((unsigned long)(~((x).pte) << SWP_TYPE_BITS >> SWP_OFFSET_SHIFT)) + +#define __pte_to_swp_entry(pte) (__swp_entry(__pteval_swp_type(pte), \ + __pteval_swp_offset(pte))) + +#include #endif /* _ASM_X86_PGTABLE_3LEVEL_H */ only in patch2: unchanged: --- linux-lts-xenial-4.4.0.orig/arch/x86/include/asm/pgtable-invert.h +++ linux-lts-xenial-4.4.0/arch/x86/include/asm/pgtable-invert.h @@ -0,0 +1,32 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef _ASM_PGTABLE_INVERT_H +#define _ASM_PGTABLE_INVERT_H 1 + +#ifndef __ASSEMBLY__ + +static inline bool __pte_needs_invert(u64 val) +{ + return !(val & _PAGE_PRESENT); +} + +/* Get a mask to xor with the page table entry to get the correct pfn. */ +static inline u64 protnone_mask(u64 val) +{ + return __pte_needs_invert(val) ? ~0ull : 0; +} + +static inline u64 flip_protnone_guard(u64 oldval, u64 val, u64 mask) +{ + /* + * When a PTE transitions from NONE to !NONE or vice-versa + * invert the PFN part to stop speculation. + * pte_pfn undoes this when needed. + */ + if (__pte_needs_invert(oldval) != __pte_needs_invert(val)) + val = (val & ~mask) | (~val & mask); + return val; +} + +#endif /* __ASSEMBLY__ */ + +#endif only in patch2: unchanged: --- linux-lts-xenial-4.4.0.orig/arch/x86/kernel/apic/htirq.c +++ linux-lts-xenial-4.4.0/arch/x86/kernel/apic/htirq.c @@ -12,6 +12,7 @@ */ #include #include +#include #include #include #include only in patch2: unchanged: --- linux-lts-xenial-4.4.0.orig/arch/x86/kernel/cpu/topology.c +++ linux-lts-xenial-4.4.0/arch/x86/kernel/cpu/topology.c @@ -21,21 +21,13 @@ #define BITS_SHIFT_NEXT_LEVEL(eax) ((eax) & 0x1f) #define LEVEL_MAX_SIBLINGS(ebx) ((ebx) & 0xffff) -/* - * Check for extended topology enumeration cpuid leaf 0xb and if it - * exists, use it for populating initial_apicid and cpu topology - * detection. - */ -void detect_extended_topology(struct cpuinfo_x86 *c) +int detect_extended_topology_early(struct cpuinfo_x86 *c) { #ifdef CONFIG_SMP - unsigned int eax, ebx, ecx, edx, sub_index; - unsigned int ht_mask_width, core_plus_mask_width; - unsigned int core_select_mask, core_level_siblings; - static bool printed; + unsigned int eax, ebx, ecx, edx; if (c->cpuid_level < 0xb) - return; + return -1; cpuid_count(0xb, SMT_LEVEL, &eax, &ebx, &ecx, &edx); @@ -43,7 +35,7 @@ * check if the cpuid leaf 0xb is actually implemented. */ if (ebx == 0 || (LEAFB_SUBTYPE(ecx) != SMT_TYPE)) - return; + return -1; set_cpu_cap(c, X86_FEATURE_XTOPOLOGY); @@ -51,10 +43,30 @@ * initial apic id, which also represents 32-bit extended x2apic id. */ c->initial_apicid = edx; + smp_num_siblings = LEVEL_MAX_SIBLINGS(ebx); +#endif + return 0; +} + +/* + * Check for extended topology enumeration cpuid leaf 0xb and if it + * exists, use it for populating initial_apicid and cpu topology + * detection. + */ +int detect_extended_topology(struct cpuinfo_x86 *c) +{ +#ifdef CONFIG_SMP + unsigned int eax, ebx, ecx, edx, sub_index; + unsigned int ht_mask_width, core_plus_mask_width; + unsigned int core_select_mask, core_level_siblings; + + if (detect_extended_topology_early(c) < 0) + return -1; /* * Populate HT related information from sub-leaf level 0. */ + cpuid_count(0xb, SMT_LEVEL, &eax, &ebx, &ecx, &edx); core_level_siblings = smp_num_siblings = LEVEL_MAX_SIBLINGS(ebx); core_plus_mask_width = ht_mask_width = BITS_SHIFT_NEXT_LEVEL(eax); @@ -85,15 +97,6 @@ c->apicid = apic->phys_pkg_id(c->initial_apicid, 0); c->x86_max_cores = (core_level_siblings / smp_num_siblings); - - if (!printed) { - printk(KERN_INFO "CPU: Physical Processor ID: %d\n", - c->phys_proc_id); - if (c->x86_max_cores > 1) - printk(KERN_INFO "CPU: Processor Core ID: %d\n", - c->cpu_core_id); - printed = 1; - } - return; #endif + return 0; } only in patch2: unchanged: --- linux-lts-xenial-4.4.0.orig/arch/x86/kernel/smp.c +++ linux-lts-xenial-4.4.0/arch/x86/kernel/smp.c @@ -261,6 +261,7 @@ { ack_APIC_irq(); __smp_reschedule_interrupt(); + kvm_set_cpu_l1tf_flush_l1d(); /* * KVM uses this interrupt to force a cpu out of guest mode */ only in patch2: unchanged: --- linux-lts-xenial-4.4.0.orig/arch/x86/kernel/time.c +++ linux-lts-xenial-4.4.0/arch/x86/kernel/time.c @@ -11,6 +11,7 @@ #include #include +#include #include #include #include only in patch2: unchanged: --- linux-lts-xenial-4.4.0.orig/arch/x86/platform/efi/efi_64.c +++ linux-lts-xenial-4.4.0/arch/x86/platform/efi/efi_64.c @@ -30,6 +30,7 @@ #include #include +#include #include #include #include @@ -143,7 +144,7 @@ int __init efi_setup_page_tables(unsigned long pa_memmap, unsigned num_pages) { - unsigned long text; + unsigned long pfn, text; struct page *page; unsigned npages; pgd_t *pgd; @@ -160,7 +161,8 @@ * and ident-map those pages containing the map before calling * phys_efi_set_virtual_address_map(). */ - if (kernel_map_pages_in_pgd(pgd, pa_memmap, pa_memmap, num_pages, _PAGE_NX)) { + pfn = pa_memmap >> PAGE_SHIFT; + if (kernel_map_pages_in_pgd(pgd, pfn, pa_memmap, num_pages, _PAGE_NX)) { pr_err("Error ident-mapping new memmap (0x%lx)!\n", pa_memmap); return 1; } @@ -185,8 +187,9 @@ npages = (_end - _text) >> PAGE_SHIFT; text = __pa(_text); + pfn = text >> PAGE_SHIFT; - if (kernel_map_pages_in_pgd(pgd, text >> PAGE_SHIFT, text, npages, 0)) { + if (kernel_map_pages_in_pgd(pgd, pfn, text, npages, 0)) { pr_err("Failed to map kernel text 1:1\n"); return 1; } @@ -204,12 +207,14 @@ static void __init __map_region(efi_memory_desc_t *md, u64 va) { pgd_t *pgd = (pgd_t *)__va(real_mode_header->trampoline_pgd); - unsigned long pf = 0; + unsigned long flags = 0; + unsigned long pfn; if (!(md->attribute & EFI_MEMORY_WB)) - pf |= _PAGE_PCD; + flags |= _PAGE_PCD; - if (kernel_map_pages_in_pgd(pgd, md->phys_addr, va, md->num_pages, pf)) + pfn = md->phys_addr >> PAGE_SHIFT; + if (kernel_map_pages_in_pgd(pgd, pfn, va, md->num_pages, flags)) pr_warn("Error mapping PA 0x%llx -> VA 0x%llx!\n", md->phys_addr, va); } only in patch2: unchanged: --- linux-lts-xenial-4.4.0.orig/arch/x86/platform/uv/tlb_uv.c +++ linux-lts-xenial-4.4.0/arch/x86/platform/uv/tlb_uv.c @@ -1249,6 +1249,7 @@ struct msg_desc msgdesc; ack_APIC_irq(); + kvm_set_cpu_l1tf_flush_l1d(); time_start = get_cycles(); bcp = &per_cpu(bau_control, smp_processor_id()); only in patch2: unchanged: --- linux-lts-xenial-4.4.0.orig/drivers/platform/x86/dell-smo8800.c +++ linux-lts-xenial-4.4.0/drivers/platform/x86/dell-smo8800.c @@ -23,6 +23,7 @@ #include #include #include +#include #include struct smo8800_device { only in patch2: unchanged: --- linux-lts-xenial-4.4.0.orig/include/linux/swapfile.h +++ linux-lts-xenial-4.4.0/include/linux/swapfile.h @@ -9,5 +9,7 @@ extern struct plist_head swap_active_head; extern struct swap_info_struct *swap_info[]; extern int try_to_unuse(unsigned int, bool, unsigned long); +extern unsigned long generic_max_swapfile_size(void); +extern unsigned long max_swapfile_size(void); #endif /* _LINUX_SWAPFILE_H */ only in patch2: unchanged: --- linux-lts-xenial-4.4.0.orig/ubuntu/ixxat/ixx_usb_fd.c +++ linux-lts-xenial-4.4.0/ubuntu/ixxat/ixx_usb_fd.c @@ -0,0 +1,1673 @@ +/* + * CAN driver for IXXAT USB-to-CAN FD + * + * Copyright (C) 2017 Michael Hengler + * + * Based on code originally by pcan_usb_core + * + * 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; version 2 of the License. + * + * 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 +#include +#include + +#include "ixx_usb_core.h" + +#ifdef CANFD_CAPABLE + +MODULE_SUPPORTED_DEVICE("IXXAT Automation GmbH USB-to-CAN FD"); + +/* use ifi can fd clock due to internal bittiming calculations */ +#define IFIFD_CRYSTAL_HZ 80000000 + +/* usb-to-can fd Endpoints */ +#define IXXAT_USBFD_EP_CMDOUT 0 +#define IXXAT_USBFD_EP_CMDIN (IXXAT_USBFD_EP_CMDOUT | USB_DIR_IN) +#define IXXAT_USBFD_EP_MSGOUT_0 1 +#define IXXAT_USBFD_EP_MSGIN_0 (IXXAT_USBFD_EP_MSGOUT_0 | USB_DIR_IN) +#define IXXAT_USBFD_EP_MSGOUT_1 2 +#define IXXAT_USBFD_EP_MSGIN_1 (IXXAT_USBFD_EP_MSGOUT_1 | USB_DIR_IN) +#define IXXAT_USBFD_EP_MSGOUT_2 3 +#define IXXAT_USBFD_EP_MSGIN_2 (IXXAT_USBFD_EP_MSGOUT_2 | USB_DIR_IN) +#define IXXAT_USBFD_EP_MSGOUT_3 4 +#define IXXAT_USBFD_EP_MSGIN_3 (IXXAT_USBFD_EP_MSGOUT_3 | USB_DIR_IN) +#define IXXAT_USBFD_EP_MSGOUT_4 5 +#define IXXAT_USBFD_EP_MSGIN_4 (IXXAT_USBFD_EP_MSGOUT_4 | USB_DIR_IN) + +/* DELL Edge GW3002 Endpoints */ +#define DELL_EDGE_GW3002_EP_MSGOUT_0 1 +#define DELL_EDGE_GW3002_EP_MSGIN_0 (2 | USB_DIR_IN) +#define DELL_EDGE_GW3002_EP_MSGOUT_1 3 +#define DELL_EDGE_GW3002_EP_MSGIN_1 (4 | USB_DIR_IN) +#define DELL_EDGE_GW3002_EP_MSGOUT_2 5 +#define DELL_EDGE_GW3002_EP_MSGIN_2 (6 | USB_DIR_IN) +#define DELL_EDGE_GW3002_EP_MSGOUT_3 7 +#define DELL_EDGE_GW3002_EP_MSGIN_3 (8 | USB_DIR_IN) +#define DELL_EDGE_GW3002_EP_MSGOUT_4 9 +#define DELL_EDGE_GW3002_EP_MSGIN_4 (10 | USB_DIR_IN) + +/* usb-to-can fd rx/tx buffers size */ +#define IXXAT_USBFD_RX_BUFFER_SIZE 512 +#define IXXAT_USBFD_TX_BUFFER_SIZE 512 + +#define IXXAT_USBFD_CMD_BUFFER_SIZE 256 + +/* reception of 11-bit id messages */ +#define IXXAT_USBFD_OPMODE_STANDARD 0x01 +/* reception of 29-bit id messages */ +#define IXXAT_USBFD_OPMODE_EXTENDED 0x02 +/* enable reception of error frames */ +#define IXXAT_USBFD_OPMODE_ERRFRAME 0x04 +/* listen only mode (TX passive) */ +#define IXXAT_USBFD_OPMODE_LISTONLY 0x08 + +/* no extended operation */ +#define IXXAT_USBFD_EXMODE_DISABLED 0x00 +/* extended data length */ +#define IXXAT_USBFD_EXMODE_EXTDATA 0x01 +/* fast data bit rate */ +#define IXXAT_USBFD_EXMODE_FASTDATA 0x02 +/* ISO conform CAN-FD frame */ +#define IXXAT_USBFD_EXMODE_ISOFD 0x04 + +/* Stuff error */ +#define IXXAT_USBFD_CAN_ERROR_STUFF 1 +/* Form error */ +#define IXXAT_USBFD_CAN_ERROR_FORM 2 +/* Acknowledgment error */ +#define IXXAT_USBFD_CAN_ERROR_ACK 3 +/* Bit error */ +#define IXXAT_USBFD_CAN_ERROR_BIT 4 +/* Fast data bit rate error */ +#define IXXAT_USBFD_CAN_ERROR_FAST_DATA 5 +/* CRC error */ +#define IXXAT_USBFD_CAN_ERROR_CRC 6 +/* Other (unspecified) error */ +#define IXXAT_USBFD_CAN_ERROR_OTHER 7 + +/* Data overrun occurred */ +#define IXXAT_USBFD_CAN_STATUS_OVRRUN 0x02 +/* Error warning limit exceeded */ +#define IXXAT_USBFD_CAN_STATUS_ERRLIM 0x04 +/* Bus off status */ +#define IXXAT_USBFD_CAN_STATUS_BUSOFF 0x08 + +#define IXXAT_USBFD_CAN_DATA 0x00 +#define IXXAT_USBFD_CAN_INFO 0x01 +#define IXXAT_USBFD_CAN_ERROR 0x02 +#define IXXAT_USBFD_CAN_STATUS 0x03 +#define IXXAT_USBFD_CAN_WAKEUP 0x04 +#define IXXAT_USBFD_CAN_TIMEOVR 0x05 +#define IXXAT_USBFD_CAN_TIMERST 0x06 + + +#define IXXAT_USBFD_MSG_FLAGS_TYPE 0x000000FF +#define IXXAT_USBFD_MSG_FLAGS_SSM 0x00000100 +#define IXXAT_USBFD_MSG_FLAGS_HPM 0x00000200 +#define IXXAT_USBFD_MSG_FLAGS_EDL 0x00000400 +#define IXXAT_USBFD_MSG_FLAGS_FDR 0x00000800 +#define IXXAT_USBFD_MSG_FLAGS_ESI 0x00001000 +#define IXXAT_USBFD_MSG_FLAGS_RES 0x0000E000 +#define IXXAT_USBFD_MSG_FLAGS_DLC 0x000F0000 +#define IXXAT_USBFD_MSG_FLAGS_OVR 0x00100000 +#define IXXAT_USBFD_MSG_FLAGS_SRR 0x00200000 +#define IXXAT_USBFD_MSG_FLAGS_RTR 0x00400000 +#define IXXAT_USBFD_MSG_FLAGS_EXT 0x00800000 +#define IXXAT_USBFD_MSG_FLAGS_AFC 0xFF000000 + +#define IXXAT_USBFD_BAL_CMD_CLASS 3 +#define IXXAT_USBFD_BRD_CMD_CLASS 4 + +#define IXXAT_USBFD_BRD_CMD_CAT 0 +#define IXXAT_USBFD_CAN_CMD_CAT 1 + +#define IXXAT_USBFD_VCI_CMD_CODE(Class, Function) \ + ((u32) (((Class) << 8) | (Function))) + +#define IXXAT_USBFD_BRD_CMD_CODE(Category, Function) \ + IXXAT_USBFD_VCI_CMD_CODE(IXXAT_USBFD_BRD_CMD_CLASS, \ + ((Category) << 5) | (Function)) + +#define IXXAT_USBFD_BAL_CMD_CODE(Category, Function) \ + IXXAT_USBFD_VCI_CMD_CODE(IXXAT_USBFD_BAL_CMD_CLASS, \ + ((Category) << 5) | (Function)) + +#define IXXAT_USBFD_CAN_GET_CAPS_CMD \ + IXXAT_USBFD_BAL_CMD_CODE(IXXAT_USBFD_CAN_CMD_CAT, 0) +#define IXXAT_USBFD_POWER_CMD \ + IXXAT_USBFD_BRD_CMD_CODE(IXXAT_USBFD_CAN_CMD_CAT, 1) +#define IXXAT_USBFD_CAN_INIT_CMD \ + IXXAT_USBFD_BAL_CMD_CODE(IXXAT_USBFD_CAN_CMD_CAT, 5) +#define IXXAT_USBFD_CAN_START_CMD \ + IXXAT_USBFD_BAL_CMD_CODE(IXXAT_USBFD_CAN_CMD_CAT, 6) +#define IXXAT_USBFD_CAN_STOP_CMD \ + IXXAT_USBFD_BAL_CMD_CODE(IXXAT_USBFD_CAN_CMD_CAT, 7) +#define IXXAT_USBFD_CAN_RESET_CMD \ + IXXAT_USBFD_BAL_CMD_CODE(IXXAT_USBFD_CAN_CMD_CAT, 8) +/* Additional commands for USB-to-CAN FD */ +#define IXXAT_USBFD_INIT_V2_CMD \ + IXXAT_USBFD_BAL_CMD_CODE(IXXAT_USBFD_CAN_CMD_CAT, 23) + +#define IXXAT_USBFD_BRD_GET_FWINFO_CMD \ + IXXAT_USBFD_BRD_CMD_CODE(IXXAT_USBFD_BRD_CMD_CAT, 0) +#define IXXAT_USBFD_BRD_GET_DEVCAPS_CMD \ + IXXAT_USBFD_BRD_CMD_CODE(IXXAT_USBFD_BRD_CMD_CAT, 1) +#define IXXAT_USBFD_BRD_GET_DEVINFO_CMD \ + IXXAT_USBFD_BRD_CMD_CODE(IXXAT_USBFD_BRD_CMD_CAT, 2) + +struct ixx_usbfd_dal_req { + u32 req_size; + u16 req_port; + u16 req_socket; + u32 req_code; +} __packed; + +struct ixx_usbfd_dal_res { + u32 res_size; + u32 ret_size; + u32 ret_code; +} __packed; + +// Additional structures for the for USB-to-CAN FD + +struct ixx_usbfd_dev_power_req { + struct ixx_usbfd_dal_req dal_req; + u8 mode; + u8 _padding1; + u16 _padding2; +} __packed; + +struct ixx_usbfd_dev_power_res { + struct ixx_usbfd_dal_res dal_res; +} __packed; + +struct ixx_usbfd_ctrl_init_v2_req { + struct ixx_usbfd_dal_req dal_req; + u8 opmode; + u8 exmode; + struct canbtp sdr; + struct canbtp fdr; + u16 _padding; +} __packed; + +struct ixx_usbfd_ctrl_init_v2_res { + struct ixx_usbfd_dal_res dal_res; +} __packed; + +struct ixx_usbfd_dev_caps_req { + struct ixx_usbfd_dal_req dal_req; +} __packed; + +struct ixx_usbfd_dev_caps_res { + struct ixx_usbfd_dal_res dal_res; + struct ixx_dev_caps dev_caps; +} __packed; + +struct ixx_usbfd_ctrl_caps_req { + struct ixx_usbfd_dal_req dal_req; +} __packed; + +struct ixx_usbfd_ctrl_caps_res { + struct ixx_usbfd_dal_res dal_res; + struct ixx_ctrl_caps ctrl_caps; +} __packed; + +struct ixx_usbfd_ctrl_init_req { + struct ixx_usbfd_dal_req dal_req; + u8 mode; + u8 btr0; + u8 btr1; + u8 padding; +} __packed; + +struct ixx_usbfd_ctrl_init_res { + struct ixx_usbfd_dal_res dal_res; +} __packed; + +struct ixx_usbfd_ctrl_start_req { + struct ixx_usbfd_dal_req dal_req; +} __packed; + +struct ixx_usbfd_ctrl_start_res { + struct ixx_usbfd_dal_res dal_res; + u32 start_time; +} __packed; + +struct ixx_usbfd_ctrl_stop_req { + struct ixx_usbfd_dal_req dal_req; + u32 action; +} __packed; + +struct ixx_usbfd_ctrl_stop_res { + struct ixx_usbfd_dal_res dal_res; +} __packed; + +struct ixx_usbfd_brd_get_fwinfo_req { + struct ixx_usbfd_dal_req dal_req; +} __packed; + +struct ixx_usbfd_brd_get_fwinfo_res { + struct ixx_usbfd_dal_res dal_res; + struct ixx_intf_fw_info fwinfo; +} __packed; + +struct ixx_usbfd_brd_get_intf_info_req { + struct ixx_usbfd_dal_req dal_req; +} __packed; + +struct ixx_usbfd_brd_get_intf_info_res { + struct ixx_usbfd_dal_res dal_res; + struct ixx_intf_info info; +} __packed; + +/* + * send usb-to-can fd command synchronously + */ +static int ixx_usbfd_send_cmd(struct usb_device *dev, + struct ixx_usbfd_dal_req *dal_req) +{ + int err, i; + u16 size, value; + u8 request, requesttype; + u8 *buf; + + request = 0xff; + requesttype = USB_TYPE_VENDOR | USB_DIR_OUT; + value = le16_to_cpu(dal_req->req_port); + size = le32_to_cpu(dal_req->req_size) + + sizeof(const struct ixx_usbfd_dal_res); + + buf = kmalloc(size, GFP_KERNEL); + if(!buf) + return -ENOMEM; + memcpy(buf, (u8 *)dal_req, size); + + for (i = 0; i < 10; ++i) { + err = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), request, + requesttype, + value, + 0, + buf, + size, + msecs_to_jiffies(50)); + + if (err < 0) + msleep(20); + else + break; + } + + kfree(buf); + + if (err < 0) { + dev_err(&dev->dev, "sending command failure: %d\n", err); + return err; + } + + return 0; +} + +/* + * receive usb-to-can fd command synchronously + */ +static int ixx_usbfd_rcv_cmd(struct usb_device *dev, + struct ixx_usbfd_dal_res *dal_res, int value) +{ + int err, res_size, i, size_to_read; + u8 request, requesttype; + u8 *buf; + + request = 0xff; + requesttype = USB_TYPE_VENDOR | USB_DIR_IN; + res_size = 0; + size_to_read = le32_to_cpu(dal_res->res_size); + + buf = kmalloc(size_to_read, GFP_KERNEL); + if(!buf) + return -ENOMEM; + + for (i = 0; i < 10; ++i) { + err = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), request, + requesttype, value, + 0, buf + (u8) res_size, + size_to_read - res_size, msecs_to_jiffies(50)); + + if (err < 0) { + msleep(20); + continue; + } + + res_size += err; + if (res_size < size_to_read) + msleep(20); + else + break; + } + + if (res_size != size_to_read) + err = -EBADMSG; + + if (err < 0) { + dev_err(&dev->dev, "receiving command failure: %d\n", err); + kfree(buf); + return err; + } + + memcpy((u8 *)dal_res, buf, size_to_read); + kfree(buf); + + return err; +} + +static int ixx_usbfd_init_ctrl(struct ixx_usb_device *dev, u8 mode, + u8 exmode, + struct can_bittiming *arbitration_phase, + struct can_bittiming *data_phase) +{ + int err = -ENODEV; + u8 data[IXXAT_USBFD_CMD_BUFFER_SIZE] = { 0 }; + struct ixx_usbfd_ctrl_init_v2_req *ctrl_init_req; + struct ixx_usbfd_ctrl_init_v2_res *ctrl_init_res; + u32 req_size = sizeof(*ctrl_init_req); + + ctrl_init_req = (struct ixx_usbfd_ctrl_init_v2_req *) data; + ctrl_init_res = (struct ixx_usbfd_ctrl_init_v2_res *)(data + req_size); + + ctrl_init_req->dal_req.req_size = cpu_to_le32(req_size); + ctrl_init_req->dal_req.req_code = + cpu_to_le32(IXXAT_USBFD_INIT_V2_CMD); + ctrl_init_req->dal_req.req_port = cpu_to_le16(dev->ctrl_idx); + ctrl_init_req->dal_req.req_socket = 0xffff; + ctrl_init_req->opmode = mode; + ctrl_init_req->exmode = exmode; + + ctrl_init_req->sdr.mode = cpu_to_le32(IXX_BTMODE_NAT); + ctrl_init_req->sdr.bps = cpu_to_le32(arbitration_phase->brp); + ctrl_init_req->sdr.ts1 = + cpu_to_le16(arbitration_phase->prop_seg + + arbitration_phase->phase_seg1); + ctrl_init_req->sdr.ts2 = cpu_to_le16(arbitration_phase->phase_seg2); + ctrl_init_req->sdr.sjw = cpu_to_le16(arbitration_phase->sjw); + ctrl_init_req->sdr.tdo = 0; + + if (exmode) { + ctrl_init_req->fdr.mode = cpu_to_le32(IXX_BTMODE_NAT); + ctrl_init_req->fdr.bps = cpu_to_le32(data_phase->brp); + ctrl_init_req->fdr.ts1 = + cpu_to_le16(data_phase->prop_seg + + data_phase->phase_seg1); + ctrl_init_req->fdr.ts2 = cpu_to_le16(data_phase->phase_seg2); + ctrl_init_req->fdr.sjw = cpu_to_le16(data_phase->sjw); + ctrl_init_req->fdr.tdo = + cpu_to_le16((1 + data_phase->phase_seg1 + + data_phase->prop_seg) * + data_phase->brp); + } + + ctrl_init_res->dal_res.res_size = + cpu_to_le32(sizeof(*ctrl_init_res)); + ctrl_init_res->dal_res.ret_size = 0; + ctrl_init_res->dal_res.ret_code = 0xffffffff; + + err = ixx_usbfd_send_cmd(dev->udev, &ctrl_init_req->dal_req); + if (err < 0) + return err; + + err = ixx_usbfd_rcv_cmd(dev->udev, + &ctrl_init_res->dal_res, + dev->ctrl_idx); + if (err < 0) + return err; + + return le32_to_cpu(ctrl_init_res->dal_res.ret_code); +} + +static int ixx_usbfd_start_ctrl(struct ixx_usb_device *dev, u32 *time_ref) +{ + int err = -ENODEV; + u8 data[IXXAT_USBFD_CMD_BUFFER_SIZE] = { 0 }; + struct ixx_usbfd_ctrl_start_req *ctrl_start_req; + struct ixx_usbfd_ctrl_start_res *ctrl_start_res; + u32 req_size = sizeof(*ctrl_start_req); + + ctrl_start_req = (struct ixx_usbfd_ctrl_start_req *) data; + ctrl_start_res = (struct ixx_usbfd_ctrl_start_res *)(data + req_size); + + ctrl_start_req->dal_req.req_size = cpu_to_le32(req_size); + ctrl_start_req->dal_req.req_code = + cpu_to_le32(IXXAT_USBFD_CAN_START_CMD); + ctrl_start_req->dal_req.req_port = cpu_to_le16(dev->ctrl_idx); + ctrl_start_req->dal_req.req_socket = 0xffff; + + ctrl_start_res->dal_res.res_size = + cpu_to_le32(sizeof(*ctrl_start_res)); + ctrl_start_res->dal_res.ret_size = 0; + ctrl_start_res->dal_res.ret_code = 0xffffffff; + ctrl_start_res->start_time = 0; + + err = ixx_usbfd_send_cmd(dev->udev, &ctrl_start_req->dal_req); + if (err < 0) + return err; + + err = ixx_usbfd_rcv_cmd(dev->udev, + &ctrl_start_res->dal_res, + dev->ctrl_idx); + if (err < 0) + return err; + + if (time_ref) + *time_ref = le32_to_cpu(ctrl_start_res->start_time); + + return le32_to_cpu(ctrl_start_res->dal_res.ret_code); +} + +static int ixx_usbfd_stop_ctrl(struct ixx_usb_device *dev) +{ + int err = -ENODEV; + u8 data[IXXAT_USBFD_CMD_BUFFER_SIZE] = { 0 }; + struct ixx_usbfd_ctrl_stop_req *ctrl_stop_req; + struct ixx_usbfd_ctrl_stop_res *ctrl_stop_res; + u32 req_size = sizeof(*ctrl_stop_req); + + ctrl_stop_req = (struct ixx_usbfd_ctrl_stop_req *) data; + ctrl_stop_res = (struct ixx_usbfd_ctrl_stop_res *)(data + req_size); + + ctrl_stop_req->dal_req.req_size = cpu_to_le32(req_size); + ctrl_stop_req->dal_req.req_code = + cpu_to_le32(IXXAT_USBFD_CAN_STOP_CMD); + ctrl_stop_req->dal_req.req_port = cpu_to_le16(dev->ctrl_idx); + ctrl_stop_req->dal_req.req_socket = 0xffff; + ctrl_stop_req->action = cpu_to_le32(0x3); + + ctrl_stop_res->dal_res.res_size = + cpu_to_le32(sizeof(*ctrl_stop_res)); + ctrl_stop_res->dal_res.ret_size = 0; + ctrl_stop_res->dal_res.ret_code = 0xffffffff; + + err = ixx_usbfd_send_cmd(dev->udev, &ctrl_stop_req->dal_req); + if (err < 0) + return err; + + err = ixx_usbfd_rcv_cmd(dev->udev, + &ctrl_stop_res->dal_res, + dev->ctrl_idx); + if (err < 0) + return err; + + if (!le32_to_cpu(ctrl_stop_res->dal_res.ret_code)) + dev->can.state = CAN_STATE_STOPPED; + + return le32_to_cpu(ctrl_stop_res->dal_res.ret_code); +} + +static int ixx_usbfd_reset_ctrl(struct ixx_usb_device *dev) +{ + int err = -ENODEV; + u8 data[IXXAT_USBFD_CMD_BUFFER_SIZE] = { 0 }; + struct ixx_usbfd_dal_req *dal_req; + struct ixx_usbfd_dal_res *dal_res; + u32 req_size = sizeof(*dal_req); + + dal_req = (struct ixx_usbfd_dal_req *) data; + dal_res = (struct ixx_usbfd_dal_res *)(data + req_size); + + dal_req->req_size = cpu_to_le32(req_size); + dal_req->req_code = cpu_to_le32(IXXAT_USBFD_CAN_RESET_CMD); + dal_req->req_port = cpu_to_le16(dev->ctrl_idx); + dal_req->req_socket = 0xffff; + + dal_res->res_size = cpu_to_le32(sizeof(*dal_res)); + dal_res->ret_size = 0; + dal_res->ret_code = 0xffffffff; + + err = ixx_usbfd_send_cmd(dev->udev, dal_req); + if (err < 0) + return err; + + err = ixx_usbfd_rcv_cmd(dev->udev, dal_res, + dev->ctrl_idx); + if (err < 0) + return err; + + return le32_to_cpu(dal_res->ret_code); +} + +static int ixx_usbfd_power_ctrl(struct usb_device *dev, u8 mode) +{ + int err = -ENODEV; + u8 data[IXXAT_USBFD_CMD_BUFFER_SIZE] = { 0 }; + struct ixx_usbfd_dev_power_req *ctrl_power_req; + struct ixx_usbfd_dev_power_res *ctrl_power_res; + u32 req_size = sizeof(*ctrl_power_req); + + ctrl_power_req = (struct ixx_usbfd_dev_power_req *) data; + ctrl_power_res = (struct ixx_usbfd_dev_power_res *)(data + req_size); + + ctrl_power_req->dal_req.req_size = cpu_to_le32(req_size); + ctrl_power_req->dal_req.req_code = + cpu_to_le32(IXXAT_USBFD_POWER_CMD); + ctrl_power_req->dal_req.req_port = cpu_to_le16(0xffff); + ctrl_power_req->dal_req.req_socket = 0xffff; + ctrl_power_req->mode = mode; + + ctrl_power_res->dal_res.res_size = + cpu_to_le32(sizeof(*ctrl_power_res)); + ctrl_power_res->dal_res.ret_size = 0; + ctrl_power_res->dal_res.ret_code = 0xffffffff; + + err = ixx_usbfd_send_cmd(dev, &ctrl_power_req->dal_req); + if (err < 0) + return err; + + err = ixx_usbfd_rcv_cmd(dev, + &ctrl_power_res->dal_res, + 0xffff); + if (err < 0) + return err; + + return le32_to_cpu(ctrl_power_res->dal_res.ret_code); +} + +/* + * handle restart but in asynchronously way + */ +static int ixx_usbfd_restart_task(void *user_data) +{ + u32 time_ref; + struct ixx_usb_device *dev = user_data; + + while (!kthread_should_stop()) { + if (!dev->must_quit) { + wait_event_interruptible(dev->wait_queue, + dev->restart_flag); + if (!dev->must_quit) { + ixx_usbfd_stop_ctrl(dev); + ixx_usbfd_start_ctrl(dev, &time_ref); + dev->restart_flag = 0; + dev->can.state = CAN_STATE_ERROR_ACTIVE; + } + } else + msleep(20); + } + return 0; +} + +static int ixx_usbfd_handle_canmsg(struct ixx_usb_device *dev, + struct ixx_can_msg_v2 *rx) +{ + struct net_device *netdev = dev->netdev; + struct canfd_frame *can_frame; + struct sk_buff *skb; + const u32 flags = le32_to_cpu(rx->flags); + + if (flags & IXXAT_USBFD_MSG_FLAGS_EDL) + skb = alloc_canfd_skb(netdev, &can_frame); + else + skb = alloc_can_skb(netdev, (struct can_frame **)&can_frame); + + if (!skb) + return -ENOMEM; + + if (flags & IXXAT_USBFD_MSG_FLAGS_EDL) { + if (flags & IXXAT_USBFD_MSG_FLAGS_FDR) + can_frame->flags |= CANFD_BRS; + + if (flags & IXXAT_USBFD_MSG_FLAGS_ESI) + can_frame->flags |= CANFD_ESI; + + can_frame->len = + can_dlc2len( + get_canfd_dlc((flags & IXXAT_USBFD_MSG_FLAGS_DLC) + >> 16)); + } else { + can_frame->len = + get_canfd_dlc((flags & IXXAT_USBFD_MSG_FLAGS_DLC) + >> 16); + } + + if (flags & IXXAT_USBFD_MSG_FLAGS_OVR) { + netdev->stats.rx_over_errors++; + netdev->stats.rx_errors++; + } + + can_frame->can_id = le32_to_cpu(rx->msg_id); + + if (flags & IXXAT_USBFD_MSG_FLAGS_EXT) + can_frame->can_id |= CAN_EFF_FLAG; + + if (flags & IXXAT_USBFD_MSG_FLAGS_RTR) + can_frame->can_id |= CAN_RTR_FLAG; + else + memcpy(can_frame->data, rx->data, can_frame->len); + + ixxat_usb_get_ts_tv(dev, le32_to_cpu(rx->time), &skb->tstamp); + + netif_rx(skb); + netdev->stats.rx_packets++; + netdev->stats.rx_bytes += can_frame->len; + + return 0; +} + +static int ixx_usbfd_handle_error(struct ixx_usb_device *dev, + struct ixx_can_msg_v2 *rx) +{ + struct net_device *netdev = dev->netdev; + struct can_frame *can_frame; + struct sk_buff *skb; + u8 raw_status = 0; + + /* nothing should be sent while in BUS_OFF state */ + if (dev->can.state == CAN_STATE_BUS_OFF) + return 0; + + raw_status = rx->data[0]; + + /* allocate an skb to store the error frame */ + skb = alloc_can_err_skb(netdev, &can_frame); + if (!skb) + return -ENOMEM; + + switch (raw_status) { + case IXXAT_USBFD_CAN_ERROR_ACK: + can_frame->can_id |= CAN_ERR_ACK; + netdev->stats.tx_errors++; + break; + case IXXAT_USBFD_CAN_ERROR_BIT: + can_frame->can_id |= CAN_ERR_PROT; + can_frame->data[2] |= CAN_ERR_PROT_BIT; + netdev->stats.rx_errors++; + break; + case IXXAT_USBFD_CAN_ERROR_CRC: + can_frame->can_id |= CAN_ERR_PROT; + can_frame->data[3] |= CAN_ERR_PROT_LOC_CRC_SEQ; + netdev->stats.rx_errors++; + break; + case IXXAT_USBFD_CAN_ERROR_FORM: + can_frame->can_id |= CAN_ERR_PROT; + can_frame->data[2] |= CAN_ERR_PROT_FORM; + netdev->stats.rx_errors++; + break; + case IXXAT_USBFD_CAN_ERROR_STUFF: + can_frame->can_id |= CAN_ERR_PROT; + can_frame->data[2] |= CAN_ERR_PROT_STUFF; + netdev->stats.rx_errors++; + break; + case IXXAT_USBFD_CAN_ERROR_OTHER: + can_frame->can_id |= CAN_ERR_PROT; + can_frame->data[2] |= CAN_ERR_PROT_UNSPEC; + netdev->stats.rx_errors++; + break; + default: + can_frame->can_id |= CAN_ERR_PROT; + netdev->stats.rx_errors++; + } + + netif_rx(skb); + netdev->stats.rx_packets++; + netdev->stats.rx_bytes += can_frame->can_dlc; + + dev->bec.txerr = le16_to_cpu(rx->data[1]); + dev->bec.rxerr = le16_to_cpu(rx->data[3]); + + return 0; +} + +static int ixx_usbfd_handle_status(struct ixx_usb_device *dev, + struct ixx_can_msg_v2 *rx) +{ + struct net_device *netdev = dev->netdev; + struct can_frame *can_frame; + struct sk_buff *skb; + u8 raw_status = 0; + u32 new_state = 0; + + raw_status = rx->data[0]; + + /* nothing should be sent while in BUS_OFF state */ + if (dev->can.state == CAN_STATE_BUS_OFF) + return 0; + + if (!raw_status) { + /* no error bit (back to active state) */ + dev->can.state = CAN_STATE_ERROR_ACTIVE; + + dev->bec.txerr = 0; + dev->bec.rxerr = 0; + return 0; + } + + /* allocate an skb to store the error frame */ + skb = alloc_can_err_skb(netdev, &can_frame); + if (!skb) + return -ENOMEM; + + if (raw_status & IXXAT_USBFD_CAN_STATUS_BUSOFF) { + can_frame->can_id |= CAN_ERR_BUSOFF; + new_state = CAN_STATE_BUS_OFF; + dev->can.can_stats.bus_off++; + can_bus_off(netdev); + } else { + if (raw_status & IXXAT_USBFD_CAN_STATUS_ERRLIM) { + can_frame->can_id |= CAN_ERR_CRTL; + can_frame->data[1] |= CAN_ERR_CRTL_TX_WARNING; + can_frame->data[1] |= CAN_ERR_CRTL_RX_WARNING; + dev->can.can_stats.error_warning++; + new_state = CAN_STATE_ERROR_WARNING; + } + + if (raw_status & IXXAT_USBFD_CAN_STATUS_OVRRUN) { + can_frame->can_id |= CAN_ERR_PROT; + can_frame->data[2] |= CAN_ERR_PROT_OVERLOAD; + netdev->stats.rx_over_errors++; + netdev->stats.rx_errors++; + } + + if (!new_state) { + new_state = CAN_STATE_ERROR_ACTIVE; + + dev->bec.txerr = 0; + dev->bec.rxerr = 0; + } + } + + dev->can.state = new_state; + + netif_rx(skb); + netdev->stats.rx_packets++; + netdev->stats.rx_bytes += can_frame->can_dlc; + + return 0; +} + +/* + * callback for bulk IN urb + */ +static int ixx_usbfd_decode_buf(struct ixx_usb_device *dev, struct urb *urb) +{ + struct net_device *netdev = dev->netdev; + struct ixx_can_msg_v2 *can_msg; + u32 msg_end; + int err = 0; + u32 read_size = 0; + u8 msg_type; + + u8 *data = urb->transfer_buffer; + + /* loop reading all the records from the incoming message */ + msg_end = urb->actual_length; + for (; msg_end > 0;) { + can_msg = (struct ixx_can_msg_v2 *) &data[read_size]; + + if (!can_msg || !can_msg->size) { + netdev_err(netdev, "got unsupported rec in usb msg:\n"); + err = -ENOTSUPP; + break; + } + + /* check if the record goes out of current packet */ + if ((read_size + can_msg->size + 1) > urb->actual_length) { + netdev_err(netdev, + "got frag rec: should inc usb rx buf size\n"); + err = -EBADMSG; + break; + } + + msg_type = (le32_to_cpu(can_msg->flags) & + IXXAT_USBFD_MSG_FLAGS_TYPE); + + switch (msg_type) { + + case IXXAT_USBFD_CAN_DATA: + err = ixx_usbfd_handle_canmsg(dev, can_msg); + if (err < 0) + goto fail; + break; + + case IXXAT_USBFD_CAN_STATUS: + err = ixx_usbfd_handle_status(dev, can_msg); + if (err < 0) + goto fail; + break; + + case IXXAT_USBFD_CAN_ERROR: + err = ixx_usbfd_handle_error(dev, can_msg); + if (err < 0) + goto fail; + break; + + case IXXAT_USBFD_CAN_TIMEOVR: + ixxat_usb_get_ts_tv(dev, can_msg->time, NULL); + break; + + case IXXAT_USBFD_CAN_INFO: + case IXXAT_USBFD_CAN_WAKEUP: + case IXXAT_USBFD_CAN_TIMERST: + break; + + default: + netdev_err(netdev, + "unhandled rec type 0x%02x (%d): ignored\n", + msg_type, msg_type); + break; + } + + read_size += can_msg->size + 1; + msg_end -= (can_msg->size + 1); + } + +fail: + if (err) + ixxat_dump_mem("received msg", urb->transfer_buffer, + urb->actual_length); + + return err; +} + +static int ixx_usbfd_encode_msg(struct ixx_usb_device *dev, struct sk_buff *skb, + u8 *obuf, size_t *size) +{ + struct canfd_frame *cf = (struct canfd_frame *) skb->data; + struct ixx_can_msg_v2 can_msg = { 0 }; + + if (cf->can_id & CAN_RTR_FLAG) + can_msg.flags |= IXXAT_USBFD_MSG_FLAGS_RTR; + + if (cf->can_id & CAN_EFF_FLAG) { + can_msg.flags |= IXXAT_USBFD_MSG_FLAGS_EXT; + can_msg.msg_id = cf->can_id & CAN_EFF_MASK; + } else { + can_msg.msg_id = cf->can_id & CAN_SFF_MASK; + } + + if (dev->can.ctrlmode & CAN_CTRLMODE_ONE_SHOT) + can_msg.flags |= IXXAT_USBFD_MSG_FLAGS_SSM; + + if (skb->len == CANFD_MTU) { + can_msg.flags |= IXXAT_USBFD_MSG_FLAGS_EDL; + + if (!(cf->can_id & CAN_RTR_FLAG) && (cf->flags & CANFD_BRS)) + can_msg.flags |= IXXAT_USBFD_MSG_FLAGS_FDR; + } + + can_msg.flags |= (can_len2dlc(cf->len) << 16) & + IXXAT_USBFD_MSG_FLAGS_DLC; + + can_msg.flags = cpu_to_le32(can_msg.flags); + can_msg.msg_id = cpu_to_le32(can_msg.msg_id); + + memcpy(can_msg.data, cf->data, cf->len); + can_msg.size = (u8)(sizeof(can_msg) - 1 - CANFD_MAX_DLEN + cf->len); + + memcpy(obuf, &can_msg, can_msg.size + 1); + + *size = can_msg.size + 1; + + skb->data_len = *size; + + return 0; +} + +static int ixx_usbfd_start(struct ixx_usb_device *dev) +{ + int err; + u32 time_ref = 0; + u8 can_opmode = IXXAT_USBFD_OPMODE_EXTENDED + | IXXAT_USBFD_OPMODE_STANDARD; + u8 can_exmode = 0; + + if (dev->can.ctrlmode & CAN_CTRLMODE_BERR_REPORTING) + can_opmode |= IXXAT_USBFD_OPMODE_ERRFRAME; + if (dev->can.ctrlmode & CAN_CTRLMODE_LISTENONLY) + can_opmode |= IXXAT_USBFD_OPMODE_LISTONLY; + + if ((CAN_CTRLMODE_FD | CAN_CTRLMODE_FD_NON_ISO) & dev->can.ctrlmode) + can_exmode |= IXXAT_USBFD_EXMODE_EXTDATA | + IXXAT_USBFD_EXMODE_FASTDATA; + + if (!(CAN_CTRLMODE_FD_NON_ISO & dev->can.ctrlmode) && can_exmode) + can_exmode |= IXXAT_USBFD_EXMODE_ISOFD; + + /* Try to reset the controller, in case it is already initalized + from a previous unclean shutdown */ + ixx_usbfd_reset_ctrl(dev); + + err = ixx_usbfd_init_ctrl(dev, can_opmode, + can_exmode, + &dev->can.bittiming, + &dev->can.data_bittiming); + if (err) + return err; + + /* opening first device: */ + if (dev->ctrl_opened_count == 0) { + err = ixx_usbfd_start_ctrl(dev, &time_ref); + if (err) + return err; + + ixxat_usb_set_ts_now(dev, time_ref); + } + + dev->ctrl_opened_count++; + + dev->bec.txerr = 0; + dev->bec.rxerr = 0; + + return err; +} + +/* + * stop interface + * (last chance before set bus off) + */ +static int ixx_usbfd_stop(struct ixx_usb_device *dev) +{ + int err; + + if (dev->ctrl_opened_count == 1) { + err = ixx_usbfd_stop_ctrl(dev); + if (err) + return err; + } + + dev->ctrl_opened_count--; + + return 0; +} + +/* + * called when probing to initialize a device object. + */ +static int ixx_usbfd_init(struct ixx_usb_device *dev) +{ + dev->restart_task = kthread_run(&ixx_usbfd_restart_task, dev, + "restart_thread"); + if (!dev->restart_task) + return -ENOBUFS; + + return 0; +} + +static void ixx_usbfd_exit(struct ixx_usb_device *dev) +{ + ixx_usbfd_reset_ctrl(dev); + + dev->must_quit = 1; + dev->restart_flag = 1; + wake_up_interruptible(&dev->wait_queue); + if (dev->restart_task) + kthread_stop(dev->restart_task); +} + +/* + * probe function for new IXXAT USB-to-CAN FD interface + */ +static int ixx_usbfd_probe(struct usb_interface *intf) +{ + struct usb_host_interface *if_desc; + int i; + + if_desc = intf->altsetting; + + /* check interface endpoint addresses */ + for (i = 0; i < if_desc->desc.bNumEndpoints; i++) { + struct usb_endpoint_descriptor *ep = &if_desc->endpoint[i].desc; + + /* + * below is the list of valid ep addreses. Any other ep address + * is considered as not-CAN interface address => no dev created + */ + switch (ep->bEndpointAddress) { + case IXXAT_USBFD_EP_MSGOUT_0: + case IXXAT_USBFD_EP_MSGOUT_1: + case IXXAT_USBFD_EP_MSGOUT_2: + case IXXAT_USBFD_EP_MSGOUT_3: + case IXXAT_USBFD_EP_MSGOUT_4: + case IXXAT_USBFD_EP_MSGIN_0: + case IXXAT_USBFD_EP_MSGIN_1: + case IXXAT_USBFD_EP_MSGIN_2: + case IXXAT_USBFD_EP_MSGIN_3: + case IXXAT_USBFD_EP_MSGIN_4: + + break; + default: + return -ENODEV; + } + } + + return 0; +} + +static int ixx_usbfd_get_dev_caps(struct usb_device *dev, + struct ixx_dev_caps *dev_caps) +{ + int err = -ENODEV, i; + u8 data[IXXAT_USBFD_CMD_BUFFER_SIZE] = { 0 }; + struct ixx_usbfd_dev_caps_req *dev_caps_req; + struct ixx_usbfd_dev_caps_res *dev_caps_res; + u32 req_size = sizeof(*dev_caps_req); + + dev_caps_req = (struct ixx_usbfd_dev_caps_req *) data; + dev_caps_res = (struct ixx_usbfd_dev_caps_res *)(data + req_size); + + dev_caps_req->dal_req.req_size = cpu_to_le32(req_size); + dev_caps_req->dal_req.req_code = + cpu_to_le32(IXXAT_USBFD_BRD_GET_DEVCAPS_CMD); + dev_caps_req->dal_req.req_port = 0xffff; + dev_caps_req->dal_req.req_socket = 0xffff; + + dev_caps_res->dal_res.res_size = cpu_to_le32( + sizeof(*dev_caps_res)); + dev_caps_res->dal_res.ret_size = 0; + dev_caps_res->dal_res.ret_code = 0xffffffff; + + err = ixx_usbfd_send_cmd(dev, &dev_caps_req->dal_req); + if (err < 0) + return err; + + err = ixx_usbfd_rcv_cmd(dev, &dev_caps_res->dal_res, + 0xffff); + if (err < 0) + return err; + + dev_caps->bus_ctrl_count = + le16_to_cpu(dev_caps_res->dev_caps.bus_ctrl_count); + for (i = 0; i < dev_caps->bus_ctrl_count; ++i) + dev_caps->bus_ctrl_types[i] = + le16_to_cpu(dev_caps_res->dev_caps.bus_ctrl_types[i]); + + return 0; +} + +static int ixx_usbfd_get_ctrl_caps(struct usb_device *dev, + struct ixx_ctrl_caps *ctrl_caps, int index) +{ + int err = -ENODEV; + u8 data[IXXAT_USBFD_CMD_BUFFER_SIZE] = { 0 }; + struct ixx_usbfd_ctrl_caps_req *ctrl_caps_req; + struct ixx_usbfd_ctrl_caps_res *ctrl_caps_res; + u32 req_size = sizeof(*ctrl_caps_req); + + ctrl_caps_req = (struct ixx_usbfd_ctrl_caps_req *) data; + ctrl_caps_res = (struct ixx_usbfd_ctrl_caps_res *)(data + req_size); + + ctrl_caps_req->dal_req.req_size = cpu_to_le32(req_size); + ctrl_caps_req->dal_req.req_code = + cpu_to_le32(IXXAT_USBFD_CAN_GET_CAPS_CMD); + ctrl_caps_req->dal_req.req_port = cpu_to_le16(index); + ctrl_caps_req->dal_req.req_socket = 0xffff; + + ctrl_caps_res->dal_res.res_size = + cpu_to_le32(sizeof(*ctrl_caps_res)); + ctrl_caps_res->dal_res.ret_size = 0; + ctrl_caps_res->dal_res.ret_code = 0xffffffff; + + err = ixx_usbfd_send_cmd(dev, &ctrl_caps_req->dal_req); + if (err < 0) + return err; + + err = ixx_usbfd_rcv_cmd(dev, + &ctrl_caps_res->dal_res, + index); + if (err < 0) + return err; + + ctrl_caps->bus_coupling = + le16_to_cpu(ctrl_caps_res->ctrl_caps.bus_coupling); + ctrl_caps->clock_freq = + le32_to_cpu(ctrl_caps_res->ctrl_caps.clock_freq); + ctrl_caps->cms_divisor = + le32_to_cpu(ctrl_caps_res->ctrl_caps.cms_divisor); + ctrl_caps->cms_max_ticks = + le32_to_cpu(ctrl_caps_res->ctrl_caps.cms_max_ticks); + ctrl_caps->ctrl_type = le16_to_cpu(ctrl_caps_res->ctrl_caps.ctrl_type); + ctrl_caps->dtx_divisor = + le32_to_cpu(ctrl_caps_res->ctrl_caps.dtx_divisor); + ctrl_caps->dtx_max_ticks = + le32_to_cpu(ctrl_caps_res->ctrl_caps.dtx_max_ticks); + ctrl_caps->features = le32_to_cpu(ctrl_caps_res->ctrl_caps.features); + ctrl_caps->tsc_divisor = + le32_to_cpu(ctrl_caps_res->ctrl_caps.tsc_divisor); + + return 0; +} + +static int ixx_usbfd_get_fwinfo(struct ixx_usb_device *dev, + struct ixx_intf_fw_info *fwinfo) +{ + int err = -ENODEV; + u8 data[IXXAT_USBFD_CMD_BUFFER_SIZE] = { 0 }; + struct ixx_usbfd_brd_get_fwinfo_req *fw_info_req; + struct ixx_usbfd_brd_get_fwinfo_res *fw_info_res; + u32 req_size = sizeof(*fw_info_req); + + fw_info_req = (struct ixx_usbfd_brd_get_fwinfo_req *) data; + fw_info_res = (struct ixx_usbfd_brd_get_fwinfo_res *)(data + req_size); + + fw_info_req->dal_req.req_size = cpu_to_le32(req_size); + fw_info_req->dal_req.req_code = + cpu_to_le32(IXXAT_USBFD_BRD_GET_FWINFO_CMD); + fw_info_req->dal_req.req_port = 0xffff; + fw_info_req->dal_req.req_socket = 0xffff; + + fw_info_res->dal_res.res_size = + cpu_to_le32(sizeof(*fw_info_res)); + fw_info_res->dal_res.ret_size = 0; + fw_info_res->dal_res.ret_code = 0xffffffff; + + err = ixx_usbfd_send_cmd(dev->udev, &fw_info_req->dal_req); + if (err < 0) + return err; + + err = ixx_usbfd_rcv_cmd(dev->udev, + &fw_info_res->dal_res, 0xffff); + if (err < 0) + return err; + + if (fwinfo) { + fwinfo->build_version = le16_to_cpu( + fw_info_res->fwinfo.build_version); + fwinfo->firmware_type = le32_to_cpu( + fw_info_res->fwinfo.firmware_type); + fwinfo->major_version = le16_to_cpu( + fw_info_res->fwinfo.major_version); + fwinfo->minor_version = le16_to_cpu( + fw_info_res->fwinfo.minor_version); + fwinfo->reserved = le16_to_cpu(fw_info_res->fwinfo.reserved); + } + + return le32_to_cpu(fw_info_res->dal_res.ret_code); +} + +static int ixx_usbfd_get_dev_info(struct ixx_usb_device *dev, + struct ixx_intf_info *dev_info) +{ + int err = -ENODEV; + u8 data[IXXAT_USBFD_CMD_BUFFER_SIZE] = { 0 }; + struct ixx_usbfd_brd_get_intf_info_req *dev_info_req; + struct ixx_usbfd_brd_get_intf_info_res *dev_info_res; + u32 req_size = sizeof(*dev_info_req); + + dev_info_req = (struct ixx_usbfd_brd_get_intf_info_req *) data; + dev_info_res = + (struct ixx_usbfd_brd_get_intf_info_res *)(data + req_size); + + dev_info_req->dal_req.req_size = cpu_to_le32(req_size); + dev_info_req->dal_req.req_code = + cpu_to_le32(IXXAT_USBFD_BRD_GET_DEVINFO_CMD); + dev_info_req->dal_req.req_port = 0xffff; + dev_info_req->dal_req.req_socket = 0xffff; + + dev_info_res->dal_res.res_size = + cpu_to_le32(sizeof(*dev_info_res)); + dev_info_res->dal_res.ret_size = 0; + dev_info_res->dal_res.ret_code = 0xffffffff; + + err = ixx_usbfd_send_cmd(dev->udev, + &dev_info_req->dal_req); + if (err < 0) + return err; + + err = ixx_usbfd_rcv_cmd(dev->udev, + &dev_info_res->dal_res, + 0xffff); + if (err < 0) + return err; + + if (dev_info) { + memcpy(dev_info->device_id, &dev_info_res->info.device_id, + sizeof(dev_info_res->info.device_id)); + memcpy(dev_info->device_name, &dev_info_res->info.device_name, + sizeof(dev_info_res->info.device_name)); + dev_info->device_fpga_version = le16_to_cpu( + dev_info_res->info.device_fpga_version); + dev_info->device_version = le32_to_cpu( + dev_info_res->info.device_version); + } + + return le32_to_cpu(dev_info_res->dal_res.ret_code); +} + +/* + * describes the USB-to-CAN FD automotive adapter + */ +struct ixx_usb_adapter usb_to_can_fd_automotive = { + .name = "USB-to-CAN FD automotive", + .device_id = USB_TO_CAN_FD_AUTOMOTIVE_PRODUCT_ID, + .clock = { + .freq = IFIFD_CRYSTAL_HZ, + }, + + .bittiming_const = { + .name = "ifi_can", + .tseg1_min = 1, + .tseg1_max = 256, + .tseg2_min = 1, + .tseg2_max = 256, + .sjw_max = 128, + .brp_min = 2, + .brp_max = 513, + .brp_inc = 1, }, + + .data_bittiming_const = { + .name = "ifi_can", + .tseg1_min = 1, + .tseg1_max = 256, + .tseg2_min = 1, + .tseg2_max = 256, + .sjw_max = 128, + .brp_min = 2, + .brp_max = 513, + .brp_inc = 1, }, + + .ctrlmode_supported = CAN_CTRLMODE_3_SAMPLES | + CAN_CTRLMODE_LISTENONLY | + CAN_CTRLMODE_LOOPBACK | + CAN_CTRLMODE_BERR_REPORTING | + CAN_CTRLMODE_FD | + CAN_CTRLMODE_FD_NON_ISO, + + /* size of device private data */ + .sizeof_dev_private = sizeof(const struct ixx_usb_device), + + /* give here messages in/out endpoints */ + .ep_msg_in = { IXXAT_USBFD_EP_MSGIN_0, IXXAT_USBFD_EP_MSGIN_1, + IXXAT_USBFD_EP_MSGIN_2, IXXAT_USBFD_EP_MSGIN_3, + IXXAT_USBFD_EP_MSGIN_4 }, + .ep_msg_out = { IXXAT_USBFD_EP_MSGOUT_0, IXXAT_USBFD_EP_MSGOUT_1, + IXXAT_USBFD_EP_MSGOUT_2, IXXAT_USBFD_EP_MSGOUT_3, + IXXAT_USBFD_EP_MSGOUT_4 }, + + /* size of rx/tx usb buffers */ + .rx_buffer_size = IXXAT_USBFD_RX_BUFFER_SIZE, + .tx_buffer_size = IXXAT_USBFD_TX_BUFFER_SIZE, + + /* device callbacks */ + .intf_probe = ixx_usbfd_probe, + .dev_get_dev_caps = ixx_usbfd_get_dev_caps, + .dev_get_ctrl_caps = ixx_usbfd_get_ctrl_caps, + .dev_init = ixx_usbfd_init, + .dev_exit = ixx_usbfd_exit, + .intf_get_info = ixx_usbfd_get_dev_info, + .intf_get_fw_info = ixx_usbfd_get_fwinfo, + .dev_decode_buf = ixx_usbfd_decode_buf, + .dev_encode_msg = ixx_usbfd_encode_msg, + .dev_start = ixx_usbfd_start, + .dev_stop = ixx_usbfd_stop, + .dev_power = ixx_usbfd_power_ctrl, + .has_bgi_ep = 1, +}; + +/* + * describes the USB-to-CAN FD compact adapter + */ +struct ixx_usb_adapter usb_to_can_fd_compact = { + .name = "USB-to-CAN FD compact", + .device_id = USB_TO_CAN_FD_COMPACT_PRODUCT_ID, + .clock = { + .freq = IFIFD_CRYSTAL_HZ, + }, + + .bittiming_const = { + .name = "ifi_can", + .tseg1_min = 1, + .tseg1_max = 256, + .tseg2_min = 1, + .tseg2_max = 256, + .sjw_max = 128, + .brp_min = 2, + .brp_max = 513, + .brp_inc = 1, }, + + .data_bittiming_const = { + .name = "ifi_can", + .tseg1_min = 1, + .tseg1_max = 256, + .tseg2_min = 1, + .tseg2_max = 256, + .sjw_max = 128, + .brp_min = 2, + .brp_max = 513, + .brp_inc = 1, }, + + .ctrlmode_supported = CAN_CTRLMODE_3_SAMPLES | + CAN_CTRLMODE_LISTENONLY | + CAN_CTRLMODE_LOOPBACK | + CAN_CTRLMODE_BERR_REPORTING | + CAN_CTRLMODE_FD | + CAN_CTRLMODE_FD_NON_ISO, + + /* size of device private data */ + .sizeof_dev_private = sizeof(const struct ixx_usb_device), + + /* give here messages in/out endpoints */ + .ep_msg_in = { IXXAT_USBFD_EP_MSGIN_0, IXXAT_USBFD_EP_MSGIN_1, + IXXAT_USBFD_EP_MSGIN_2, IXXAT_USBFD_EP_MSGIN_3, + IXXAT_USBFD_EP_MSGIN_4 }, + .ep_msg_out = { IXXAT_USBFD_EP_MSGOUT_0, IXXAT_USBFD_EP_MSGOUT_1, + IXXAT_USBFD_EP_MSGOUT_2, IXXAT_USBFD_EP_MSGOUT_3, + IXXAT_USBFD_EP_MSGOUT_4 }, + + /* size of rx/tx usb buffers */ + .rx_buffer_size = IXXAT_USBFD_RX_BUFFER_SIZE, + .tx_buffer_size = IXXAT_USBFD_TX_BUFFER_SIZE, + + /* device callbacks */ + .intf_probe = ixx_usbfd_probe, + .dev_get_dev_caps = ixx_usbfd_get_dev_caps, + .dev_get_ctrl_caps = ixx_usbfd_get_ctrl_caps, + .dev_init = ixx_usbfd_init, + .dev_exit = ixx_usbfd_exit, + .intf_get_info = ixx_usbfd_get_dev_info, + .intf_get_fw_info = ixx_usbfd_get_fwinfo, + .dev_decode_buf = ixx_usbfd_decode_buf, + .dev_encode_msg = ixx_usbfd_encode_msg, + .dev_start = ixx_usbfd_start, + .dev_stop = ixx_usbfd_stop, + .dev_power = ixx_usbfd_power_ctrl, + .has_bgi_ep = 1, +}; + +/* + * describes the DELL Edge GW3002 + */ +struct ixx_usb_adapter dell_edge_gw3002 = { + .name = "USB DELL Edge GW3002", + .device_id = DELL_EDGE_GW3002_PRODUCT_ID, + .clock = { + .freq = IFIFD_CRYSTAL_HZ, + }, + + .bittiming_const = { + .name = "mcan", + .tseg1_min = 1, + .tseg1_max = 64, + .tseg2_min = 1, + .tseg2_max = 16, + .sjw_max = 16, + .brp_min = 1, + .brp_max = 1024, + .brp_inc = 1, }, + + .data_bittiming_const = { + .name = "mcan", + .tseg1_min = 1, + .tseg1_max = 16, + .tseg2_min = 1, + .tseg2_max = 8, + .sjw_max = 4, + .brp_min = 1, + .brp_max = 32, + .brp_inc = 1, }, + + .ctrlmode_supported = CAN_CTRLMODE_3_SAMPLES | + CAN_CTRLMODE_LISTENONLY | + CAN_CTRLMODE_LOOPBACK | + CAN_CTRLMODE_BERR_REPORTING + + /* currently not supported + CAN_CTRLMODE_FD | + CAN_CTRLMODE_FD_NON_ISO + */, + + /* size of device private data */ + .sizeof_dev_private = sizeof(const struct ixx_usb_device), + + /* give here messages in/out endpoints */ + .ep_msg_in = { DELL_EDGE_GW3002_EP_MSGIN_0, DELL_EDGE_GW3002_EP_MSGIN_1, + DELL_EDGE_GW3002_EP_MSGIN_2, DELL_EDGE_GW3002_EP_MSGIN_3, + DELL_EDGE_GW3002_EP_MSGIN_4 }, + .ep_msg_out = { DELL_EDGE_GW3002_EP_MSGOUT_0, DELL_EDGE_GW3002_EP_MSGOUT_1, + DELL_EDGE_GW3002_EP_MSGOUT_2, DELL_EDGE_GW3002_EP_MSGOUT_3, + DELL_EDGE_GW3002_EP_MSGOUT_4 }, + + /* size of rx/tx usb buffers */ + .rx_buffer_size = IXXAT_USBFD_RX_BUFFER_SIZE, + .tx_buffer_size = IXXAT_USBFD_TX_BUFFER_SIZE, + + /* device callbacks */ + .intf_probe = ixx_usbfd_probe, + .dev_get_dev_caps = ixx_usbfd_get_dev_caps, + .dev_get_ctrl_caps = ixx_usbfd_get_ctrl_caps, + .dev_init = ixx_usbfd_init, + .dev_exit = ixx_usbfd_exit, + .intf_get_info = ixx_usbfd_get_dev_info, + .intf_get_fw_info = ixx_usbfd_get_fwinfo, + .dev_decode_buf = ixx_usbfd_decode_buf, + .dev_encode_msg = ixx_usbfd_encode_msg, + .dev_start = ixx_usbfd_start, + .dev_stop = ixx_usbfd_stop, + .dev_power = ixx_usbfd_power_ctrl, + .has_bgi_ep = 0, +}; + +/* + * describes the USB-to-CAN FD professional adapter + */ +struct ixx_usb_adapter usb_to_can_fd_professional = { + .name = "USB-to-CAN FD professional", + .device_id = USB_TO_CAN_FD_PROFESSIONAL_PRODUCT_ID, + .clock = { + .freq = IFIFD_CRYSTAL_HZ, + }, + + .bittiming_const = { + .name = "ifi_can", + .tseg1_min = 1, + .tseg1_max = 256, + .tseg2_min = 1, + .tseg2_max = 256, + .sjw_max = 128, + .brp_min = 2, + .brp_max = 513, + .brp_inc = 1, }, + + .data_bittiming_const = { + .name = "ifi_can", + .tseg1_min = 1, + .tseg1_max = 256, + .tseg2_min = 1, + .tseg2_max = 256, + .sjw_max = 128, + .brp_min = 2, + .brp_max = 513, + .brp_inc = 1, }, + + .ctrlmode_supported = CAN_CTRLMODE_3_SAMPLES | + CAN_CTRLMODE_LISTENONLY | + CAN_CTRLMODE_LOOPBACK | + CAN_CTRLMODE_BERR_REPORTING | + CAN_CTRLMODE_FD | + CAN_CTRLMODE_FD_NON_ISO, + + /* size of device private data */ + .sizeof_dev_private = sizeof(const struct ixx_usb_device), + + /* give here messages in/out endpoints */ + .ep_msg_in = { IXXAT_USBFD_EP_MSGIN_0, IXXAT_USBFD_EP_MSGIN_1, + IXXAT_USBFD_EP_MSGIN_2, IXXAT_USBFD_EP_MSGIN_3, + IXXAT_USBFD_EP_MSGIN_4 }, + .ep_msg_out = { IXXAT_USBFD_EP_MSGOUT_0, IXXAT_USBFD_EP_MSGOUT_1, + IXXAT_USBFD_EP_MSGOUT_2, IXXAT_USBFD_EP_MSGOUT_3, + IXXAT_USBFD_EP_MSGOUT_4 }, + + /* size of rx/tx usb buffers */ + .rx_buffer_size = IXXAT_USBFD_RX_BUFFER_SIZE, + .tx_buffer_size = IXXAT_USBFD_TX_BUFFER_SIZE, + + /* device callbacks */ + .intf_probe = ixx_usbfd_probe, + .dev_get_dev_caps = ixx_usbfd_get_dev_caps, + .dev_get_ctrl_caps = ixx_usbfd_get_ctrl_caps, + .dev_init = ixx_usbfd_init, + .dev_exit = ixx_usbfd_exit, + .intf_get_info = ixx_usbfd_get_dev_info, + .intf_get_fw_info = ixx_usbfd_get_fwinfo, + .dev_decode_buf = ixx_usbfd_decode_buf, + .dev_encode_msg = ixx_usbfd_encode_msg, + .dev_start = ixx_usbfd_start, + .dev_stop = ixx_usbfd_stop, + .dev_power = ixx_usbfd_power_ctrl, + .has_bgi_ep = 1, +}; + +/* + * describes the USB-to-CAN FD PCIe mini adapter + */ +struct ixx_usb_adapter usb_to_can_fd_pcie_mini = { + .name = "USB-to-CAN FD PCIe mini", + .device_id = USB_TO_CAN_FD_PCIE_MINI_PRODUCT_ID, + .clock = { + .freq = IFIFD_CRYSTAL_HZ, + }, + + .bittiming_const = { + .name = "ifi_can", + .tseg1_min = 1, + .tseg1_max = 256, + .tseg2_min = 1, + .tseg2_max = 256, + .sjw_max = 128, + .brp_min = 2, + .brp_max = 513, + .brp_inc = 1, }, + + .data_bittiming_const = { + .name = "ifi_can", + .tseg1_min = 1, + .tseg1_max = 256, + .tseg2_min = 1, + .tseg2_max = 256, + .sjw_max = 128, + .brp_min = 2, + .brp_max = 513, + .brp_inc = 1, }, + + .ctrlmode_supported = CAN_CTRLMODE_3_SAMPLES | + CAN_CTRLMODE_LISTENONLY | + CAN_CTRLMODE_LOOPBACK | + CAN_CTRLMODE_BERR_REPORTING | + CAN_CTRLMODE_FD | + CAN_CTRLMODE_FD_NON_ISO, + + /* size of device private data */ + .sizeof_dev_private = sizeof(const struct ixx_usb_device), + + /* give here messages in/out endpoints */ + .ep_msg_in = { IXXAT_USBFD_EP_MSGIN_0, IXXAT_USBFD_EP_MSGIN_1, + IXXAT_USBFD_EP_MSGIN_2, IXXAT_USBFD_EP_MSGIN_3, + IXXAT_USBFD_EP_MSGIN_4 }, + .ep_msg_out = { IXXAT_USBFD_EP_MSGOUT_0, IXXAT_USBFD_EP_MSGOUT_1, + IXXAT_USBFD_EP_MSGOUT_2, IXXAT_USBFD_EP_MSGOUT_3, + IXXAT_USBFD_EP_MSGOUT_4 }, + + /* size of rx/tx usb buffers */ + .rx_buffer_size = IXXAT_USBFD_RX_BUFFER_SIZE, + .tx_buffer_size = IXXAT_USBFD_TX_BUFFER_SIZE, + + /* device callbacks */ + .intf_probe = ixx_usbfd_probe, + .dev_get_dev_caps = ixx_usbfd_get_dev_caps, + .dev_get_ctrl_caps = ixx_usbfd_get_ctrl_caps, + .dev_init = ixx_usbfd_init, + .dev_exit = ixx_usbfd_exit, + .intf_get_info = ixx_usbfd_get_dev_info, + .intf_get_fw_info = ixx_usbfd_get_fwinfo, + .dev_decode_buf = ixx_usbfd_decode_buf, + .dev_encode_msg = ixx_usbfd_encode_msg, + .dev_start = ixx_usbfd_start, + .dev_stop = ixx_usbfd_stop, + .dev_power = ixx_usbfd_power_ctrl, + .has_bgi_ep = 1, +}; + +/* + * describes the USB-to-CAR adapter + */ +struct ixx_usb_adapter usb_to_car = { + .name = "USB-to-CAR", + .device_id = USB_TO_CAR_ID, + .clock = { + .freq = IFIFD_CRYSTAL_HZ, + }, + + .bittiming_const = { + .name = "ifi_can", + .tseg1_min = 1, + .tseg1_max = 256, + .tseg2_min = 1, + .tseg2_max = 256, + .sjw_max = 128, + .brp_min = 2, + .brp_max = 513, + .brp_inc = 1, }, + + .data_bittiming_const = { + .name = "ifi_can", + .tseg1_min = 1, + .tseg1_max = 256, + .tseg2_min = 1, + .tseg2_max = 256, + .sjw_max = 128, + .brp_min = 2, + .brp_max = 513, + .brp_inc = 1, }, + + .ctrlmode_supported = CAN_CTRLMODE_3_SAMPLES | + CAN_CTRLMODE_LISTENONLY | + CAN_CTRLMODE_LOOPBACK | + CAN_CTRLMODE_BERR_REPORTING | + CAN_CTRLMODE_FD | + CAN_CTRLMODE_FD_NON_ISO, + + /* size of device private data */ + .sizeof_dev_private = sizeof(const struct ixx_usb_device), + + /* give here messages in/out endpoints */ + .ep_msg_in = { IXXAT_USBFD_EP_MSGIN_0, IXXAT_USBFD_EP_MSGIN_1, + IXXAT_USBFD_EP_MSGIN_2, IXXAT_USBFD_EP_MSGIN_3, + IXXAT_USBFD_EP_MSGIN_4 }, + .ep_msg_out = { IXXAT_USBFD_EP_MSGOUT_0, IXXAT_USBFD_EP_MSGOUT_1, + IXXAT_USBFD_EP_MSGOUT_2, IXXAT_USBFD_EP_MSGOUT_3, + IXXAT_USBFD_EP_MSGOUT_4 }, + + /* size of rx/tx usb buffers */ + .rx_buffer_size = IXXAT_USBFD_RX_BUFFER_SIZE, + .tx_buffer_size = IXXAT_USBFD_TX_BUFFER_SIZE, + + /* device callbacks */ + .intf_probe = ixx_usbfd_probe, + .dev_get_dev_caps = ixx_usbfd_get_dev_caps, + .dev_get_ctrl_caps = ixx_usbfd_get_ctrl_caps, + .dev_init = ixx_usbfd_init, + .dev_exit = ixx_usbfd_exit, + .intf_get_info = ixx_usbfd_get_dev_info, + .intf_get_fw_info = ixx_usbfd_get_fwinfo, + .dev_decode_buf = ixx_usbfd_decode_buf, + .dev_encode_msg = ixx_usbfd_encode_msg, + .dev_start = ixx_usbfd_start, + .dev_stop = ixx_usbfd_stop, + .dev_power = ixx_usbfd_power_ctrl, + .has_bgi_ep = 1, +}; + + +#endif // CANFD_CAPABLE only in patch2: unchanged: --- linux-lts-xenial-4.4.0.orig/ubuntu/ixxat/ixx_usb_v2.c +++ linux-lts-xenial-4.4.0/ubuntu/ixxat/ixx_usb_v2.c @@ -0,0 +1,1450 @@ +/* + * CAN driver for IXXAT USB-to-CAN V2 + * + * Copyright (C) 2014 Michael Hengler + * + * Based on code originally by pcan_usb_core + * + * 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; version 2 of the License. + * + * 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 +#include +#include + +#include "ixx_usb_core.h" + +MODULE_SUPPORTED_DEVICE("IXXAT Automation GmbH USB-to-CAN V2"); + +/* use sja 1000 clock due to internal bittiming calculations */ +#define SJA1000_CRYSTAL_HZ 8000000 + +/* usb-to-can v2 Endpoints */ +#define IXXAT_USBV2_EP_CMDOUT 0 +#define IXXAT_USBV2_EP_CMDIN (IXXAT_USBV2_EP_CMDOUT | USB_DIR_IN) +#define IXXAT_USBV2_EP_MSGOUT_0 1 +#define IXXAT_USBV2_EP_MSGIN_0 (IXXAT_USBV2_EP_MSGOUT_0 | USB_DIR_IN) +#define IXXAT_USBV2_EP_MSGOUT_1 2 +#define IXXAT_USBV2_EP_MSGIN_1 (IXXAT_USBV2_EP_MSGOUT_1 | USB_DIR_IN) +#define IXXAT_USBV2_EP_MSGOUT_2 3 +#define IXXAT_USBV2_EP_MSGIN_2 (IXXAT_USBV2_EP_MSGOUT_2 | USB_DIR_IN) +#define IXXAT_USBV2_EP_MSGOUT_3 4 +#define IXXAT_USBV2_EP_MSGIN_3 (IXXAT_USBV2_EP_MSGOUT_3 | USB_DIR_IN) +#define IXXAT_USBV2_EP_MSGOUT_4 5 +#define IXXAT_USBV2_EP_MSGIN_4 (IXXAT_USBV2_EP_MSGOUT_4 | USB_DIR_IN) + +/* usb-to-can v2 rx/tx buffers size */ +#define IXXAT_USBV2_RX_BUFFER_SIZE 512 +#define IXXAT_USBV2_TX_BUFFER_SIZE 256 + +#define IXXAT_USBV2_CMD_BUFFER_SIZE 256 + +#define IXXAT_USBV2_OPMODE_STANDARD 0x01 /* reception of 11-bit id messages */ +#define IXXAT_USBV2_OPMODE_EXTENDED 0x02 /* reception of 29-bit id messages */ +#define IXXAT_USBV2_OPMODE_ERRFRAME 0x04 /* enable reception of error frames */ +#define IXXAT_USBV2_OPMODE_LISTONLY 0x08 /* listen only mode (TX passive) */ + +/* Stuff error */ +#define IXXAT_USBV2_CAN_ERROR_STUFF 1 +/* Form error */ +#define IXXAT_USBV2_CAN_ERROR_FORM 2 +/* Acknowledgment error */ +#define IXXAT_USBV2_CAN_ERROR_ACK 3 +/* Bit error */ +#define IXXAT_USBV2_CAN_ERROR_BIT 4 +/* CRC error */ +#define IXXAT_USBV2_CAN_ERROR_CRC 6 +/* Other (unspecified) error */ +#define IXXAT_USBV2_CAN_ERROR_OTHER 7 + +/* Data overrun occurred */ +#define IXXAT_USBV2_CAN_STATUS_OVRRUN 0x02 +/* Error warning limit exceeded */ +#define IXXAT_USBV2_CAN_STATUS_ERRLIM 0x04 +/* Bus off status */ +#define IXXAT_USBV2_CAN_STATUS_BUSOFF 0x08 + +#define IXXAT_USBV2_CAN_DATA 0x00 +#define IXXAT_USBV2_CAN_INFO 0x01 +#define IXXAT_USBV2_CAN_ERROR 0x02 +#define IXXAT_USBV2_CAN_STATUS 0x03 +#define IXXAT_USBV2_CAN_WAKEUP 0x04 +#define IXXAT_USBV2_CAN_TIMEOVR 0x05 +#define IXXAT_USBV2_CAN_TIMERST 0x06 + +#define IXXAT_USBV2_MSG_FLAGS_TYPE 0x000000FF +#define IXXAT_USBV2_MSG_FLAGS_SSM 0x00000100 +#define IXXAT_USBV2_MSG_FLAGS_HPM 0x00000600 +#define IXXAT_USBV2_MSG_FLAGS_RES 0x0000F800 +#define IXXAT_USBV2_MSG_FLAGS_DLC 0x000F0000 +#define IXXAT_USBV2_MSG_FLAGS_OVR 0x00100000 +#define IXXAT_USBV2_MSG_FLAGS_SRR 0x00200000 +#define IXXAT_USBV2_MSG_FLAGS_RTR 0x00400000 +#define IXXAT_USBV2_MSG_FLAGS_EXT 0x00800000 +#define IXXAT_USBV2_MSG_FLAGS_AFC 0xFF000000 + +#define IXXAT_USBV2_BAL_CMD_CLASS 3 +#define IXXAT_USBV2_BRD_CMD_CLASS 4 +#define IXXAT_USBV2_BMG_CMD_CLASS 5 + +#define IXXAT_USBV2_BRD_CMD_CAT 0 +#define IXXAT_USBV2_CAN_CMD_CAT 1 + +#define IXXAT_USBV2_VCI_CMD_CODE(Class, Function) \ + ((u32) (((Class) << 8) | (Function))) + +#define IXXAT_USBV2_BRD_CMD_CODE(Category, Function) \ + IXXAT_USBV2_VCI_CMD_CODE(IXXAT_USBV2_BRD_CMD_CLASS, \ + ((Category) << 5) | (Function)) + +#define IXXAT_USBV2_BAL_CMD_CODE(Category, Function) \ + IXXAT_USBV2_VCI_CMD_CODE(IXXAT_USBV2_BAL_CMD_CLASS, \ + ((Category) << 5) | (Function)) + +#define IXXAT_USBV2_CAN_GET_CAPS_CMD \ + IXXAT_USBV2_BAL_CMD_CODE(IXXAT_USBV2_CAN_CMD_CAT, 0) +#define IXXAT_USBV2_CAN_INIT_CMD \ + IXXAT_USBV2_BAL_CMD_CODE(IXXAT_USBV2_CAN_CMD_CAT, 5) +#define IXXAT_USBV2_CAN_START_CMD \ + IXXAT_USBV2_BAL_CMD_CODE(IXXAT_USBV2_CAN_CMD_CAT, 6) +#define IXXAT_USBV2_CAN_STOP_CMD \ + IXXAT_USBV2_BAL_CMD_CODE(IXXAT_USBV2_CAN_CMD_CAT, 7) +#define IXXAT_USBV2_CAN_RESET_CMD \ + IXXAT_USBV2_BAL_CMD_CODE(IXXAT_USBV2_CAN_CMD_CAT, 8) + +#define IXXAT_USBV2_BRD_GET_FWINFO_CMD \ + IXXAT_USBV2_BRD_CMD_CODE(IXXAT_USBV2_BRD_CMD_CAT, 0) +#define IXXAT_USBV2_BRD_GET_DEVCAPS_CMD \ + IXXAT_USBV2_BRD_CMD_CODE(IXXAT_USBV2_BRD_CMD_CAT, 1) +#define IXXAT_USBV2_BRD_GET_DEVINFO_CMD \ + IXXAT_USBV2_BRD_CMD_CODE(IXXAT_USBV2_BRD_CMD_CAT, 2) + +struct ixx_usbv2_dal_req { + u32 req_size; + u16 req_port; + u16 req_socket; + u32 req_code; +} __packed; + +struct ixx_usbv2_dal_res { + u32 res_size; + u32 ret_size; + u32 ret_code; +} __packed; + +struct ixx_usbv2_dev_caps_req { + struct ixx_usbv2_dal_req dal_req; +} __packed; + +struct ixx_usbv2_dev_caps_res { + struct ixx_usbv2_dal_res dal_res; + struct ixx_dev_caps dev_caps; +} __packed; + +struct ixx_usbv2_ctrl_caps_req { + struct ixx_usbv2_dal_req dal_req; +} __packed; + +struct ixx_usbv2_ctrl_caps_res { + struct ixx_usbv2_dal_res dal_res; + struct ixx_ctrl_caps ctrl_caps; +} __packed; + +struct ixx_usbv2_ctrl_init_req { + struct ixx_usbv2_dal_req dal_req; + u8 mode; + u8 btr0; + u8 btr1; + u8 padding; +} __packed; + +struct ixx_usbv2_ctrl_init_res { + struct ixx_usbv2_dal_res dal_res; +} __packed; + +struct ixx_usbv2_ctrl_start_req { + struct ixx_usbv2_dal_req dal_req; +} __packed; + +struct ixx_usbv2_ctrl_start_res { + struct ixx_usbv2_dal_res dal_res; + u32 start_time; +} __packed; + +struct ixx_usbv2_ctrl_stop_req { + struct ixx_usbv2_dal_req dal_req; + u32 action; +} __packed; + +struct ixx_usbv2_ctrl_stop_res { + struct ixx_usbv2_dal_res dal_res; +} __packed; + +struct ixx_usbv2_brd_get_fwinfo_req { + struct ixx_usbv2_dal_req dal_req; +} __packed; + +struct ixx_usbv2_brd_get_fwinfo_res { + struct ixx_usbv2_dal_res dal_res; + struct ixx_intf_fw_info fwinfo; +} __packed; + +struct ixx_usbv2_brd_get_intf_info_req { + struct ixx_usbv2_dal_req dal_req; +} __packed; + +struct ixx_usbv2_brd_get_intf_info_res { + struct ixx_usbv2_dal_res dal_res; + struct ixx_intf_info info; +} __packed; + +/* + * send usb-to-can v2 command synchronously + */ +static int ixx_usbv2_send_cmd(struct usb_device *dev, + struct ixx_usbv2_dal_req *dal_req) +{ + int err, i; + u16 size, value; + u8 request, requesttype; + u8 *buf; + + request = 0xff; + requesttype = USB_TYPE_VENDOR | USB_DIR_OUT; + value = le16_to_cpu(dal_req->req_port); + size = le32_to_cpu(dal_req->req_size) + + sizeof(const struct ixx_usbv2_dal_res); + + buf = kmalloc(size, GFP_KERNEL); + if(!buf) + return -ENOMEM; + memcpy(buf, (u8 *)dal_req, size); + + + for (i = 0; i < 10; ++i) { + err = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), request, + requesttype, + value, + 0, + buf, + size, + msecs_to_jiffies(50)); + + if (err < 0) + msleep(20); + else + break; + } + + kfree(buf); + + if (err < 0) { + dev_err(&dev->dev, "sending command failure: %d\n", err); + return err; + } + + return 0; +} + +/* + * receive usb-to-can v2 command synchronously + */ +static int ixx_usbv2_rcv_cmd(struct usb_device *dev, + struct ixx_usbv2_dal_res *dal_res, int value) +{ + int err, res_size, i, size_to_read; + u8 request, requesttype; + u8 *buf; + + request = 0xff; + requesttype = USB_TYPE_VENDOR | USB_DIR_IN; + res_size = 0; + size_to_read = le32_to_cpu(dal_res->res_size); + + buf = kmalloc(size_to_read, GFP_KERNEL); + if(!buf) + return -ENOMEM; + + + for (i = 0; i < 10; ++i) { + err = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), request, + requesttype, value, + 0, buf + (u8) res_size, + size_to_read - res_size, msecs_to_jiffies(50)); + + if (err < 0) { + msleep(20); + continue; + } + + res_size += err; + if (res_size < size_to_read) + msleep(20); + else + break; + } + + if (res_size != size_to_read) + err = -EBADMSG; + + if (err < 0) { + dev_err(&dev->dev, "receiving command failure: %d\n", err); + kfree(buf); + return err; + } + + memcpy((u8 *)dal_res, buf, size_to_read); + kfree(buf); + + return err; +} + +static int ixx_usbv2_init_ctrl(struct ixx_usb_device *dev, u8 mode, u8 btr0, + u8 btr1) +{ + int err = -ENODEV; + u8 data[IXXAT_USBV2_CMD_BUFFER_SIZE] = { 0 }; + struct ixx_usbv2_ctrl_init_req *ctrl_init_req; + struct ixx_usbv2_ctrl_init_res *ctrl_init_res; + u32 req_size = sizeof(*ctrl_init_req); + + ctrl_init_req = (struct ixx_usbv2_ctrl_init_req *) data; + ctrl_init_res = (struct ixx_usbv2_ctrl_init_res *)(data + req_size); + + ctrl_init_req->dal_req.req_size = cpu_to_le32(req_size); + ctrl_init_req->dal_req.req_code = + cpu_to_le32(IXXAT_USBV2_CAN_INIT_CMD); + ctrl_init_req->dal_req.req_port = cpu_to_le16(dev->ctrl_idx); + ctrl_init_req->dal_req.req_socket = 0xffff; + ctrl_init_req->mode = mode; + ctrl_init_req->btr0 = btr0; + ctrl_init_req->btr1 = btr1; + + ctrl_init_res->dal_res.res_size = cpu_to_le32( + sizeof(*ctrl_init_res)); + ctrl_init_res->dal_res.ret_size = 0; + ctrl_init_res->dal_res.ret_code = 0xffffffff; + + err = ixx_usbv2_send_cmd(dev->udev, &ctrl_init_req->dal_req); + if (err < 0) + return err; + + err = ixx_usbv2_rcv_cmd(dev->udev, + &ctrl_init_res->dal_res, + dev->ctrl_idx); + if (err < 0) + return err; + + return le32_to_cpu(ctrl_init_res->dal_res.ret_code); +} + +static int ixx_usbv2_start_ctrl(struct ixx_usb_device *dev, u32 *time_ref) +{ + int err = -ENODEV; + u8 data[IXXAT_USBV2_CMD_BUFFER_SIZE] = { 0 }; + struct ixx_usbv2_ctrl_start_req *ctrl_start_req; + struct ixx_usbv2_ctrl_start_res *ctrl_start_res; + u32 req_size = sizeof(*ctrl_start_req); + + ctrl_start_req = (struct ixx_usbv2_ctrl_start_req *) data; + ctrl_start_res = (struct ixx_usbv2_ctrl_start_res *)(data + req_size); + + ctrl_start_req->dal_req.req_size = cpu_to_le32(req_size); + ctrl_start_req->dal_req.req_code = + cpu_to_le32(IXXAT_USBV2_CAN_START_CMD); + ctrl_start_req->dal_req.req_port = cpu_to_le16(dev->ctrl_idx); + ctrl_start_req->dal_req.req_socket = 0xffff; + + ctrl_start_res->dal_res.res_size = cpu_to_le32( + sizeof(*ctrl_start_res)); + ctrl_start_res->dal_res.ret_size = 0; + ctrl_start_res->dal_res.ret_code = 0xffffffff; + ctrl_start_res->start_time = 0; + + err = ixx_usbv2_send_cmd(dev->udev, &ctrl_start_req->dal_req); + if (err < 0) + return err; + + err = ixx_usbv2_rcv_cmd(dev->udev, + &ctrl_start_res->dal_res, + dev->ctrl_idx); + if (err < 0) + return err; + + if (time_ref) + *time_ref = le32_to_cpu(ctrl_start_res->start_time); + + return le32_to_cpu(ctrl_start_res->dal_res.ret_code); +} + +static int ixx_usbv2_stop_ctrl(struct ixx_usb_device *dev) +{ + int err = -ENODEV; + u8 data[IXXAT_USBV2_CMD_BUFFER_SIZE] = { 0 }; + struct ixx_usbv2_ctrl_stop_req *ctrl_stop_req; + struct ixx_usbv2_ctrl_stop_res *ctrl_stop_res; + u32 req_size = sizeof(struct ixx_usbv2_ctrl_stop_req); + + ctrl_stop_req = (struct ixx_usbv2_ctrl_stop_req *) data; + ctrl_stop_res = (struct ixx_usbv2_ctrl_stop_res *)(data + req_size); + + ctrl_stop_req->dal_req.req_size = cpu_to_le32(req_size); + ctrl_stop_req->dal_req.req_code = + cpu_to_le32(IXXAT_USBV2_CAN_STOP_CMD); + ctrl_stop_req->dal_req.req_port = cpu_to_le16(dev->ctrl_idx); + ctrl_stop_req->dal_req.req_socket = 0xffff; + ctrl_stop_req->action = cpu_to_le32(0x3); + + ctrl_stop_res->dal_res.res_size = + cpu_to_le32(sizeof(*ctrl_stop_res)); + ctrl_stop_res->dal_res.ret_size = 0; + ctrl_stop_res->dal_res.ret_code = 0xffffffff; + + err = ixx_usbv2_send_cmd(dev->udev, &ctrl_stop_req->dal_req); + if (err < 0) + return err; + + err = ixx_usbv2_rcv_cmd(dev->udev, + &ctrl_stop_res->dal_res, + dev->ctrl_idx); + if (err < 0) + return err; + + if (!le32_to_cpu(ctrl_stop_res->dal_res.ret_code)) + dev->can.state = CAN_STATE_STOPPED; + + return le32_to_cpu(ctrl_stop_res->dal_res.ret_code); +} + +static int ixx_usbv2_reset_ctrl(struct ixx_usb_device *dev) +{ + int err = -ENODEV; + u8 data[IXXAT_USBV2_CMD_BUFFER_SIZE] = { 0 }; + struct ixx_usbv2_dal_req *dal_req; + struct ixx_usbv2_dal_res *dal_res; + u32 req_size = sizeof(*dal_req); + + dal_req = (struct ixx_usbv2_dal_req *) data; + dal_res = (struct ixx_usbv2_dal_res *)(data + req_size); + + dal_req->req_size = cpu_to_le32(req_size); + dal_req->req_code = cpu_to_le32(IXXAT_USBV2_CAN_RESET_CMD); + dal_req->req_port = cpu_to_le16(dev->ctrl_idx); + dal_req->req_socket = 0xffff; + + dal_res->res_size = cpu_to_le32(sizeof(*dal_res)); + dal_res->ret_size = 0; + dal_res->ret_code = 0xffffffff; + + err = ixx_usbv2_send_cmd(dev->udev, dal_req); + if (err < 0) + return err; + + err = ixx_usbv2_rcv_cmd(dev->udev, dal_res, + dev->ctrl_idx); + if (err < 0) + return err; + + return le32_to_cpu(dal_res->ret_code); +} + +static int ixx_usbv2_set_bittiming(struct ixx_usb_device *dev, + struct can_bittiming *bt) +{ + u8 btr0 = 0, btr1 = 0, can_opmode = 0; + + btr0 = ((bt->brp - 1) & 0x3f) | (((bt->sjw - 1) & 0x3) << 6); + btr1 = ((bt->prop_seg + bt->phase_seg1 - 1) & 0xf) + | (((bt->phase_seg2 - 1) & 0x7) << 4); + if (dev->can.ctrlmode & CAN_CTRLMODE_3_SAMPLES) + btr1 |= 0x80; + + can_opmode = IXXAT_USBV2_OPMODE_EXTENDED | IXXAT_USBV2_OPMODE_STANDARD; + + if (dev->can.ctrlmode & CAN_CTRLMODE_BERR_REPORTING) + can_opmode |= IXXAT_USBV2_OPMODE_ERRFRAME; + if (dev->can.ctrlmode & CAN_CTRLMODE_LISTENONLY) + can_opmode |= IXXAT_USBV2_OPMODE_LISTONLY; + + dev->btr0 = btr0; + dev->btr1 = btr1; + + netdev_dbg(dev->netdev, "setting btr0=0x%08x btr1=0x%08x mode=0x%08x\n", + btr0, btr1, can_opmode); + + return ixx_usbv2_init_ctrl(dev, can_opmode, btr0, btr1); +} + +/* + * handle restart but in asynchronously way + */ +static int ixx_usbv2_restart_task(void *user_data) +{ + u32 time_ref; + struct ixx_usb_device *dev = user_data; + + while (!kthread_should_stop()) { + if (!dev->must_quit) { + wait_event_interruptible(dev->wait_queue, + dev->restart_flag); + if (!dev->must_quit) { + ixx_usbv2_stop_ctrl(dev); + ixx_usbv2_start_ctrl(dev, &time_ref); + dev->restart_flag = 0; + dev->can.state = CAN_STATE_ERROR_ACTIVE; + } + } else + msleep(20); + } + return 0; +} + +static int ixx_usbv2_handle_canmsg(struct ixx_usb_device *dev, + struct ixx_can_msg *rx) +{ + struct net_device *netdev = dev->netdev; + struct can_frame *can_frame; + struct sk_buff *skb; + + skb = alloc_can_skb(netdev, &can_frame); + if (!skb) + return -ENOMEM; + + if (le32_to_cpu(rx->flags) & IXXAT_USBV2_MSG_FLAGS_OVR) { + netdev->stats.rx_over_errors++; + netdev->stats.rx_errors++; + } + + can_frame->can_id = le32_to_cpu(rx->msg_id); + can_frame->can_dlc = + (le32_to_cpu(rx->flags) & + IXXAT_USBV2_MSG_FLAGS_DLC) >> 16; + + if (le32_to_cpu(rx->flags) & IXXAT_USBV2_MSG_FLAGS_EXT) + can_frame->can_id |= CAN_EFF_FLAG; + + if (le32_to_cpu(rx->flags) & IXXAT_USBV2_MSG_FLAGS_RTR) + can_frame->can_id |= CAN_RTR_FLAG; + else + memcpy(can_frame->data, rx->data, can_frame->can_dlc); + + ixxat_usb_get_ts_tv(dev, le32_to_cpu(rx->time), &skb->tstamp); + + netif_rx(skb); + netdev->stats.rx_packets++; + netdev->stats.rx_bytes += can_frame->can_dlc; + + return 0; +} + +static int ixx_usbv2_handle_error(struct ixx_usb_device *dev, + struct ixx_can_msg *rx) +{ + struct net_device *netdev = dev->netdev; + struct can_frame *can_frame; + struct sk_buff *skb; + u8 raw_status = 0; + + /* nothing should be sent while in BUS_OFF state */ + if (dev->can.state == CAN_STATE_BUS_OFF) + return 0; + + raw_status = rx->data[0]; + + /* allocate an skb to store the error frame */ + skb = alloc_can_err_skb(netdev, &can_frame); + if (!skb) + return -ENOMEM; + + switch (raw_status) { + case IXXAT_USBV2_CAN_ERROR_ACK: + can_frame->can_id |= CAN_ERR_ACK; + netdev->stats.tx_errors++; + break; + case IXXAT_USBV2_CAN_ERROR_BIT: + can_frame->can_id |= CAN_ERR_PROT; + can_frame->data[2] |= CAN_ERR_PROT_BIT; + netdev->stats.rx_errors++; + break; + case IXXAT_USBV2_CAN_ERROR_CRC: + can_frame->can_id |= CAN_ERR_PROT; + can_frame->data[3] |= CAN_ERR_PROT_LOC_CRC_SEQ; + netdev->stats.rx_errors++; + break; + case IXXAT_USBV2_CAN_ERROR_FORM: + can_frame->can_id |= CAN_ERR_PROT; + can_frame->data[2] |= CAN_ERR_PROT_FORM; + netdev->stats.rx_errors++; + break; + case IXXAT_USBV2_CAN_ERROR_STUFF: + can_frame->can_id |= CAN_ERR_PROT; + can_frame->data[2] |= CAN_ERR_PROT_STUFF; + netdev->stats.rx_errors++; + break; + case IXXAT_USBV2_CAN_ERROR_OTHER: + can_frame->can_id |= CAN_ERR_PROT; + can_frame->data[2] |= CAN_ERR_PROT_UNSPEC; + netdev->stats.rx_errors++; + break; + default: + can_frame->can_id |= CAN_ERR_PROT; + netdev->stats.rx_errors++; + } + + netif_rx(skb); + netdev->stats.rx_packets++; + netdev->stats.rx_bytes += can_frame->can_dlc; + + dev->bec.txerr = le16_to_cpu(rx->data[1]); + dev->bec.rxerr = le16_to_cpu(rx->data[3]); + + return 0; +} + +static int ixx_usbv2_handle_status(struct ixx_usb_device *dev, + struct ixx_can_msg *rx) +{ + struct net_device *netdev = dev->netdev; + struct can_frame *can_frame; + struct sk_buff *skb; + u8 raw_status = 0; + u32 new_state = 0; + + raw_status = rx->data[0]; + + /* nothing should be sent while in BUS_OFF state */ + if (dev->can.state == CAN_STATE_BUS_OFF) + return 0; + + if (!raw_status) { + /* no error bit (back to active state) */ + dev->can.state = CAN_STATE_ERROR_ACTIVE; + + dev->bec.txerr = 0; + dev->bec.rxerr = 0; + return 0; + } + + /* allocate an skb to store the error frame */ + skb = alloc_can_err_skb(netdev, &can_frame); + if (!skb) + return -ENOMEM; + + if (raw_status & IXXAT_USBV2_CAN_STATUS_BUSOFF) { + can_frame->can_id |= CAN_ERR_BUSOFF; + new_state = CAN_STATE_BUS_OFF; + dev->can.can_stats.bus_off++; + can_bus_off(netdev); + } else { + if (raw_status & IXXAT_USBV2_CAN_STATUS_ERRLIM) { + can_frame->can_id |= CAN_ERR_CRTL; + can_frame->data[1] |= CAN_ERR_CRTL_TX_WARNING; + can_frame->data[1] |= CAN_ERR_CRTL_RX_WARNING; + dev->can.can_stats.error_warning++; + new_state = CAN_STATE_ERROR_WARNING; + } + + if (raw_status & IXXAT_USBV2_CAN_STATUS_OVRRUN) { + can_frame->can_id |= CAN_ERR_PROT; + can_frame->data[2] |= CAN_ERR_PROT_OVERLOAD; + netdev->stats.rx_over_errors++; + netdev->stats.rx_errors++; + } + + if (!new_state) { + new_state = CAN_STATE_ERROR_ACTIVE; + + dev->bec.txerr = 0; + dev->bec.rxerr = 0; + } + } + + dev->can.state = new_state; + + netif_rx(skb); + netdev->stats.rx_packets++; + netdev->stats.rx_bytes += can_frame->can_dlc; + + return 0; +} + +/* + * callback for bulk IN urb + */ +static int ixx_usbv2_decode_buf(struct ixx_usb_device *dev, struct urb *urb) +{ + struct net_device *netdev = dev->netdev; + struct ixx_can_msg *can_msg; + u32 msg_end; + int err = 0; + u32 read_size = 0; + u8 msg_type; + u8 *data; + + data = urb->transfer_buffer; + + /* loop reading all the records from the incoming message */ + msg_end = urb->actual_length; + for (; msg_end > 0;) { + can_msg = (struct ixx_can_msg *) &data[read_size]; + + if (!can_msg || !can_msg->size) { + netdev_err(netdev, "got unsupported rec in usb msg:\n"); + err = -ENOTSUPP; + break; + } + + /* check if the record goes out of current packet */ + if ((read_size + can_msg->size + 1) > urb->actual_length) { + netdev_err(netdev, + "got frag rec: should inc usb rx buf size\n"); + err = -EBADMSG; + break; + } + + msg_type = + (le32_to_cpu(can_msg->flags) & + IXXAT_USBV2_MSG_FLAGS_TYPE); + + switch (msg_type) { + + case IXXAT_USBV2_CAN_DATA: + err = ixx_usbv2_handle_canmsg(dev, can_msg); + if (err < 0) + goto fail; + break; + + case IXXAT_USBV2_CAN_STATUS: + err = ixx_usbv2_handle_status(dev, can_msg); + if (err < 0) + goto fail; + break; + + case IXXAT_USBV2_CAN_ERROR: + err = ixx_usbv2_handle_error(dev, can_msg); + if (err < 0) + goto fail; + break; + + case IXXAT_USBV2_CAN_TIMEOVR: + ixxat_usb_get_ts_tv(dev, can_msg->time, NULL); + break; + + case IXXAT_USBV2_CAN_INFO: + case IXXAT_USBV2_CAN_WAKEUP: + case IXXAT_USBV2_CAN_TIMERST: + break; + + default: + netdev_err(netdev, + "unhandled rec type 0x%02x (%d): ignored\n", + msg_type, msg_type); + break; + } + + read_size += can_msg->size + 1; + msg_end -= (can_msg->size + 1); + } + +fail: + if (err) + ixxat_dump_mem("received msg", urb->transfer_buffer, + urb->actual_length); + + return err; +} + +static int ixx_usbv2_encode_msg(struct ixx_usb_device *dev, struct sk_buff *skb, + u8 *obuf, size_t *size) +{ + struct can_frame *cf = (struct can_frame *) skb->data; + struct ixx_can_msg can_msg = { 0 }; + + if (cf->can_id & CAN_RTR_FLAG) + can_msg.flags |= IXXAT_USBV2_MSG_FLAGS_RTR; + + if (cf->can_id & CAN_EFF_FLAG) { + can_msg.flags |= IXXAT_USBV2_MSG_FLAGS_EXT; + can_msg.msg_id = cf->can_id & CAN_EFF_MASK; + } else { + can_msg.msg_id = cf->can_id & CAN_SFF_MASK; + } + + if (dev->can.ctrlmode & CAN_CTRLMODE_ONE_SHOT) + can_msg.flags |= IXXAT_USBV2_MSG_FLAGS_SSM; + + can_msg.flags |= (cf->can_dlc << 16) & IXXAT_USBV2_MSG_FLAGS_DLC; + + can_msg.flags = cpu_to_le32(can_msg.flags); + can_msg.msg_id = cpu_to_le32(can_msg.msg_id); + + memcpy(can_msg.data, cf->data, cf->can_dlc); + can_msg.size = (u8)(sizeof(can_msg) - 1 - CAN_MAX_DLEN + cf->can_dlc); + + memcpy(obuf, &can_msg, can_msg.size + 1); + + *size = can_msg.size + 1; + + skb->data_len = *size; + + return 0; +} + +static int ixx_usbv2_start(struct ixx_usb_device *dev) +{ + int err; + u32 time_ref = 0; + u8 can_opmode = IXXAT_USBV2_OPMODE_EXTENDED + | IXXAT_USBV2_OPMODE_STANDARD; + + if (dev->can.ctrlmode & CAN_CTRLMODE_BERR_REPORTING) + can_opmode |= IXXAT_USBV2_OPMODE_ERRFRAME; + if (dev->can.ctrlmode & CAN_CTRLMODE_LISTENONLY) + can_opmode |= IXXAT_USBV2_OPMODE_LISTONLY; + + err = ixx_usbv2_init_ctrl(dev, can_opmode, dev->btr0, dev->btr1); + if (err) + return err; + + /* opening first device: */ + if (dev->ctrl_opened_count == 0) { + err = ixx_usbv2_start_ctrl(dev, &time_ref); + if (err) + return err; + + ixxat_usb_set_ts_now(dev, time_ref); + } + + dev->ctrl_opened_count++; + + dev->bec.txerr = 0; + dev->bec.rxerr = 0; + + return err; +} + +/* + * stop interface + * (last chance before set bus off) + */ +static int ixx_usbv2_stop(struct ixx_usb_device *dev) +{ + int err; + + if (dev->ctrl_opened_count == 1) { + err = ixx_usbv2_stop_ctrl(dev); + if (err) + return err; + } + + /* turn off ts msgs for that interface if no other dev opened */ +// if (pdev->usb_if->dev_opened_count == 1) +// ixx_usbv2_set_ts(dev, 0); + dev->ctrl_opened_count--; + + return 0; +} + +/* + * called when probing to initialize a device object. + */ +static int ixx_usbv2_init(struct ixx_usb_device *dev) +{ + dev->restart_task = kthread_run(&ixx_usbv2_restart_task, dev, + "restart_thread"); + if (!dev->restart_task) + return -ENOBUFS; + + return 0; +} + +static void ixx_usbv2_exit(struct ixx_usb_device *dev) +{ + ixx_usbv2_reset_ctrl(dev); + + dev->must_quit = 1; + dev->restart_flag = 1; + wake_up_interruptible(&dev->wait_queue); + if (dev->restart_task) + kthread_stop(dev->restart_task); +} + +/* + * probe function for new IXXAT USB-to-CAN V2 interface + */ +static int ixx_usbv2_probe(struct usb_interface *intf) +{ + struct usb_host_interface *if_desc; + int i; + + if_desc = intf->altsetting; + + /* check interface endpoint addresses */ + for (i = 0; i < if_desc->desc.bNumEndpoints; i++) { + struct usb_endpoint_descriptor *ep = &if_desc->endpoint[i].desc; + + /* + * below is the list of valid ep addreses. Any other ep address + * is considered as not-CAN interface address => no dev created + */ + switch (ep->bEndpointAddress) { + case IXXAT_USBV2_EP_MSGOUT_0: + case IXXAT_USBV2_EP_MSGOUT_1: + case IXXAT_USBV2_EP_MSGOUT_2: + case IXXAT_USBV2_EP_MSGOUT_3: + case IXXAT_USBV2_EP_MSGOUT_4: + case IXXAT_USBV2_EP_MSGIN_0: + case IXXAT_USBV2_EP_MSGIN_1: + case IXXAT_USBV2_EP_MSGIN_2: + case IXXAT_USBV2_EP_MSGIN_3: + case IXXAT_USBV2_EP_MSGIN_4: + + break; + default: + return -ENODEV; + } + } + + return 0; +} + +static int ixx_usbv2_get_dev_caps(struct usb_device *dev, + struct ixx_dev_caps *dev_caps) +{ + int err = -ENODEV, i; + u8 data[IXXAT_USBV2_CMD_BUFFER_SIZE] = { 0 }; + struct ixx_usbv2_dev_caps_req *dev_caps_req; + struct ixx_usbv2_dev_caps_res *dev_caps_res; + u32 req_size = sizeof(*dev_caps_req); + + dev_caps_req = (struct ixx_usbv2_dev_caps_req *) data; + dev_caps_res = (struct ixx_usbv2_dev_caps_res *)(data + req_size); + + dev_caps_req->dal_req.req_size = cpu_to_le32(req_size); + dev_caps_req->dal_req.req_code = + cpu_to_le32(IXXAT_USBV2_BRD_GET_DEVCAPS_CMD); + dev_caps_req->dal_req.req_port = 0xffff; + dev_caps_req->dal_req.req_socket = 0xffff; + + dev_caps_res->dal_res.res_size = + cpu_to_le32(sizeof(*dev_caps_res)); + dev_caps_res->dal_res.ret_size = 0; + dev_caps_res->dal_res.ret_code = 0xffffffff; + + err = ixx_usbv2_send_cmd(dev, &dev_caps_req->dal_req); + if (err < 0) + return err; + + err = ixx_usbv2_rcv_cmd(dev, &dev_caps_res->dal_res, + 0xffff); + if (err < 0) + return err; + + dev_caps->bus_ctrl_count = + le16_to_cpu(dev_caps_res->dev_caps.bus_ctrl_count); + for (i = 0; i < dev_caps->bus_ctrl_count; ++i) + dev_caps->bus_ctrl_types[i] = + le16_to_cpu(dev_caps_res->dev_caps.bus_ctrl_types[i]); + + return 0; +} + +static int ixx_usbv2_get_ctrl_caps(struct usb_device *dev, + struct ixx_ctrl_caps *ctrl_caps, int index) +{ + int err = -ENODEV; + u8 data[IXXAT_USBV2_CMD_BUFFER_SIZE] = { 0 }; + struct ixx_usbv2_ctrl_caps_req *ctrl_caps_req; + struct ixx_usbv2_ctrl_caps_res *ctrl_caps_res; + u32 req_size = sizeof(*ctrl_caps_req); + + ctrl_caps_req = (struct ixx_usbv2_ctrl_caps_req *) data; + ctrl_caps_res = (struct ixx_usbv2_ctrl_caps_res *)(data + req_size); + + ctrl_caps_req->dal_req.req_size = cpu_to_le32(req_size); + ctrl_caps_req->dal_req.req_code = + cpu_to_le32(IXXAT_USBV2_CAN_GET_CAPS_CMD); + ctrl_caps_req->dal_req.req_port = cpu_to_le16(index); + ctrl_caps_req->dal_req.req_socket = 0xffff; + + ctrl_caps_res->dal_res.res_size = + cpu_to_le32(sizeof(*ctrl_caps_res)); + ctrl_caps_res->dal_res.ret_size = 0; + ctrl_caps_res->dal_res.ret_code = 0xffffffff; + + err = ixx_usbv2_send_cmd(dev, &ctrl_caps_req->dal_req); + if (err < 0) + return err; + + err = ixx_usbv2_rcv_cmd(dev, &ctrl_caps_res->dal_res, + index); + if (err < 0) + return err; + + ctrl_caps->bus_coupling = le16_to_cpu( + ctrl_caps_res->ctrl_caps.bus_coupling); + ctrl_caps->clock_freq = + le32_to_cpu(ctrl_caps_res->ctrl_caps.clock_freq); + ctrl_caps->cms_divisor = le32_to_cpu( + ctrl_caps_res->ctrl_caps.cms_divisor); + ctrl_caps->cms_max_ticks = le32_to_cpu( + ctrl_caps_res->ctrl_caps.cms_max_ticks); + ctrl_caps->ctrl_type = le16_to_cpu(ctrl_caps_res->ctrl_caps.ctrl_type); + ctrl_caps->dtx_divisor = le32_to_cpu( + ctrl_caps_res->ctrl_caps.dtx_divisor); + ctrl_caps->dtx_max_ticks = le32_to_cpu( + ctrl_caps_res->ctrl_caps.dtx_max_ticks); + ctrl_caps->features = le32_to_cpu(ctrl_caps_res->ctrl_caps.features); + ctrl_caps->tsc_divisor = le32_to_cpu( + ctrl_caps_res->ctrl_caps.tsc_divisor); + + return 0; +} + +static int ixx_usbv2_get_fwinfo(struct ixx_usb_device *dev, + struct ixx_intf_fw_info *fwinfo) +{ + int err = -ENODEV; + u8 data[IXXAT_USBV2_CMD_BUFFER_SIZE] = { 0 }; + struct ixx_usbv2_brd_get_fwinfo_req *fw_info_req; + struct ixx_usbv2_brd_get_fwinfo_res *fw_info_res; + u32 req_size = sizeof(*fw_info_req); + + fw_info_req = (struct ixx_usbv2_brd_get_fwinfo_req *) data; + fw_info_res = (struct ixx_usbv2_brd_get_fwinfo_res *)(data + req_size); + + fw_info_req->dal_req.req_size = cpu_to_le32(req_size); + fw_info_req->dal_req.req_code = + cpu_to_le32(IXXAT_USBV2_BRD_GET_FWINFO_CMD); + fw_info_req->dal_req.req_port = 0xffff; + fw_info_req->dal_req.req_socket = 0xffff; + + fw_info_res->dal_res.res_size = + cpu_to_le32(sizeof(*fw_info_res)); + fw_info_res->dal_res.ret_size = 0; + fw_info_res->dal_res.ret_code = 0xffffffff; + + err = ixx_usbv2_send_cmd(dev->udev, &fw_info_req->dal_req); + if (err < 0) + return err; + + err = ixx_usbv2_rcv_cmd(dev->udev, + &fw_info_res->dal_res, 0xffff); + if (err < 0) + return err; + + if (fwinfo) { + fwinfo->build_version = + le16_to_cpu(fw_info_res->fwinfo.build_version); + fwinfo->firmware_type = + le32_to_cpu(fw_info_res->fwinfo.firmware_type); + fwinfo->major_version = + le16_to_cpu(fw_info_res->fwinfo.major_version); + fwinfo->minor_version = + le16_to_cpu(fw_info_res->fwinfo.minor_version); + fwinfo->reserved = + le16_to_cpu(fw_info_res->fwinfo.reserved); + } + + return le32_to_cpu(fw_info_res->dal_res.ret_code); +} + +static int ixx_usbv2_get_dev_info(struct ixx_usb_device *dev, + struct ixx_intf_info *dev_info) +{ + int err = -ENODEV; + u8 data[IXXAT_USBV2_CMD_BUFFER_SIZE] = { 0 }; + struct ixx_usbv2_brd_get_intf_info_req *dev_info_req; + struct ixx_usbv2_brd_get_intf_info_res *dev_info_res; + u32 req_size = sizeof(*dev_info_req); + + dev_info_req = (struct ixx_usbv2_brd_get_intf_info_req *) data; + dev_info_res = + (struct ixx_usbv2_brd_get_intf_info_res *)(data + req_size); + + dev_info_req->dal_req.req_size = cpu_to_le32(req_size); + dev_info_req->dal_req.req_code = + cpu_to_le32(IXXAT_USBV2_BRD_GET_DEVINFO_CMD); + dev_info_req->dal_req.req_port = 0xffff; + dev_info_req->dal_req.req_socket = 0xffff; + + dev_info_res->dal_res.res_size = + cpu_to_le32(sizeof(*dev_info_res)); + dev_info_res->dal_res.ret_size = 0; + dev_info_res->dal_res.ret_code = 0xffffffff; + + err = ixx_usbv2_send_cmd(dev->udev, &dev_info_req->dal_req); + if (err < 0) + return err; + + err = ixx_usbv2_rcv_cmd(dev->udev, + &dev_info_res->dal_res, 0xffff); + if (err < 0) + return err; + + if (dev_info) { + memcpy(dev_info->device_id, &dev_info_res->info.device_id, + sizeof(dev_info_res->info.device_id)); + memcpy(dev_info->device_name, &dev_info_res->info.device_name, + sizeof(dev_info_res->info.device_name)); + dev_info->device_fpga_version = + le16_to_cpu(dev_info_res->info.device_fpga_version); + dev_info->device_version = + le32_to_cpu(dev_info_res->info.device_version); + } + + return le32_to_cpu(dev_info_res->dal_res.ret_code); +} + +/* + * describe the describes the USB-to-CAN V2 compact adapter + */ +struct ixx_usb_adapter usb_to_can_v2_compact = { + .name = "USB-to-CAN V2 compact", + .device_id = USB_TO_CAN_V2_COMPACT_PRODUCT_ID, + .clock = { + .freq = SJA1000_CRYSTAL_HZ, + }, + .bittiming_const = { + .name = "ixxat_usb", + .tseg1_min = 1, + .tseg1_max = 16, + .tseg2_min = 1, + .tseg2_max = 8, + .sjw_max = 4, + .brp_min = 1, + .brp_max = 64, + .brp_inc = 1, + }, + + .ctrlmode_supported = CAN_CTRLMODE_3_SAMPLES | + CAN_CTRLMODE_BERR_REPORTING | + CAN_CTRLMODE_LOOPBACK | + CAN_CTRLMODE_LISTENONLY, + + /* size of device private data */ + .sizeof_dev_private = sizeof(struct ixx_usb_device), + + /* give here messages in/out endpoints */ + .ep_msg_in = { IXXAT_USBV2_EP_MSGIN_0, IXXAT_USBV2_EP_MSGIN_1, + IXXAT_USBV2_EP_MSGIN_2, IXXAT_USBV2_EP_MSGIN_3, + IXXAT_USBV2_EP_MSGIN_4 }, + .ep_msg_out = { IXXAT_USBV2_EP_MSGOUT_0, IXXAT_USBV2_EP_MSGOUT_1, + IXXAT_USBV2_EP_MSGOUT_2, IXXAT_USBV2_EP_MSGOUT_3, + IXXAT_USBV2_EP_MSGOUT_4 }, + + /* size of rx/tx usb buffers */ + .rx_buffer_size = IXXAT_USBV2_RX_BUFFER_SIZE, + .tx_buffer_size = IXXAT_USBV2_TX_BUFFER_SIZE, + + /* device callbacks */ + .intf_probe = ixx_usbv2_probe, + .dev_get_dev_caps = ixx_usbv2_get_dev_caps, + .dev_get_ctrl_caps = ixx_usbv2_get_ctrl_caps, + .dev_init = ixx_usbv2_init, + .dev_exit = ixx_usbv2_exit, + .dev_set_bittiming = ixx_usbv2_set_bittiming, + .intf_get_info = ixx_usbv2_get_dev_info, + .intf_get_fw_info = ixx_usbv2_get_fwinfo, + .dev_decode_buf = ixx_usbv2_decode_buf, + .dev_encode_msg = ixx_usbv2_encode_msg, + .dev_start = ixx_usbv2_start, + .dev_stop = ixx_usbv2_stop, +}; + +/* + * describes the USB-to-CAN V2 automotive adapter + */ +struct ixx_usb_adapter usb_to_can_v2_automotive = { + .name = "USB-to-CAN V2 automotive", + .device_id = USB_TO_CAN_V2_AUTOMOTIVE_PRODUCT_ID, + .clock = { + .freq = SJA1000_CRYSTAL_HZ, + }, + .bittiming_const = { + .name = "ixxat_usb", + .tseg1_min = 1, + .tseg1_max = 16, + .tseg2_min = 1, + .tseg2_max = 8, + .sjw_max = 4, + .brp_min = 1, + .brp_max = 64, + .brp_inc = 1, + }, + + .ctrlmode_supported = CAN_CTRLMODE_3_SAMPLES | + CAN_CTRLMODE_BERR_REPORTING | + CAN_CTRLMODE_LOOPBACK | + CAN_CTRLMODE_LISTENONLY, + + /* size of device private data */ + .sizeof_dev_private = sizeof(struct ixx_usb_device), + + /* give here messages in/out endpoints */ + .ep_msg_in = { IXXAT_USBV2_EP_MSGIN_0, IXXAT_USBV2_EP_MSGIN_1, + IXXAT_USBV2_EP_MSGIN_2, IXXAT_USBV2_EP_MSGIN_3, + IXXAT_USBV2_EP_MSGIN_4 }, + .ep_msg_out = { IXXAT_USBV2_EP_MSGOUT_0, IXXAT_USBV2_EP_MSGOUT_1, + IXXAT_USBV2_EP_MSGOUT_2, IXXAT_USBV2_EP_MSGOUT_3, + IXXAT_USBV2_EP_MSGOUT_4 }, + + /* size of rx/tx usb buffers */ + .rx_buffer_size = IXXAT_USBV2_RX_BUFFER_SIZE, + .tx_buffer_size = IXXAT_USBV2_TX_BUFFER_SIZE, + + /* device callbacks */ + .intf_probe = ixx_usbv2_probe, + .dev_get_dev_caps = ixx_usbv2_get_dev_caps, + .dev_get_ctrl_caps = ixx_usbv2_get_ctrl_caps, + .dev_init = ixx_usbv2_init, + .dev_exit = ixx_usbv2_exit, + .dev_set_bittiming = ixx_usbv2_set_bittiming, + .intf_get_info = ixx_usbv2_get_dev_info, + .intf_get_fw_info = ixx_usbv2_get_fwinfo, + .dev_decode_buf = ixx_usbv2_decode_buf, + .dev_encode_msg = ixx_usbv2_encode_msg, + .dev_start = ixx_usbv2_start, + .dev_stop = ixx_usbv2_stop, +}; + +/* + * describes the USB-to-CAN V2 embedded adapter + */ +struct ixx_usb_adapter usb_to_can_v2_embedded = { + .name = "USB-to-CAN V2 embedded", + .device_id = USB_TO_CAN_V2_EMBEDDED_PRODUCT_ID, + .clock = { + .freq = SJA1000_CRYSTAL_HZ, + }, + .bittiming_const = { + .name = "ixxat_usb", + .tseg1_min = 1, + .tseg1_max = 16, + .tseg2_min = 1, + .tseg2_max = 8, + .sjw_max = 4, + .brp_min = 1, + .brp_max = 64, + .brp_inc = 1, + }, + + .ctrlmode_supported = CAN_CTRLMODE_3_SAMPLES | + CAN_CTRLMODE_BERR_REPORTING | + CAN_CTRLMODE_LOOPBACK | + CAN_CTRLMODE_LISTENONLY, + + /* size of device private data */ + .sizeof_dev_private = sizeof(struct ixx_usb_device), + + /* give here messages in/out endpoints */ + .ep_msg_in = { IXXAT_USBV2_EP_MSGIN_0, IXXAT_USBV2_EP_MSGIN_1, + IXXAT_USBV2_EP_MSGIN_2, IXXAT_USBV2_EP_MSGIN_3, + IXXAT_USBV2_EP_MSGIN_4 }, + .ep_msg_out = { IXXAT_USBV2_EP_MSGOUT_0, IXXAT_USBV2_EP_MSGOUT_1, + IXXAT_USBV2_EP_MSGOUT_2, IXXAT_USBV2_EP_MSGOUT_3, + IXXAT_USBV2_EP_MSGOUT_4 }, + + /* size of rx/tx usb buffers */ + .rx_buffer_size = IXXAT_USBV2_RX_BUFFER_SIZE, + .tx_buffer_size = IXXAT_USBV2_TX_BUFFER_SIZE, + + /* device callbacks */ + .intf_probe = ixx_usbv2_probe, + .dev_get_dev_caps = ixx_usbv2_get_dev_caps, + .dev_get_ctrl_caps = ixx_usbv2_get_ctrl_caps, + .dev_init = ixx_usbv2_init, + .dev_exit = ixx_usbv2_exit, + .dev_set_bittiming = ixx_usbv2_set_bittiming, + .intf_get_info = ixx_usbv2_get_dev_info, + .intf_get_fw_info = ixx_usbv2_get_fwinfo, + .dev_decode_buf = ixx_usbv2_decode_buf, + .dev_encode_msg = ixx_usbv2_encode_msg, + .dev_start = ixx_usbv2_start, + .dev_stop = ixx_usbv2_stop, +}; + +/* + * describes the USB-to-CAN V2 professional adapter + */ +struct ixx_usb_adapter usb_to_can_v2_professional = { + .name = "USB-to-CAN V2 professional", + .device_id = USB_TO_CAN_V2_PROFESSIONAL_PRODUCT_ID, + .clock = { + .freq = SJA1000_CRYSTAL_HZ, + }, + .bittiming_const = { + .name = "ixxat_usb", + .tseg1_min = 1, + .tseg1_max = 16, + .tseg2_min = 1, + .tseg2_max = 8, + .sjw_max = 4, + .brp_min = 1, + .brp_max = 64, + .brp_inc = 1, + }, + + .ctrlmode_supported = CAN_CTRLMODE_3_SAMPLES | + CAN_CTRLMODE_BERR_REPORTING | + CAN_CTRLMODE_LOOPBACK | + CAN_CTRLMODE_LISTENONLY, + + /* size of device private data */ + .sizeof_dev_private = sizeof(struct ixx_usb_device), + + /* give here messages in/out endpoints */ + .ep_msg_in = { IXXAT_USBV2_EP_MSGIN_0, IXXAT_USBV2_EP_MSGIN_1, + IXXAT_USBV2_EP_MSGIN_2, IXXAT_USBV2_EP_MSGIN_3, + IXXAT_USBV2_EP_MSGIN_4 }, + .ep_msg_out = { IXXAT_USBV2_EP_MSGOUT_0, IXXAT_USBV2_EP_MSGOUT_1, + IXXAT_USBV2_EP_MSGOUT_2, IXXAT_USBV2_EP_MSGOUT_3, + IXXAT_USBV2_EP_MSGOUT_4 }, + + /* size of rx/tx usb buffers */ + .rx_buffer_size = IXXAT_USBV2_RX_BUFFER_SIZE, + .tx_buffer_size = IXXAT_USBV2_TX_BUFFER_SIZE, + + /* device callbacks */ + .intf_probe = ixx_usbv2_probe, + .dev_get_dev_caps = ixx_usbv2_get_dev_caps, + .dev_get_ctrl_caps = ixx_usbv2_get_ctrl_caps, + .dev_init = ixx_usbv2_init, + .dev_exit = ixx_usbv2_exit, + .dev_set_bittiming = ixx_usbv2_set_bittiming, + .intf_get_info = ixx_usbv2_get_dev_info, + .intf_get_fw_info = ixx_usbv2_get_fwinfo, + .dev_decode_buf = ixx_usbv2_decode_buf, + .dev_encode_msg = ixx_usbv2_encode_msg, + .dev_start = ixx_usbv2_start, + .dev_stop = ixx_usbv2_stop, +}; + +/* + * describes the USB-to-CAN V2 low speed adapter + */ +struct ixx_usb_adapter usb_to_can_v2_low_speed = { + .name = "USB-to-CAN V2 low speed", + .device_id = USB_TO_CAN_V2_LOW_SPEED_PRODUCT_ID, + .clock = { + .freq = SJA1000_CRYSTAL_HZ, + }, + .bittiming_const = { + .name = "ixxat_usb", + .tseg1_min = 1, + .tseg1_max = 16, + .tseg2_min = 1, + .tseg2_max = 8, + .sjw_max = 4, + .brp_min = 1, + .brp_max = 64, + .brp_inc = 1, + }, + + .ctrlmode_supported = CAN_CTRLMODE_3_SAMPLES | + CAN_CTRLMODE_BERR_REPORTING | + CAN_CTRLMODE_LOOPBACK | + CAN_CTRLMODE_LISTENONLY, + + /* size of device private data */ + .sizeof_dev_private = sizeof(struct ixx_usb_device), + + /* give here messages in/out endpoints */ + .ep_msg_in = { IXXAT_USBV2_EP_MSGIN_0, IXXAT_USBV2_EP_MSGIN_1, + IXXAT_USBV2_EP_MSGIN_2, IXXAT_USBV2_EP_MSGIN_3, + IXXAT_USBV2_EP_MSGIN_4 }, + .ep_msg_out = { IXXAT_USBV2_EP_MSGOUT_0, IXXAT_USBV2_EP_MSGOUT_1, + IXXAT_USBV2_EP_MSGOUT_2, IXXAT_USBV2_EP_MSGOUT_3, + IXXAT_USBV2_EP_MSGOUT_4 }, + + /* size of rx/tx usb buffers */ + .rx_buffer_size = IXXAT_USBV2_RX_BUFFER_SIZE, + .tx_buffer_size = IXXAT_USBV2_TX_BUFFER_SIZE, + + /* device callbacks */ + .intf_probe = ixx_usbv2_probe, + .dev_get_dev_caps = ixx_usbv2_get_dev_caps, + .dev_get_ctrl_caps = ixx_usbv2_get_ctrl_caps, + .dev_init = ixx_usbv2_init, + .dev_exit = ixx_usbv2_exit, + .dev_set_bittiming = ixx_usbv2_set_bittiming, + .intf_get_info = ixx_usbv2_get_dev_info, + .intf_get_fw_info = ixx_usbv2_get_fwinfo, + .dev_decode_buf = ixx_usbv2_decode_buf, + .dev_encode_msg = ixx_usbv2_encode_msg, + .dev_start = ixx_usbv2_start, + .dev_stop = ixx_usbv2_stop, +}; + +/* + * describes the USB-to-CAN V2 extended adapter + */ +struct ixx_usb_adapter usb_to_can_v2_extended = { + .name = "USB-to-CAN V2 extended", + .device_id = USB_TO_CAN_V2_EXTENDED_PRODUCT_ID, + .clock = { + .freq = SJA1000_CRYSTAL_HZ, + }, + .bittiming_const = { + .name = "ixxat_usb", + .tseg1_min = 1, + .tseg1_max = 16, + .tseg2_min = 1, + .tseg2_max = 8, + .sjw_max = 4, + .brp_min = 1, + .brp_max = 64, + .brp_inc = 1, + }, + + .ctrlmode_supported = CAN_CTRLMODE_3_SAMPLES | + CAN_CTRLMODE_BERR_REPORTING | + CAN_CTRLMODE_LOOPBACK | + CAN_CTRLMODE_LISTENONLY, + + /* size of device private data */ + .sizeof_dev_private = sizeof(struct ixx_usb_device), + + /* give here messages in/out endpoints */ + .ep_msg_in = { IXXAT_USBV2_EP_MSGIN_0, IXXAT_USBV2_EP_MSGIN_1, + IXXAT_USBV2_EP_MSGIN_2, IXXAT_USBV2_EP_MSGIN_3, + IXXAT_USBV2_EP_MSGIN_4 }, + .ep_msg_out = { IXXAT_USBV2_EP_MSGOUT_0, IXXAT_USBV2_EP_MSGOUT_1, + IXXAT_USBV2_EP_MSGOUT_2, IXXAT_USBV2_EP_MSGOUT_3, + IXXAT_USBV2_EP_MSGOUT_4 }, + + /* size of rx/tx usb buffers */ + .rx_buffer_size = IXXAT_USBV2_RX_BUFFER_SIZE, + .tx_buffer_size = IXXAT_USBV2_TX_BUFFER_SIZE, + + /* device callbacks */ + .intf_probe = ixx_usbv2_probe, + .dev_get_dev_caps = ixx_usbv2_get_dev_caps, + .dev_get_ctrl_caps = ixx_usbv2_get_ctrl_caps, + .dev_init = ixx_usbv2_init, + .dev_exit = ixx_usbv2_exit, + .dev_set_bittiming = ixx_usbv2_set_bittiming, + .intf_get_info = ixx_usbv2_get_dev_info, + .intf_get_fw_info = ixx_usbv2_get_fwinfo, + .dev_decode_buf = ixx_usbv2_decode_buf, + .dev_encode_msg = ixx_usbv2_encode_msg, + .dev_start = ixx_usbv2_start, + .dev_stop = ixx_usbv2_stop, +}; only in patch2: unchanged: --- linux-lts-xenial-4.4.0.orig/zfs/config/kernel-mount-nodev.m4 +++ linux-lts-xenial-4.4.0/zfs/config/kernel-mount-nodev.m4 @@ -0,0 +1,20 @@ +dnl # +dnl # 2.6.39 API change +dnl # The .get_sb callback has been replaced by a .mount callback +dnl # in the file_system_type structure. When using the new +dnl # interface the caller must now use the mount_nodev() helper. +dnl # This updated callback and helper no longer pass the vfsmount. +dnl # +AC_DEFUN([ZFS_AC_KERNEL_MOUNT_NODEV], + [AC_MSG_CHECKING([whether mount_nodev() is available]) + ZFS_LINUX_TRY_COMPILE_SYMBOL([ + #include + ], [ + mount_nodev(NULL, 0, NULL, NULL); + ], [mount_nodev], [fs/super.c], [ + AC_MSG_RESULT(yes) + AC_DEFINE(HAVE_MOUNT_NODEV, 1, [mount_nodev() is available]) + ], [ + AC_MSG_RESULT(no) + ]) +])