mirror of
https://github.com/commaai/agnos-kernel-sdm845.git
synced 2026-06-08 11:24:51 +08:00
Merge "Merge android-4.9-o.80 (a9fd318) into msm-4.9"
This commit is contained in:
committed by
Gerrit - the friendly Code Review server
commit
b7e257f0a6
@@ -78,7 +78,7 @@ this protection comes at a cost:
|
||||
non-PTI SYSCALL entry code, so requires mapping fewer
|
||||
things into the userspace page tables. The downside is
|
||||
that stacks must be switched at entry time.
|
||||
d. Global pages are disabled for all kernel structures not
|
||||
c. Global pages are disabled for all kernel structures not
|
||||
mapped into both kernel and userspace page tables. This
|
||||
feature of the MMU allows different processes to share TLB
|
||||
entries mapping the kernel. Losing the feature means more
|
||||
|
||||
2
Makefile
2
Makefile
@@ -1,6 +1,6 @@
|
||||
VERSION = 4
|
||||
PATCHLEVEL = 9
|
||||
SUBLEVEL = 77
|
||||
SUBLEVEL = 80
|
||||
EXTRAVERSION =
|
||||
NAME = Roaring Lionus
|
||||
|
||||
|
||||
@@ -85,7 +85,7 @@
|
||||
timer@20200 {
|
||||
compatible = "arm,cortex-a9-global-timer";
|
||||
reg = <0x20200 0x100>;
|
||||
interrupts = <GIC_PPI 11 IRQ_TYPE_LEVEL_HIGH>;
|
||||
interrupts = <GIC_PPI 11 IRQ_TYPE_EDGE_RISING>;
|
||||
clocks = <&periph_clk>;
|
||||
};
|
||||
|
||||
@@ -93,7 +93,7 @@
|
||||
compatible = "arm,cortex-a9-twd-timer";
|
||||
reg = <0x20600 0x20>;
|
||||
interrupts = <GIC_PPI 13 (GIC_CPU_MASK_SIMPLE(2) |
|
||||
IRQ_TYPE_LEVEL_HIGH)>;
|
||||
IRQ_TYPE_EDGE_RISING)>;
|
||||
clocks = <&periph_clk>;
|
||||
};
|
||||
|
||||
|
||||
@@ -53,7 +53,8 @@
|
||||
};
|
||||
|
||||
pinctrl: pin-controller@10000 {
|
||||
pinctrl-0 = <&pmx_dip_switches &pmx_gpio_header>;
|
||||
pinctrl-0 = <&pmx_dip_switches &pmx_gpio_header
|
||||
&pmx_gpio_header_gpo>;
|
||||
pinctrl-names = "default";
|
||||
|
||||
pmx_uart0: pmx-uart0 {
|
||||
@@ -85,11 +86,16 @@
|
||||
* ground.
|
||||
*/
|
||||
pmx_gpio_header: pmx-gpio-header {
|
||||
marvell,pins = "mpp17", "mpp7", "mpp29", "mpp28",
|
||||
marvell,pins = "mpp17", "mpp29", "mpp28",
|
||||
"mpp35", "mpp34", "mpp40";
|
||||
marvell,function = "gpio";
|
||||
};
|
||||
|
||||
pmx_gpio_header_gpo: pxm-gpio-header-gpo {
|
||||
marvell,pins = "mpp7";
|
||||
marvell,function = "gpo";
|
||||
};
|
||||
|
||||
pmx_gpio_init: pmx-init {
|
||||
marvell,pins = "mpp38";
|
||||
marvell,function = "gpio";
|
||||
|
||||
@@ -11,6 +11,7 @@ CONFIG_SMP=y
|
||||
CONFIG_NR_CPUS=8
|
||||
CONFIG_AEABI=y
|
||||
CONFIG_HIGHMEM=y
|
||||
CONFIG_CMA=y
|
||||
CONFIG_ARM_APPENDED_DTB=y
|
||||
CONFIG_ARM_ATAG_DTB_COMPAT=y
|
||||
CONFIG_CPU_FREQ=y
|
||||
@@ -35,6 +36,7 @@ CONFIG_CAN_SUN4I=y
|
||||
# CONFIG_WIRELESS is not set
|
||||
CONFIG_DEVTMPFS=y
|
||||
CONFIG_DEVTMPFS_MOUNT=y
|
||||
CONFIG_DMA_CMA=y
|
||||
CONFIG_BLK_DEV_SD=y
|
||||
CONFIG_ATA=y
|
||||
CONFIG_AHCI_SUNXI=y
|
||||
|
||||
@@ -1284,7 +1284,7 @@ static int user_mem_abort(struct kvm_vcpu *vcpu, phys_addr_t fault_ipa,
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
if (is_vm_hugetlb_page(vma) && !logging_active) {
|
||||
if (vma_kernel_pagesize(vma) && !logging_active) {
|
||||
hugetlb = true;
|
||||
gfn = (fault_ipa & PMD_MASK) >> PAGE_SHIFT;
|
||||
} else {
|
||||
|
||||
@@ -82,19 +82,21 @@ static inline void efi_set_pgd(struct mm_struct *mm)
|
||||
if (mm != current->active_mm) {
|
||||
/*
|
||||
* Update the current thread's saved ttbr0 since it is
|
||||
* restored as part of a return from exception. Set
|
||||
* the hardware TTBR0_EL1 using cpu_switch_mm()
|
||||
* directly to enable potential errata workarounds.
|
||||
* restored as part of a return from exception. Enable
|
||||
* access to the valid TTBR0_EL1 and invoke the errata
|
||||
* workaround directly since there is no return from
|
||||
* exception when invoking the EFI run-time services.
|
||||
*/
|
||||
update_saved_ttbr0(current, mm);
|
||||
cpu_switch_mm(mm->pgd, mm);
|
||||
uaccess_ttbr0_enable();
|
||||
post_ttbr_update_workaround();
|
||||
} else {
|
||||
/*
|
||||
* Defer the switch to the current thread's TTBR0_EL1
|
||||
* until uaccess_enable(). Restore the current
|
||||
* thread's saved ttbr0 corresponding to its active_mm
|
||||
*/
|
||||
cpu_set_reserved_ttbr0();
|
||||
uaccess_ttbr0_disable();
|
||||
update_saved_ttbr0(current, current->active_mm);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -177,7 +177,7 @@ static inline void update_saved_ttbr0(struct task_struct *tsk,
|
||||
else
|
||||
ttbr = virt_to_phys(mm->pgd) | ASID(mm) << 48;
|
||||
|
||||
task_thread_info(tsk)->ttbr0 = ttbr;
|
||||
WRITE_ONCE(task_thread_info(tsk)->ttbr0, ttbr);
|
||||
}
|
||||
#else
|
||||
static inline void update_saved_ttbr0(struct task_struct *tsk,
|
||||
@@ -232,5 +232,6 @@ switch_mm(struct mm_struct *prev, struct mm_struct *next,
|
||||
#define activate_mm(prev,next) switch_mm(prev, next, current)
|
||||
|
||||
void verify_cpu_asid_bits(void);
|
||||
void post_ttbr_update_workaround(void);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -132,16 +132,18 @@ static inline void set_fs(mm_segment_t fs)
|
||||
#ifdef CONFIG_ARM64_SW_TTBR0_PAN
|
||||
static inline void __uaccess_ttbr0_disable(void)
|
||||
{
|
||||
unsigned long ttbr;
|
||||
unsigned long flags, ttbr;
|
||||
|
||||
local_irq_save(flags);
|
||||
ttbr = read_sysreg(ttbr1_el1);
|
||||
ttbr &= ~TTBR_ASID_MASK;
|
||||
/* reserved_ttbr0 placed at the end of swapper_pg_dir */
|
||||
write_sysreg(ttbr + SWAPPER_DIR_SIZE, ttbr0_el1);
|
||||
isb();
|
||||
/* Set reserved ASID */
|
||||
ttbr &= ~TTBR_ASID_MASK;
|
||||
write_sysreg(ttbr, ttbr1_el1);
|
||||
isb();
|
||||
local_irq_restore(flags);
|
||||
}
|
||||
|
||||
static inline void __uaccess_ttbr0_enable(void)
|
||||
@@ -154,10 +156,11 @@ static inline void __uaccess_ttbr0_enable(void)
|
||||
* roll-over and an update of 'ttbr0'.
|
||||
*/
|
||||
local_irq_save(flags);
|
||||
ttbr0 = current_thread_info()->ttbr0;
|
||||
ttbr0 = READ_ONCE(current_thread_info()->ttbr0);
|
||||
|
||||
/* Restore active ASID */
|
||||
ttbr1 = read_sysreg(ttbr1_el1);
|
||||
ttbr1 &= ~TTBR_ASID_MASK; /* safety measure */
|
||||
ttbr1 |= ttbr0 & TTBR_ASID_MASK;
|
||||
write_sysreg(ttbr1, ttbr1_el1);
|
||||
isb();
|
||||
@@ -450,11 +453,11 @@ extern __must_check long strnlen_user(const char __user *str, long n);
|
||||
#ifdef CONFIG_ARM64_SW_TTBR0_PAN
|
||||
.macro __uaccess_ttbr0_disable, tmp1
|
||||
mrs \tmp1, ttbr1_el1 // swapper_pg_dir
|
||||
bic \tmp1, \tmp1, #TTBR_ASID_MASK
|
||||
add \tmp1, \tmp1, #SWAPPER_DIR_SIZE // reserved_ttbr0 at the end of swapper_pg_dir
|
||||
msr ttbr0_el1, \tmp1 // set reserved TTBR0_EL1
|
||||
isb
|
||||
sub \tmp1, \tmp1, #SWAPPER_DIR_SIZE
|
||||
bic \tmp1, \tmp1, #TTBR_ASID_MASK
|
||||
msr ttbr1_el1, \tmp1 // set reserved ASID
|
||||
isb
|
||||
.endm
|
||||
@@ -471,9 +474,11 @@ extern __must_check long strnlen_user(const char __user *str, long n);
|
||||
isb
|
||||
.endm
|
||||
|
||||
.macro uaccess_ttbr0_disable, tmp1
|
||||
.macro uaccess_ttbr0_disable, tmp1, tmp2
|
||||
alternative_if_not ARM64_HAS_PAN
|
||||
save_and_disable_irq \tmp2 // avoid preemption
|
||||
__uaccess_ttbr0_disable \tmp1
|
||||
restore_irq \tmp2
|
||||
alternative_else_nop_endif
|
||||
.endm
|
||||
|
||||
@@ -485,7 +490,7 @@ alternative_if_not ARM64_HAS_PAN
|
||||
alternative_else_nop_endif
|
||||
.endm
|
||||
#else
|
||||
.macro uaccess_ttbr0_disable, tmp1
|
||||
.macro uaccess_ttbr0_disable, tmp1, tmp2
|
||||
.endm
|
||||
|
||||
.macro uaccess_ttbr0_enable, tmp1, tmp2, tmp3
|
||||
@@ -495,8 +500,8 @@ alternative_else_nop_endif
|
||||
/*
|
||||
* These macros are no-ops when UAO is present.
|
||||
*/
|
||||
.macro uaccess_disable_not_uao, tmp1
|
||||
uaccess_ttbr0_disable \tmp1
|
||||
.macro uaccess_disable_not_uao, tmp1, tmp2
|
||||
uaccess_ttbr0_disable \tmp1, \tmp2
|
||||
alternative_if ARM64_ALT_PAN_NOT_UAO
|
||||
SET_PSTATE_PAN(1)
|
||||
alternative_else_nop_endif
|
||||
|
||||
@@ -150,7 +150,7 @@ alternative_if ARM64_HAS_PAN
|
||||
alternative_else_nop_endif
|
||||
|
||||
.if \el != 0
|
||||
mrs x21, ttbr1_el1
|
||||
mrs x21, ttbr0_el1
|
||||
tst x21, #TTBR_ASID_MASK // Check for the reserved ASID
|
||||
orr x23, x23, #PSR_PAN_BIT // Set the emulated PAN in the saved SPSR
|
||||
b.eq 1f // TTBR0 access already disabled
|
||||
|
||||
@@ -44,7 +44,7 @@ static int handle_hvc(struct kvm_vcpu *vcpu, struct kvm_run *run)
|
||||
|
||||
ret = kvm_psci_call(vcpu);
|
||||
if (ret < 0) {
|
||||
kvm_inject_undefined(vcpu);
|
||||
vcpu_set_reg(vcpu, 0, ~0UL);
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -53,7 +53,7 @@ static int handle_hvc(struct kvm_vcpu *vcpu, struct kvm_run *run)
|
||||
|
||||
static int handle_smc(struct kvm_vcpu *vcpu, struct kvm_run *run)
|
||||
{
|
||||
kvm_inject_undefined(vcpu);
|
||||
vcpu_set_reg(vcpu, 0, ~0UL);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
@@ -50,7 +50,7 @@ uao_user_alternative 9f, strh, sttrh, wzr, x0, 2
|
||||
b.mi 5f
|
||||
uao_user_alternative 9f, strb, sttrb, wzr, x0, 0
|
||||
5: mov x0, #0
|
||||
uaccess_disable_not_uao x2
|
||||
uaccess_disable_not_uao x2, x3
|
||||
ret
|
||||
ENDPROC(__clear_user)
|
||||
|
||||
|
||||
@@ -67,7 +67,7 @@ ENTRY(__arch_copy_from_user)
|
||||
uaccess_enable_not_uao x3, x4, x5
|
||||
add end, x0, x2
|
||||
#include "copy_template.S"
|
||||
uaccess_disable_not_uao x3
|
||||
uaccess_disable_not_uao x3, x4
|
||||
mov x0, #0 // Nothing to copy
|
||||
ret
|
||||
ENDPROC(__arch_copy_from_user)
|
||||
|
||||
@@ -68,7 +68,7 @@ ENTRY(__copy_in_user)
|
||||
uaccess_enable_not_uao x3, x4, x5
|
||||
add end, x0, x2
|
||||
#include "copy_template.S"
|
||||
uaccess_disable_not_uao x3
|
||||
uaccess_disable_not_uao x3, x4
|
||||
mov x0, #0
|
||||
ret
|
||||
ENDPROC(__copy_in_user)
|
||||
|
||||
@@ -66,7 +66,7 @@ ENTRY(__arch_copy_to_user)
|
||||
uaccess_enable_not_uao x3, x4, x5
|
||||
add end, x0, x2
|
||||
#include "copy_template.S"
|
||||
uaccess_disable_not_uao x3
|
||||
uaccess_disable_not_uao x3, x4
|
||||
mov x0, #0
|
||||
ret
|
||||
ENDPROC(__arch_copy_to_user)
|
||||
|
||||
@@ -145,7 +145,7 @@ USER(9f, ic ivau, x4 ) // invalidate I line PoU
|
||||
isb
|
||||
mov x0, #0
|
||||
1:
|
||||
uaccess_ttbr0_disable x1
|
||||
uaccess_ttbr0_disable x1, x2
|
||||
ret
|
||||
9:
|
||||
mov x0, #-EFAULT
|
||||
|
||||
@@ -186,6 +186,9 @@ ENDPROC(cpu_do_resume)
|
||||
ENTRY(cpu_do_switch_mm)
|
||||
mrs x2, ttbr1_el1
|
||||
mmid x1, x1 // get mm->context.id
|
||||
#ifdef CONFIG_ARM64_SW_TTBR0_PAN
|
||||
bfi x0, x1, #48, #16 // set the ASID field in TTBR0
|
||||
#endif
|
||||
bfi x2, x1, #48, #16 // set the ASID
|
||||
msr ttbr1_el1, x2 // in TTBR1 (since TCR.A1 is set)
|
||||
isb
|
||||
|
||||
@@ -106,6 +106,6 @@ ENTRY(privcmd_call)
|
||||
/*
|
||||
* Disable userspace access from kernel once the hyp call completed.
|
||||
*/
|
||||
uaccess_ttbr0_disable x6
|
||||
uaccess_ttbr0_disable x6, x7
|
||||
ret
|
||||
ENDPROC(privcmd_call);
|
||||
|
||||
@@ -576,7 +576,7 @@ static int __init ar7_register_uarts(void)
|
||||
uart_port.type = PORT_AR7;
|
||||
uart_port.uartclk = clk_get_rate(bus_clk) / 2;
|
||||
uart_port.iotype = UPIO_MEM32;
|
||||
uart_port.flags = UPF_FIXED_TYPE;
|
||||
uart_port.flags = UPF_FIXED_TYPE | UPF_BOOT_AUTOCONF;
|
||||
uart_port.regshift = 2;
|
||||
|
||||
uart_port.line = 0;
|
||||
|
||||
@@ -117,7 +117,7 @@ archheaders:
|
||||
archprepare: include/generated/user_constants.h
|
||||
|
||||
LINK-$(CONFIG_LD_SCRIPT_STATIC) += -static
|
||||
LINK-$(CONFIG_LD_SCRIPT_DYN) += -Wl,-rpath,/lib
|
||||
LINK-$(CONFIG_LD_SCRIPT_DYN) += -Wl,-rpath,/lib $(call cc-option, -no-pie)
|
||||
|
||||
CFLAGS_NO_HARDENING := $(call cc-option, -fno-PIC,) $(call cc-option, -fno-pic,) \
|
||||
$(call cc-option, -fno-stack-protector,) \
|
||||
|
||||
@@ -906,7 +906,7 @@ static int helper_rfc4106_encrypt(struct aead_request *req)
|
||||
|
||||
if (sg_is_last(req->src) &&
|
||||
req->src->offset + req->src->length <= PAGE_SIZE &&
|
||||
sg_is_last(req->dst) &&
|
||||
+ sg_is_last(req->dst) && req->dst->length &&
|
||||
req->dst->offset + req->dst->length <= PAGE_SIZE) {
|
||||
one_entry_in_sg = 1;
|
||||
scatterwalk_start(&src_sg_walk, req->src);
|
||||
|
||||
@@ -229,6 +229,17 @@ ENTRY(__switch_to_asm)
|
||||
movl %ebx, PER_CPU_VAR(stack_canary)+stack_canary_offset
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_RETPOLINE
|
||||
/*
|
||||
* When switching from a shallower to a deeper call stack
|
||||
* the RSB may either underflow or use entries populated
|
||||
* with userspace addresses. On CPUs where those concerns
|
||||
* exist, overwrite the RSB with entries which capture
|
||||
* speculative execution to prevent attack.
|
||||
*/
|
||||
FILL_RETURN_BUFFER %ebx, RSB_CLEAR_LOOPS, X86_FEATURE_RSB_CTXSW
|
||||
#endif
|
||||
|
||||
/* restore callee-saved registers */
|
||||
popl %esi
|
||||
popl %edi
|
||||
|
||||
@@ -427,6 +427,17 @@ ENTRY(__switch_to_asm)
|
||||
movq %rbx, PER_CPU_VAR(irq_stack_union)+stack_canary_offset
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_RETPOLINE
|
||||
/*
|
||||
* When switching from a shallower to a deeper call stack
|
||||
* the RSB may either underflow or use entries populated
|
||||
* with userspace addresses. On CPUs where those concerns
|
||||
* exist, overwrite the RSB with entries which capture
|
||||
* speculative execution to prevent attack.
|
||||
*/
|
||||
FILL_RETURN_BUFFER %r12, RSB_CLEAR_LOOPS, X86_FEATURE_RSB_CTXSW
|
||||
#endif
|
||||
|
||||
/* restore callee-saved registers */
|
||||
popq %r15
|
||||
popq %r14
|
||||
@@ -1053,7 +1064,7 @@ idtentry async_page_fault do_async_page_fault has_error_code=1
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_X86_MCE
|
||||
idtentry machine_check has_error_code=0 paranoid=1 do_sym=*machine_check_vector(%rip)
|
||||
idtentry machine_check do_mce has_error_code=0 paranoid=1
|
||||
#endif
|
||||
|
||||
/*
|
||||
|
||||
@@ -46,6 +46,7 @@ static enum { EMULATE, NATIVE, NONE } vsyscall_mode =
|
||||
#else
|
||||
EMULATE;
|
||||
#endif
|
||||
unsigned long vsyscall_pgprot = __PAGE_KERNEL_VSYSCALL;
|
||||
|
||||
static int __init vsyscall_setup(char *str)
|
||||
{
|
||||
@@ -336,11 +337,11 @@ void __init map_vsyscall(void)
|
||||
extern char __vsyscall_page;
|
||||
unsigned long physaddr_vsyscall = __pa_symbol(&__vsyscall_page);
|
||||
|
||||
if (vsyscall_mode != NATIVE)
|
||||
vsyscall_pgprot = __PAGE_KERNEL_VVAR;
|
||||
if (vsyscall_mode != NONE)
|
||||
__set_fixmap(VSYSCALL_PAGE, physaddr_vsyscall,
|
||||
vsyscall_mode == NATIVE
|
||||
? PAGE_KERNEL_VSYSCALL
|
||||
: PAGE_KERNEL_VVAR);
|
||||
__pgprot(vsyscall_pgprot));
|
||||
|
||||
BUILD_BUG_ON((unsigned long)__fix_to_virt(VSYSCALL_PAGE) !=
|
||||
(unsigned long)VSYSCALL_ADDR);
|
||||
|
||||
@@ -277,7 +277,7 @@ static int __init amd_power_pmu_init(void)
|
||||
int ret;
|
||||
|
||||
if (!x86_match_cpu(cpu_match))
|
||||
return 0;
|
||||
return -ENODEV;
|
||||
|
||||
if (!boot_cpu_has(X86_FEATURE_ACC_POWER))
|
||||
return -ENODEV;
|
||||
|
||||
@@ -197,9 +197,9 @@
|
||||
#define X86_FEATURE_RETPOLINE ( 7*32+12) /* Generic Retpoline mitigation for Spectre variant 2 */
|
||||
#define X86_FEATURE_RETPOLINE_AMD ( 7*32+13) /* AMD Retpoline mitigation for Spectre variant 2 */
|
||||
|
||||
#define X86_FEATURE_INTEL_PT ( 7*32+15) /* Intel Processor Trace */
|
||||
#define X86_FEATURE_AVX512_4VNNIW (7*32+16) /* AVX-512 Neural Network Instructions */
|
||||
#define X86_FEATURE_AVX512_4FMAPS (7*32+17) /* AVX-512 Multiply Accumulation Single precision */
|
||||
#define X86_FEATURE_RSB_CTXSW ( 7*32+19) /* Fill RSB on context switches */
|
||||
|
||||
/* 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 */
|
||||
@@ -235,6 +235,7 @@
|
||||
#define X86_FEATURE_SMAP ( 9*32+20) /* Supervisor Mode Access Prevention */
|
||||
#define X86_FEATURE_CLFLUSHOPT ( 9*32+23) /* CLFLUSHOPT instruction */
|
||||
#define X86_FEATURE_CLWB ( 9*32+24) /* CLWB instruction */
|
||||
#define X86_FEATURE_INTEL_PT ( 9*32+25) /* Intel Processor Trace */
|
||||
#define X86_FEATURE_AVX512PF ( 9*32+26) /* AVX-512 Prefetch */
|
||||
#define X86_FEATURE_AVX512ER ( 9*32+27) /* AVX-512 Exponential and Reciprocal */
|
||||
#define X86_FEATURE_AVX512CD ( 9*32+28) /* AVX-512 Conflict Detection */
|
||||
|
||||
@@ -1113,7 +1113,8 @@ int x86_emulate_instruction(struct kvm_vcpu *vcpu, unsigned long cr2,
|
||||
static inline int emulate_instruction(struct kvm_vcpu *vcpu,
|
||||
int emulation_type)
|
||||
{
|
||||
return x86_emulate_instruction(vcpu, 0, emulation_type, NULL, 0);
|
||||
return x86_emulate_instruction(vcpu, 0,
|
||||
emulation_type | EMULTYPE_NO_REEXECUTE, NULL, 0);
|
||||
}
|
||||
|
||||
void kvm_enable_efer_bits(u64);
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
* Fill the CPU return stack buffer.
|
||||
*
|
||||
* Each entry in the RSB, if used for a speculative 'ret', contains an
|
||||
* infinite 'pause; jmp' loop to capture speculative execution.
|
||||
* infinite 'pause; lfence; jmp' loop to capture speculative execution.
|
||||
*
|
||||
* This is required in various cases for retpoline and IBRS-based
|
||||
* mitigations for the Spectre variant 2 vulnerability. Sometimes to
|
||||
@@ -38,11 +38,13 @@
|
||||
call 772f; \
|
||||
773: /* speculation trap */ \
|
||||
pause; \
|
||||
lfence; \
|
||||
jmp 773b; \
|
||||
772: \
|
||||
call 774f; \
|
||||
775: /* speculation trap */ \
|
||||
pause; \
|
||||
lfence; \
|
||||
jmp 775b; \
|
||||
774: \
|
||||
dec reg; \
|
||||
@@ -73,6 +75,7 @@
|
||||
call .Ldo_rop_\@
|
||||
.Lspec_trap_\@:
|
||||
pause
|
||||
lfence
|
||||
jmp .Lspec_trap_\@
|
||||
.Ldo_rop_\@:
|
||||
mov \reg, (%_ASM_SP)
|
||||
@@ -165,6 +168,7 @@
|
||||
" .align 16\n" \
|
||||
"901: call 903f;\n" \
|
||||
"902: pause;\n" \
|
||||
" lfence;\n" \
|
||||
" jmp 902b;\n" \
|
||||
" .align 16\n" \
|
||||
"903: addl $4, %%esp;\n" \
|
||||
@@ -190,6 +194,9 @@ enum spectre_v2_mitigation {
|
||||
SPECTRE_V2_IBRS,
|
||||
};
|
||||
|
||||
extern char __indirect_thunk_start[];
|
||||
extern char __indirect_thunk_end[];
|
||||
|
||||
/*
|
||||
* On VMEXIT we must ensure that no RSB predictions learned in the guest
|
||||
* can be followed in the host, by overwriting the RSB completely. Both
|
||||
@@ -199,16 +206,17 @@ enum spectre_v2_mitigation {
|
||||
static inline void vmexit_fill_RSB(void)
|
||||
{
|
||||
#ifdef CONFIG_RETPOLINE
|
||||
unsigned long loops = RSB_CLEAR_LOOPS / 2;
|
||||
unsigned long loops;
|
||||
|
||||
asm volatile (ANNOTATE_NOSPEC_ALTERNATIVE
|
||||
ALTERNATIVE("jmp 910f",
|
||||
__stringify(__FILL_RETURN_BUFFER(%0, RSB_CLEAR_LOOPS, %1)),
|
||||
X86_FEATURE_RETPOLINE)
|
||||
"910:"
|
||||
: "=&r" (loops), ASM_CALL_CONSTRAINT
|
||||
: "r" (loops) : "memory" );
|
||||
: "=r" (loops), ASM_CALL_CONSTRAINT
|
||||
: : "memory" );
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif /* __ASSEMBLY__ */
|
||||
#endif /* __NOSPEC_BRANCH_H__ */
|
||||
|
||||
@@ -596,7 +596,7 @@ static inline void sync_core(void)
|
||||
{
|
||||
int tmp;
|
||||
|
||||
#ifdef CONFIG_M486
|
||||
#ifdef CONFIG_X86_32
|
||||
/*
|
||||
* Do a CPUID if available, otherwise do a jump. The jump
|
||||
* can conveniently enough be the jump around CPUID.
|
||||
|
||||
@@ -92,6 +92,7 @@ dotraplinkage void do_simd_coprocessor_error(struct pt_regs *, long);
|
||||
#ifdef CONFIG_X86_32
|
||||
dotraplinkage void do_iret_error(struct pt_regs *, long);
|
||||
#endif
|
||||
dotraplinkage void do_mce(struct pt_regs *, long);
|
||||
|
||||
static inline int get_si_code(unsigned long condition)
|
||||
{
|
||||
|
||||
@@ -13,6 +13,7 @@ extern void map_vsyscall(void);
|
||||
*/
|
||||
extern bool emulate_vsyscall(struct pt_regs *regs, unsigned long address);
|
||||
extern bool vsyscall_enabled(void);
|
||||
extern unsigned long vsyscall_pgprot;
|
||||
#else
|
||||
static inline void map_vsyscall(void) {}
|
||||
static inline bool emulate_vsyscall(struct pt_regs *regs, unsigned long address)
|
||||
|
||||
@@ -361,14 +361,17 @@ static int x86_vector_alloc_irqs(struct irq_domain *domain, unsigned int virq,
|
||||
irq_data->chip_data = data;
|
||||
irq_data->hwirq = virq + i;
|
||||
err = assign_irq_vector_policy(virq + i, node, data, info);
|
||||
if (err)
|
||||
if (err) {
|
||||
irq_data->chip_data = NULL;
|
||||
free_apic_chip_data(data);
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
error:
|
||||
x86_vector_free_irqs(domain, virq, i + 1);
|
||||
x86_vector_free_irqs(domain, virq, i);
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
#include <asm/alternative.h>
|
||||
#include <asm/pgtable.h>
|
||||
#include <asm/cacheflush.h>
|
||||
#include <asm/intel-family.h>
|
||||
|
||||
static void __init spectre_v2_select_mitigation(void);
|
||||
|
||||
@@ -154,6 +155,23 @@ disable:
|
||||
return SPECTRE_V2_CMD_NONE;
|
||||
}
|
||||
|
||||
/* Check for Skylake-like CPUs (for RSB handling) */
|
||||
static bool __init is_skylake_era(void)
|
||||
{
|
||||
if (boot_cpu_data.x86_vendor == X86_VENDOR_INTEL &&
|
||||
boot_cpu_data.x86 == 6) {
|
||||
switch (boot_cpu_data.x86_model) {
|
||||
case INTEL_FAM6_SKYLAKE_MOBILE:
|
||||
case INTEL_FAM6_SKYLAKE_DESKTOP:
|
||||
case INTEL_FAM6_SKYLAKE_X:
|
||||
case INTEL_FAM6_KABYLAKE_MOBILE:
|
||||
case INTEL_FAM6_KABYLAKE_DESKTOP:
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static void __init spectre_v2_select_mitigation(void)
|
||||
{
|
||||
enum spectre_v2_mitigation_cmd cmd = spectre_v2_parse_cmdline();
|
||||
@@ -212,6 +230,24 @@ retpoline_auto:
|
||||
|
||||
spectre_v2_enabled = mode;
|
||||
pr_info("%s\n", spectre_v2_strings[mode]);
|
||||
|
||||
/*
|
||||
* If neither SMEP or KPTI are available, there is a risk of
|
||||
* hitting userspace addresses in the RSB after a context switch
|
||||
* from a shallow call stack to a deeper one. To prevent this fill
|
||||
* the entire RSB, even when using IBRS.
|
||||
*
|
||||
* Skylake era CPUs have a separate issue with *underflow* of the
|
||||
* RSB, when they will predict 'ret' targets from the generic BTB.
|
||||
* The proper mitigation for this is IBRS. If IBRS is not supported
|
||||
* or deactivated in favour of retpolines the RSB fill on context
|
||||
* switch is required.
|
||||
*/
|
||||
if ((!boot_cpu_has(X86_FEATURE_KAISER) &&
|
||||
!boot_cpu_has(X86_FEATURE_SMEP)) || is_skylake_era()) {
|
||||
setup_force_cpu_cap(X86_FEATURE_RSB_CTXSW);
|
||||
pr_info("Filling RSB on context switch\n");
|
||||
}
|
||||
}
|
||||
|
||||
#undef pr_fmt
|
||||
|
||||
@@ -883,8 +883,8 @@ static void __init early_identify_cpu(struct cpuinfo_x86 *c)
|
||||
|
||||
setup_force_cpu_cap(X86_FEATURE_ALWAYS);
|
||||
|
||||
/* Assume for now that ALL x86 CPUs are insecure */
|
||||
setup_force_cpu_bug(X86_BUG_CPU_MELTDOWN);
|
||||
if (c->x86_vendor != X86_VENDOR_AMD)
|
||||
setup_force_cpu_bug(X86_BUG_CPU_MELTDOWN);
|
||||
|
||||
setup_force_cpu_bug(X86_BUG_SPECTRE_V1);
|
||||
setup_force_cpu_bug(X86_BUG_SPECTRE_V2);
|
||||
|
||||
@@ -934,6 +934,8 @@ static int __populate_cache_leaves(unsigned int cpu)
|
||||
ci_leaf_init(this_leaf++, &id4_regs);
|
||||
__cache_cpumap_setup(cpu, idx, &id4_regs);
|
||||
}
|
||||
this_cpu_ci->cpu_map_populated = true;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -1754,6 +1754,11 @@ static void unexpected_machine_check(struct pt_regs *regs, long error_code)
|
||||
void (*machine_check_vector)(struct pt_regs *, long error_code) =
|
||||
unexpected_machine_check;
|
||||
|
||||
dotraplinkage void do_mce(struct pt_regs *regs, long error_code)
|
||||
{
|
||||
machine_check_vector(regs, error_code);
|
||||
}
|
||||
|
||||
/*
|
||||
* Called for each booted CPU to set up machine checks.
|
||||
* Must be called with preempt off:
|
||||
|
||||
@@ -40,6 +40,9 @@
|
||||
#include <asm/setup.h>
|
||||
#include <asm/msr.h>
|
||||
|
||||
/* last level cache size per core */
|
||||
static int llc_size_per_core;
|
||||
|
||||
/*
|
||||
* Temporary microcode blobs pointers storage. We note here during early load
|
||||
* the pointers to microcode blobs we've got from whatever storage (detached
|
||||
@@ -1053,12 +1056,14 @@ static bool is_blacklisted(unsigned int cpu)
|
||||
|
||||
/*
|
||||
* Late loading on model 79 with microcode revision less than 0x0b000021
|
||||
* may result in a system hang. This behavior is documented in item
|
||||
* BDF90, #334165 (Intel Xeon Processor E7-8800/4800 v4 Product Family).
|
||||
* and LLC size per core bigger than 2.5MB may result in a system hang.
|
||||
* This behavior is documented in item BDF90, #334165 (Intel Xeon
|
||||
* Processor E7-8800/4800 v4 Product Family).
|
||||
*/
|
||||
if (c->x86 == 6 &&
|
||||
c->x86_model == INTEL_FAM6_BROADWELL_X &&
|
||||
c->x86_mask == 0x01 &&
|
||||
llc_size_per_core > 2621440 &&
|
||||
c->microcode < 0x0b000021) {
|
||||
pr_err_once("Erratum BDF90: late loading with revision < 0x0b000021 (0x%x) disabled.\n", c->microcode);
|
||||
pr_err_once("Please consider either early loading through initrd/built-in or a potential BIOS update.\n");
|
||||
@@ -1125,6 +1130,15 @@ static struct microcode_ops microcode_intel_ops = {
|
||||
.microcode_fini_cpu = microcode_fini_cpu,
|
||||
};
|
||||
|
||||
static int __init calc_llc_size_per_core(struct cpuinfo_x86 *c)
|
||||
{
|
||||
u64 llc_size = c->x86_cache_size * 1024;
|
||||
|
||||
do_div(llc_size, c->x86_max_cores);
|
||||
|
||||
return (int)llc_size;
|
||||
}
|
||||
|
||||
struct microcode_ops * __init init_intel_microcode(void)
|
||||
{
|
||||
struct cpuinfo_x86 *c = &boot_cpu_data;
|
||||
@@ -1135,6 +1149,8 @@ struct microcode_ops * __init init_intel_microcode(void)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
llc_size_per_core = calc_llc_size_per_core(c);
|
||||
|
||||
return µcode_intel_ops;
|
||||
}
|
||||
|
||||
|
||||
@@ -31,7 +31,6 @@ void init_scattered_cpuid_features(struct cpuinfo_x86 *c)
|
||||
const struct cpuid_bit *cb;
|
||||
|
||||
static const struct cpuid_bit cpuid_bits[] = {
|
||||
{ X86_FEATURE_INTEL_PT, CR_EBX,25, 0x00000007, 0 },
|
||||
{ X86_FEATURE_AVX512_4VNNIW, CR_EDX, 2, 0x00000007, 0 },
|
||||
{ X86_FEATURE_AVX512_4FMAPS, CR_EDX, 3, 0x00000007, 0 },
|
||||
{ X86_FEATURE_APERFMPERF, CR_ECX, 0, 0x00000006, 0 },
|
||||
|
||||
@@ -37,6 +37,7 @@
|
||||
#include <asm/alternative.h>
|
||||
#include <asm/insn.h>
|
||||
#include <asm/debugreg.h>
|
||||
#include <asm/nospec-branch.h>
|
||||
|
||||
#include "common.h"
|
||||
|
||||
@@ -192,7 +193,7 @@ static int copy_optimized_instructions(u8 *dest, u8 *src)
|
||||
}
|
||||
|
||||
/* Check whether insn is indirect jump */
|
||||
static int insn_is_indirect_jump(struct insn *insn)
|
||||
static int __insn_is_indirect_jump(struct insn *insn)
|
||||
{
|
||||
return ((insn->opcode.bytes[0] == 0xff &&
|
||||
(X86_MODRM_REG(insn->modrm.value) & 6) == 4) || /* Jump */
|
||||
@@ -226,6 +227,26 @@ static int insn_jump_into_range(struct insn *insn, unsigned long start, int len)
|
||||
return (start <= target && target <= start + len);
|
||||
}
|
||||
|
||||
static int insn_is_indirect_jump(struct insn *insn)
|
||||
{
|
||||
int ret = __insn_is_indirect_jump(insn);
|
||||
|
||||
#ifdef CONFIG_RETPOLINE
|
||||
/*
|
||||
* Jump to x86_indirect_thunk_* is treated as an indirect jump.
|
||||
* Note that even with CONFIG_RETPOLINE=y, the kernel compiled with
|
||||
* older gcc may use indirect jump. So we add this check instead of
|
||||
* replace indirect-jump check.
|
||||
*/
|
||||
if (!ret)
|
||||
ret = insn_jump_into_range(insn,
|
||||
(unsigned long)__indirect_thunk_start,
|
||||
(unsigned long)__indirect_thunk_end -
|
||||
(unsigned long)__indirect_thunk_start);
|
||||
#endif
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Decode whole function to ensure any instructions don't jump into target */
|
||||
static int can_optimize(unsigned long paddr)
|
||||
{
|
||||
|
||||
@@ -693,7 +693,6 @@ unsigned long native_calibrate_tsc(void)
|
||||
case INTEL_FAM6_KABYLAKE_DESKTOP:
|
||||
crystal_khz = 24000; /* 24.0 MHz */
|
||||
break;
|
||||
case INTEL_FAM6_SKYLAKE_X:
|
||||
case INTEL_FAM6_ATOM_DENVERTON:
|
||||
crystal_khz = 25000; /* 25.0 MHz */
|
||||
break;
|
||||
|
||||
@@ -105,6 +105,13 @@ SECTIONS
|
||||
SOFTIRQENTRY_TEXT
|
||||
*(.fixup)
|
||||
*(.gnu.warning)
|
||||
|
||||
#ifdef CONFIG_RETPOLINE
|
||||
__indirect_thunk_start = .;
|
||||
*(.text.__x86.indirect_thunk)
|
||||
__indirect_thunk_end = .;
|
||||
#endif
|
||||
|
||||
/* End of text section */
|
||||
_etext = .;
|
||||
} :text = 0x9090
|
||||
|
||||
@@ -4990,6 +4990,8 @@ int x86_decode_insn(struct x86_emulate_ctxt *ctxt, void *insn, int insn_len)
|
||||
bool op_prefix = false;
|
||||
bool has_seg_override = false;
|
||||
struct opcode opcode;
|
||||
u16 dummy;
|
||||
struct desc_struct desc;
|
||||
|
||||
ctxt->memop.type = OP_NONE;
|
||||
ctxt->memopp = NULL;
|
||||
@@ -5008,6 +5010,11 @@ int x86_decode_insn(struct x86_emulate_ctxt *ctxt, void *insn, int insn_len)
|
||||
switch (mode) {
|
||||
case X86EMUL_MODE_REAL:
|
||||
case X86EMUL_MODE_VM86:
|
||||
def_op_bytes = def_ad_bytes = 2;
|
||||
ctxt->ops->get_segment(ctxt, &dummy, &desc, NULL, VCPU_SREG_CS);
|
||||
if (desc.d)
|
||||
def_op_bytes = def_ad_bytes = 4;
|
||||
break;
|
||||
case X86EMUL_MODE_PROT16:
|
||||
def_op_bytes = def_ad_bytes = 2;
|
||||
break;
|
||||
|
||||
@@ -257,8 +257,7 @@ void kvm_ioapic_scan_entry(struct kvm_vcpu *vcpu, ulong *ioapic_handled_vectors)
|
||||
index == RTC_GSI) {
|
||||
if (kvm_apic_match_dest(vcpu, NULL, 0,
|
||||
e->fields.dest_id, e->fields.dest_mode) ||
|
||||
(e->fields.trig_mode == IOAPIC_EDGE_TRIG &&
|
||||
kvm_apic_pending_eoi(vcpu, e->fields.vector)))
|
||||
kvm_apic_pending_eoi(vcpu, e->fields.vector))
|
||||
__set_bit(e->fields.vector,
|
||||
ioapic_handled_vectors);
|
||||
}
|
||||
@@ -279,6 +278,7 @@ static void ioapic_write_indirect(struct kvm_ioapic *ioapic, u32 val)
|
||||
{
|
||||
unsigned index;
|
||||
bool mask_before, mask_after;
|
||||
int old_remote_irr, old_delivery_status;
|
||||
union kvm_ioapic_redirect_entry *e;
|
||||
|
||||
switch (ioapic->ioregsel) {
|
||||
@@ -301,14 +301,28 @@ static void ioapic_write_indirect(struct kvm_ioapic *ioapic, u32 val)
|
||||
return;
|
||||
e = &ioapic->redirtbl[index];
|
||||
mask_before = e->fields.mask;
|
||||
/* Preserve read-only fields */
|
||||
old_remote_irr = e->fields.remote_irr;
|
||||
old_delivery_status = e->fields.delivery_status;
|
||||
if (ioapic->ioregsel & 1) {
|
||||
e->bits &= 0xffffffff;
|
||||
e->bits |= (u64) val << 32;
|
||||
} else {
|
||||
e->bits &= ~0xffffffffULL;
|
||||
e->bits |= (u32) val;
|
||||
e->fields.remote_irr = 0;
|
||||
}
|
||||
e->fields.remote_irr = old_remote_irr;
|
||||
e->fields.delivery_status = old_delivery_status;
|
||||
|
||||
/*
|
||||
* Some OSes (Linux, Xen) assume that Remote IRR bit will
|
||||
* be cleared by IOAPIC hardware when the entry is configured
|
||||
* as edge-triggered. This behavior is used to simulate an
|
||||
* explicit EOI on IOAPICs that don't have the EOI register.
|
||||
*/
|
||||
if (e->fields.trig_mode == IOAPIC_EDGE_TRIG)
|
||||
e->fields.remote_irr = 0;
|
||||
|
||||
mask_after = e->fields.mask;
|
||||
if (mask_before != mask_after)
|
||||
kvm_fire_mask_notifiers(ioapic->kvm, KVM_IRQCHIP_IOAPIC, index, mask_after);
|
||||
|
||||
@@ -5194,7 +5194,7 @@ static void vmx_vcpu_reset(struct kvm_vcpu *vcpu, bool init_event)
|
||||
vmcs_write64(GUEST_IA32_DEBUGCTL, 0);
|
||||
}
|
||||
|
||||
vmcs_writel(GUEST_RFLAGS, 0x02);
|
||||
kvm_set_rflags(vcpu, X86_EFLAGS_FIXED);
|
||||
kvm_rip_write(vcpu, 0xfff0);
|
||||
|
||||
vmcs_writel(GUEST_GDTR_BASE, 0);
|
||||
@@ -6257,7 +6257,7 @@ static int handle_invalid_guest_state(struct kvm_vcpu *vcpu)
|
||||
if (test_bit(KVM_REQ_EVENT, &vcpu->requests))
|
||||
return 1;
|
||||
|
||||
err = emulate_instruction(vcpu, EMULTYPE_NO_REEXECUTE);
|
||||
err = emulate_instruction(vcpu, 0);
|
||||
|
||||
if (err == EMULATE_USER_EXIT) {
|
||||
++vcpu->stat.mmio_exits;
|
||||
|
||||
@@ -1751,10 +1751,13 @@ static u64 __get_kvmclock_ns(struct kvm *kvm)
|
||||
/* both __this_cpu_read() and rdtsc() should be on the same cpu */
|
||||
get_cpu();
|
||||
|
||||
kvm_get_time_scale(NSEC_PER_SEC, __this_cpu_read(cpu_tsc_khz) * 1000LL,
|
||||
&hv_clock.tsc_shift,
|
||||
&hv_clock.tsc_to_system_mul);
|
||||
ret = __pvclock_read_cycles(&hv_clock, rdtsc());
|
||||
if (__this_cpu_read(cpu_tsc_khz)) {
|
||||
kvm_get_time_scale(NSEC_PER_SEC, __this_cpu_read(cpu_tsc_khz) * 1000LL,
|
||||
&hv_clock.tsc_shift,
|
||||
&hv_clock.tsc_to_system_mul);
|
||||
ret = __pvclock_read_cycles(&hv_clock, rdtsc());
|
||||
} else
|
||||
ret = ktime_get_boot_ns() + ka->kvmclock_offset;
|
||||
|
||||
put_cpu();
|
||||
|
||||
@@ -5308,7 +5311,7 @@ static int handle_emulation_failure(struct kvm_vcpu *vcpu)
|
||||
vcpu->run->exit_reason = KVM_EXIT_INTERNAL_ERROR;
|
||||
vcpu->run->internal.suberror = KVM_INTERNAL_ERROR_EMULATION;
|
||||
vcpu->run->internal.ndata = 0;
|
||||
r = EMULATE_FAIL;
|
||||
r = EMULATE_USER_EXIT;
|
||||
}
|
||||
kvm_queue_exception(vcpu, UD_VECTOR);
|
||||
|
||||
|
||||
@@ -93,6 +93,13 @@ static void delay_mwaitx(unsigned long __loops)
|
||||
{
|
||||
u64 start, end, delay, loops = __loops;
|
||||
|
||||
/*
|
||||
* Timer value of 0 causes MWAITX to wait indefinitely, unless there
|
||||
* is a store on the memory monitored by MONITORX.
|
||||
*/
|
||||
if (loops == 0)
|
||||
return;
|
||||
|
||||
start = rdtsc_ordered();
|
||||
|
||||
for (;;) {
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
#include <asm/nospec-branch.h>
|
||||
|
||||
.macro THUNK reg
|
||||
.section .text.__x86.indirect_thunk.\reg
|
||||
.section .text.__x86.indirect_thunk
|
||||
|
||||
ENTRY(__x86_indirect_thunk_\reg)
|
||||
CFI_STARTPROC
|
||||
@@ -25,7 +25,8 @@ ENDPROC(__x86_indirect_thunk_\reg)
|
||||
* than one per register with the correct names. So we do it
|
||||
* the simple and nasty way...
|
||||
*/
|
||||
#define EXPORT_THUNK(reg) EXPORT_SYMBOL(__x86_indirect_thunk_ ## reg)
|
||||
#define __EXPORT_THUNK(sym) _ASM_NOKPROBE(sym); EXPORT_SYMBOL(sym)
|
||||
#define EXPORT_THUNK(reg) __EXPORT_THUNK(__x86_indirect_thunk_ ## reg)
|
||||
#define GENERATE_THUNK(reg) THUNK reg ; EXPORT_THUNK(reg)
|
||||
|
||||
GENERATE_THUNK(_ASM_AX)
|
||||
|
||||
@@ -191,14 +191,15 @@ is_prefetch(struct pt_regs *regs, unsigned long error_code, unsigned long addr)
|
||||
* 6. T1 : reaches here, sees vma_pkey(vma)=5, when we really
|
||||
* faulted on a pte with its pkey=4.
|
||||
*/
|
||||
static void fill_sig_info_pkey(int si_code, siginfo_t *info, u32 *pkey)
|
||||
static void fill_sig_info_pkey(int si_signo, int si_code, siginfo_t *info,
|
||||
u32 *pkey)
|
||||
{
|
||||
/* This is effectively an #ifdef */
|
||||
if (!boot_cpu_has(X86_FEATURE_OSPKE))
|
||||
return;
|
||||
|
||||
/* Fault not from Protection Keys: nothing to do */
|
||||
if (si_code != SEGV_PKUERR)
|
||||
if ((si_code != SEGV_PKUERR) || (si_signo != SIGSEGV))
|
||||
return;
|
||||
/*
|
||||
* force_sig_info_fault() is called from a number of
|
||||
@@ -237,7 +238,7 @@ force_sig_info_fault(int si_signo, int si_code, unsigned long address,
|
||||
lsb = PAGE_SHIFT;
|
||||
info.si_addr_lsb = lsb;
|
||||
|
||||
fill_sig_info_pkey(si_code, &info, pkey);
|
||||
fill_sig_info_pkey(si_signo, si_code, &info, pkey);
|
||||
|
||||
force_sig_info(si_signo, &info, tsk);
|
||||
}
|
||||
|
||||
@@ -344,7 +344,7 @@ void __init kaiser_init(void)
|
||||
if (vsyscall_enabled())
|
||||
kaiser_add_user_map_early((void *)VSYSCALL_ADDR,
|
||||
PAGE_SIZE,
|
||||
__PAGE_KERNEL_VSYSCALL);
|
||||
vsyscall_pgprot);
|
||||
|
||||
for_each_possible_cpu(cpu) {
|
||||
void *percpu_vaddr = __per_cpu_user_mapped_start +
|
||||
|
||||
@@ -278,10 +278,10 @@ static void emit_bpf_tail_call(u8 **pprog)
|
||||
/* if (index >= array->map.max_entries)
|
||||
* goto out;
|
||||
*/
|
||||
EMIT4(0x48, 0x8B, 0x46, /* mov rax, qword ptr [rsi + 16] */
|
||||
EMIT2(0x89, 0xD2); /* mov edx, edx */
|
||||
EMIT3(0x39, 0x56, /* cmp dword ptr [rsi + 16], edx */
|
||||
offsetof(struct bpf_array, map.max_entries));
|
||||
EMIT3(0x48, 0x39, 0xD0); /* cmp rax, rdx */
|
||||
#define OFFSET1 47 /* number of bytes to jump */
|
||||
#define OFFSET1 43 /* number of bytes to jump */
|
||||
EMIT2(X86_JBE, OFFSET1); /* jbe out */
|
||||
label1 = cnt;
|
||||
|
||||
@@ -290,21 +290,20 @@ static void emit_bpf_tail_call(u8 **pprog)
|
||||
*/
|
||||
EMIT2_off32(0x8B, 0x85, -STACKSIZE + 36); /* mov eax, dword ptr [rbp - 516] */
|
||||
EMIT3(0x83, 0xF8, MAX_TAIL_CALL_CNT); /* cmp eax, MAX_TAIL_CALL_CNT */
|
||||
#define OFFSET2 36
|
||||
#define OFFSET2 32
|
||||
EMIT2(X86_JA, OFFSET2); /* ja out */
|
||||
label2 = cnt;
|
||||
EMIT3(0x83, 0xC0, 0x01); /* add eax, 1 */
|
||||
EMIT2_off32(0x89, 0x85, -STACKSIZE + 36); /* mov dword ptr [rbp - 516], eax */
|
||||
|
||||
/* prog = array->ptrs[index]; */
|
||||
EMIT4_off32(0x48, 0x8D, 0x84, 0xD6, /* lea rax, [rsi + rdx * 8 + offsetof(...)] */
|
||||
EMIT4_off32(0x48, 0x8B, 0x84, 0xD6, /* mov rax, [rsi + rdx * 8 + offsetof(...)] */
|
||||
offsetof(struct bpf_array, ptrs));
|
||||
EMIT3(0x48, 0x8B, 0x00); /* mov rax, qword ptr [rax] */
|
||||
|
||||
/* if (prog == NULL)
|
||||
* goto out;
|
||||
*/
|
||||
EMIT4(0x48, 0x83, 0xF8, 0x00); /* cmp rax, 0 */
|
||||
EMIT3(0x48, 0x85, 0xC0); /* test rax,rax */
|
||||
#define OFFSET3 10
|
||||
EMIT2(X86_JE, OFFSET3); /* je out */
|
||||
label3 = cnt;
|
||||
|
||||
@@ -120,7 +120,7 @@ config CRYPTO_DH
|
||||
|
||||
config CRYPTO_ECDH
|
||||
tristate "ECDH algorithm"
|
||||
select CRYTPO_KPP
|
||||
select CRYPTO_KPP
|
||||
help
|
||||
Generic implementation of the ECDH algorithm
|
||||
|
||||
|
||||
@@ -149,7 +149,7 @@ EXPORT_SYMBOL_GPL(af_alg_release_parent);
|
||||
|
||||
static int alg_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
|
||||
{
|
||||
const u32 forbidden = CRYPTO_ALG_INTERNAL;
|
||||
const u32 allowed = CRYPTO_ALG_KERN_DRIVER_ONLY;
|
||||
struct sock *sk = sock->sk;
|
||||
struct alg_sock *ask = alg_sk(sk);
|
||||
struct sockaddr_alg *sa = (void *)uaddr;
|
||||
@@ -157,6 +157,10 @@ static int alg_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
|
||||
void *private;
|
||||
int err;
|
||||
|
||||
/* If caller uses non-allowed flag, return error. */
|
||||
if ((sa->salg_feat & ~allowed) || (sa->salg_mask & ~allowed))
|
||||
return -EINVAL;
|
||||
|
||||
if (sock->state == SS_CONNECTED)
|
||||
return -EINVAL;
|
||||
|
||||
@@ -175,9 +179,7 @@ static int alg_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
|
||||
if (IS_ERR(type))
|
||||
return PTR_ERR(type);
|
||||
|
||||
private = type->bind(sa->salg_name,
|
||||
sa->salg_feat & ~forbidden,
|
||||
sa->salg_mask & ~forbidden);
|
||||
private = type->bind(sa->salg_name, sa->salg_feat, sa->salg_mask);
|
||||
if (IS_ERR(private)) {
|
||||
module_put(type->owner);
|
||||
return PTR_ERR(private);
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
#include <linux/types.h>
|
||||
#include <crypto/sha3.h>
|
||||
#include <asm/byteorder.h>
|
||||
#include <asm/unaligned.h>
|
||||
|
||||
#define KECCAK_ROUNDS 24
|
||||
|
||||
@@ -149,7 +150,7 @@ static int sha3_update(struct shash_desc *desc, const u8 *data,
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < sctx->rsizw; i++)
|
||||
sctx->st[i] ^= ((u64 *) src)[i];
|
||||
sctx->st[i] ^= get_unaligned_le64(src + 8 * i);
|
||||
keccakf(sctx->st);
|
||||
|
||||
done += sctx->rsiz;
|
||||
@@ -174,7 +175,7 @@ static int sha3_final(struct shash_desc *desc, u8 *out)
|
||||
sctx->buf[sctx->rsiz - 1] |= 0x80;
|
||||
|
||||
for (i = 0; i < sctx->rsizw; i++)
|
||||
sctx->st[i] ^= ((u64 *) sctx->buf)[i];
|
||||
sctx->st[i] ^= get_unaligned_le64(sctx->buf + 8 * i);
|
||||
|
||||
keccakf(sctx->st);
|
||||
|
||||
|
||||
@@ -594,25 +594,20 @@ struct acpi_namespace_node *acpi_ns_validate_handle(acpi_handle handle)
|
||||
void acpi_ns_terminate(void)
|
||||
{
|
||||
acpi_status status;
|
||||
union acpi_operand_object *prev;
|
||||
union acpi_operand_object *next;
|
||||
|
||||
ACPI_FUNCTION_TRACE(ns_terminate);
|
||||
|
||||
#ifdef ACPI_EXEC_APP
|
||||
{
|
||||
union acpi_operand_object *prev;
|
||||
union acpi_operand_object *next;
|
||||
/* Delete any module-level code blocks */
|
||||
|
||||
/* Delete any module-level code blocks */
|
||||
|
||||
next = acpi_gbl_module_code_list;
|
||||
while (next) {
|
||||
prev = next;
|
||||
next = next->method.mutex;
|
||||
prev->method.mutex = NULL; /* Clear the Mutex (cheated) field */
|
||||
acpi_ut_remove_reference(prev);
|
||||
}
|
||||
next = acpi_gbl_module_code_list;
|
||||
while (next) {
|
||||
prev = next;
|
||||
next = next->method.mutex;
|
||||
prev->method.mutex = NULL; /* Clear the Mutex (cheated) field */
|
||||
acpi_ut_remove_reference(prev);
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Free the entire namespace -- all nodes and all objects
|
||||
|
||||
@@ -146,6 +146,10 @@ static int create_pnp_modalias(struct acpi_device *acpi_dev, char *modalias,
|
||||
int count;
|
||||
struct acpi_hardware_id *id;
|
||||
|
||||
/* Avoid unnecessarily loading modules for non present devices. */
|
||||
if (!acpi_device_is_present(acpi_dev))
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* Since we skip ACPI_DT_NAMESPACE_HID from the modalias below, 0 should
|
||||
* be returned if ACPI_DT_NAMESPACE_HID is the only ACPI/PNP ID in the
|
||||
|
||||
@@ -99,13 +99,13 @@ static int find_child_checks(struct acpi_device *adev, bool check_children)
|
||||
return -ENODEV;
|
||||
|
||||
/*
|
||||
* If the device has a _HID (or _CID) returning a valid ACPI/PNP
|
||||
* device ID, it is better to make it look less attractive here, so that
|
||||
* the other device with the same _ADR value (that may not have a valid
|
||||
* device ID) can be matched going forward. [This means a second spec
|
||||
* violation in a row, so whatever we do here is best effort anyway.]
|
||||
* If the device has a _HID returning a valid ACPI/PNP device ID, it is
|
||||
* better to make it look less attractive here, so that the other device
|
||||
* with the same _ADR value (that may not have a valid device ID) can be
|
||||
* matched going forward. [This means a second spec violation in a row,
|
||||
* so whatever we do here is best effort anyway.]
|
||||
*/
|
||||
return sta_present && list_empty(&adev->pnp.ids) ?
|
||||
return sta_present && !adev->pnp.type.platform_id ?
|
||||
FIND_CHILD_MAX_SCORE : FIND_CHILD_MIN_SCORE;
|
||||
}
|
||||
|
||||
|
||||
@@ -4322,6 +4322,7 @@ static const struct ata_blacklist_entry ata_device_blacklist [] = {
|
||||
* https://bugzilla.kernel.org/show_bug.cgi?id=121671
|
||||
*/
|
||||
{ "LITEON CX1-JB*-HP", NULL, ATA_HORKAGE_MAX_SEC_1024 },
|
||||
{ "LITEON EP1-*", NULL, ATA_HORKAGE_MAX_SEC_1024 },
|
||||
|
||||
/* Devices we expect to fail diagnostics */
|
||||
|
||||
|
||||
@@ -121,6 +121,7 @@ config CFAG12864B_RATE
|
||||
|
||||
config IMG_ASCII_LCD
|
||||
tristate "Imagination Technologies ASCII LCD Display"
|
||||
depends on HAS_IOMEM
|
||||
default y if MIPS_MALTA || MIPS_SEAD3
|
||||
select SYSCON
|
||||
help
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include <linux/acpi.h>
|
||||
#include <linux/bitops.h>
|
||||
#include <linux/cacheinfo.h>
|
||||
#include <linux/compiler.h>
|
||||
@@ -104,9 +105,16 @@ static int cache_shared_cpu_map_setup(unsigned int cpu)
|
||||
struct cpu_cacheinfo *this_cpu_ci = get_cpu_cacheinfo(cpu);
|
||||
struct cacheinfo *this_leaf, *sib_leaf;
|
||||
unsigned int index;
|
||||
int ret;
|
||||
int ret = 0;
|
||||
|
||||
ret = cache_setup_of_node(cpu);
|
||||
if (this_cpu_ci->cpu_map_populated)
|
||||
return 0;
|
||||
|
||||
if (of_have_populated_dt())
|
||||
ret = cache_setup_of_node(cpu);
|
||||
else if (!acpi_disabled)
|
||||
/* No cache property/hierarchy support yet in ACPI */
|
||||
ret = -ENOTSUPP;
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
@@ -203,8 +211,7 @@ static int detect_cache_attributes(unsigned int cpu)
|
||||
*/
|
||||
ret = cache_shared_cpu_map_setup(cpu);
|
||||
if (ret) {
|
||||
pr_warn("Unable to detect cache hierarchy from DT for CPU %d\n",
|
||||
cpu);
|
||||
pr_warn("Unable to detect cache hierarchy for CPU %d\n", cpu);
|
||||
goto free_ci;
|
||||
}
|
||||
return 0;
|
||||
|
||||
@@ -1558,9 +1558,8 @@ out:
|
||||
return err;
|
||||
}
|
||||
|
||||
static void lo_release(struct gendisk *disk, fmode_t mode)
|
||||
static void __lo_release(struct loop_device *lo)
|
||||
{
|
||||
struct loop_device *lo = disk->private_data;
|
||||
int err;
|
||||
|
||||
if (atomic_dec_return(&lo->lo_refcnt))
|
||||
@@ -1586,6 +1585,13 @@ static void lo_release(struct gendisk *disk, fmode_t mode)
|
||||
mutex_unlock(&lo->lo_ctl_mutex);
|
||||
}
|
||||
|
||||
static void lo_release(struct gendisk *disk, fmode_t mode)
|
||||
{
|
||||
mutex_lock(&loop_index_mutex);
|
||||
__lo_release(disk->private_data);
|
||||
mutex_unlock(&loop_index_mutex);
|
||||
}
|
||||
|
||||
static const struct block_device_operations lo_fops = {
|
||||
.owner = THIS_MODULE,
|
||||
.open = lo_open,
|
||||
|
||||
@@ -331,6 +331,7 @@ endif
|
||||
if MIPS
|
||||
config LOONGSON2_CPUFREQ
|
||||
tristate "Loongson2 CPUFreq Driver"
|
||||
depends on LEMOTE_MACH2F
|
||||
help
|
||||
This option adds a CPUFreq driver for loongson processors which
|
||||
support software configurable cpu frequency.
|
||||
@@ -343,6 +344,7 @@ config LOONGSON2_CPUFREQ
|
||||
|
||||
config LOONGSON1_CPUFREQ
|
||||
tristate "Loongson1 CPUFreq Driver"
|
||||
depends on LOONGSON1_LS1B
|
||||
help
|
||||
This option adds a CPUFreq driver for loongson1 processors which
|
||||
support software configurable cpu frequency.
|
||||
|
||||
@@ -323,3 +323,6 @@ static struct platform_driver ath79_gpio_driver = {
|
||||
};
|
||||
|
||||
module_platform_driver(ath79_gpio_driver);
|
||||
|
||||
MODULE_DESCRIPTION("Atheros AR71XX/AR724X/AR913X GPIO API support");
|
||||
MODULE_LICENSE("GPL v2");
|
||||
|
||||
@@ -58,3 +58,7 @@ static int __init iop3xx_gpio_init(void)
|
||||
return platform_driver_register(&iop3xx_gpio_driver);
|
||||
}
|
||||
arch_initcall(iop3xx_gpio_init);
|
||||
|
||||
MODULE_DESCRIPTION("GPIO handling for Intel IOP3xx processors");
|
||||
MODULE_AUTHOR("Lennert Buytenhek <buytenh@wantstofly.org>");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
@@ -190,6 +190,16 @@ static void stmpe_gpio_irq_sync_unlock(struct irq_data *d)
|
||||
};
|
||||
int i, j;
|
||||
|
||||
/*
|
||||
* STMPE1600: to be able to get IRQ from pins,
|
||||
* a read must be done on GPMR register, or a write in
|
||||
* GPSR or GPCR registers
|
||||
*/
|
||||
if (stmpe->partnum == STMPE1600) {
|
||||
stmpe_reg_read(stmpe, stmpe->regs[STMPE_IDX_GPMR_LSB]);
|
||||
stmpe_reg_read(stmpe, stmpe->regs[STMPE_IDX_GPMR_CSB]);
|
||||
}
|
||||
|
||||
for (i = 0; i < CACHE_NR_REGS; i++) {
|
||||
/* STMPE801 and STMPE1600 don't have RE and FE registers */
|
||||
if ((stmpe->partnum == STMPE801 ||
|
||||
@@ -227,21 +237,11 @@ static void stmpe_gpio_irq_unmask(struct irq_data *d)
|
||||
{
|
||||
struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
|
||||
struct stmpe_gpio *stmpe_gpio = gpiochip_get_data(gc);
|
||||
struct stmpe *stmpe = stmpe_gpio->stmpe;
|
||||
int offset = d->hwirq;
|
||||
int regoffset = offset / 8;
|
||||
int mask = BIT(offset % 8);
|
||||
|
||||
stmpe_gpio->regs[REG_IE][regoffset] |= mask;
|
||||
|
||||
/*
|
||||
* STMPE1600 workaround: to be able to get IRQ from pins,
|
||||
* a read must be done on GPMR register, or a write in
|
||||
* GPSR or GPCR registers
|
||||
*/
|
||||
if (stmpe->partnum == STMPE1600)
|
||||
stmpe_reg_read(stmpe,
|
||||
stmpe->regs[STMPE_IDX_GPMR_LSB + regoffset]);
|
||||
}
|
||||
|
||||
static void stmpe_dbg_show_one(struct seq_file *s,
|
||||
|
||||
@@ -705,6 +705,9 @@ static irqreturn_t lineevent_irq_thread(int irq, void *p)
|
||||
struct gpioevent_data ge;
|
||||
int ret, level;
|
||||
|
||||
/* Do not leak kernel stack to userspace */
|
||||
memset(&ge, 0, sizeof(ge));
|
||||
|
||||
ge.timestamp = ktime_get_real_ns();
|
||||
level = gpiod_get_value_cansleep(le->desc);
|
||||
|
||||
|
||||
@@ -367,29 +367,50 @@ static int kgd_hqd_sdma_load(struct kgd_dev *kgd, void *mqd)
|
||||
{
|
||||
struct amdgpu_device *adev = get_amdgpu_device(kgd);
|
||||
struct cik_sdma_rlc_registers *m;
|
||||
unsigned long end_jiffies;
|
||||
uint32_t sdma_base_addr;
|
||||
uint32_t data;
|
||||
|
||||
m = get_sdma_mqd(mqd);
|
||||
sdma_base_addr = get_sdma_base_addr(m);
|
||||
|
||||
WREG32(sdma_base_addr + mmSDMA0_RLC0_VIRTUAL_ADDR,
|
||||
m->sdma_rlc_virtual_addr);
|
||||
WREG32(sdma_base_addr + mmSDMA0_RLC0_RB_CNTL,
|
||||
m->sdma_rlc_rb_cntl & (~SDMA0_RLC0_RB_CNTL__RB_ENABLE_MASK));
|
||||
|
||||
WREG32(sdma_base_addr + mmSDMA0_RLC0_RB_BASE,
|
||||
m->sdma_rlc_rb_base);
|
||||
|
||||
WREG32(sdma_base_addr + mmSDMA0_RLC0_RB_BASE_HI,
|
||||
m->sdma_rlc_rb_base_hi);
|
||||
|
||||
WREG32(sdma_base_addr + mmSDMA0_RLC0_RB_RPTR_ADDR_LO,
|
||||
m->sdma_rlc_rb_rptr_addr_lo);
|
||||
|
||||
WREG32(sdma_base_addr + mmSDMA0_RLC0_RB_RPTR_ADDR_HI,
|
||||
m->sdma_rlc_rb_rptr_addr_hi);
|
||||
end_jiffies = msecs_to_jiffies(2000) + jiffies;
|
||||
while (true) {
|
||||
data = RREG32(sdma_base_addr + mmSDMA0_RLC0_CONTEXT_STATUS);
|
||||
if (data & SDMA0_RLC0_CONTEXT_STATUS__IDLE_MASK)
|
||||
break;
|
||||
if (time_after(jiffies, end_jiffies))
|
||||
return -ETIME;
|
||||
usleep_range(500, 1000);
|
||||
}
|
||||
if (m->sdma_engine_id) {
|
||||
data = RREG32(mmSDMA1_GFX_CONTEXT_CNTL);
|
||||
data = REG_SET_FIELD(data, SDMA1_GFX_CONTEXT_CNTL,
|
||||
RESUME_CTX, 0);
|
||||
WREG32(mmSDMA1_GFX_CONTEXT_CNTL, data);
|
||||
} else {
|
||||
data = RREG32(mmSDMA0_GFX_CONTEXT_CNTL);
|
||||
data = REG_SET_FIELD(data, SDMA0_GFX_CONTEXT_CNTL,
|
||||
RESUME_CTX, 0);
|
||||
WREG32(mmSDMA0_GFX_CONTEXT_CNTL, data);
|
||||
}
|
||||
|
||||
WREG32(sdma_base_addr + mmSDMA0_RLC0_DOORBELL,
|
||||
m->sdma_rlc_doorbell);
|
||||
|
||||
m->sdma_rlc_doorbell);
|
||||
WREG32(sdma_base_addr + mmSDMA0_RLC0_RB_RPTR, 0);
|
||||
WREG32(sdma_base_addr + mmSDMA0_RLC0_RB_WPTR, 0);
|
||||
WREG32(sdma_base_addr + mmSDMA0_RLC0_VIRTUAL_ADDR,
|
||||
m->sdma_rlc_virtual_addr);
|
||||
WREG32(sdma_base_addr + mmSDMA0_RLC0_RB_BASE, m->sdma_rlc_rb_base);
|
||||
WREG32(sdma_base_addr + mmSDMA0_RLC0_RB_BASE_HI,
|
||||
m->sdma_rlc_rb_base_hi);
|
||||
WREG32(sdma_base_addr + mmSDMA0_RLC0_RB_RPTR_ADDR_LO,
|
||||
m->sdma_rlc_rb_rptr_addr_lo);
|
||||
WREG32(sdma_base_addr + mmSDMA0_RLC0_RB_RPTR_ADDR_HI,
|
||||
m->sdma_rlc_rb_rptr_addr_hi);
|
||||
WREG32(sdma_base_addr + mmSDMA0_RLC0_RB_CNTL,
|
||||
m->sdma_rlc_rb_cntl);
|
||||
|
||||
@@ -493,9 +514,9 @@ static int kgd_hqd_sdma_destroy(struct kgd_dev *kgd, void *mqd,
|
||||
}
|
||||
|
||||
WREG32(sdma_base_addr + mmSDMA0_RLC0_DOORBELL, 0);
|
||||
WREG32(sdma_base_addr + mmSDMA0_RLC0_RB_RPTR, 0);
|
||||
WREG32(sdma_base_addr + mmSDMA0_RLC0_RB_WPTR, 0);
|
||||
WREG32(sdma_base_addr + mmSDMA0_RLC0_RB_BASE, 0);
|
||||
WREG32(sdma_base_addr + mmSDMA0_RLC0_RB_CNTL,
|
||||
RREG32(sdma_base_addr + mmSDMA0_RLC0_RB_CNTL) |
|
||||
SDMA0_RLC0_RB_CNTL__RB_ENABLE_MASK);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -416,6 +416,10 @@ static bool amdgpu_cs_try_evict(struct amdgpu_cs_parser *p,
|
||||
if (candidate == lobj)
|
||||
break;
|
||||
|
||||
/* We can't move pinned BOs here */
|
||||
if (bo->pin_count)
|
||||
continue;
|
||||
|
||||
other = amdgpu_mem_type_to_domain(bo->tbo.mem.mem_type);
|
||||
|
||||
/* Check if this BO is in one of the domains we need space for */
|
||||
|
||||
@@ -215,8 +215,8 @@ static int update_mqd_sdma(struct mqd_manager *mm, void *mqd,
|
||||
BUG_ON(!mm || !mqd || !q);
|
||||
|
||||
m = get_sdma_mqd(mqd);
|
||||
m->sdma_rlc_rb_cntl = ffs(q->queue_size / sizeof(unsigned int)) <<
|
||||
SDMA0_RLC0_RB_CNTL__RB_SIZE__SHIFT |
|
||||
m->sdma_rlc_rb_cntl = (ffs(q->queue_size / sizeof(unsigned int)) - 1)
|
||||
<< SDMA0_RLC0_RB_CNTL__RB_SIZE__SHIFT |
|
||||
q->vmid << SDMA0_RLC0_RB_CNTL__RB_VMID__SHIFT |
|
||||
1 << SDMA0_RLC0_RB_CNTL__RPTR_WRITEBACK_ENABLE__SHIFT |
|
||||
6 << SDMA0_RLC0_RB_CNTL__RPTR_WRITEBACK_TIMER__SHIFT;
|
||||
|
||||
@@ -205,6 +205,24 @@ int pqm_create_queue(struct process_queue_manager *pqm,
|
||||
|
||||
switch (type) {
|
||||
case KFD_QUEUE_TYPE_SDMA:
|
||||
if (dev->dqm->queue_count >=
|
||||
CIK_SDMA_QUEUES_PER_ENGINE * CIK_SDMA_ENGINE_NUM) {
|
||||
pr_err("Over-subscription is not allowed for SDMA.\n");
|
||||
retval = -EPERM;
|
||||
goto err_create_queue;
|
||||
}
|
||||
|
||||
retval = create_cp_queue(pqm, dev, &q, properties, f, *qid);
|
||||
if (retval != 0)
|
||||
goto err_create_queue;
|
||||
pqn->q = q;
|
||||
pqn->kq = NULL;
|
||||
retval = dev->dqm->ops.create_queue(dev->dqm, q, &pdd->qpd,
|
||||
&q->properties.vmid);
|
||||
pr_debug("DQM returned %d for create_queue\n", retval);
|
||||
print_queue(q);
|
||||
break;
|
||||
|
||||
case KFD_QUEUE_TYPE_COMPUTE:
|
||||
/* check if there is over subscription */
|
||||
if ((sched_policy == KFD_SCHED_POLICY_HWS_NO_OVERSUBSCRIPTION) &&
|
||||
|
||||
@@ -97,7 +97,7 @@
|
||||
#define DP0_ACTIVEVAL 0x0650
|
||||
#define DP0_SYNCVAL 0x0654
|
||||
#define DP0_MISC 0x0658
|
||||
#define TU_SIZE_RECOMMENDED (0x3f << 16) /* LSCLK cycles per TU */
|
||||
#define TU_SIZE_RECOMMENDED (63) /* LSCLK cycles per TU */
|
||||
#define BPC_6 (0 << 5)
|
||||
#define BPC_8 (1 << 5)
|
||||
|
||||
@@ -318,7 +318,7 @@ static ssize_t tc_aux_transfer(struct drm_dp_aux *aux,
|
||||
tmp = (tmp << 8) | buf[i];
|
||||
i++;
|
||||
if (((i % 4) == 0) || (i == size)) {
|
||||
tc_write(DP0_AUXWDATA(i >> 2), tmp);
|
||||
tc_write(DP0_AUXWDATA((i - 1) >> 2), tmp);
|
||||
tmp = 0;
|
||||
}
|
||||
}
|
||||
@@ -603,8 +603,15 @@ static int tc_get_display_props(struct tc_data *tc)
|
||||
ret = drm_dp_link_probe(&tc->aux, &tc->link.base);
|
||||
if (ret < 0)
|
||||
goto err_dpcd_read;
|
||||
if ((tc->link.base.rate != 162000) && (tc->link.base.rate != 270000))
|
||||
goto err_dpcd_inval;
|
||||
if (tc->link.base.rate != 162000 && tc->link.base.rate != 270000) {
|
||||
dev_dbg(tc->dev, "Falling to 2.7 Gbps rate\n");
|
||||
tc->link.base.rate = 270000;
|
||||
}
|
||||
|
||||
if (tc->link.base.num_lanes > 2) {
|
||||
dev_dbg(tc->dev, "Falling to 2 lanes\n");
|
||||
tc->link.base.num_lanes = 2;
|
||||
}
|
||||
|
||||
ret = drm_dp_dpcd_readb(&tc->aux, DP_MAX_DOWNSPREAD, tmp);
|
||||
if (ret < 0)
|
||||
@@ -637,9 +644,6 @@ static int tc_get_display_props(struct tc_data *tc)
|
||||
err_dpcd_read:
|
||||
dev_err(tc->dev, "failed to read DPCD: %d\n", ret);
|
||||
return ret;
|
||||
err_dpcd_inval:
|
||||
dev_err(tc->dev, "invalid DPCD\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static int tc_set_video_mode(struct tc_data *tc, struct drm_display_mode *mode)
|
||||
@@ -655,6 +659,14 @@ static int tc_set_video_mode(struct tc_data *tc, struct drm_display_mode *mode)
|
||||
int lower_margin = mode->vsync_start - mode->vdisplay;
|
||||
int vsync_len = mode->vsync_end - mode->vsync_start;
|
||||
|
||||
/*
|
||||
* Recommended maximum number of symbols transferred in a transfer unit:
|
||||
* DIV_ROUND_UP((input active video bandwidth in bytes) * tu_size,
|
||||
* (output active video bandwidth in bytes))
|
||||
* Must be less than tu_size.
|
||||
*/
|
||||
max_tu_symbol = TU_SIZE_RECOMMENDED - 1;
|
||||
|
||||
dev_dbg(tc->dev, "set mode %dx%d\n",
|
||||
mode->hdisplay, mode->vdisplay);
|
||||
dev_dbg(tc->dev, "H margin %d,%d sync %d\n",
|
||||
@@ -664,13 +676,18 @@ static int tc_set_video_mode(struct tc_data *tc, struct drm_display_mode *mode)
|
||||
dev_dbg(tc->dev, "total: %dx%d\n", mode->htotal, mode->vtotal);
|
||||
|
||||
|
||||
/* LCD Ctl Frame Size */
|
||||
tc_write(VPCTRL0, (0x40 << 20) /* VSDELAY */ |
|
||||
/*
|
||||
* LCD Ctl Frame Size
|
||||
* datasheet is not clear of vsdelay in case of DPI
|
||||
* assume we do not need any delay when DPI is a source of
|
||||
* sync signals
|
||||
*/
|
||||
tc_write(VPCTRL0, (0 << 20) /* VSDELAY */ |
|
||||
OPXLFMT_RGB888 | FRMSYNC_DISABLED | MSF_DISABLED);
|
||||
tc_write(HTIM01, (left_margin << 16) | /* H back porch */
|
||||
(hsync_len << 0)); /* Hsync */
|
||||
tc_write(HTIM02, (right_margin << 16) | /* H front porch */
|
||||
(mode->hdisplay << 0)); /* width */
|
||||
tc_write(HTIM01, (ALIGN(left_margin, 2) << 16) | /* H back porch */
|
||||
(ALIGN(hsync_len, 2) << 0)); /* Hsync */
|
||||
tc_write(HTIM02, (ALIGN(right_margin, 2) << 16) | /* H front porch */
|
||||
(ALIGN(mode->hdisplay, 2) << 0)); /* width */
|
||||
tc_write(VTIM01, (upper_margin << 16) | /* V back porch */
|
||||
(vsync_len << 0)); /* Vsync */
|
||||
tc_write(VTIM02, (lower_margin << 16) | /* V front porch */
|
||||
@@ -689,7 +706,7 @@ static int tc_set_video_mode(struct tc_data *tc, struct drm_display_mode *mode)
|
||||
/* DP Main Stream Attributes */
|
||||
vid_sync_dly = hsync_len + left_margin + mode->hdisplay;
|
||||
tc_write(DP0_VIDSYNCDELAY,
|
||||
(0x003e << 16) | /* thresh_dly */
|
||||
(max_tu_symbol << 16) | /* thresh_dly */
|
||||
(vid_sync_dly << 0));
|
||||
|
||||
tc_write(DP0_TOTALVAL, (mode->vtotal << 16) | (mode->htotal));
|
||||
@@ -705,14 +722,8 @@ static int tc_set_video_mode(struct tc_data *tc, struct drm_display_mode *mode)
|
||||
tc_write(DPIPXLFMT, VS_POL_ACTIVE_LOW | HS_POL_ACTIVE_LOW |
|
||||
DE_POL_ACTIVE_HIGH | SUB_CFG_TYPE_CONFIG1 | DPI_BPP_RGB888);
|
||||
|
||||
/*
|
||||
* Recommended maximum number of symbols transferred in a transfer unit:
|
||||
* DIV_ROUND_UP((input active video bandwidth in bytes) * tu_size,
|
||||
* (output active video bandwidth in bytes))
|
||||
* Must be less than tu_size.
|
||||
*/
|
||||
max_tu_symbol = TU_SIZE_RECOMMENDED - 1;
|
||||
tc_write(DP0_MISC, (max_tu_symbol << 23) | TU_SIZE_RECOMMENDED | BPC_8);
|
||||
tc_write(DP0_MISC, (max_tu_symbol << 23) | (TU_SIZE_RECOMMENDED << 16) |
|
||||
BPC_8);
|
||||
|
||||
return 0;
|
||||
err:
|
||||
@@ -808,8 +819,6 @@ static int tc_main_link_setup(struct tc_data *tc)
|
||||
unsigned int rate;
|
||||
u32 dp_phy_ctrl;
|
||||
int timeout;
|
||||
bool aligned;
|
||||
bool ready;
|
||||
u32 value;
|
||||
int ret;
|
||||
u8 tmp[8];
|
||||
@@ -954,16 +963,15 @@ static int tc_main_link_setup(struct tc_data *tc)
|
||||
ret = drm_dp_dpcd_read_link_status(aux, tmp + 2);
|
||||
if (ret < 0)
|
||||
goto err_dpcd_read;
|
||||
ready = (tmp[2] == ((DP_CHANNEL_EQ_BITS << 4) | /* Lane1 */
|
||||
DP_CHANNEL_EQ_BITS)); /* Lane0 */
|
||||
aligned = tmp[4] & DP_INTERLANE_ALIGN_DONE;
|
||||
} while ((--timeout) && !(ready && aligned));
|
||||
} while ((--timeout) &&
|
||||
!(drm_dp_channel_eq_ok(tmp + 2, tc->link.base.num_lanes)));
|
||||
|
||||
if (timeout == 0) {
|
||||
/* Read DPCD 0x200-0x201 */
|
||||
ret = drm_dp_dpcd_read(aux, DP_SINK_COUNT, tmp, 2);
|
||||
if (ret < 0)
|
||||
goto err_dpcd_read;
|
||||
dev_err(dev, "channel(s) EQ not ok\n");
|
||||
dev_info(dev, "0x0200 SINK_COUNT: 0x%02x\n", tmp[0]);
|
||||
dev_info(dev, "0x0201 DEVICE_SERVICE_IRQ_VECTOR: 0x%02x\n",
|
||||
tmp[1]);
|
||||
@@ -974,10 +982,6 @@ static int tc_main_link_setup(struct tc_data *tc)
|
||||
dev_info(dev, "0x0206 ADJUST_REQUEST_LANE0_1: 0x%02x\n",
|
||||
tmp[6]);
|
||||
|
||||
if (!ready)
|
||||
dev_err(dev, "Lane0/1 not ready\n");
|
||||
if (!aligned)
|
||||
dev_err(dev, "Lane0/1 not aligned\n");
|
||||
return -EAGAIN;
|
||||
}
|
||||
|
||||
@@ -1105,7 +1109,10 @@ static bool tc_bridge_mode_fixup(struct drm_bridge *bridge,
|
||||
static int tc_connector_mode_valid(struct drm_connector *connector,
|
||||
struct drm_display_mode *mode)
|
||||
{
|
||||
/* Accept any mode */
|
||||
/* DPI interface clock limitation: upto 154 MHz */
|
||||
if (mode->clock > 154000)
|
||||
return MODE_CLOCK_HIGH;
|
||||
|
||||
return MODE_OK;
|
||||
}
|
||||
|
||||
|
||||
@@ -638,7 +638,8 @@ static int omap_dmm_probe(struct platform_device *dev)
|
||||
match = of_match_node(dmm_of_match, dev->dev.of_node);
|
||||
if (!match) {
|
||||
dev_err(&dev->dev, "failed to find matching device node\n");
|
||||
return -ENODEV;
|
||||
ret = -ENODEV;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
omap_dmm->plat_data = match->data;
|
||||
|
||||
@@ -225,6 +225,9 @@ vc4_irq_uninstall(struct drm_device *dev)
|
||||
/* Clear any pending interrupts we might have left. */
|
||||
V3D_WRITE(V3D_INTCTL, V3D_DRIVER_IRQS);
|
||||
|
||||
/* Finish any interrupt handler still in flight. */
|
||||
disable_irq(dev->irq);
|
||||
|
||||
cancel_work_sync(&vc4->overflow_mem_work);
|
||||
}
|
||||
|
||||
|
||||
@@ -173,6 +173,9 @@ static int vc4_v3d_runtime_resume(struct device *dev)
|
||||
struct vc4_dev *vc4 = v3d->vc4;
|
||||
|
||||
vc4_v3d_init_hw(vc4->dev);
|
||||
|
||||
/* We disabled the IRQ as part of vc4_irq_uninstall in suspend. */
|
||||
enable_irq(vc4->dev->irq);
|
||||
vc4_irq_postinstall(vc4->dev);
|
||||
|
||||
return 0;
|
||||
|
||||
@@ -2192,23 +2192,23 @@ static void wacom_remote_destroy_one(struct wacom *wacom, unsigned int index)
|
||||
int i;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&remote->remote_lock, flags);
|
||||
remote->remotes[index].registered = false;
|
||||
spin_unlock_irqrestore(&remote->remote_lock, flags);
|
||||
|
||||
if (remote->remotes[index].battery.battery)
|
||||
devres_release_group(&wacom->hdev->dev,
|
||||
&remote->remotes[index].battery.bat_desc);
|
||||
|
||||
if (remote->remotes[index].group.name)
|
||||
devres_release_group(&wacom->hdev->dev,
|
||||
&remote->remotes[index]);
|
||||
|
||||
for (i = 0; i < WACOM_MAX_REMOTES; i++) {
|
||||
if (remote->remotes[i].serial == serial) {
|
||||
|
||||
spin_lock_irqsave(&remote->remote_lock, flags);
|
||||
remote->remotes[i].registered = false;
|
||||
spin_unlock_irqrestore(&remote->remote_lock, flags);
|
||||
|
||||
if (remote->remotes[i].battery.battery)
|
||||
devres_release_group(&wacom->hdev->dev,
|
||||
&remote->remotes[i].battery.bat_desc);
|
||||
|
||||
if (remote->remotes[i].group.name)
|
||||
devres_release_group(&wacom->hdev->dev,
|
||||
&remote->remotes[i]);
|
||||
|
||||
remote->remotes[i].serial = 0;
|
||||
remote->remotes[i].group.name = NULL;
|
||||
remote->remotes[i].registered = false;
|
||||
remote->remotes[i].battery.battery = NULL;
|
||||
wacom->led.groups[i].select = WACOM_STATUS_UNKNOWN;
|
||||
}
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/math64.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/err.h>
|
||||
@@ -476,8 +477,8 @@ static long pmbus_reg2data_linear(struct pmbus_data *data,
|
||||
static long pmbus_reg2data_direct(struct pmbus_data *data,
|
||||
struct pmbus_sensor *sensor)
|
||||
{
|
||||
long val = (s16) sensor->data;
|
||||
long m, b, R;
|
||||
s64 b, val = (s16)sensor->data;
|
||||
s32 m, R;
|
||||
|
||||
m = data->info->m[sensor->class];
|
||||
b = data->info->b[sensor->class];
|
||||
@@ -505,11 +506,12 @@ static long pmbus_reg2data_direct(struct pmbus_data *data,
|
||||
R--;
|
||||
}
|
||||
while (R < 0) {
|
||||
val = DIV_ROUND_CLOSEST(val, 10);
|
||||
val = div_s64(val + 5LL, 10L); /* round closest */
|
||||
R++;
|
||||
}
|
||||
|
||||
return (val - b) / m;
|
||||
val = div_s64(val - b, m);
|
||||
return clamp_val(val, LONG_MIN, LONG_MAX);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -629,7 +631,8 @@ static u16 pmbus_data2reg_linear(struct pmbus_data *data,
|
||||
static u16 pmbus_data2reg_direct(struct pmbus_data *data,
|
||||
struct pmbus_sensor *sensor, long val)
|
||||
{
|
||||
long m, b, R;
|
||||
s64 b, val64 = val;
|
||||
s32 m, R;
|
||||
|
||||
m = data->info->m[sensor->class];
|
||||
b = data->info->b[sensor->class];
|
||||
@@ -646,18 +649,18 @@ static u16 pmbus_data2reg_direct(struct pmbus_data *data,
|
||||
R -= 3; /* Adjust R and b for data in milli-units */
|
||||
b *= 1000;
|
||||
}
|
||||
val = val * m + b;
|
||||
val64 = val64 * m + b;
|
||||
|
||||
while (R > 0) {
|
||||
val *= 10;
|
||||
val64 *= 10;
|
||||
R--;
|
||||
}
|
||||
while (R < 0) {
|
||||
val = DIV_ROUND_CLOSEST(val, 10);
|
||||
val64 = div_s64(val64 + 5LL, 10L); /* round closest */
|
||||
R++;
|
||||
}
|
||||
|
||||
return val;
|
||||
return (u16)clamp_val(val64, S16_MIN, S16_MAX);
|
||||
}
|
||||
|
||||
static u16 pmbus_data2reg_vid(struct pmbus_data *data,
|
||||
|
||||
@@ -2575,6 +2575,18 @@ error_0:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static u8 mlx5_get_umr_fence(u8 umr_fence_cap)
|
||||
{
|
||||
switch (umr_fence_cap) {
|
||||
case MLX5_CAP_UMR_FENCE_NONE:
|
||||
return MLX5_FENCE_MODE_NONE;
|
||||
case MLX5_CAP_UMR_FENCE_SMALL:
|
||||
return MLX5_FENCE_MODE_INITIATOR_SMALL;
|
||||
default:
|
||||
return MLX5_FENCE_MODE_STRONG_ORDERING;
|
||||
}
|
||||
}
|
||||
|
||||
static int create_dev_resources(struct mlx5_ib_resources *devr)
|
||||
{
|
||||
struct ib_srq_init_attr attr;
|
||||
@@ -3101,6 +3113,8 @@ static void *mlx5_ib_add(struct mlx5_core_dev *mdev)
|
||||
|
||||
mlx5_ib_internal_fill_odp_caps(dev);
|
||||
|
||||
dev->umr_fence = mlx5_get_umr_fence(MLX5_CAP_GEN(mdev, umr_fence));
|
||||
|
||||
if (MLX5_CAP_GEN(mdev, imaicl)) {
|
||||
dev->ib_dev.alloc_mw = mlx5_ib_alloc_mw;
|
||||
dev->ib_dev.dealloc_mw = mlx5_ib_dealloc_mw;
|
||||
|
||||
@@ -345,7 +345,7 @@ struct mlx5_ib_qp {
|
||||
struct mlx5_ib_wq rq;
|
||||
|
||||
u8 sq_signal_bits;
|
||||
u8 fm_cache;
|
||||
u8 next_fence;
|
||||
struct mlx5_ib_wq sq;
|
||||
|
||||
/* serialize qp state modifications
|
||||
@@ -643,6 +643,7 @@ struct mlx5_ib_dev {
|
||||
struct list_head qp_list;
|
||||
/* Array with num_ports elements */
|
||||
struct mlx5_ib_port *port;
|
||||
u8 umr_fence;
|
||||
};
|
||||
|
||||
static inline struct mlx5_ib_cq *to_mibcq(struct mlx5_core_cq *mcq)
|
||||
|
||||
@@ -3755,24 +3755,6 @@ static void mlx5_bf_copy(u64 __iomem *dst, u64 *src,
|
||||
}
|
||||
}
|
||||
|
||||
static u8 get_fence(u8 fence, struct ib_send_wr *wr)
|
||||
{
|
||||
if (unlikely(wr->opcode == IB_WR_LOCAL_INV &&
|
||||
wr->send_flags & IB_SEND_FENCE))
|
||||
return MLX5_FENCE_MODE_STRONG_ORDERING;
|
||||
|
||||
if (unlikely(fence)) {
|
||||
if (wr->send_flags & IB_SEND_FENCE)
|
||||
return MLX5_FENCE_MODE_SMALL_AND_FENCE;
|
||||
else
|
||||
return fence;
|
||||
} else if (unlikely(wr->send_flags & IB_SEND_FENCE)) {
|
||||
return MLX5_FENCE_MODE_FENCE;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int begin_wqe(struct mlx5_ib_qp *qp, void **seg,
|
||||
struct mlx5_wqe_ctrl_seg **ctrl,
|
||||
struct ib_send_wr *wr, unsigned *idx,
|
||||
@@ -3801,8 +3783,7 @@ static int begin_wqe(struct mlx5_ib_qp *qp, void **seg,
|
||||
static void finish_wqe(struct mlx5_ib_qp *qp,
|
||||
struct mlx5_wqe_ctrl_seg *ctrl,
|
||||
u8 size, unsigned idx, u64 wr_id,
|
||||
int nreq, u8 fence, u8 next_fence,
|
||||
u32 mlx5_opcode)
|
||||
int nreq, u8 fence, u32 mlx5_opcode)
|
||||
{
|
||||
u8 opmod = 0;
|
||||
|
||||
@@ -3810,7 +3791,6 @@ static void finish_wqe(struct mlx5_ib_qp *qp,
|
||||
mlx5_opcode | ((u32)opmod << 24));
|
||||
ctrl->qpn_ds = cpu_to_be32(size | (qp->trans_qp.base.mqp.qpn << 8));
|
||||
ctrl->fm_ce_se |= fence;
|
||||
qp->fm_cache = next_fence;
|
||||
if (unlikely(qp->wq_sig))
|
||||
ctrl->signature = wq_sig(ctrl);
|
||||
|
||||
@@ -3870,7 +3850,6 @@ int mlx5_ib_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr,
|
||||
goto out;
|
||||
}
|
||||
|
||||
fence = qp->fm_cache;
|
||||
num_sge = wr->num_sge;
|
||||
if (unlikely(num_sge > qp->sq.max_gs)) {
|
||||
mlx5_ib_warn(dev, "\n");
|
||||
@@ -3887,6 +3866,19 @@ int mlx5_ib_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr,
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (wr->opcode == IB_WR_LOCAL_INV ||
|
||||
wr->opcode == IB_WR_REG_MR) {
|
||||
fence = dev->umr_fence;
|
||||
next_fence = MLX5_FENCE_MODE_INITIATOR_SMALL;
|
||||
} else if (wr->send_flags & IB_SEND_FENCE) {
|
||||
if (qp->next_fence)
|
||||
fence = MLX5_FENCE_MODE_SMALL_AND_FENCE;
|
||||
else
|
||||
fence = MLX5_FENCE_MODE_FENCE;
|
||||
} else {
|
||||
fence = qp->next_fence;
|
||||
}
|
||||
|
||||
switch (ibqp->qp_type) {
|
||||
case IB_QPT_XRC_INI:
|
||||
xrc = seg;
|
||||
@@ -3913,7 +3905,6 @@ int mlx5_ib_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr,
|
||||
goto out;
|
||||
|
||||
case IB_WR_LOCAL_INV:
|
||||
next_fence = MLX5_FENCE_MODE_INITIATOR_SMALL;
|
||||
qp->sq.wr_data[idx] = IB_WR_LOCAL_INV;
|
||||
ctrl->imm = cpu_to_be32(wr->ex.invalidate_rkey);
|
||||
set_linv_wr(qp, &seg, &size);
|
||||
@@ -3921,7 +3912,6 @@ int mlx5_ib_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr,
|
||||
break;
|
||||
|
||||
case IB_WR_REG_MR:
|
||||
next_fence = MLX5_FENCE_MODE_INITIATOR_SMALL;
|
||||
qp->sq.wr_data[idx] = IB_WR_REG_MR;
|
||||
ctrl->imm = cpu_to_be32(reg_wr(wr)->key);
|
||||
err = set_reg_wr(qp, reg_wr(wr), &seg, &size);
|
||||
@@ -3944,9 +3934,8 @@ int mlx5_ib_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr,
|
||||
goto out;
|
||||
}
|
||||
|
||||
finish_wqe(qp, ctrl, size, idx, wr->wr_id,
|
||||
nreq, get_fence(fence, wr),
|
||||
next_fence, MLX5_OPCODE_UMR);
|
||||
finish_wqe(qp, ctrl, size, idx, wr->wr_id, nreq,
|
||||
fence, MLX5_OPCODE_UMR);
|
||||
/*
|
||||
* SET_PSV WQEs are not signaled and solicited
|
||||
* on error
|
||||
@@ -3971,9 +3960,8 @@ int mlx5_ib_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr,
|
||||
goto out;
|
||||
}
|
||||
|
||||
finish_wqe(qp, ctrl, size, idx, wr->wr_id,
|
||||
nreq, get_fence(fence, wr),
|
||||
next_fence, MLX5_OPCODE_SET_PSV);
|
||||
finish_wqe(qp, ctrl, size, idx, wr->wr_id, nreq,
|
||||
fence, MLX5_OPCODE_SET_PSV);
|
||||
err = begin_wqe(qp, &seg, &ctrl, wr,
|
||||
&idx, &size, nreq);
|
||||
if (err) {
|
||||
@@ -3983,7 +3971,6 @@ int mlx5_ib_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr,
|
||||
goto out;
|
||||
}
|
||||
|
||||
next_fence = MLX5_FENCE_MODE_INITIATOR_SMALL;
|
||||
err = set_psv_wr(&sig_handover_wr(wr)->sig_attrs->wire,
|
||||
mr->sig->psv_wire.psv_idx, &seg,
|
||||
&size);
|
||||
@@ -3993,9 +3980,9 @@ int mlx5_ib_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr,
|
||||
goto out;
|
||||
}
|
||||
|
||||
finish_wqe(qp, ctrl, size, idx, wr->wr_id,
|
||||
nreq, get_fence(fence, wr),
|
||||
next_fence, MLX5_OPCODE_SET_PSV);
|
||||
finish_wqe(qp, ctrl, size, idx, wr->wr_id, nreq,
|
||||
fence, MLX5_OPCODE_SET_PSV);
|
||||
qp->next_fence = MLX5_FENCE_MODE_INITIATOR_SMALL;
|
||||
num_sge = 0;
|
||||
goto skip_psv;
|
||||
|
||||
@@ -4100,8 +4087,8 @@ int mlx5_ib_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr,
|
||||
}
|
||||
}
|
||||
|
||||
finish_wqe(qp, ctrl, size, idx, wr->wr_id, nreq,
|
||||
get_fence(fence, wr), next_fence,
|
||||
qp->next_fence = next_fence;
|
||||
finish_wqe(qp, ctrl, size, idx, wr->wr_id, nreq, fence,
|
||||
mlx5_ib_opcode[wr->opcode]);
|
||||
skip_psv:
|
||||
if (0)
|
||||
|
||||
@@ -747,6 +747,7 @@ isert_connect_error(struct rdma_cm_id *cma_id)
|
||||
{
|
||||
struct isert_conn *isert_conn = cma_id->qp->qp_context;
|
||||
|
||||
ib_drain_qp(isert_conn->qp);
|
||||
list_del_init(&isert_conn->node);
|
||||
isert_conn->cm_id = NULL;
|
||||
isert_put_conn(isert_conn);
|
||||
|
||||
@@ -178,12 +178,14 @@ static SIMPLE_DEV_PM_OPS(twl4030_vibra_pm_ops,
|
||||
twl4030_vibra_suspend, twl4030_vibra_resume);
|
||||
|
||||
static bool twl4030_vibra_check_coexist(struct twl4030_vibra_data *pdata,
|
||||
struct device_node *node)
|
||||
struct device_node *parent)
|
||||
{
|
||||
struct device_node *node;
|
||||
|
||||
if (pdata && pdata->coexist)
|
||||
return true;
|
||||
|
||||
node = of_find_node_by_name(node, "codec");
|
||||
node = of_get_child_by_name(parent, "codec");
|
||||
if (node) {
|
||||
of_node_put(node);
|
||||
return true;
|
||||
|
||||
@@ -248,8 +248,7 @@ static int twl6040_vibra_probe(struct platform_device *pdev)
|
||||
int vddvibr_uV = 0;
|
||||
int error;
|
||||
|
||||
of_node_get(twl6040_core_dev->of_node);
|
||||
twl6040_core_node = of_find_node_by_name(twl6040_core_dev->of_node,
|
||||
twl6040_core_node = of_get_child_by_name(twl6040_core_dev->of_node,
|
||||
"vibra");
|
||||
if (!twl6040_core_node) {
|
||||
dev_err(&pdev->dev, "parent of node is missing?\n");
|
||||
|
||||
@@ -1247,29 +1247,32 @@ static int alps_decode_ss4_v2(struct alps_fields *f,
|
||||
case SS4_PACKET_ID_MULTI:
|
||||
if (priv->flags & ALPS_BUTTONPAD) {
|
||||
if (IS_SS4PLUS_DEV(priv->dev_id)) {
|
||||
f->mt[0].x = SS4_PLUS_BTL_MF_X_V2(p, 0);
|
||||
f->mt[1].x = SS4_PLUS_BTL_MF_X_V2(p, 1);
|
||||
f->mt[2].x = SS4_PLUS_BTL_MF_X_V2(p, 0);
|
||||
f->mt[3].x = SS4_PLUS_BTL_MF_X_V2(p, 1);
|
||||
no_data_x = SS4_PLUS_MFPACKET_NO_AX_BL;
|
||||
} else {
|
||||
f->mt[2].x = SS4_BTL_MF_X_V2(p, 0);
|
||||
f->mt[3].x = SS4_BTL_MF_X_V2(p, 1);
|
||||
no_data_x = SS4_MFPACKET_NO_AX_BL;
|
||||
}
|
||||
no_data_y = SS4_MFPACKET_NO_AY_BL;
|
||||
|
||||
f->mt[2].y = SS4_BTL_MF_Y_V2(p, 0);
|
||||
f->mt[3].y = SS4_BTL_MF_Y_V2(p, 1);
|
||||
no_data_x = SS4_MFPACKET_NO_AX_BL;
|
||||
no_data_y = SS4_MFPACKET_NO_AY_BL;
|
||||
} else {
|
||||
if (IS_SS4PLUS_DEV(priv->dev_id)) {
|
||||
f->mt[0].x = SS4_PLUS_STD_MF_X_V2(p, 0);
|
||||
f->mt[1].x = SS4_PLUS_STD_MF_X_V2(p, 1);
|
||||
f->mt[2].x = SS4_PLUS_STD_MF_X_V2(p, 0);
|
||||
f->mt[3].x = SS4_PLUS_STD_MF_X_V2(p, 1);
|
||||
no_data_x = SS4_PLUS_MFPACKET_NO_AX;
|
||||
} else {
|
||||
f->mt[0].x = SS4_STD_MF_X_V2(p, 0);
|
||||
f->mt[1].x = SS4_STD_MF_X_V2(p, 1);
|
||||
f->mt[2].x = SS4_STD_MF_X_V2(p, 0);
|
||||
f->mt[3].x = SS4_STD_MF_X_V2(p, 1);
|
||||
no_data_x = SS4_MFPACKET_NO_AX;
|
||||
}
|
||||
no_data_y = SS4_MFPACKET_NO_AY;
|
||||
|
||||
f->mt[2].y = SS4_STD_MF_Y_V2(p, 0);
|
||||
f->mt[3].y = SS4_STD_MF_Y_V2(p, 1);
|
||||
no_data_x = SS4_MFPACKET_NO_AX;
|
||||
no_data_y = SS4_MFPACKET_NO_AY;
|
||||
}
|
||||
|
||||
f->first_mp = 0;
|
||||
|
||||
@@ -120,10 +120,12 @@ enum SS4_PACKET_ID {
|
||||
#define SS4_IS_5F_DETECTED(_b) ((_b[2] & 0x10) == 0x10)
|
||||
|
||||
|
||||
#define SS4_MFPACKET_NO_AX 8160 /* X-Coordinate value */
|
||||
#define SS4_MFPACKET_NO_AY 4080 /* Y-Coordinate value */
|
||||
#define SS4_MFPACKET_NO_AX_BL 8176 /* Buttonless X-Coordinate value */
|
||||
#define SS4_MFPACKET_NO_AY_BL 4088 /* Buttonless Y-Coordinate value */
|
||||
#define SS4_MFPACKET_NO_AX 8160 /* X-Coordinate value */
|
||||
#define SS4_MFPACKET_NO_AY 4080 /* Y-Coordinate value */
|
||||
#define SS4_MFPACKET_NO_AX_BL 8176 /* Buttonless X-Coord value */
|
||||
#define SS4_MFPACKET_NO_AY_BL 4088 /* Buttonless Y-Coord value */
|
||||
#define SS4_PLUS_MFPACKET_NO_AX 4080 /* SS4 PLUS, X */
|
||||
#define SS4_PLUS_MFPACKET_NO_AX_BL 4088 /* Buttonless SS4 PLUS, X */
|
||||
|
||||
/*
|
||||
* enum V7_PACKET_ID - defines the packet type for V7
|
||||
|
||||
@@ -383,6 +383,9 @@ int trackpoint_detect(struct psmouse *psmouse, bool set_properties)
|
||||
if (trackpoint_read(&psmouse->ps2dev, TP_EXT_BTN, &button_info)) {
|
||||
psmouse_warn(psmouse, "failed to get extended button data, assuming 3 buttons\n");
|
||||
button_info = 0x33;
|
||||
} else if (!button_info) {
|
||||
psmouse_warn(psmouse, "got 0 in extended button data, assuming 3 buttons\n");
|
||||
button_info = 0x33;
|
||||
}
|
||||
|
||||
psmouse->private = kzalloc(sizeof(struct trackpoint_data), GFP_KERNEL);
|
||||
|
||||
@@ -126,7 +126,7 @@ static int pm860x_touch_dt_init(struct platform_device *pdev,
|
||||
int data, n, ret;
|
||||
if (!np)
|
||||
return -ENODEV;
|
||||
np = of_find_node_by_name(np, "touch");
|
||||
np = of_get_child_by_name(np, "touch");
|
||||
if (!np) {
|
||||
dev_err(&pdev->dev, "Can't find touch node\n");
|
||||
return -EINVAL;
|
||||
@@ -144,13 +144,13 @@ static int pm860x_touch_dt_init(struct platform_device *pdev,
|
||||
if (data) {
|
||||
ret = pm860x_reg_write(i2c, PM8607_GPADC_MISC1, data);
|
||||
if (ret < 0)
|
||||
return -EINVAL;
|
||||
goto err_put_node;
|
||||
}
|
||||
/* set tsi prebias time */
|
||||
if (!of_property_read_u32(np, "marvell,88pm860x-tsi-prebias", &data)) {
|
||||
ret = pm860x_reg_write(i2c, PM8607_TSI_PREBIAS, data);
|
||||
if (ret < 0)
|
||||
return -EINVAL;
|
||||
goto err_put_node;
|
||||
}
|
||||
/* set prebias & prechg time of pen detect */
|
||||
data = 0;
|
||||
@@ -161,10 +161,18 @@ static int pm860x_touch_dt_init(struct platform_device *pdev,
|
||||
if (data) {
|
||||
ret = pm860x_reg_write(i2c, PM8607_PD_PREBIAS, data);
|
||||
if (ret < 0)
|
||||
return -EINVAL;
|
||||
goto err_put_node;
|
||||
}
|
||||
of_property_read_u32(np, "marvell,88pm860x-resistor-X", res_x);
|
||||
|
||||
of_node_put(np);
|
||||
|
||||
return 0;
|
||||
|
||||
err_put_node:
|
||||
of_node_put(np);
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
#else
|
||||
#define pm860x_touch_dt_init(x, y, z) (-1)
|
||||
|
||||
@@ -803,7 +803,10 @@ int bch_btree_cache_alloc(struct cache_set *c)
|
||||
c->shrink.scan_objects = bch_mca_scan;
|
||||
c->shrink.seeks = 4;
|
||||
c->shrink.batch = c->btree_pages * 2;
|
||||
register_shrinker(&c->shrink);
|
||||
|
||||
if (register_shrinker(&c->shrink))
|
||||
pr_warn("bcache: %s: could not register shrinker",
|
||||
__func__);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -81,10 +81,14 @@
|
||||
#define SECTOR_TO_BLOCK_SHIFT 3
|
||||
|
||||
/*
|
||||
* For btree insert:
|
||||
* 3 for btree insert +
|
||||
* 2 for btree lookup used within space map
|
||||
* For btree remove:
|
||||
* 2 for shadow spine +
|
||||
* 4 for rebalance 3 child node
|
||||
*/
|
||||
#define THIN_MAX_CONCURRENT_LOCKS 5
|
||||
#define THIN_MAX_CONCURRENT_LOCKS 6
|
||||
|
||||
/* This should be plenty */
|
||||
#define SPACE_MAP_ROOT_SIZE 128
|
||||
|
||||
@@ -678,23 +678,8 @@ static int btree_split_beneath(struct shadow_spine *s, uint64_t key)
|
||||
pn->keys[1] = rn->keys[0];
|
||||
memcpy_disk(value_ptr(pn, 1), &val, sizeof(__le64));
|
||||
|
||||
/*
|
||||
* rejig the spine. This is ugly, since it knows too
|
||||
* much about the spine
|
||||
*/
|
||||
if (s->nodes[0] != new_parent) {
|
||||
unlock_block(s->info, s->nodes[0]);
|
||||
s->nodes[0] = new_parent;
|
||||
}
|
||||
if (key < le64_to_cpu(rn->keys[0])) {
|
||||
unlock_block(s->info, right);
|
||||
s->nodes[1] = left;
|
||||
} else {
|
||||
unlock_block(s->info, left);
|
||||
s->nodes[1] = right;
|
||||
}
|
||||
s->count = 2;
|
||||
|
||||
unlock_block(s->info, left);
|
||||
unlock_block(s->info, right);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -141,6 +141,7 @@ static void usbtv_disconnect(struct usb_interface *intf)
|
||||
|
||||
static struct usb_device_id usbtv_id_table[] = {
|
||||
{ USB_DEVICE(0x1b71, 0x3002) },
|
||||
{ USB_DEVICE(0x1f71, 0x3301) },
|
||||
{}
|
||||
};
|
||||
MODULE_DEVICE_TABLE(usb, usbtv_id_table);
|
||||
|
||||
@@ -119,3 +119,7 @@ static struct pci_driver denali_pci_driver = {
|
||||
};
|
||||
|
||||
module_pci_driver(denali_pci_driver);
|
||||
|
||||
MODULE_DESCRIPTION("PCI driver for Denali NAND controller");
|
||||
MODULE_AUTHOR("Intel Corporation and its suppliers");
|
||||
MODULE_LICENSE("GPL v2");
|
||||
|
||||
@@ -184,7 +184,7 @@ static int pcan_usb_fd_send_cmd(struct peak_usb_device *dev, void *cmd_tail)
|
||||
void *cmd_head = pcan_usb_fd_cmd_buffer(dev);
|
||||
int err = 0;
|
||||
u8 *packet_ptr;
|
||||
int i, n = 1, packet_len;
|
||||
int packet_len;
|
||||
ptrdiff_t cmd_len;
|
||||
|
||||
/* usb device unregistered? */
|
||||
@@ -201,17 +201,13 @@ static int pcan_usb_fd_send_cmd(struct peak_usb_device *dev, void *cmd_tail)
|
||||
}
|
||||
|
||||
packet_ptr = cmd_head;
|
||||
packet_len = cmd_len;
|
||||
|
||||
/* firmware is not able to re-assemble 512 bytes buffer in full-speed */
|
||||
if ((dev->udev->speed != USB_SPEED_HIGH) &&
|
||||
(cmd_len > PCAN_UFD_LOSPD_PKT_SIZE)) {
|
||||
packet_len = PCAN_UFD_LOSPD_PKT_SIZE;
|
||||
n += cmd_len / packet_len;
|
||||
} else {
|
||||
packet_len = cmd_len;
|
||||
}
|
||||
if (unlikely(dev->udev->speed != USB_SPEED_HIGH))
|
||||
packet_len = min(packet_len, PCAN_UFD_LOSPD_PKT_SIZE);
|
||||
|
||||
for (i = 0; i < n; i++) {
|
||||
do {
|
||||
err = usb_bulk_msg(dev->udev,
|
||||
usb_sndbulkpipe(dev->udev,
|
||||
PCAN_USBPRO_EP_CMDOUT),
|
||||
@@ -224,7 +220,12 @@ static int pcan_usb_fd_send_cmd(struct peak_usb_device *dev, void *cmd_tail)
|
||||
}
|
||||
|
||||
packet_ptr += packet_len;
|
||||
}
|
||||
cmd_len -= packet_len;
|
||||
|
||||
if (cmd_len < PCAN_UFD_LOSPD_PKT_SIZE)
|
||||
packet_len = cmd_len;
|
||||
|
||||
} while (packet_len > 0);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
@@ -1843,8 +1843,8 @@ static int bnxt_get_module_eeprom(struct net_device *dev,
|
||||
/* Read A2 portion of the EEPROM */
|
||||
if (length) {
|
||||
start -= ETH_MODULE_SFF_8436_LEN;
|
||||
bnxt_read_sfp_module_eeprom_info(bp, I2C_DEV_ADDR_A2, 1, start,
|
||||
length, data);
|
||||
rc = bnxt_read_sfp_module_eeprom_info(bp, I2C_DEV_ADDR_A2, 1,
|
||||
start, length, data);
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
@@ -4733,6 +4733,15 @@ int be_update_queues(struct be_adapter *adapter)
|
||||
|
||||
be_schedule_worker(adapter);
|
||||
|
||||
/*
|
||||
* The IF was destroyed and re-created. We need to clear
|
||||
* all promiscuous flags valid for the destroyed IF.
|
||||
* Without this promisc mode is not restored during
|
||||
* be_open() because the driver thinks that it is
|
||||
* already enabled in HW.
|
||||
*/
|
||||
adapter->if_flags &= ~BE_IF_FLAGS_ALL_PROMISCUOUS;
|
||||
|
||||
if (netif_running(netdev))
|
||||
status = be_open(netdev);
|
||||
|
||||
|
||||
@@ -3273,7 +3273,7 @@ static int __igb_close(struct net_device *netdev, bool suspending)
|
||||
|
||||
int igb_close(struct net_device *netdev)
|
||||
{
|
||||
if (netif_device_present(netdev))
|
||||
if (netif_device_present(netdev) || netdev->dismantle)
|
||||
return __igb_close(netdev, false);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -765,11 +765,8 @@ static void mlxsw_sp_router_neigh_ent_ipv4_process(struct mlxsw_sp *mlxsw_sp,
|
||||
dipn = htonl(dip);
|
||||
dev = mlxsw_sp->rifs[rif]->dev;
|
||||
n = neigh_lookup(&arp_tbl, &dipn, dev);
|
||||
if (!n) {
|
||||
netdev_err(dev, "Failed to find matching neighbour for IP=%pI4h\n",
|
||||
&dip);
|
||||
if (!n)
|
||||
return;
|
||||
}
|
||||
|
||||
netdev_dbg(dev, "Updating neighbour with IP=%pI4h\n", &dip);
|
||||
neigh_event_send(n, NULL);
|
||||
|
||||
@@ -2222,19 +2222,14 @@ static bool rtl8169_do_counters(struct net_device *dev, u32 counter_cmd)
|
||||
void __iomem *ioaddr = tp->mmio_addr;
|
||||
dma_addr_t paddr = tp->counters_phys_addr;
|
||||
u32 cmd;
|
||||
bool ret;
|
||||
|
||||
RTL_W32(CounterAddrHigh, (u64)paddr >> 32);
|
||||
RTL_R32(CounterAddrHigh);
|
||||
cmd = (u64)paddr & DMA_BIT_MASK(32);
|
||||
RTL_W32(CounterAddrLow, cmd);
|
||||
RTL_W32(CounterAddrLow, cmd | counter_cmd);
|
||||
|
||||
ret = rtl_udelay_loop_wait_low(tp, &rtl_counters_cond, 10, 1000);
|
||||
|
||||
RTL_W32(CounterAddrLow, 0);
|
||||
RTL_W32(CounterAddrHigh, 0);
|
||||
|
||||
return ret;
|
||||
return rtl_udelay_loop_wait_low(tp, &rtl_counters_cond, 10, 1000);
|
||||
}
|
||||
|
||||
static bool rtl8169_reset_counters(struct net_device *dev)
|
||||
|
||||
@@ -34,6 +34,7 @@ config XILINX_AXI_EMAC
|
||||
config XILINX_LL_TEMAC
|
||||
tristate "Xilinx LL TEMAC (LocalLink Tri-mode Ethernet MAC) driver"
|
||||
depends on (PPC || MICROBLAZE)
|
||||
depends on !64BIT || BROKEN
|
||||
select PHYLIB
|
||||
---help---
|
||||
This driver supports the Xilinx 10/100/1000 LocalLink TEMAC
|
||||
|
||||
@@ -1002,17 +1002,18 @@ static int ppp_unit_register(struct ppp *ppp, int unit, bool ifname_is_set)
|
||||
if (!ifname_is_set)
|
||||
snprintf(ppp->dev->name, IFNAMSIZ, "ppp%i", ppp->file.index);
|
||||
|
||||
mutex_unlock(&pn->all_ppp_mutex);
|
||||
|
||||
ret = register_netdevice(ppp->dev);
|
||||
if (ret < 0)
|
||||
goto err_unit;
|
||||
|
||||
atomic_inc(&ppp_unit_count);
|
||||
|
||||
mutex_unlock(&pn->all_ppp_mutex);
|
||||
|
||||
return 0;
|
||||
|
||||
err_unit:
|
||||
mutex_lock(&pn->all_ppp_mutex);
|
||||
unit_put(&pn->units_idr, ppp->file.index);
|
||||
err:
|
||||
mutex_unlock(&pn->all_ppp_mutex);
|
||||
|
||||
@@ -842,6 +842,7 @@ static int pppoe_sendmsg(struct socket *sock, struct msghdr *m,
|
||||
struct pppoe_hdr *ph;
|
||||
struct net_device *dev;
|
||||
char *start;
|
||||
int hlen;
|
||||
|
||||
lock_sock(sk);
|
||||
if (sock_flag(sk, SOCK_DEAD) || !(sk->sk_state & PPPOX_CONNECTED)) {
|
||||
@@ -860,16 +861,16 @@ static int pppoe_sendmsg(struct socket *sock, struct msghdr *m,
|
||||
if (total_len > (dev->mtu + dev->hard_header_len))
|
||||
goto end;
|
||||
|
||||
|
||||
skb = sock_wmalloc(sk, total_len + dev->hard_header_len + 32,
|
||||
0, GFP_KERNEL);
|
||||
hlen = LL_RESERVED_SPACE(dev);
|
||||
skb = sock_wmalloc(sk, hlen + sizeof(*ph) + total_len +
|
||||
dev->needed_tailroom, 0, GFP_KERNEL);
|
||||
if (!skb) {
|
||||
error = -ENOMEM;
|
||||
goto end;
|
||||
}
|
||||
|
||||
/* Reserve space for headers. */
|
||||
skb_reserve(skb, dev->hard_header_len);
|
||||
skb_reserve(skb, hlen);
|
||||
skb_reset_network_header(skb);
|
||||
|
||||
skb->dev = dev;
|
||||
@@ -930,7 +931,7 @@ static int __pppoe_xmit(struct sock *sk, struct sk_buff *skb)
|
||||
/* Copy the data if there is no space for the header or if it's
|
||||
* read-only.
|
||||
*/
|
||||
if (skb_cow_head(skb, sizeof(*ph) + dev->hard_header_len))
|
||||
if (skb_cow_head(skb, LL_RESERVED_SPACE(dev) + sizeof(*ph)))
|
||||
goto abort;
|
||||
|
||||
__skb_push(skb, sizeof(*ph));
|
||||
|
||||
@@ -525,6 +525,14 @@ static void tun_queue_purge(struct tun_file *tfile)
|
||||
skb_queue_purge(&tfile->sk.sk_error_queue);
|
||||
}
|
||||
|
||||
static void tun_cleanup_tx_array(struct tun_file *tfile)
|
||||
{
|
||||
if (tfile->tx_array.ring.queue) {
|
||||
skb_array_cleanup(&tfile->tx_array);
|
||||
memset(&tfile->tx_array, 0, sizeof(tfile->tx_array));
|
||||
}
|
||||
}
|
||||
|
||||
static void __tun_detach(struct tun_file *tfile, bool clean)
|
||||
{
|
||||
struct tun_file *ntfile;
|
||||
@@ -566,8 +574,7 @@ static void __tun_detach(struct tun_file *tfile, bool clean)
|
||||
tun->dev->reg_state == NETREG_REGISTERED)
|
||||
unregister_netdevice(tun->dev);
|
||||
}
|
||||
if (tun)
|
||||
skb_array_cleanup(&tfile->tx_array);
|
||||
tun_cleanup_tx_array(tfile);
|
||||
sock_put(&tfile->sk);
|
||||
}
|
||||
}
|
||||
@@ -606,11 +613,13 @@ static void tun_detach_all(struct net_device *dev)
|
||||
/* Drop read queue */
|
||||
tun_queue_purge(tfile);
|
||||
sock_put(&tfile->sk);
|
||||
tun_cleanup_tx_array(tfile);
|
||||
}
|
||||
list_for_each_entry_safe(tfile, tmp, &tun->disabled, next) {
|
||||
tun_enable_queue(tfile);
|
||||
tun_queue_purge(tfile);
|
||||
sock_put(&tfile->sk);
|
||||
tun_cleanup_tx_array(tfile);
|
||||
}
|
||||
BUG_ON(tun->numdisabled != 0);
|
||||
|
||||
@@ -2373,6 +2382,8 @@ static int tun_chr_open(struct inode *inode, struct file * file)
|
||||
|
||||
sock_set_flag(&tfile->sk, SOCK_ZEROCOPY);
|
||||
|
||||
memset(&tfile->tx_array, 0, sizeof(tfile->tx_array));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user