mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-07 03:15:31 +09:00
Merge branch 'android-4.9' into amlogic-4.9-dev
This commit is contained in:
2
Makefile
2
Makefile
@@ -1,6 +1,6 @@
|
||||
VERSION = 4
|
||||
PATCHLEVEL = 9
|
||||
SUBLEVEL = 30
|
||||
SUBLEVEL = 32
|
||||
EXTRAVERSION =
|
||||
NAME = Roaring Lionus
|
||||
|
||||
|
||||
@@ -81,7 +81,7 @@ __setup("fpe=", fpe_setup);
|
||||
extern void init_default_cache_policy(unsigned long);
|
||||
extern void paging_init(const struct machine_desc *desc);
|
||||
extern void early_paging_init(const struct machine_desc *);
|
||||
extern void sanity_check_meminfo(void);
|
||||
extern void adjust_lowmem_bounds(void);
|
||||
extern enum reboot_mode reboot_mode;
|
||||
extern void setup_dma_zone(const struct machine_desc *desc);
|
||||
|
||||
@@ -1093,8 +1093,14 @@ void __init setup_arch(char **cmdline_p)
|
||||
setup_dma_zone(mdesc);
|
||||
xen_early_init();
|
||||
efi_init();
|
||||
sanity_check_meminfo();
|
||||
/*
|
||||
* Make sure the calculation for lowmem/highmem is set appropriately
|
||||
* before reserving/allocating any mmeory
|
||||
*/
|
||||
adjust_lowmem_bounds();
|
||||
arm_memblock_init(mdesc);
|
||||
/* Memory may have been removed so recalculate the bounds. */
|
||||
adjust_lowmem_bounds();
|
||||
|
||||
early_ioremap_reset();
|
||||
|
||||
|
||||
@@ -95,7 +95,6 @@ __do_hyp_init:
|
||||
@ - Write permission implies XN: disabled
|
||||
@ - Instruction cache: enabled
|
||||
@ - Data/Unified cache: enabled
|
||||
@ - Memory alignment checks: enabled
|
||||
@ - MMU: enabled (this code must be run from an identity mapping)
|
||||
mrc p15, 4, r0, c1, c0, 0 @ HSCR
|
||||
ldr r2, =HSCTLR_MASK
|
||||
@@ -103,8 +102,8 @@ __do_hyp_init:
|
||||
mrc p15, 0, r1, c1, c0, 0 @ SCTLR
|
||||
ldr r2, =(HSCTLR_EE | HSCTLR_FI | HSCTLR_I | HSCTLR_C)
|
||||
and r1, r1, r2
|
||||
ARM( ldr r2, =(HSCTLR_M | HSCTLR_A) )
|
||||
THUMB( ldr r2, =(HSCTLR_M | HSCTLR_A | HSCTLR_TE) )
|
||||
ARM( ldr r2, =(HSCTLR_M) )
|
||||
THUMB( ldr r2, =(HSCTLR_M | HSCTLR_TE) )
|
||||
orr r1, r1, r2
|
||||
orr r0, r0, r1
|
||||
mcr p15, 4, r0, c1, c0, 0 @ HSCR
|
||||
|
||||
@@ -872,6 +872,9 @@ static pmd_t *stage2_get_pmd(struct kvm *kvm, struct kvm_mmu_memory_cache *cache
|
||||
pmd_t *pmd;
|
||||
|
||||
pud = stage2_get_pud(kvm, cache, addr);
|
||||
if (!pud)
|
||||
return NULL;
|
||||
|
||||
if (stage2_pud_none(*pud)) {
|
||||
if (!cache)
|
||||
return NULL;
|
||||
|
||||
@@ -1152,13 +1152,12 @@ early_param("vmalloc", early_vmalloc);
|
||||
|
||||
phys_addr_t arm_lowmem_limit __initdata = 0;
|
||||
|
||||
void __init sanity_check_meminfo(void)
|
||||
void __init adjust_lowmem_bounds(void)
|
||||
{
|
||||
phys_addr_t memblock_limit = 0;
|
||||
int highmem = 0;
|
||||
u64 vmalloc_limit;
|
||||
struct memblock_region *reg;
|
||||
bool should_use_highmem = false;
|
||||
phys_addr_t lowmem_limit = 0;
|
||||
|
||||
/*
|
||||
* Let's use our own (unoptimized) equivalent of __pa() that is
|
||||
@@ -1172,43 +1171,18 @@ void __init sanity_check_meminfo(void)
|
||||
for_each_memblock(memory, reg) {
|
||||
phys_addr_t block_start = reg->base;
|
||||
phys_addr_t block_end = reg->base + reg->size;
|
||||
phys_addr_t size_limit = reg->size;
|
||||
|
||||
if (reg->base >= vmalloc_limit)
|
||||
highmem = 1;
|
||||
else
|
||||
size_limit = vmalloc_limit - reg->base;
|
||||
|
||||
|
||||
if (!IS_ENABLED(CONFIG_HIGHMEM) || cache_is_vipt_aliasing()) {
|
||||
|
||||
if (highmem) {
|
||||
pr_notice("Ignoring RAM at %pa-%pa (!CONFIG_HIGHMEM)\n",
|
||||
&block_start, &block_end);
|
||||
memblock_remove(reg->base, reg->size);
|
||||
should_use_highmem = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (reg->size > size_limit) {
|
||||
phys_addr_t overlap_size = reg->size - size_limit;
|
||||
|
||||
pr_notice("Truncating RAM at %pa-%pa",
|
||||
&block_start, &block_end);
|
||||
block_end = vmalloc_limit;
|
||||
pr_cont(" to -%pa", &block_end);
|
||||
memblock_remove(vmalloc_limit, overlap_size);
|
||||
should_use_highmem = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!highmem) {
|
||||
if (block_end > arm_lowmem_limit) {
|
||||
if (reg->size > size_limit)
|
||||
arm_lowmem_limit = vmalloc_limit;
|
||||
else
|
||||
arm_lowmem_limit = block_end;
|
||||
}
|
||||
if (reg->base < vmalloc_limit) {
|
||||
if (block_end > lowmem_limit)
|
||||
/*
|
||||
* Compare as u64 to ensure vmalloc_limit does
|
||||
* not get truncated. block_end should always
|
||||
* fit in phys_addr_t so there should be no
|
||||
* issue with assignment.
|
||||
*/
|
||||
lowmem_limit = min_t(u64,
|
||||
vmalloc_limit,
|
||||
block_end);
|
||||
|
||||
/*
|
||||
* Find the first non-pmd-aligned page, and point
|
||||
@@ -1227,14 +1201,13 @@ void __init sanity_check_meminfo(void)
|
||||
if (!IS_ALIGNED(block_start, PMD_SIZE))
|
||||
memblock_limit = block_start;
|
||||
else if (!IS_ALIGNED(block_end, PMD_SIZE))
|
||||
memblock_limit = arm_lowmem_limit;
|
||||
memblock_limit = lowmem_limit;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
if (should_use_highmem)
|
||||
pr_notice("Consider using a HIGHMEM enabled kernel.\n");
|
||||
arm_lowmem_limit = lowmem_limit;
|
||||
|
||||
high_memory = __va(arm_lowmem_limit - 1) + 1;
|
||||
|
||||
@@ -1248,6 +1221,18 @@ void __init sanity_check_meminfo(void)
|
||||
if (!memblock_limit)
|
||||
memblock_limit = arm_lowmem_limit;
|
||||
|
||||
if (!IS_ENABLED(CONFIG_HIGHMEM) || cache_is_vipt_aliasing()) {
|
||||
if (memblock_end_of_DRAM() > arm_lowmem_limit) {
|
||||
phys_addr_t end = memblock_end_of_DRAM();
|
||||
|
||||
pr_notice("Ignoring RAM at %pa-%pa\n",
|
||||
&memblock_limit, &end);
|
||||
pr_notice("Consider using a HIGHMEM enabled kernel.\n");
|
||||
|
||||
memblock_remove(memblock_limit, end - memblock_limit);
|
||||
}
|
||||
}
|
||||
|
||||
memblock_set_current_limit(memblock_limit);
|
||||
}
|
||||
|
||||
|
||||
@@ -85,7 +85,7 @@ static unsigned long irbar_read(void)
|
||||
}
|
||||
|
||||
/* MPU initialisation functions */
|
||||
void __init sanity_check_meminfo_mpu(void)
|
||||
void __init adjust_lowmem_bounds_mpu(void)
|
||||
{
|
||||
phys_addr_t phys_offset = PHYS_OFFSET;
|
||||
phys_addr_t aligned_region_size, specified_mem_size, rounded_mem_size;
|
||||
@@ -274,7 +274,7 @@ void __init mpu_setup(void)
|
||||
}
|
||||
}
|
||||
#else
|
||||
static void sanity_check_meminfo_mpu(void) {}
|
||||
static void adjust_lowmem_bounds_mpu(void) {}
|
||||
static void __init mpu_setup(void) {}
|
||||
#endif /* CONFIG_ARM_MPU */
|
||||
|
||||
@@ -295,10 +295,10 @@ void __init arm_mm_memblock_reserve(void)
|
||||
#endif
|
||||
}
|
||||
|
||||
void __init sanity_check_meminfo(void)
|
||||
void __init adjust_lowmem_bounds(void)
|
||||
{
|
||||
phys_addr_t end;
|
||||
sanity_check_meminfo_mpu();
|
||||
adjust_lowmem_bounds_mpu();
|
||||
end = memblock_end_of_DRAM();
|
||||
high_memory = __va(end - 1) + 1;
|
||||
memblock_set_current_limit(end);
|
||||
|
||||
13
arch/arm64/include/asm/asm-uaccess.h
Normal file
13
arch/arm64/include/asm/asm-uaccess.h
Normal file
@@ -0,0 +1,13 @@
|
||||
#ifndef __ASM_ASM_UACCESS_H
|
||||
#define __ASM_ASM_UACCESS_H
|
||||
|
||||
/*
|
||||
* Remove the address tag from a virtual address, if present.
|
||||
*/
|
||||
.macro clear_address_tag, dst, addr
|
||||
tst \addr, #(1 << 55)
|
||||
bic \dst, \addr, #(0xff << 56)
|
||||
csel \dst, \dst, \addr, eq
|
||||
.endm
|
||||
|
||||
#endif
|
||||
@@ -94,6 +94,10 @@
|
||||
#define SCTLR_ELx_A (1 << 1)
|
||||
#define SCTLR_ELx_M 1
|
||||
|
||||
#define SCTLR_EL2_RES1 ((1 << 4) | (1 << 5) | (1 << 11) | (1 << 16) | \
|
||||
(1 << 16) | (1 << 18) | (1 << 22) | (1 << 23) | \
|
||||
(1 << 28) | (1 << 29))
|
||||
|
||||
#define SCTLR_ELx_FLAGS (SCTLR_ELx_M | SCTLR_ELx_A | SCTLR_ELx_C | \
|
||||
SCTLR_ELx_SA | SCTLR_ELx_I)
|
||||
|
||||
|
||||
@@ -109,9 +109,9 @@ static inline void set_fs(mm_segment_t fs)
|
||||
})
|
||||
|
||||
/*
|
||||
* When dealing with data aborts or instruction traps we may end up with
|
||||
* a tagged userland pointer. Clear the tag to get a sane pointer to pass
|
||||
* on to access_ok(), for instance.
|
||||
* When dealing with data aborts, watchpoints, or instruction traps we may end
|
||||
* up with a tagged userland pointer. Clear the tag to get a sane pointer to
|
||||
* pass on to access_ok(), for instance.
|
||||
*/
|
||||
#define untagged_addr(addr) sign_extend64(addr, 55)
|
||||
|
||||
|
||||
@@ -32,6 +32,7 @@
|
||||
#include <asm/ptrace.h>
|
||||
#include <asm/thread_info.h>
|
||||
#include <asm/uaccess.h>
|
||||
#include <asm/asm-uaccess.h>
|
||||
#include <asm/unistd.h>
|
||||
|
||||
/*
|
||||
@@ -428,12 +429,13 @@ el1_da:
|
||||
/*
|
||||
* Data abort handling
|
||||
*/
|
||||
mrs x0, far_el1
|
||||
mrs x3, far_el1
|
||||
enable_dbg
|
||||
// re-enable interrupts if they were enabled in the aborted context
|
||||
tbnz x23, #7, 1f // PSR_I_BIT
|
||||
enable_irq
|
||||
1:
|
||||
clear_address_tag x0, x3
|
||||
mov x2, sp // struct pt_regs
|
||||
bl do_mem_abort
|
||||
|
||||
@@ -594,7 +596,7 @@ el0_da:
|
||||
// enable interrupts before calling the main handler
|
||||
enable_dbg_and_irq
|
||||
ct_user_exit
|
||||
bic x0, x26, #(0xff << 56)
|
||||
clear_address_tag x0, x26
|
||||
mov x1, x25
|
||||
mov x2, sp
|
||||
bl do_mem_abort
|
||||
|
||||
@@ -36,6 +36,7 @@
|
||||
#include <asm/traps.h>
|
||||
#include <asm/cputype.h>
|
||||
#include <asm/system_misc.h>
|
||||
#include <asm/uaccess.h>
|
||||
|
||||
/* Breakpoint currently in use for each BRP. */
|
||||
static DEFINE_PER_CPU(struct perf_event *, bp_on_reg[ARM_MAX_BRP]);
|
||||
|
||||
@@ -435,7 +435,7 @@ int cpu_enable_cache_maint_trap(void *__unused)
|
||||
}
|
||||
|
||||
#define __user_cache_maint(insn, address, res) \
|
||||
if (untagged_addr(address) >= user_addr_max()) { \
|
||||
if (address >= user_addr_max()) { \
|
||||
res = -EFAULT; \
|
||||
} else { \
|
||||
uaccess_ttbr0_enable(); \
|
||||
@@ -461,7 +461,7 @@ static void user_cache_maint_handler(unsigned int esr, struct pt_regs *regs)
|
||||
int crm = (esr & ESR_ELx_SYS64_ISS_CRM_MASK) >> ESR_ELx_SYS64_ISS_CRM_SHIFT;
|
||||
int ret = 0;
|
||||
|
||||
address = (rt == 31) ? 0 : regs->regs[rt];
|
||||
address = (rt == 31) ? 0 : untagged_addr(regs->regs[rt]);
|
||||
|
||||
switch (crm) {
|
||||
case ESR_ELx_SYS64_ISS_CRM_DC_CVAU: /* DC CVAU, gets promoted */
|
||||
|
||||
@@ -102,10 +102,13 @@ __do_hyp_init:
|
||||
tlbi alle2
|
||||
dsb sy
|
||||
|
||||
mrs x4, sctlr_el2
|
||||
and x4, x4, #SCTLR_ELx_EE // preserve endianness of EL2
|
||||
ldr x5, =SCTLR_ELx_FLAGS
|
||||
orr x4, x4, x5
|
||||
/*
|
||||
* Preserve all the RES1 bits while setting the default flags,
|
||||
* as well as the EE bit on BE. Drop the A flag since the compiler
|
||||
* is allowed to generate unaligned accesses.
|
||||
*/
|
||||
ldr x4, =(SCTLR_EL2_RES1 | (SCTLR_ELx_FLAGS & ~SCTLR_ELx_A))
|
||||
CPU_BE( orr x4, x4, #SCTLR_ELx_EE)
|
||||
msr sctlr_el2, x4
|
||||
isb
|
||||
|
||||
|
||||
@@ -252,8 +252,9 @@ static int emit_bpf_tail_call(struct jit_ctx *ctx)
|
||||
*/
|
||||
off = offsetof(struct bpf_array, ptrs);
|
||||
emit_a64_mov_i64(tmp, off, ctx);
|
||||
emit(A64_LDR64(tmp, r2, tmp), ctx);
|
||||
emit(A64_LDR64(prg, tmp, r3), ctx);
|
||||
emit(A64_ADD(1, tmp, r2, tmp), ctx);
|
||||
emit(A64_LSL(1, prg, r3, 3), ctx);
|
||||
emit(A64_LDR64(prg, tmp, prg), ctx);
|
||||
emit(A64_CBZ(1, prg, jmp_offset), ctx);
|
||||
|
||||
/* goto *(prog->bpf_func + prologue_size); */
|
||||
|
||||
@@ -44,8 +44,22 @@ extern void __init dump_numa_cpu_topology(void);
|
||||
extern int sysfs_add_device_to_node(struct device *dev, int nid);
|
||||
extern void sysfs_remove_device_from_node(struct device *dev, int nid);
|
||||
|
||||
static inline int early_cpu_to_node(int cpu)
|
||||
{
|
||||
int nid;
|
||||
|
||||
nid = numa_cpu_lookup_table[cpu];
|
||||
|
||||
/*
|
||||
* Fall back to node 0 if nid is unset (it should be, except bugs).
|
||||
* This allows callers to safely do NODE_DATA(early_cpu_to_node(cpu)).
|
||||
*/
|
||||
return (nid < 0) ? 0 : nid;
|
||||
}
|
||||
#else
|
||||
|
||||
static inline int early_cpu_to_node(int cpu) { return 0; }
|
||||
|
||||
static inline void dump_numa_cpu_topology(void) {}
|
||||
|
||||
static inline int sysfs_add_device_to_node(struct device *dev, int nid)
|
||||
|
||||
@@ -1659,6 +1659,7 @@ void start_thread(struct pt_regs *regs, unsigned long start, unsigned long sp)
|
||||
#ifdef CONFIG_VSX
|
||||
current->thread.used_vsr = 0;
|
||||
#endif
|
||||
current->thread.load_fp = 0;
|
||||
memset(¤t->thread.fp_state, 0, sizeof(current->thread.fp_state));
|
||||
current->thread.fp_save_area = NULL;
|
||||
#ifdef CONFIG_ALTIVEC
|
||||
@@ -1667,6 +1668,7 @@ void start_thread(struct pt_regs *regs, unsigned long start, unsigned long sp)
|
||||
current->thread.vr_save_area = NULL;
|
||||
current->thread.vrsave = 0;
|
||||
current->thread.used_vr = 0;
|
||||
current->thread.load_vec = 0;
|
||||
#endif /* CONFIG_ALTIVEC */
|
||||
#ifdef CONFIG_SPE
|
||||
memset(current->thread.evr, 0, sizeof(current->thread.evr));
|
||||
@@ -1678,6 +1680,7 @@ void start_thread(struct pt_regs *regs, unsigned long start, unsigned long sp)
|
||||
current->thread.tm_tfhar = 0;
|
||||
current->thread.tm_texasr = 0;
|
||||
current->thread.tm_tfiar = 0;
|
||||
current->thread.load_tm = 0;
|
||||
#endif /* CONFIG_PPC_TRANSACTIONAL_MEM */
|
||||
}
|
||||
EXPORT_SYMBOL(start_thread);
|
||||
|
||||
@@ -595,7 +595,7 @@ void __init emergency_stack_init(void)
|
||||
|
||||
static void * __init pcpu_fc_alloc(unsigned int cpu, size_t size, size_t align)
|
||||
{
|
||||
return __alloc_bootmem_node(NODE_DATA(cpu_to_node(cpu)), size, align,
|
||||
return __alloc_bootmem_node(NODE_DATA(early_cpu_to_node(cpu)), size, align,
|
||||
__pa(MAX_DMA_ADDRESS));
|
||||
}
|
||||
|
||||
@@ -606,7 +606,7 @@ static void __init pcpu_fc_free(void *ptr, size_t size)
|
||||
|
||||
static int pcpu_cpu_distance(unsigned int from, unsigned int to)
|
||||
{
|
||||
if (cpu_to_node(from) == cpu_to_node(to))
|
||||
if (early_cpu_to_node(from) == early_cpu_to_node(to))
|
||||
return LOCAL_DISTANCE;
|
||||
else
|
||||
return REMOTE_DISTANCE;
|
||||
|
||||
@@ -197,7 +197,9 @@ static int __spu_trap_data_map(struct spu *spu, unsigned long ea, u64 dsisr)
|
||||
(REGION_ID(ea) != USER_REGION_ID)) {
|
||||
|
||||
spin_unlock(&spu->register_lock);
|
||||
ret = hash_page(ea, _PAGE_PRESENT | _PAGE_READ, 0x300, dsisr);
|
||||
ret = hash_page(ea,
|
||||
_PAGE_PRESENT | _PAGE_READ | _PAGE_PRIVILEGED,
|
||||
0x300, dsisr);
|
||||
spin_lock(&spu->register_lock);
|
||||
|
||||
if (!ret) {
|
||||
|
||||
@@ -124,6 +124,7 @@ static struct property *dlpar_clone_drconf_property(struct device_node *dn)
|
||||
for (i = 0; i < num_lmbs; i++) {
|
||||
lmbs[i].base_addr = be64_to_cpu(lmbs[i].base_addr);
|
||||
lmbs[i].drc_index = be32_to_cpu(lmbs[i].drc_index);
|
||||
lmbs[i].aa_index = be32_to_cpu(lmbs[i].aa_index);
|
||||
lmbs[i].flags = be32_to_cpu(lmbs[i].flags);
|
||||
}
|
||||
|
||||
@@ -147,6 +148,7 @@ static void dlpar_update_drconf_property(struct device_node *dn,
|
||||
for (i = 0; i < num_lmbs; i++) {
|
||||
lmbs[i].base_addr = cpu_to_be64(lmbs[i].base_addr);
|
||||
lmbs[i].drc_index = cpu_to_be32(lmbs[i].drc_index);
|
||||
lmbs[i].aa_index = cpu_to_be32(lmbs[i].aa_index);
|
||||
lmbs[i].flags = cpu_to_be32(lmbs[i].flags);
|
||||
}
|
||||
|
||||
|
||||
@@ -75,7 +75,8 @@ static int u8_gpio_dir_out(struct gpio_chip *gc, unsigned int gpio, int val)
|
||||
|
||||
static void u8_gpio_save_regs(struct of_mm_gpio_chip *mm_gc)
|
||||
{
|
||||
struct u8_gpio_chip *u8_gc = gpiochip_get_data(&mm_gc->gc);
|
||||
struct u8_gpio_chip *u8_gc =
|
||||
container_of(mm_gc, struct u8_gpio_chip, mm_gc);
|
||||
|
||||
u8_gc->data = in_8(mm_gc->regs);
|
||||
}
|
||||
|
||||
@@ -187,9 +187,9 @@ config NR_CPUS
|
||||
int "Maximum number of CPUs"
|
||||
depends on SMP
|
||||
range 2 32 if SPARC32
|
||||
range 2 1024 if SPARC64
|
||||
range 2 4096 if SPARC64
|
||||
default 32 if SPARC32
|
||||
default 64 if SPARC64
|
||||
default 4096 if SPARC64
|
||||
|
||||
source kernel/Kconfig.hz
|
||||
|
||||
|
||||
@@ -52,7 +52,7 @@
|
||||
#define CTX_NR_MASK TAG_CONTEXT_BITS
|
||||
#define CTX_HW_MASK (CTX_NR_MASK | CTX_PGSZ_MASK)
|
||||
|
||||
#define CTX_FIRST_VERSION ((_AC(1,UL) << CTX_VERSION_SHIFT) + _AC(1,UL))
|
||||
#define CTX_FIRST_VERSION BIT(CTX_VERSION_SHIFT)
|
||||
#define CTX_VALID(__ctx) \
|
||||
(!(((__ctx.sparc64_ctx_val) ^ tlb_context_cache) & CTX_VERSION_MASK))
|
||||
#define CTX_HWBITS(__ctx) ((__ctx.sparc64_ctx_val) & CTX_HW_MASK)
|
||||
|
||||
@@ -17,13 +17,8 @@ extern spinlock_t ctx_alloc_lock;
|
||||
extern unsigned long tlb_context_cache;
|
||||
extern unsigned long mmu_context_bmap[];
|
||||
|
||||
DECLARE_PER_CPU(struct mm_struct *, per_cpu_secondary_mm);
|
||||
void get_new_mmu_context(struct mm_struct *mm);
|
||||
#ifdef CONFIG_SMP
|
||||
void smp_new_mmu_context_version(void);
|
||||
#else
|
||||
#define smp_new_mmu_context_version() do { } while (0)
|
||||
#endif
|
||||
|
||||
int init_new_context(struct task_struct *tsk, struct mm_struct *mm);
|
||||
void destroy_context(struct mm_struct *mm);
|
||||
|
||||
@@ -74,8 +69,9 @@ void __flush_tlb_mm(unsigned long, unsigned long);
|
||||
static inline void switch_mm(struct mm_struct *old_mm, struct mm_struct *mm, struct task_struct *tsk)
|
||||
{
|
||||
unsigned long ctx_valid, flags;
|
||||
int cpu;
|
||||
int cpu = smp_processor_id();
|
||||
|
||||
per_cpu(per_cpu_secondary_mm, cpu) = mm;
|
||||
if (unlikely(mm == &init_mm))
|
||||
return;
|
||||
|
||||
@@ -121,7 +117,6 @@ static inline void switch_mm(struct mm_struct *old_mm, struct mm_struct *mm, str
|
||||
* for the first time, we must flush that context out of the
|
||||
* local TLB.
|
||||
*/
|
||||
cpu = smp_processor_id();
|
||||
if (!ctx_valid || !cpumask_test_cpu(cpu, mm_cpumask(mm))) {
|
||||
cpumask_set_cpu(cpu, mm_cpumask(mm));
|
||||
__flush_tlb_mm(CTX_HWBITS(mm->context),
|
||||
@@ -131,26 +126,7 @@ static inline void switch_mm(struct mm_struct *old_mm, struct mm_struct *mm, str
|
||||
}
|
||||
|
||||
#define deactivate_mm(tsk,mm) do { } while (0)
|
||||
|
||||
/* Activate a new MM instance for the current task. */
|
||||
static inline void activate_mm(struct mm_struct *active_mm, struct mm_struct *mm)
|
||||
{
|
||||
unsigned long flags;
|
||||
int cpu;
|
||||
|
||||
spin_lock_irqsave(&mm->context.lock, flags);
|
||||
if (!CTX_VALID(mm->context))
|
||||
get_new_mmu_context(mm);
|
||||
cpu = smp_processor_id();
|
||||
if (!cpumask_test_cpu(cpu, mm_cpumask(mm)))
|
||||
cpumask_set_cpu(cpu, mm_cpumask(mm));
|
||||
|
||||
load_secondary_context(mm);
|
||||
__flush_tlb_mm(CTX_HWBITS(mm->context), SECONDARY_CONTEXT);
|
||||
tsb_context_switch(mm);
|
||||
spin_unlock_irqrestore(&mm->context.lock, flags);
|
||||
}
|
||||
|
||||
#define activate_mm(active_mm, mm) switch_mm(active_mm, mm, NULL)
|
||||
#endif /* !(__ASSEMBLY__) */
|
||||
|
||||
#endif /* !(__SPARC64_MMU_CONTEXT_H) */
|
||||
|
||||
@@ -91,9 +91,9 @@ extern unsigned long pfn_base;
|
||||
* ZERO_PAGE is a global shared page that is always zero: used
|
||||
* for zero-mapped memory areas etc..
|
||||
*/
|
||||
extern unsigned long empty_zero_page;
|
||||
extern unsigned long empty_zero_page[PAGE_SIZE / sizeof(unsigned long)];
|
||||
|
||||
#define ZERO_PAGE(vaddr) (virt_to_page(&empty_zero_page))
|
||||
#define ZERO_PAGE(vaddr) (virt_to_page(empty_zero_page))
|
||||
|
||||
/*
|
||||
* In general all page table modifications should use the V8 atomic
|
||||
|
||||
@@ -20,7 +20,6 @@
|
||||
#define PIL_SMP_CALL_FUNC 1
|
||||
#define PIL_SMP_RECEIVE_SIGNAL 2
|
||||
#define PIL_SMP_CAPTURE 3
|
||||
#define PIL_SMP_CTX_NEW_VERSION 4
|
||||
#define PIL_DEVICE_IRQ 5
|
||||
#define PIL_SMP_CALL_FUNC_SNGL 6
|
||||
#define PIL_DEFERRED_PCR_WORK 7
|
||||
|
||||
@@ -16,7 +16,7 @@ extern char reboot_command[];
|
||||
*/
|
||||
extern unsigned char boot_cpu_id;
|
||||
|
||||
extern unsigned long empty_zero_page;
|
||||
extern unsigned long empty_zero_page[PAGE_SIZE / sizeof(unsigned long)];
|
||||
|
||||
extern int serial_console;
|
||||
static inline int con_is_present(void)
|
||||
|
||||
@@ -327,6 +327,7 @@ struct vio_dev {
|
||||
int compat_len;
|
||||
|
||||
u64 dev_no;
|
||||
u64 id;
|
||||
|
||||
unsigned long channel_id;
|
||||
|
||||
|
||||
@@ -130,18 +130,17 @@ unsigned long prepare_ftrace_return(unsigned long parent,
|
||||
if (unlikely(atomic_read(¤t->tracing_graph_pause)))
|
||||
return parent + 8UL;
|
||||
|
||||
trace.func = self_addr;
|
||||
trace.depth = current->curr_ret_stack + 1;
|
||||
|
||||
/* Only trace if the calling function expects to */
|
||||
if (!ftrace_graph_entry(&trace))
|
||||
return parent + 8UL;
|
||||
|
||||
if (ftrace_push_return_trace(parent, self_addr, &trace.depth,
|
||||
frame_pointer, NULL) == -EBUSY)
|
||||
return parent + 8UL;
|
||||
|
||||
trace.func = self_addr;
|
||||
|
||||
/* Only trace if the calling function expects to */
|
||||
if (!ftrace_graph_entry(&trace)) {
|
||||
current->curr_ret_stack--;
|
||||
return parent + 8UL;
|
||||
}
|
||||
|
||||
return return_hooker;
|
||||
}
|
||||
#endif /* CONFIG_FUNCTION_GRAPH_TRACER */
|
||||
|
||||
@@ -1034,17 +1034,26 @@ static void __init init_cpu_send_mondo_info(struct trap_per_cpu *tb)
|
||||
{
|
||||
#ifdef CONFIG_SMP
|
||||
unsigned long page;
|
||||
void *mondo, *p;
|
||||
|
||||
BUILD_BUG_ON((NR_CPUS * sizeof(u16)) > (PAGE_SIZE - 64));
|
||||
BUILD_BUG_ON((NR_CPUS * sizeof(u16)) > PAGE_SIZE);
|
||||
|
||||
/* Make sure mondo block is 64byte aligned */
|
||||
p = kzalloc(127, GFP_KERNEL);
|
||||
if (!p) {
|
||||
prom_printf("SUN4V: Error, cannot allocate mondo block.\n");
|
||||
prom_halt();
|
||||
}
|
||||
mondo = (void *)(((unsigned long)p + 63) & ~0x3f);
|
||||
tb->cpu_mondo_block_pa = __pa(mondo);
|
||||
|
||||
page = get_zeroed_page(GFP_KERNEL);
|
||||
if (!page) {
|
||||
prom_printf("SUN4V: Error, cannot allocate cpu mondo page.\n");
|
||||
prom_printf("SUN4V: Error, cannot allocate cpu list page.\n");
|
||||
prom_halt();
|
||||
}
|
||||
|
||||
tb->cpu_mondo_block_pa = __pa(page);
|
||||
tb->cpu_list_pa = __pa(page + 64);
|
||||
tb->cpu_list_pa = __pa(page);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@@ -37,7 +37,6 @@ void handle_stdfmna(struct pt_regs *regs, unsigned long sfar, unsigned long sfsr
|
||||
/* smp_64.c */
|
||||
void __irq_entry smp_call_function_client(int irq, struct pt_regs *regs);
|
||||
void __irq_entry smp_call_function_single_client(int irq, struct pt_regs *regs);
|
||||
void __irq_entry smp_new_mmu_context_version_client(int irq, struct pt_regs *regs);
|
||||
void __irq_entry smp_penguin_jailcell(int irq, struct pt_regs *regs);
|
||||
void __irq_entry smp_receive_signal_client(int irq, struct pt_regs *regs);
|
||||
|
||||
|
||||
@@ -963,37 +963,6 @@ void flush_dcache_page_all(struct mm_struct *mm, struct page *page)
|
||||
preempt_enable();
|
||||
}
|
||||
|
||||
void __irq_entry smp_new_mmu_context_version_client(int irq, struct pt_regs *regs)
|
||||
{
|
||||
struct mm_struct *mm;
|
||||
unsigned long flags;
|
||||
|
||||
clear_softint(1 << irq);
|
||||
|
||||
/* See if we need to allocate a new TLB context because
|
||||
* the version of the one we are using is now out of date.
|
||||
*/
|
||||
mm = current->active_mm;
|
||||
if (unlikely(!mm || (mm == &init_mm)))
|
||||
return;
|
||||
|
||||
spin_lock_irqsave(&mm->context.lock, flags);
|
||||
|
||||
if (unlikely(!CTX_VALID(mm->context)))
|
||||
get_new_mmu_context(mm);
|
||||
|
||||
spin_unlock_irqrestore(&mm->context.lock, flags);
|
||||
|
||||
load_secondary_context(mm);
|
||||
__flush_tlb_mm(CTX_HWBITS(mm->context),
|
||||
SECONDARY_CONTEXT);
|
||||
}
|
||||
|
||||
void smp_new_mmu_context_version(void)
|
||||
{
|
||||
smp_cross_call(&xcall_new_mmu_context_version, 0, 0, 0);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_KGDB
|
||||
void kgdb_roundup_cpus(unsigned long flags)
|
||||
{
|
||||
|
||||
@@ -470,13 +470,16 @@ __tsb_context_switch:
|
||||
.type copy_tsb,#function
|
||||
copy_tsb: /* %o0=old_tsb_base, %o1=old_tsb_size
|
||||
* %o2=new_tsb_base, %o3=new_tsb_size
|
||||
* %o4=page_size_shift
|
||||
*/
|
||||
sethi %uhi(TSB_PASS_BITS), %g7
|
||||
srlx %o3, 4, %o3
|
||||
add %o0, %o1, %g1 /* end of old tsb */
|
||||
add %o0, %o1, %o1 /* end of old tsb */
|
||||
sllx %g7, 32, %g7
|
||||
sub %o3, 1, %o3 /* %o3 == new tsb hash mask */
|
||||
|
||||
mov %o4, %g1 /* page_size_shift */
|
||||
|
||||
661: prefetcha [%o0] ASI_N, #one_read
|
||||
.section .tsb_phys_patch, "ax"
|
||||
.word 661b
|
||||
@@ -501,9 +504,9 @@ copy_tsb: /* %o0=old_tsb_base, %o1=old_tsb_size
|
||||
/* This can definitely be computed faster... */
|
||||
srlx %o0, 4, %o5 /* Build index */
|
||||
and %o5, 511, %o5 /* Mask index */
|
||||
sllx %o5, PAGE_SHIFT, %o5 /* Put into vaddr position */
|
||||
sllx %o5, %g1, %o5 /* Put into vaddr position */
|
||||
or %o4, %o5, %o4 /* Full VADDR. */
|
||||
srlx %o4, PAGE_SHIFT, %o4 /* Shift down to create index */
|
||||
srlx %o4, %g1, %o4 /* Shift down to create index */
|
||||
and %o4, %o3, %o4 /* Mask with new_tsb_nents-1 */
|
||||
sllx %o4, 4, %o4 /* Shift back up into tsb ent offset */
|
||||
TSB_STORE(%o2 + %o4, %g2) /* Store TAG */
|
||||
@@ -511,7 +514,7 @@ copy_tsb: /* %o0=old_tsb_base, %o1=old_tsb_size
|
||||
TSB_STORE(%o2 + %o4, %g3) /* Store TTE */
|
||||
|
||||
80: add %o0, 16, %o0
|
||||
cmp %o0, %g1
|
||||
cmp %o0, %o1
|
||||
bne,pt %xcc, 90b
|
||||
nop
|
||||
|
||||
|
||||
@@ -50,7 +50,7 @@ tl0_resv03e: BTRAP(0x3e) BTRAP(0x3f) BTRAP(0x40)
|
||||
tl0_irq1: TRAP_IRQ(smp_call_function_client, 1)
|
||||
tl0_irq2: TRAP_IRQ(smp_receive_signal_client, 2)
|
||||
tl0_irq3: TRAP_IRQ(smp_penguin_jailcell, 3)
|
||||
tl0_irq4: TRAP_IRQ(smp_new_mmu_context_version_client, 4)
|
||||
tl0_irq4: BTRAP(0x44)
|
||||
#else
|
||||
tl0_irq1: BTRAP(0x41)
|
||||
tl0_irq2: BTRAP(0x42)
|
||||
|
||||
@@ -302,13 +302,16 @@ static struct vio_dev *vio_create_one(struct mdesc_handle *hp, u64 mp,
|
||||
if (!id) {
|
||||
dev_set_name(&vdev->dev, "%s", bus_id_name);
|
||||
vdev->dev_no = ~(u64)0;
|
||||
vdev->id = ~(u64)0;
|
||||
} else if (!cfg_handle) {
|
||||
dev_set_name(&vdev->dev, "%s-%llu", bus_id_name, *id);
|
||||
vdev->dev_no = *id;
|
||||
vdev->id = ~(u64)0;
|
||||
} else {
|
||||
dev_set_name(&vdev->dev, "%s-%llu-%llu", bus_id_name,
|
||||
*cfg_handle, *id);
|
||||
vdev->dev_no = *cfg_handle;
|
||||
vdev->id = *id;
|
||||
}
|
||||
|
||||
vdev->dev.parent = parent;
|
||||
@@ -351,27 +354,84 @@ static void vio_add(struct mdesc_handle *hp, u64 node)
|
||||
(void) vio_create_one(hp, node, &root_vdev->dev);
|
||||
}
|
||||
|
||||
struct vio_md_node_query {
|
||||
const char *type;
|
||||
u64 dev_no;
|
||||
u64 id;
|
||||
};
|
||||
|
||||
static int vio_md_node_match(struct device *dev, void *arg)
|
||||
{
|
||||
struct vio_md_node_query *query = (struct vio_md_node_query *) arg;
|
||||
struct vio_dev *vdev = to_vio_dev(dev);
|
||||
|
||||
if (vdev->mp == (u64) arg)
|
||||
return 1;
|
||||
if (vdev->dev_no != query->dev_no)
|
||||
return 0;
|
||||
if (vdev->id != query->id)
|
||||
return 0;
|
||||
if (strcmp(vdev->type, query->type))
|
||||
return 0;
|
||||
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void vio_remove(struct mdesc_handle *hp, u64 node)
|
||||
{
|
||||
const char *type;
|
||||
const u64 *id, *cfg_handle;
|
||||
u64 a;
|
||||
struct vio_md_node_query query;
|
||||
struct device *dev;
|
||||
|
||||
dev = device_find_child(&root_vdev->dev, (void *) node,
|
||||
type = mdesc_get_property(hp, node, "device-type", NULL);
|
||||
if (!type) {
|
||||
type = mdesc_get_property(hp, node, "name", NULL);
|
||||
if (!type)
|
||||
type = mdesc_node_name(hp, node);
|
||||
}
|
||||
|
||||
query.type = type;
|
||||
|
||||
id = mdesc_get_property(hp, node, "id", NULL);
|
||||
cfg_handle = NULL;
|
||||
mdesc_for_each_arc(a, hp, node, MDESC_ARC_TYPE_BACK) {
|
||||
u64 target;
|
||||
|
||||
target = mdesc_arc_target(hp, a);
|
||||
cfg_handle = mdesc_get_property(hp, target,
|
||||
"cfg-handle", NULL);
|
||||
if (cfg_handle)
|
||||
break;
|
||||
}
|
||||
|
||||
if (!id) {
|
||||
query.dev_no = ~(u64)0;
|
||||
query.id = ~(u64)0;
|
||||
} else if (!cfg_handle) {
|
||||
query.dev_no = *id;
|
||||
query.id = ~(u64)0;
|
||||
} else {
|
||||
query.dev_no = *cfg_handle;
|
||||
query.id = *id;
|
||||
}
|
||||
|
||||
dev = device_find_child(&root_vdev->dev, &query,
|
||||
vio_md_node_match);
|
||||
if (dev) {
|
||||
printk(KERN_INFO "VIO: Removing device %s\n", dev_name(dev));
|
||||
|
||||
device_unregister(dev);
|
||||
put_device(dev);
|
||||
} else {
|
||||
if (!id)
|
||||
printk(KERN_ERR "VIO: Removed unknown %s node.\n",
|
||||
type);
|
||||
else if (!cfg_handle)
|
||||
printk(KERN_ERR "VIO: Removed unknown %s node %llu.\n",
|
||||
type, *id);
|
||||
else
|
||||
printk(KERN_ERR "VIO: Removed unknown %s node %llu-%llu.\n",
|
||||
type, *cfg_handle, *id);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -15,6 +15,7 @@ lib-$(CONFIG_SPARC32) += copy_user.o locks.o
|
||||
lib-$(CONFIG_SPARC64) += atomic_64.o
|
||||
lib-$(CONFIG_SPARC32) += lshrdi3.o ashldi3.o
|
||||
lib-$(CONFIG_SPARC32) += muldi3.o bitext.o cmpdi2.o
|
||||
lib-$(CONFIG_SPARC64) += multi3.o
|
||||
|
||||
lib-$(CONFIG_SPARC64) += copy_page.o clear_page.o bzero.o
|
||||
lib-$(CONFIG_SPARC64) += csum_copy.o csum_copy_from_user.o csum_copy_to_user.o
|
||||
|
||||
35
arch/sparc/lib/multi3.S
Normal file
35
arch/sparc/lib/multi3.S
Normal file
@@ -0,0 +1,35 @@
|
||||
#include <linux/linkage.h>
|
||||
#include <asm/export.h>
|
||||
|
||||
.text
|
||||
.align 4
|
||||
ENTRY(__multi3) /* %o0 = u, %o1 = v */
|
||||
mov %o1, %g1
|
||||
srl %o3, 0, %g4
|
||||
mulx %g4, %g1, %o1
|
||||
srlx %g1, 0x20, %g3
|
||||
mulx %g3, %g4, %g5
|
||||
sllx %g5, 0x20, %o5
|
||||
srl %g1, 0, %g4
|
||||
sub %o1, %o5, %o5
|
||||
srlx %o5, 0x20, %o5
|
||||
addcc %g5, %o5, %g5
|
||||
srlx %o3, 0x20, %o5
|
||||
mulx %g4, %o5, %g4
|
||||
mulx %g3, %o5, %o5
|
||||
sethi %hi(0x80000000), %g3
|
||||
addcc %g5, %g4, %g5
|
||||
srlx %g5, 0x20, %g5
|
||||
add %g3, %g3, %g3
|
||||
movcc %xcc, %g0, %g3
|
||||
addcc %o5, %g5, %o5
|
||||
sllx %g4, 0x20, %g4
|
||||
add %o1, %g4, %o1
|
||||
add %o5, %g3, %g2
|
||||
mulx %g1, %o2, %g1
|
||||
add %g1, %g2, %g1
|
||||
mulx %o0, %o3, %o0
|
||||
retl
|
||||
add %g1, %o0, %o0
|
||||
ENDPROC(__multi3)
|
||||
EXPORT_SYMBOL(__multi3)
|
||||
@@ -301,7 +301,7 @@ void __init mem_init(void)
|
||||
|
||||
|
||||
/* Saves us work later. */
|
||||
memset((void *)&empty_zero_page, 0, PAGE_SIZE);
|
||||
memset((void *)empty_zero_page, 0, PAGE_SIZE);
|
||||
|
||||
i = last_valid_pfn >> ((20 - PAGE_SHIFT) + 5);
|
||||
i += 1;
|
||||
|
||||
@@ -658,10 +658,58 @@ EXPORT_SYMBOL(__flush_dcache_range);
|
||||
|
||||
/* get_new_mmu_context() uses "cache + 1". */
|
||||
DEFINE_SPINLOCK(ctx_alloc_lock);
|
||||
unsigned long tlb_context_cache = CTX_FIRST_VERSION - 1;
|
||||
unsigned long tlb_context_cache = CTX_FIRST_VERSION;
|
||||
#define MAX_CTX_NR (1UL << CTX_NR_BITS)
|
||||
#define CTX_BMAP_SLOTS BITS_TO_LONGS(MAX_CTX_NR)
|
||||
DECLARE_BITMAP(mmu_context_bmap, MAX_CTX_NR);
|
||||
DEFINE_PER_CPU(struct mm_struct *, per_cpu_secondary_mm) = {0};
|
||||
|
||||
static void mmu_context_wrap(void)
|
||||
{
|
||||
unsigned long old_ver = tlb_context_cache & CTX_VERSION_MASK;
|
||||
unsigned long new_ver, new_ctx, old_ctx;
|
||||
struct mm_struct *mm;
|
||||
int cpu;
|
||||
|
||||
bitmap_zero(mmu_context_bmap, 1 << CTX_NR_BITS);
|
||||
|
||||
/* Reserve kernel context */
|
||||
set_bit(0, mmu_context_bmap);
|
||||
|
||||
new_ver = (tlb_context_cache & CTX_VERSION_MASK) + CTX_FIRST_VERSION;
|
||||
if (unlikely(new_ver == 0))
|
||||
new_ver = CTX_FIRST_VERSION;
|
||||
tlb_context_cache = new_ver;
|
||||
|
||||
/*
|
||||
* Make sure that any new mm that are added into per_cpu_secondary_mm,
|
||||
* are going to go through get_new_mmu_context() path.
|
||||
*/
|
||||
mb();
|
||||
|
||||
/*
|
||||
* Updated versions to current on those CPUs that had valid secondary
|
||||
* contexts
|
||||
*/
|
||||
for_each_online_cpu(cpu) {
|
||||
/*
|
||||
* If a new mm is stored after we took this mm from the array,
|
||||
* it will go into get_new_mmu_context() path, because we
|
||||
* already bumped the version in tlb_context_cache.
|
||||
*/
|
||||
mm = per_cpu(per_cpu_secondary_mm, cpu);
|
||||
|
||||
if (unlikely(!mm || mm == &init_mm))
|
||||
continue;
|
||||
|
||||
old_ctx = mm->context.sparc64_ctx_val;
|
||||
if (likely((old_ctx & CTX_VERSION_MASK) == old_ver)) {
|
||||
new_ctx = (old_ctx & ~CTX_VERSION_MASK) | new_ver;
|
||||
set_bit(new_ctx & CTX_NR_MASK, mmu_context_bmap);
|
||||
mm->context.sparc64_ctx_val = new_ctx;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Caller does TLB context flushing on local CPU if necessary.
|
||||
* The caller also ensures that CTX_VALID(mm->context) is false.
|
||||
@@ -677,48 +725,30 @@ void get_new_mmu_context(struct mm_struct *mm)
|
||||
{
|
||||
unsigned long ctx, new_ctx;
|
||||
unsigned long orig_pgsz_bits;
|
||||
int new_version;
|
||||
|
||||
spin_lock(&ctx_alloc_lock);
|
||||
retry:
|
||||
/* wrap might have happened, test again if our context became valid */
|
||||
if (unlikely(CTX_VALID(mm->context)))
|
||||
goto out;
|
||||
orig_pgsz_bits = (mm->context.sparc64_ctx_val & CTX_PGSZ_MASK);
|
||||
ctx = (tlb_context_cache + 1) & CTX_NR_MASK;
|
||||
new_ctx = find_next_zero_bit(mmu_context_bmap, 1 << CTX_NR_BITS, ctx);
|
||||
new_version = 0;
|
||||
if (new_ctx >= (1 << CTX_NR_BITS)) {
|
||||
new_ctx = find_next_zero_bit(mmu_context_bmap, ctx, 1);
|
||||
if (new_ctx >= ctx) {
|
||||
int i;
|
||||
new_ctx = (tlb_context_cache & CTX_VERSION_MASK) +
|
||||
CTX_FIRST_VERSION;
|
||||
if (new_ctx == 1)
|
||||
new_ctx = CTX_FIRST_VERSION;
|
||||
|
||||
/* Don't call memset, for 16 entries that's just
|
||||
* plain silly...
|
||||
*/
|
||||
mmu_context_bmap[0] = 3;
|
||||
mmu_context_bmap[1] = 0;
|
||||
mmu_context_bmap[2] = 0;
|
||||
mmu_context_bmap[3] = 0;
|
||||
for (i = 4; i < CTX_BMAP_SLOTS; i += 4) {
|
||||
mmu_context_bmap[i + 0] = 0;
|
||||
mmu_context_bmap[i + 1] = 0;
|
||||
mmu_context_bmap[i + 2] = 0;
|
||||
mmu_context_bmap[i + 3] = 0;
|
||||
}
|
||||
new_version = 1;
|
||||
goto out;
|
||||
mmu_context_wrap();
|
||||
goto retry;
|
||||
}
|
||||
}
|
||||
if (mm->context.sparc64_ctx_val)
|
||||
cpumask_clear(mm_cpumask(mm));
|
||||
mmu_context_bmap[new_ctx>>6] |= (1UL << (new_ctx & 63));
|
||||
new_ctx |= (tlb_context_cache & CTX_VERSION_MASK);
|
||||
out:
|
||||
tlb_context_cache = new_ctx;
|
||||
mm->context.sparc64_ctx_val = new_ctx | orig_pgsz_bits;
|
||||
out:
|
||||
spin_unlock(&ctx_alloc_lock);
|
||||
|
||||
if (unlikely(new_version))
|
||||
smp_new_mmu_context_version();
|
||||
}
|
||||
|
||||
static int numa_enabled = 1;
|
||||
|
||||
@@ -451,7 +451,8 @@ retry_tsb_alloc:
|
||||
extern void copy_tsb(unsigned long old_tsb_base,
|
||||
unsigned long old_tsb_size,
|
||||
unsigned long new_tsb_base,
|
||||
unsigned long new_tsb_size);
|
||||
unsigned long new_tsb_size,
|
||||
unsigned long page_size_shift);
|
||||
unsigned long old_tsb_base = (unsigned long) old_tsb;
|
||||
unsigned long new_tsb_base = (unsigned long) new_tsb;
|
||||
|
||||
@@ -459,7 +460,9 @@ retry_tsb_alloc:
|
||||
old_tsb_base = __pa(old_tsb_base);
|
||||
new_tsb_base = __pa(new_tsb_base);
|
||||
}
|
||||
copy_tsb(old_tsb_base, old_size, new_tsb_base, new_size);
|
||||
copy_tsb(old_tsb_base, old_size, new_tsb_base, new_size,
|
||||
tsb_index == MM_TSB_BASE ?
|
||||
PAGE_SHIFT : REAL_HPAGE_SHIFT);
|
||||
}
|
||||
|
||||
mm->context.tsb_block[tsb_index].tsb = new_tsb;
|
||||
|
||||
@@ -971,11 +971,6 @@ xcall_capture:
|
||||
wr %g0, (1 << PIL_SMP_CAPTURE), %set_softint
|
||||
retry
|
||||
|
||||
.globl xcall_new_mmu_context_version
|
||||
xcall_new_mmu_context_version:
|
||||
wr %g0, (1 << PIL_SMP_CTX_NEW_VERSION), %set_softint
|
||||
retry
|
||||
|
||||
#ifdef CONFIG_KGDB
|
||||
.globl xcall_kgdb_capture
|
||||
xcall_kgdb_capture:
|
||||
|
||||
@@ -94,7 +94,7 @@ vmlinux-objs-$(CONFIG_EFI_MIXED) += $(obj)/efi_thunk_$(BITS).o
|
||||
quiet_cmd_check_data_rel = DATAREL $@
|
||||
define cmd_check_data_rel
|
||||
for obj in $(filter %.o,$^); do \
|
||||
readelf -S $$obj | grep -qF .rel.local && { \
|
||||
${CROSS_COMPILE}readelf -S $$obj | grep -qF .rel.local && { \
|
||||
echo "error: $$obj has data relocations!" >&2; \
|
||||
exit 1; \
|
||||
} || true; \
|
||||
|
||||
@@ -257,6 +257,7 @@ static inline void mce_amd_feature_init(struct cpuinfo_x86 *c) { }
|
||||
#endif
|
||||
|
||||
int mce_available(struct cpuinfo_x86 *c);
|
||||
bool mce_is_memory_error(struct mce *m);
|
||||
|
||||
DECLARE_PER_CPU(unsigned, mce_exception_count);
|
||||
DECLARE_PER_CPU(unsigned, mce_poll_count);
|
||||
|
||||
@@ -598,16 +598,14 @@ static void mce_read_aux(struct mce *m, int i)
|
||||
}
|
||||
}
|
||||
|
||||
static bool memory_error(struct mce *m)
|
||||
bool mce_is_memory_error(struct mce *m)
|
||||
{
|
||||
struct cpuinfo_x86 *c = &boot_cpu_data;
|
||||
|
||||
if (c->x86_vendor == X86_VENDOR_AMD) {
|
||||
if (m->cpuvendor == X86_VENDOR_AMD) {
|
||||
/* ErrCodeExt[20:16] */
|
||||
u8 xec = (m->status >> 16) & 0x1f;
|
||||
|
||||
return (xec == 0x0 || xec == 0x8);
|
||||
} else if (c->x86_vendor == X86_VENDOR_INTEL) {
|
||||
} else if (m->cpuvendor == X86_VENDOR_INTEL) {
|
||||
/*
|
||||
* Intel SDM Volume 3B - 15.9.2 Compound Error Codes
|
||||
*
|
||||
@@ -628,6 +626,7 @@ static bool memory_error(struct mce *m)
|
||||
|
||||
return false;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mce_is_memory_error);
|
||||
|
||||
DEFINE_PER_CPU(unsigned, mce_poll_count);
|
||||
|
||||
@@ -691,7 +690,7 @@ bool machine_check_poll(enum mcp_flags flags, mce_banks_t *b)
|
||||
|
||||
severity = mce_severity(&m, mca_cfg.tolerant, NULL, false);
|
||||
|
||||
if (severity == MCE_DEFERRED_SEVERITY && memory_error(&m))
|
||||
if (severity == MCE_DEFERRED_SEVERITY && mce_is_memory_error(&m))
|
||||
if (m.status & MCI_STATUS_ADDRV)
|
||||
m.severity = severity;
|
||||
|
||||
|
||||
@@ -162,8 +162,8 @@ void kvm_async_pf_task_wait(u32 token)
|
||||
*/
|
||||
rcu_irq_exit();
|
||||
native_safe_halt();
|
||||
rcu_irq_enter();
|
||||
local_irq_disable();
|
||||
rcu_irq_enter();
|
||||
}
|
||||
}
|
||||
if (!n.halted)
|
||||
|
||||
@@ -765,18 +765,20 @@ out:
|
||||
static int move_to_next_stateful_cpuid_entry(struct kvm_vcpu *vcpu, int i)
|
||||
{
|
||||
struct kvm_cpuid_entry2 *e = &vcpu->arch.cpuid_entries[i];
|
||||
int j, nent = vcpu->arch.cpuid_nent;
|
||||
struct kvm_cpuid_entry2 *ej;
|
||||
int j = i;
|
||||
int nent = vcpu->arch.cpuid_nent;
|
||||
|
||||
e->flags &= ~KVM_CPUID_FLAG_STATE_READ_NEXT;
|
||||
/* when no next entry is found, the current entry[i] is reselected */
|
||||
for (j = i + 1; ; j = (j + 1) % nent) {
|
||||
struct kvm_cpuid_entry2 *ej = &vcpu->arch.cpuid_entries[j];
|
||||
if (ej->function == e->function) {
|
||||
ej->flags |= KVM_CPUID_FLAG_STATE_READ_NEXT;
|
||||
return j;
|
||||
}
|
||||
}
|
||||
return 0; /* silence gcc, even though control never reaches here */
|
||||
do {
|
||||
j = (j + 1) % nent;
|
||||
ej = &vcpu->arch.cpuid_entries[j];
|
||||
} while (ej->function != e->function);
|
||||
|
||||
ej->flags |= KVM_CPUID_FLAG_STATE_READ_NEXT;
|
||||
|
||||
return j;
|
||||
}
|
||||
|
||||
/* find an entry with matching function, matching index (if needed), and that
|
||||
|
||||
@@ -3489,12 +3489,15 @@ static int kvm_arch_setup_async_pf(struct kvm_vcpu *vcpu, gva_t gva, gfn_t gfn)
|
||||
return kvm_setup_async_pf(vcpu, gva, kvm_vcpu_gfn_to_hva(vcpu, gfn), &arch);
|
||||
}
|
||||
|
||||
static bool can_do_async_pf(struct kvm_vcpu *vcpu)
|
||||
bool kvm_can_do_async_pf(struct kvm_vcpu *vcpu)
|
||||
{
|
||||
if (unlikely(!lapic_in_kernel(vcpu) ||
|
||||
kvm_event_needs_reinjection(vcpu)))
|
||||
return false;
|
||||
|
||||
if (is_guest_mode(vcpu))
|
||||
return false;
|
||||
|
||||
return kvm_x86_ops->interrupt_allowed(vcpu);
|
||||
}
|
||||
|
||||
@@ -3510,7 +3513,7 @@ static bool try_async_pf(struct kvm_vcpu *vcpu, bool prefault, gfn_t gfn,
|
||||
if (!async)
|
||||
return false; /* *pfn has correct page already */
|
||||
|
||||
if (!prefault && can_do_async_pf(vcpu)) {
|
||||
if (!prefault && kvm_can_do_async_pf(vcpu)) {
|
||||
trace_kvm_try_async_get_page(gva, gfn);
|
||||
if (kvm_find_async_pf_gfn(vcpu, gfn)) {
|
||||
trace_kvm_async_pf_doublefault(gva, gfn);
|
||||
|
||||
@@ -75,6 +75,7 @@ enum {
|
||||
int handle_mmio_page_fault(struct kvm_vcpu *vcpu, u64 addr, bool direct);
|
||||
void kvm_init_shadow_mmu(struct kvm_vcpu *vcpu);
|
||||
void kvm_init_shadow_ept_mmu(struct kvm_vcpu *vcpu, bool execonly);
|
||||
bool kvm_can_do_async_pf(struct kvm_vcpu *vcpu);
|
||||
|
||||
static inline unsigned int kvm_mmu_available_pages(struct kvm *kvm)
|
||||
{
|
||||
|
||||
@@ -8444,8 +8444,7 @@ bool kvm_arch_can_inject_async_page_present(struct kvm_vcpu *vcpu)
|
||||
if (!(vcpu->arch.apf.msr_val & KVM_ASYNC_PF_ENABLED))
|
||||
return true;
|
||||
else
|
||||
return !kvm_event_needs_reinjection(vcpu) &&
|
||||
kvm_x86_ops->interrupt_allowed(vcpu);
|
||||
return kvm_can_do_async_pf(vcpu);
|
||||
}
|
||||
|
||||
void kvm_arch_start_assignment(struct kvm *kvm)
|
||||
|
||||
@@ -358,6 +358,9 @@ void __init efi_free_boot_services(void)
|
||||
free_bootmem_late(start, size);
|
||||
}
|
||||
|
||||
if (!num_entries)
|
||||
return;
|
||||
|
||||
new_size = efi.memmap.desc_size * num_entries;
|
||||
new_phys = efi_memmap_alloc(num_entries);
|
||||
if (!new_phys) {
|
||||
|
||||
@@ -36,9 +36,13 @@ static const u64 cfq_target_latency = (u64)NSEC_PER_SEC * 3/10; /* 300 ms */
|
||||
static const int cfq_hist_divisor = 4;
|
||||
|
||||
/*
|
||||
* offset from end of service tree
|
||||
* offset from end of queue service tree for idle class
|
||||
*/
|
||||
#define CFQ_IDLE_DELAY (NSEC_PER_SEC / 5)
|
||||
/* offset from end of group service tree under time slice mode */
|
||||
#define CFQ_SLICE_MODE_GROUP_DELAY (NSEC_PER_SEC / 5)
|
||||
/* offset from end of group service under IOPS mode */
|
||||
#define CFQ_IOPS_MODE_GROUP_DELAY (HZ / 5)
|
||||
|
||||
/*
|
||||
* below this threshold, we consider thinktime immediate
|
||||
@@ -1370,6 +1374,14 @@ cfq_group_service_tree_add(struct cfq_rb_root *st, struct cfq_group *cfqg)
|
||||
cfqg->vfraction = max_t(unsigned, vfr, 1);
|
||||
}
|
||||
|
||||
static inline u64 cfq_get_cfqg_vdisktime_delay(struct cfq_data *cfqd)
|
||||
{
|
||||
if (!iops_mode(cfqd))
|
||||
return CFQ_SLICE_MODE_GROUP_DELAY;
|
||||
else
|
||||
return CFQ_IOPS_MODE_GROUP_DELAY;
|
||||
}
|
||||
|
||||
static void
|
||||
cfq_group_notify_queue_add(struct cfq_data *cfqd, struct cfq_group *cfqg)
|
||||
{
|
||||
@@ -1389,7 +1401,8 @@ cfq_group_notify_queue_add(struct cfq_data *cfqd, struct cfq_group *cfqg)
|
||||
n = rb_last(&st->rb);
|
||||
if (n) {
|
||||
__cfqg = rb_entry_cfqg(n);
|
||||
cfqg->vdisktime = __cfqg->vdisktime + CFQ_IDLE_DELAY;
|
||||
cfqg->vdisktime = __cfqg->vdisktime +
|
||||
cfq_get_cfqg_vdisktime_delay(cfqd);
|
||||
} else
|
||||
cfqg->vdisktime = st->min_vdisktime;
|
||||
cfq_group_service_tree_add(st, cfqg);
|
||||
|
||||
@@ -140,7 +140,7 @@ int public_key_verify_signature(const struct public_key *pkey,
|
||||
* signature and returns that to us.
|
||||
*/
|
||||
ret = crypto_akcipher_verify(req);
|
||||
if (ret == -EINPROGRESS) {
|
||||
if ((ret == -EINPROGRESS) || (ret == -EBUSY)) {
|
||||
wait_for_completion(&compl.completion);
|
||||
ret = compl.err;
|
||||
}
|
||||
|
||||
@@ -1768,9 +1768,8 @@ static int drbg_kcapi_sym_ctr(struct drbg_state *drbg,
|
||||
break;
|
||||
case -EINPROGRESS:
|
||||
case -EBUSY:
|
||||
ret = wait_for_completion_interruptible(
|
||||
&drbg->ctr_completion);
|
||||
if (!ret && !drbg->ctr_async_err) {
|
||||
wait_for_completion(&drbg->ctr_completion);
|
||||
if (!drbg->ctr_async_err) {
|
||||
reinit_completion(&drbg->ctr_completion);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -152,10 +152,8 @@ static int crypto_gcm_setkey(struct crypto_aead *aead, const u8 *key,
|
||||
|
||||
err = crypto_skcipher_encrypt(&data->req);
|
||||
if (err == -EINPROGRESS || err == -EBUSY) {
|
||||
err = wait_for_completion_interruptible(
|
||||
&data->result.completion);
|
||||
if (!err)
|
||||
err = data->result.err;
|
||||
wait_for_completion(&data->result.completion);
|
||||
err = data->result.err;
|
||||
}
|
||||
|
||||
if (err)
|
||||
|
||||
@@ -221,6 +221,44 @@ static int crypto_init_skcipher_ops_ablkcipher(struct crypto_tfm *tfm)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int skcipher_setkey_unaligned(struct crypto_skcipher *tfm,
|
||||
const u8 *key, unsigned int keylen)
|
||||
{
|
||||
unsigned long alignmask = crypto_skcipher_alignmask(tfm);
|
||||
struct skcipher_alg *cipher = crypto_skcipher_alg(tfm);
|
||||
u8 *buffer, *alignbuffer;
|
||||
unsigned long absize;
|
||||
int ret;
|
||||
|
||||
absize = keylen + alignmask;
|
||||
buffer = kmalloc(absize, GFP_ATOMIC);
|
||||
if (!buffer)
|
||||
return -ENOMEM;
|
||||
|
||||
alignbuffer = (u8 *)ALIGN((unsigned long)buffer, alignmask + 1);
|
||||
memcpy(alignbuffer, key, keylen);
|
||||
ret = cipher->setkey(tfm, alignbuffer, keylen);
|
||||
kzfree(buffer);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int skcipher_setkey(struct crypto_skcipher *tfm, const u8 *key,
|
||||
unsigned int keylen)
|
||||
{
|
||||
struct skcipher_alg *cipher = crypto_skcipher_alg(tfm);
|
||||
unsigned long alignmask = crypto_skcipher_alignmask(tfm);
|
||||
|
||||
if (keylen < cipher->min_keysize || keylen > cipher->max_keysize) {
|
||||
crypto_skcipher_set_flags(tfm, CRYPTO_TFM_RES_BAD_KEY_LEN);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if ((unsigned long)key & alignmask)
|
||||
return skcipher_setkey_unaligned(tfm, key, keylen);
|
||||
|
||||
return cipher->setkey(tfm, key, keylen);
|
||||
}
|
||||
|
||||
static void crypto_skcipher_exit_tfm(struct crypto_tfm *tfm)
|
||||
{
|
||||
struct crypto_skcipher *skcipher = __crypto_skcipher_cast(tfm);
|
||||
@@ -241,7 +279,7 @@ static int crypto_skcipher_init_tfm(struct crypto_tfm *tfm)
|
||||
tfm->__crt_alg->cra_type == &crypto_givcipher_type)
|
||||
return crypto_init_skcipher_ops_ablkcipher(tfm);
|
||||
|
||||
skcipher->setkey = alg->setkey;
|
||||
skcipher->setkey = skcipher_setkey;
|
||||
skcipher->encrypt = alg->encrypt;
|
||||
skcipher->decrypt = alg->decrypt;
|
||||
skcipher->ivsize = alg->ivsize;
|
||||
|
||||
@@ -113,7 +113,7 @@ struct acpi_button {
|
||||
|
||||
static BLOCKING_NOTIFIER_HEAD(acpi_lid_notifier);
|
||||
static struct acpi_device *lid_device;
|
||||
static u8 lid_init_state = ACPI_BUTTON_LID_INIT_OPEN;
|
||||
static u8 lid_init_state = ACPI_BUTTON_LID_INIT_METHOD;
|
||||
|
||||
static unsigned long lid_report_interval __read_mostly = 500;
|
||||
module_param(lid_report_interval, ulong, 0644);
|
||||
|
||||
@@ -26,7 +26,7 @@ static int nfit_handle_mce(struct notifier_block *nb, unsigned long val,
|
||||
struct nfit_spa *nfit_spa;
|
||||
|
||||
/* We only care about memory errors */
|
||||
if (!(mce->status & MCACOD))
|
||||
if (!mce_is_memory_error(mce))
|
||||
return NOTIFY_DONE;
|
||||
|
||||
/*
|
||||
|
||||
@@ -1362,6 +1362,40 @@ static inline void ahci_gtf_filter_workaround(struct ata_host *host)
|
||||
{}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* On the Acer Aspire Switch Alpha 12, sometimes all SATA ports are detected
|
||||
* as DUMMY, or detected but eventually get a "link down" and never get up
|
||||
* again. When this happens, CAP.NP may hold a value of 0x00 or 0x01, and the
|
||||
* port_map may hold a value of 0x00.
|
||||
*
|
||||
* Overriding CAP.NP to 0x02 and the port_map to 0x7 will reveal all 3 ports
|
||||
* and can significantly reduce the occurrence of the problem.
|
||||
*
|
||||
* https://bugzilla.kernel.org/show_bug.cgi?id=189471
|
||||
*/
|
||||
static void acer_sa5_271_workaround(struct ahci_host_priv *hpriv,
|
||||
struct pci_dev *pdev)
|
||||
{
|
||||
static const struct dmi_system_id sysids[] = {
|
||||
{
|
||||
.ident = "Acer Switch Alpha 12",
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "Switch SA5-271")
|
||||
},
|
||||
},
|
||||
{ }
|
||||
};
|
||||
|
||||
if (dmi_check_system(sysids)) {
|
||||
dev_info(&pdev->dev, "enabling Acer Switch Alpha 12 workaround\n");
|
||||
if ((hpriv->saved_cap & 0xC734FF00) == 0xC734FF00) {
|
||||
hpriv->port_map = 0x7;
|
||||
hpriv->cap = 0xC734FF02;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef CONFIG_ARM64
|
||||
/*
|
||||
* Due to ERRATA#22536, ThunderX needs to handle HOST_IRQ_STAT differently.
|
||||
@@ -1597,6 +1631,10 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
|
||||
"online status unreliable, applying workaround\n");
|
||||
}
|
||||
|
||||
|
||||
/* Acer SA5-271 workaround modifies private_data */
|
||||
acer_sa5_271_workaround(hpriv, pdev);
|
||||
|
||||
/* CAP.NP sometimes indicate the index of the last enabled
|
||||
* port, at other times, that of the last possible port, so
|
||||
* determining the maximum port number requires looking at
|
||||
|
||||
@@ -343,7 +343,7 @@ static int mmap_mem(struct file *file, struct vm_area_struct *vma)
|
||||
phys_addr_t offset = (phys_addr_t)vma->vm_pgoff << PAGE_SHIFT;
|
||||
|
||||
/* It's illegal to wrap around the end of the physical address space. */
|
||||
if (offset + (phys_addr_t)size < offset)
|
||||
if (offset + (phys_addr_t)size - 1 < offset)
|
||||
return -EINVAL;
|
||||
|
||||
if (!valid_mmap_phys_addr_range(vma->vm_pgoff, size))
|
||||
|
||||
@@ -374,7 +374,7 @@ static ssize_t cm4040_write(struct file *filp, const char __user *buf,
|
||||
|
||||
rc = write_sync_reg(SCR_HOST_TO_READER_START, dev);
|
||||
if (rc <= 0) {
|
||||
DEBUGP(5, dev, "write_sync_reg c=%.2Zx\n", rc);
|
||||
DEBUGP(5, dev, "write_sync_reg c=%.2zx\n", rc);
|
||||
DEBUGP(2, dev, "<- cm4040_write (failed)\n");
|
||||
if (rc == -ERESTARTSYS)
|
||||
return rc;
|
||||
@@ -387,7 +387,7 @@ static ssize_t cm4040_write(struct file *filp, const char __user *buf,
|
||||
for (i = 0; i < bytes_to_write; i++) {
|
||||
rc = wait_for_bulk_out_ready(dev);
|
||||
if (rc <= 0) {
|
||||
DEBUGP(5, dev, "wait_for_bulk_out_ready rc=%.2Zx\n",
|
||||
DEBUGP(5, dev, "wait_for_bulk_out_ready rc=%.2zx\n",
|
||||
rc);
|
||||
DEBUGP(2, dev, "<- cm4040_write (failed)\n");
|
||||
if (rc == -ERESTARTSYS)
|
||||
@@ -403,7 +403,7 @@ static ssize_t cm4040_write(struct file *filp, const char __user *buf,
|
||||
rc = write_sync_reg(SCR_HOST_TO_READER_DONE, dev);
|
||||
|
||||
if (rc <= 0) {
|
||||
DEBUGP(5, dev, "write_sync_reg c=%.2Zx\n", rc);
|
||||
DEBUGP(5, dev, "write_sync_reg c=%.2zx\n", rc);
|
||||
DEBUGP(2, dev, "<- cm4040_write (failed)\n");
|
||||
if (rc == -ERESTARTSYS)
|
||||
return rc;
|
||||
|
||||
@@ -2539,6 +2539,7 @@ int cpufreq_register_driver(struct cpufreq_driver *driver_data)
|
||||
if (!(cpufreq_driver->flags & CPUFREQ_STICKY) &&
|
||||
list_empty(&cpufreq_policy_list)) {
|
||||
/* if all ->init() calls failed, unregister */
|
||||
ret = -ENODEV;
|
||||
pr_debug("%s: No CPU initialized for driver %s\n", __func__,
|
||||
driver_data->name);
|
||||
goto err_if_unreg;
|
||||
|
||||
@@ -570,13 +570,15 @@ again:
|
||||
|
||||
for_each_cpu(cpu, &tmp_mask) {
|
||||
struct interactive_cpu *icpu = &per_cpu(interactive_cpu, cpu);
|
||||
struct cpufreq_policy *policy = icpu->ipolicy->policy;
|
||||
struct cpufreq_policy *policy;
|
||||
|
||||
if (unlikely(!down_read_trylock(&icpu->enable_sem)))
|
||||
continue;
|
||||
|
||||
if (likely(icpu->ipolicy))
|
||||
if (likely(icpu->ipolicy)) {
|
||||
policy = icpu->ipolicy->policy;
|
||||
cpufreq_interactive_adjust_cpu(cpu, policy);
|
||||
}
|
||||
|
||||
up_read(&icpu->enable_sem);
|
||||
}
|
||||
|
||||
@@ -201,6 +201,7 @@ struct ep93xx_dma_engine {
|
||||
struct dma_device dma_dev;
|
||||
bool m2m;
|
||||
int (*hw_setup)(struct ep93xx_dma_chan *);
|
||||
void (*hw_synchronize)(struct ep93xx_dma_chan *);
|
||||
void (*hw_shutdown)(struct ep93xx_dma_chan *);
|
||||
void (*hw_submit)(struct ep93xx_dma_chan *);
|
||||
int (*hw_interrupt)(struct ep93xx_dma_chan *);
|
||||
@@ -323,6 +324,8 @@ static int m2p_hw_setup(struct ep93xx_dma_chan *edmac)
|
||||
| M2P_CONTROL_ENABLE;
|
||||
m2p_set_control(edmac, control);
|
||||
|
||||
edmac->buffer = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -331,21 +334,27 @@ static inline u32 m2p_channel_state(struct ep93xx_dma_chan *edmac)
|
||||
return (readl(edmac->regs + M2P_STATUS) >> 4) & 0x3;
|
||||
}
|
||||
|
||||
static void m2p_hw_shutdown(struct ep93xx_dma_chan *edmac)
|
||||
static void m2p_hw_synchronize(struct ep93xx_dma_chan *edmac)
|
||||
{
|
||||
unsigned long flags;
|
||||
u32 control;
|
||||
|
||||
spin_lock_irqsave(&edmac->lock, flags);
|
||||
control = readl(edmac->regs + M2P_CONTROL);
|
||||
control &= ~(M2P_CONTROL_STALLINT | M2P_CONTROL_NFBINT);
|
||||
m2p_set_control(edmac, control);
|
||||
spin_unlock_irqrestore(&edmac->lock, flags);
|
||||
|
||||
while (m2p_channel_state(edmac) >= M2P_STATE_ON)
|
||||
cpu_relax();
|
||||
schedule();
|
||||
}
|
||||
|
||||
static void m2p_hw_shutdown(struct ep93xx_dma_chan *edmac)
|
||||
{
|
||||
m2p_set_control(edmac, 0);
|
||||
|
||||
while (m2p_channel_state(edmac) == M2P_STATE_STALL)
|
||||
cpu_relax();
|
||||
while (m2p_channel_state(edmac) != M2P_STATE_IDLE)
|
||||
dev_warn(chan2dev(edmac), "M2P: Not yet IDLE\n");
|
||||
}
|
||||
|
||||
static void m2p_fill_desc(struct ep93xx_dma_chan *edmac)
|
||||
@@ -1160,6 +1169,26 @@ fail:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* ep93xx_dma_synchronize - Synchronizes the termination of transfers to the
|
||||
* current context.
|
||||
* @chan: channel
|
||||
*
|
||||
* Synchronizes the DMA channel termination to the current context. When this
|
||||
* function returns it is guaranteed that all transfers for previously issued
|
||||
* descriptors have stopped and and it is safe to free the memory associated
|
||||
* with them. Furthermore it is guaranteed that all complete callback functions
|
||||
* for a previously submitted descriptor have finished running and it is safe to
|
||||
* free resources accessed from within the complete callbacks.
|
||||
*/
|
||||
static void ep93xx_dma_synchronize(struct dma_chan *chan)
|
||||
{
|
||||
struct ep93xx_dma_chan *edmac = to_ep93xx_dma_chan(chan);
|
||||
|
||||
if (edmac->edma->hw_synchronize)
|
||||
edmac->edma->hw_synchronize(edmac);
|
||||
}
|
||||
|
||||
/**
|
||||
* ep93xx_dma_terminate_all - terminate all transactions
|
||||
* @chan: channel
|
||||
@@ -1323,6 +1352,7 @@ static int __init ep93xx_dma_probe(struct platform_device *pdev)
|
||||
dma_dev->device_prep_slave_sg = ep93xx_dma_prep_slave_sg;
|
||||
dma_dev->device_prep_dma_cyclic = ep93xx_dma_prep_dma_cyclic;
|
||||
dma_dev->device_config = ep93xx_dma_slave_config;
|
||||
dma_dev->device_synchronize = ep93xx_dma_synchronize;
|
||||
dma_dev->device_terminate_all = ep93xx_dma_terminate_all;
|
||||
dma_dev->device_issue_pending = ep93xx_dma_issue_pending;
|
||||
dma_dev->device_tx_status = ep93xx_dma_tx_status;
|
||||
@@ -1340,6 +1370,7 @@ static int __init ep93xx_dma_probe(struct platform_device *pdev)
|
||||
} else {
|
||||
dma_cap_set(DMA_PRIVATE, dma_dev->cap_mask);
|
||||
|
||||
edma->hw_synchronize = m2p_hw_synchronize;
|
||||
edma->hw_setup = m2p_hw_setup;
|
||||
edma->hw_shutdown = m2p_hw_shutdown;
|
||||
edma->hw_submit = m2p_hw_submit;
|
||||
|
||||
@@ -161,6 +161,7 @@ struct mv_xor_v2_device {
|
||||
struct mv_xor_v2_sw_desc *sw_desq;
|
||||
int desc_size;
|
||||
unsigned int npendings;
|
||||
unsigned int hw_queue_idx;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -213,18 +214,6 @@ static void mv_xor_v2_set_data_buffers(struct mv_xor_v2_device *xor_dev,
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Return the next available index in the DESQ.
|
||||
*/
|
||||
static int mv_xor_v2_get_desq_write_ptr(struct mv_xor_v2_device *xor_dev)
|
||||
{
|
||||
/* read the index for the next available descriptor in the DESQ */
|
||||
u32 reg = readl(xor_dev->dma_base + MV_XOR_V2_DMA_DESQ_ALLOC_OFF);
|
||||
|
||||
return ((reg >> MV_XOR_V2_DMA_DESQ_ALLOC_WRPTR_SHIFT)
|
||||
& MV_XOR_V2_DMA_DESQ_ALLOC_WRPTR_MASK);
|
||||
}
|
||||
|
||||
/*
|
||||
* notify the engine of new descriptors, and update the available index.
|
||||
*/
|
||||
@@ -257,22 +246,6 @@ static int mv_xor_v2_set_desc_size(struct mv_xor_v2_device *xor_dev)
|
||||
return MV_XOR_V2_EXT_DESC_SIZE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set the IMSG threshold
|
||||
*/
|
||||
static inline
|
||||
void mv_xor_v2_set_imsg_thrd(struct mv_xor_v2_device *xor_dev, int thrd_val)
|
||||
{
|
||||
u32 reg;
|
||||
|
||||
reg = readl(xor_dev->dma_base + MV_XOR_V2_DMA_IMSG_THRD_OFF);
|
||||
|
||||
reg &= (~MV_XOR_V2_DMA_IMSG_THRD_MASK << MV_XOR_V2_DMA_IMSG_THRD_SHIFT);
|
||||
reg |= (thrd_val << MV_XOR_V2_DMA_IMSG_THRD_SHIFT);
|
||||
|
||||
writel(reg, xor_dev->dma_base + MV_XOR_V2_DMA_IMSG_THRD_OFF);
|
||||
}
|
||||
|
||||
static irqreturn_t mv_xor_v2_interrupt_handler(int irq, void *data)
|
||||
{
|
||||
struct mv_xor_v2_device *xor_dev = data;
|
||||
@@ -288,12 +261,6 @@ static irqreturn_t mv_xor_v2_interrupt_handler(int irq, void *data)
|
||||
if (!ndescs)
|
||||
return IRQ_NONE;
|
||||
|
||||
/*
|
||||
* Update IMSG threshold, to disable new IMSG interrupts until
|
||||
* end of the tasklet
|
||||
*/
|
||||
mv_xor_v2_set_imsg_thrd(xor_dev, MV_XOR_V2_DESC_NUM);
|
||||
|
||||
/* schedule a tasklet to handle descriptors callbacks */
|
||||
tasklet_schedule(&xor_dev->irq_tasklet);
|
||||
|
||||
@@ -306,7 +273,6 @@ static irqreturn_t mv_xor_v2_interrupt_handler(int irq, void *data)
|
||||
static dma_cookie_t
|
||||
mv_xor_v2_tx_submit(struct dma_async_tx_descriptor *tx)
|
||||
{
|
||||
int desq_ptr;
|
||||
void *dest_hw_desc;
|
||||
dma_cookie_t cookie;
|
||||
struct mv_xor_v2_sw_desc *sw_desc =
|
||||
@@ -322,15 +288,15 @@ mv_xor_v2_tx_submit(struct dma_async_tx_descriptor *tx)
|
||||
spin_lock_bh(&xor_dev->lock);
|
||||
cookie = dma_cookie_assign(tx);
|
||||
|
||||
/* get the next available slot in the DESQ */
|
||||
desq_ptr = mv_xor_v2_get_desq_write_ptr(xor_dev);
|
||||
|
||||
/* copy the HW descriptor from the SW descriptor to the DESQ */
|
||||
dest_hw_desc = xor_dev->hw_desq_virt + desq_ptr;
|
||||
dest_hw_desc = xor_dev->hw_desq_virt + xor_dev->hw_queue_idx;
|
||||
|
||||
memcpy(dest_hw_desc, &sw_desc->hw_desc, xor_dev->desc_size);
|
||||
|
||||
xor_dev->npendings++;
|
||||
xor_dev->hw_queue_idx++;
|
||||
if (xor_dev->hw_queue_idx >= MV_XOR_V2_DESC_NUM)
|
||||
xor_dev->hw_queue_idx = 0;
|
||||
|
||||
spin_unlock_bh(&xor_dev->lock);
|
||||
|
||||
@@ -344,6 +310,7 @@ static struct mv_xor_v2_sw_desc *
|
||||
mv_xor_v2_prep_sw_desc(struct mv_xor_v2_device *xor_dev)
|
||||
{
|
||||
struct mv_xor_v2_sw_desc *sw_desc;
|
||||
bool found = false;
|
||||
|
||||
/* Lock the channel */
|
||||
spin_lock_bh(&xor_dev->lock);
|
||||
@@ -355,19 +322,23 @@ mv_xor_v2_prep_sw_desc(struct mv_xor_v2_device *xor_dev)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* get a free SW descriptor from the SW DESQ */
|
||||
sw_desc = list_first_entry(&xor_dev->free_sw_desc,
|
||||
struct mv_xor_v2_sw_desc, free_list);
|
||||
list_for_each_entry(sw_desc, &xor_dev->free_sw_desc, free_list) {
|
||||
if (async_tx_test_ack(&sw_desc->async_tx)) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!found) {
|
||||
spin_unlock_bh(&xor_dev->lock);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
list_del(&sw_desc->free_list);
|
||||
|
||||
/* Release the channel */
|
||||
spin_unlock_bh(&xor_dev->lock);
|
||||
|
||||
/* set the async tx descriptor */
|
||||
dma_async_tx_descriptor_init(&sw_desc->async_tx, &xor_dev->dmachan);
|
||||
sw_desc->async_tx.tx_submit = mv_xor_v2_tx_submit;
|
||||
async_tx_ack(&sw_desc->async_tx);
|
||||
|
||||
return sw_desc;
|
||||
}
|
||||
|
||||
@@ -389,6 +360,8 @@ mv_xor_v2_prep_dma_memcpy(struct dma_chan *chan, dma_addr_t dest,
|
||||
__func__, len, &src, &dest, flags);
|
||||
|
||||
sw_desc = mv_xor_v2_prep_sw_desc(xor_dev);
|
||||
if (!sw_desc)
|
||||
return NULL;
|
||||
|
||||
sw_desc->async_tx.flags = flags;
|
||||
|
||||
@@ -443,6 +416,8 @@ mv_xor_v2_prep_dma_xor(struct dma_chan *chan, dma_addr_t dest, dma_addr_t *src,
|
||||
__func__, src_cnt, len, &dest, flags);
|
||||
|
||||
sw_desc = mv_xor_v2_prep_sw_desc(xor_dev);
|
||||
if (!sw_desc)
|
||||
return NULL;
|
||||
|
||||
sw_desc->async_tx.flags = flags;
|
||||
|
||||
@@ -491,6 +466,8 @@ mv_xor_v2_prep_dma_interrupt(struct dma_chan *chan, unsigned long flags)
|
||||
container_of(chan, struct mv_xor_v2_device, dmachan);
|
||||
|
||||
sw_desc = mv_xor_v2_prep_sw_desc(xor_dev);
|
||||
if (!sw_desc)
|
||||
return NULL;
|
||||
|
||||
/* set the HW descriptor */
|
||||
hw_descriptor = &sw_desc->hw_desc;
|
||||
@@ -554,7 +531,6 @@ static void mv_xor_v2_tasklet(unsigned long data)
|
||||
{
|
||||
struct mv_xor_v2_device *xor_dev = (struct mv_xor_v2_device *) data;
|
||||
int pending_ptr, num_of_pending, i;
|
||||
struct mv_xor_v2_descriptor *next_pending_hw_desc = NULL;
|
||||
struct mv_xor_v2_sw_desc *next_pending_sw_desc = NULL;
|
||||
|
||||
dev_dbg(xor_dev->dmadev.dev, "%s %d\n", __func__, __LINE__);
|
||||
@@ -562,17 +538,10 @@ static void mv_xor_v2_tasklet(unsigned long data)
|
||||
/* get the pending descriptors parameters */
|
||||
num_of_pending = mv_xor_v2_get_pending_params(xor_dev, &pending_ptr);
|
||||
|
||||
/* next HW descriptor */
|
||||
next_pending_hw_desc = xor_dev->hw_desq_virt + pending_ptr;
|
||||
|
||||
/* loop over free descriptors */
|
||||
for (i = 0; i < num_of_pending; i++) {
|
||||
|
||||
if (pending_ptr > MV_XOR_V2_DESC_NUM)
|
||||
pending_ptr = 0;
|
||||
|
||||
if (next_pending_sw_desc != NULL)
|
||||
next_pending_hw_desc++;
|
||||
struct mv_xor_v2_descriptor *next_pending_hw_desc =
|
||||
xor_dev->hw_desq_virt + pending_ptr;
|
||||
|
||||
/* get the SW descriptor related to the HW descriptor */
|
||||
next_pending_sw_desc =
|
||||
@@ -608,15 +577,14 @@ static void mv_xor_v2_tasklet(unsigned long data)
|
||||
|
||||
/* increment the next descriptor */
|
||||
pending_ptr++;
|
||||
if (pending_ptr >= MV_XOR_V2_DESC_NUM)
|
||||
pending_ptr = 0;
|
||||
}
|
||||
|
||||
if (num_of_pending != 0) {
|
||||
/* free the descriptores */
|
||||
mv_xor_v2_free_desc_from_desq(xor_dev, num_of_pending);
|
||||
}
|
||||
|
||||
/* Update IMSG threshold, to enable new IMSG interrupts */
|
||||
mv_xor_v2_set_imsg_thrd(xor_dev, 0);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -648,9 +616,6 @@ static int mv_xor_v2_descq_init(struct mv_xor_v2_device *xor_dev)
|
||||
writel((xor_dev->hw_desq & 0xFFFF00000000) >> 32,
|
||||
xor_dev->dma_base + MV_XOR_V2_DMA_DESQ_BAHR_OFF);
|
||||
|
||||
/* enable the DMA engine */
|
||||
writel(0, xor_dev->dma_base + MV_XOR_V2_DMA_DESQ_STOP_OFF);
|
||||
|
||||
/*
|
||||
* This is a temporary solution, until we activate the
|
||||
* SMMU. Set the attributes for reading & writing data buffers
|
||||
@@ -694,6 +659,9 @@ static int mv_xor_v2_descq_init(struct mv_xor_v2_device *xor_dev)
|
||||
reg |= MV_XOR_V2_GLOB_PAUSE_AXI_TIME_DIS_VAL;
|
||||
writel(reg, xor_dev->glob_base + MV_XOR_V2_GLOB_PAUSE);
|
||||
|
||||
/* enable the DMA engine */
|
||||
writel(0, xor_dev->dma_base + MV_XOR_V2_DMA_DESQ_STOP_OFF);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -725,6 +693,10 @@ static int mv_xor_v2_probe(struct platform_device *pdev)
|
||||
|
||||
platform_set_drvdata(pdev, xor_dev);
|
||||
|
||||
ret = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(40));
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
xor_dev->clk = devm_clk_get(&pdev->dev, NULL);
|
||||
if (IS_ERR(xor_dev->clk) && PTR_ERR(xor_dev->clk) == -EPROBE_DEFER)
|
||||
return -EPROBE_DEFER;
|
||||
@@ -785,8 +757,15 @@ static int mv_xor_v2_probe(struct platform_device *pdev)
|
||||
|
||||
/* add all SW descriptors to the free list */
|
||||
for (i = 0; i < MV_XOR_V2_DESC_NUM; i++) {
|
||||
xor_dev->sw_desq[i].idx = i;
|
||||
list_add(&xor_dev->sw_desq[i].free_list,
|
||||
struct mv_xor_v2_sw_desc *sw_desc =
|
||||
xor_dev->sw_desq + i;
|
||||
sw_desc->idx = i;
|
||||
dma_async_tx_descriptor_init(&sw_desc->async_tx,
|
||||
&xor_dev->dmachan);
|
||||
sw_desc->async_tx.tx_submit = mv_xor_v2_tx_submit;
|
||||
async_tx_ack(&sw_desc->async_tx);
|
||||
|
||||
list_add(&sw_desc->free_list,
|
||||
&xor_dev->free_sw_desc);
|
||||
}
|
||||
|
||||
|
||||
@@ -117,7 +117,7 @@ struct usb_dmac {
|
||||
#define USB_DMASWR 0x0008
|
||||
#define USB_DMASWR_SWR (1 << 0)
|
||||
#define USB_DMAOR 0x0060
|
||||
#define USB_DMAOR_AE (1 << 2)
|
||||
#define USB_DMAOR_AE (1 << 1)
|
||||
#define USB_DMAOR_DME (1 << 0)
|
||||
|
||||
#define USB_DMASAR 0x0000
|
||||
|
||||
@@ -900,6 +900,12 @@ static bool ci_dpm_vblank_too_short(struct amdgpu_device *adev)
|
||||
u32 vblank_time = amdgpu_dpm_get_vblank_time(adev);
|
||||
u32 switch_limit = adev->mc.vram_type == AMDGPU_VRAM_TYPE_GDDR5 ? 450 : 300;
|
||||
|
||||
/* disable mclk switching if the refresh is >120Hz, even if the
|
||||
* blanking period would allow it
|
||||
*/
|
||||
if (amdgpu_dpm_get_vrefresh(adev) > 120)
|
||||
return true;
|
||||
|
||||
if (vblank_time < switch_limit)
|
||||
return true;
|
||||
else
|
||||
|
||||
@@ -379,7 +379,12 @@ EXPORT_SYMBOL(drm_put_dev);
|
||||
void drm_unplug_dev(struct drm_device *dev)
|
||||
{
|
||||
/* for a USB device */
|
||||
drm_dev_unregister(dev);
|
||||
if (drm_core_check_feature(dev, DRIVER_MODESET))
|
||||
drm_modeset_unregister_all(dev);
|
||||
|
||||
drm_minor_unregister(dev, DRM_MINOR_PRIMARY);
|
||||
drm_minor_unregister(dev, DRM_MINOR_RENDER);
|
||||
drm_minor_unregister(dev, DRM_MINOR_CONTROL);
|
||||
|
||||
mutex_lock(&drm_global_mutex);
|
||||
|
||||
|
||||
@@ -774,20 +774,23 @@ void psb_intel_lvds_init(struct drm_device *dev,
|
||||
if (scan->type & DRM_MODE_TYPE_PREFERRED) {
|
||||
mode_dev->panel_fixed_mode =
|
||||
drm_mode_duplicate(dev, scan);
|
||||
DRM_DEBUG_KMS("Using mode from DDC\n");
|
||||
goto out; /* FIXME: check for quirks */
|
||||
}
|
||||
}
|
||||
|
||||
/* Failed to get EDID, what about VBT? do we need this? */
|
||||
if (mode_dev->vbt_mode)
|
||||
if (dev_priv->lfp_lvds_vbt_mode) {
|
||||
mode_dev->panel_fixed_mode =
|
||||
drm_mode_duplicate(dev, mode_dev->vbt_mode);
|
||||
drm_mode_duplicate(dev, dev_priv->lfp_lvds_vbt_mode);
|
||||
|
||||
if (!mode_dev->panel_fixed_mode)
|
||||
if (dev_priv->lfp_lvds_vbt_mode)
|
||||
mode_dev->panel_fixed_mode =
|
||||
drm_mode_duplicate(dev,
|
||||
dev_priv->lfp_lvds_vbt_mode);
|
||||
if (mode_dev->panel_fixed_mode) {
|
||||
mode_dev->panel_fixed_mode->type |=
|
||||
DRM_MODE_TYPE_PREFERRED;
|
||||
DRM_DEBUG_KMS("Using mode from VBT\n");
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* If we didn't get EDID, try checking if the panel is already turned
|
||||
@@ -804,6 +807,7 @@ void psb_intel_lvds_init(struct drm_device *dev,
|
||||
if (mode_dev->panel_fixed_mode) {
|
||||
mode_dev->panel_fixed_mode->type |=
|
||||
DRM_MODE_TYPE_PREFERRED;
|
||||
DRM_DEBUG_KMS("Using pre-programmed mode\n");
|
||||
goto out; /* FIXME: check for quirks */
|
||||
}
|
||||
}
|
||||
|
||||
@@ -573,9 +573,7 @@ static int i915_load_modeset_init(struct drm_device *dev)
|
||||
if (i915_inject_load_failure())
|
||||
return -ENODEV;
|
||||
|
||||
ret = intel_bios_init(dev_priv);
|
||||
if (ret)
|
||||
DRM_INFO("failed to find VBIOS tables\n");
|
||||
intel_bios_init(dev_priv);
|
||||
|
||||
/* If we have > 1 VGA cards, then we need to arbitrate access
|
||||
* to the common VGA resources.
|
||||
|
||||
@@ -3584,7 +3584,7 @@ static inline bool intel_gmbus_is_forced_bit(struct i2c_adapter *adapter)
|
||||
extern void intel_i2c_reset(struct drm_device *dev);
|
||||
|
||||
/* intel_bios.c */
|
||||
int intel_bios_init(struct drm_i915_private *dev_priv);
|
||||
void intel_bios_init(struct drm_i915_private *dev_priv);
|
||||
bool intel_bios_is_valid_vbt(const void *buf, size_t size);
|
||||
bool intel_bios_is_tv_present(struct drm_i915_private *dev_priv);
|
||||
bool intel_bios_is_lvds_present(struct drm_i915_private *dev_priv, u8 *i2c_pin);
|
||||
|
||||
@@ -1332,6 +1332,7 @@ parse_device_mapping(struct drm_i915_private *dev_priv,
|
||||
return;
|
||||
}
|
||||
|
||||
/* Common defaults which may be overridden by VBT. */
|
||||
static void
|
||||
init_vbt_defaults(struct drm_i915_private *dev_priv)
|
||||
{
|
||||
@@ -1368,6 +1369,18 @@ init_vbt_defaults(struct drm_i915_private *dev_priv)
|
||||
&dev_priv->vbt.ddi_port_info[port];
|
||||
|
||||
info->hdmi_level_shift = HDMI_LEVEL_SHIFT_UNKNOWN;
|
||||
}
|
||||
}
|
||||
|
||||
/* Defaults to initialize only if there is no VBT. */
|
||||
static void
|
||||
init_vbt_missing_defaults(struct drm_i915_private *dev_priv)
|
||||
{
|
||||
enum port port;
|
||||
|
||||
for (port = PORT_A; port < I915_MAX_PORTS; port++) {
|
||||
struct ddi_vbt_port_info *info =
|
||||
&dev_priv->vbt.ddi_port_info[port];
|
||||
|
||||
info->supports_dvi = (port != PORT_A && port != PORT_E);
|
||||
info->supports_hdmi = info->supports_dvi;
|
||||
@@ -1450,36 +1463,35 @@ static const struct vbt_header *find_vbt(void __iomem *bios, size_t size)
|
||||
* intel_bios_init - find VBT and initialize settings from the BIOS
|
||||
* @dev_priv: i915 device instance
|
||||
*
|
||||
* Loads the Video BIOS and checks that the VBT exists. Sets scratch registers
|
||||
* to appropriate values.
|
||||
*
|
||||
* Returns 0 on success, nonzero on failure.
|
||||
* Parse and initialize settings from the Video BIOS Tables (VBT). If the VBT
|
||||
* was not found in ACPI OpRegion, try to find it in PCI ROM first. Also
|
||||
* initialize some defaults if the VBT is not present at all.
|
||||
*/
|
||||
int
|
||||
intel_bios_init(struct drm_i915_private *dev_priv)
|
||||
void intel_bios_init(struct drm_i915_private *dev_priv)
|
||||
{
|
||||
struct pci_dev *pdev = dev_priv->drm.pdev;
|
||||
const struct vbt_header *vbt = dev_priv->opregion.vbt;
|
||||
const struct bdb_header *bdb;
|
||||
u8 __iomem *bios = NULL;
|
||||
|
||||
if (HAS_PCH_NOP(dev_priv))
|
||||
return -ENODEV;
|
||||
if (HAS_PCH_NOP(dev_priv)) {
|
||||
DRM_DEBUG_KMS("Skipping VBT init due to disabled display.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
init_vbt_defaults(dev_priv);
|
||||
|
||||
/* If the OpRegion does not have VBT, look in PCI ROM. */
|
||||
if (!vbt) {
|
||||
size_t size;
|
||||
|
||||
bios = pci_map_rom(pdev, &size);
|
||||
if (!bios)
|
||||
return -1;
|
||||
goto out;
|
||||
|
||||
vbt = find_vbt(bios, size);
|
||||
if (!vbt) {
|
||||
pci_unmap_rom(pdev, bios);
|
||||
return -1;
|
||||
}
|
||||
if (!vbt)
|
||||
goto out;
|
||||
|
||||
DRM_DEBUG_KMS("Found valid VBT in PCI ROM\n");
|
||||
}
|
||||
@@ -1504,10 +1516,14 @@ intel_bios_init(struct drm_i915_private *dev_priv)
|
||||
parse_mipi_sequence(dev_priv, bdb);
|
||||
parse_ddi_ports(dev_priv, bdb);
|
||||
|
||||
out:
|
||||
if (!vbt) {
|
||||
DRM_INFO("Failed to find VBIOS tables (VBT)\n");
|
||||
init_vbt_missing_defaults(dev_priv);
|
||||
}
|
||||
|
||||
if (bios)
|
||||
pci_unmap_rom(pdev, bios);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -218,9 +218,10 @@ mdp5_plane_duplicate_state(struct drm_plane *plane)
|
||||
|
||||
mdp5_state = kmemdup(to_mdp5_plane_state(plane->state),
|
||||
sizeof(*mdp5_state), GFP_KERNEL);
|
||||
if (!mdp5_state)
|
||||
return NULL;
|
||||
|
||||
if (mdp5_state && mdp5_state->base.fb)
|
||||
drm_framebuffer_reference(mdp5_state->base.fb);
|
||||
__drm_atomic_helper_plane_duplicate_state(plane, &mdp5_state->base);
|
||||
|
||||
mdp5_state->mode_changed = false;
|
||||
mdp5_state->pending = false;
|
||||
|
||||
@@ -801,6 +801,7 @@ static struct drm_driver msm_driver = {
|
||||
.prime_fd_to_handle = drm_gem_prime_fd_to_handle,
|
||||
.gem_prime_export = drm_gem_prime_export,
|
||||
.gem_prime_import = drm_gem_prime_import,
|
||||
.gem_prime_res_obj = msm_gem_prime_res_obj,
|
||||
.gem_prime_pin = msm_gem_prime_pin,
|
||||
.gem_prime_unpin = msm_gem_prime_unpin,
|
||||
.gem_prime_get_sg_table = msm_gem_prime_get_sg_table,
|
||||
|
||||
@@ -203,6 +203,7 @@ struct sg_table *msm_gem_prime_get_sg_table(struct drm_gem_object *obj);
|
||||
void *msm_gem_prime_vmap(struct drm_gem_object *obj);
|
||||
void msm_gem_prime_vunmap(struct drm_gem_object *obj, void *vaddr);
|
||||
int msm_gem_prime_mmap(struct drm_gem_object *obj, struct vm_area_struct *vma);
|
||||
struct reservation_object *msm_gem_prime_res_obj(struct drm_gem_object *obj);
|
||||
struct drm_gem_object *msm_gem_prime_import_sg_table(struct drm_device *dev,
|
||||
struct dma_buf_attachment *attach, struct sg_table *sg);
|
||||
int msm_gem_prime_pin(struct drm_gem_object *obj);
|
||||
|
||||
@@ -70,3 +70,10 @@ void msm_gem_prime_unpin(struct drm_gem_object *obj)
|
||||
if (!obj->import_attach)
|
||||
msm_gem_put_pages(obj);
|
||||
}
|
||||
|
||||
struct reservation_object *msm_gem_prime_res_obj(struct drm_gem_object *obj)
|
||||
{
|
||||
struct msm_gem_object *msm_obj = to_msm_bo(obj);
|
||||
|
||||
return msm_obj->resv;
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||
struct nvkm_alarm {
|
||||
struct list_head head;
|
||||
struct list_head exec;
|
||||
u64 timestamp;
|
||||
void (*func)(struct nvkm_alarm *);
|
||||
};
|
||||
|
||||
@@ -50,7 +50,8 @@ nvkm_timer_alarm_trigger(struct nvkm_timer *tmr)
|
||||
/* Move to completed list. We'll drop the lock before
|
||||
* executing the callback so it can reschedule itself.
|
||||
*/
|
||||
list_move_tail(&alarm->head, &exec);
|
||||
list_del_init(&alarm->head);
|
||||
list_add(&alarm->exec, &exec);
|
||||
}
|
||||
|
||||
/* Shut down interrupt if no more pending alarms. */
|
||||
@@ -59,8 +60,8 @@ nvkm_timer_alarm_trigger(struct nvkm_timer *tmr)
|
||||
spin_unlock_irqrestore(&tmr->lock, flags);
|
||||
|
||||
/* Execute completed callbacks. */
|
||||
list_for_each_entry_safe(alarm, atemp, &exec, head) {
|
||||
list_del_init(&alarm->head);
|
||||
list_for_each_entry_safe(alarm, atemp, &exec, exec) {
|
||||
list_del(&alarm->exec);
|
||||
alarm->func(alarm);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -776,6 +776,12 @@ bool ci_dpm_vblank_too_short(struct radeon_device *rdev)
|
||||
u32 vblank_time = r600_dpm_get_vblank_time(rdev);
|
||||
u32 switch_limit = pi->mem_gddr5 ? 450 : 300;
|
||||
|
||||
/* disable mclk switching if the refresh is >120Hz, even if the
|
||||
* blanking period would allow it
|
||||
*/
|
||||
if (r600_dpm_get_vrefresh(rdev) > 120)
|
||||
return true;
|
||||
|
||||
if (vblank_time < switch_limit)
|
||||
return true;
|
||||
else
|
||||
|
||||
@@ -7416,7 +7416,7 @@ static inline void cik_irq_ack(struct radeon_device *rdev)
|
||||
WREG32(DC_HPD5_INT_CONTROL, tmp);
|
||||
}
|
||||
if (rdev->irq.stat_regs.cik.disp_int_cont5 & DC_HPD6_INTERRUPT) {
|
||||
tmp = RREG32(DC_HPD5_INT_CONTROL);
|
||||
tmp = RREG32(DC_HPD6_INT_CONTROL);
|
||||
tmp |= DC_HPDx_INT_ACK;
|
||||
WREG32(DC_HPD6_INT_CONTROL, tmp);
|
||||
}
|
||||
@@ -7446,7 +7446,7 @@ static inline void cik_irq_ack(struct radeon_device *rdev)
|
||||
WREG32(DC_HPD5_INT_CONTROL, tmp);
|
||||
}
|
||||
if (rdev->irq.stat_regs.cik.disp_int_cont5 & DC_HPD6_RX_INTERRUPT) {
|
||||
tmp = RREG32(DC_HPD5_INT_CONTROL);
|
||||
tmp = RREG32(DC_HPD6_INT_CONTROL);
|
||||
tmp |= DC_HPDx_RX_INT_ACK;
|
||||
WREG32(DC_HPD6_INT_CONTROL, tmp);
|
||||
}
|
||||
|
||||
@@ -4933,7 +4933,7 @@ static void evergreen_irq_ack(struct radeon_device *rdev)
|
||||
WREG32(DC_HPD5_INT_CONTROL, tmp);
|
||||
}
|
||||
if (rdev->irq.stat_regs.evergreen.disp_int_cont5 & DC_HPD6_INTERRUPT) {
|
||||
tmp = RREG32(DC_HPD5_INT_CONTROL);
|
||||
tmp = RREG32(DC_HPD6_INT_CONTROL);
|
||||
tmp |= DC_HPDx_INT_ACK;
|
||||
WREG32(DC_HPD6_INT_CONTROL, tmp);
|
||||
}
|
||||
@@ -4964,7 +4964,7 @@ static void evergreen_irq_ack(struct radeon_device *rdev)
|
||||
WREG32(DC_HPD5_INT_CONTROL, tmp);
|
||||
}
|
||||
if (rdev->irq.stat_regs.evergreen.disp_int_cont5 & DC_HPD6_RX_INTERRUPT) {
|
||||
tmp = RREG32(DC_HPD5_INT_CONTROL);
|
||||
tmp = RREG32(DC_HPD6_INT_CONTROL);
|
||||
tmp |= DC_HPDx_RX_INT_ACK;
|
||||
WREG32(DC_HPD6_INT_CONTROL, tmp);
|
||||
}
|
||||
|
||||
@@ -3995,7 +3995,7 @@ static void r600_irq_ack(struct radeon_device *rdev)
|
||||
WREG32(DC_HPD5_INT_CONTROL, tmp);
|
||||
}
|
||||
if (rdev->irq.stat_regs.r600.disp_int_cont2 & DC_HPD6_INTERRUPT) {
|
||||
tmp = RREG32(DC_HPD5_INT_CONTROL);
|
||||
tmp = RREG32(DC_HPD6_INT_CONTROL);
|
||||
tmp |= DC_HPDx_INT_ACK;
|
||||
WREG32(DC_HPD6_INT_CONTROL, tmp);
|
||||
}
|
||||
|
||||
@@ -97,9 +97,10 @@
|
||||
* 2.46.0 - Add PFP_SYNC_ME support on evergreen
|
||||
* 2.47.0 - Add UVD_NO_OP register support
|
||||
* 2.48.0 - TA_CS_BC_BASE_ADDR allowed on SI
|
||||
* 2.49.0 - DRM_RADEON_GEM_INFO ioctl returns correct vram_size/visible values
|
||||
*/
|
||||
#define KMS_DRIVER_MAJOR 2
|
||||
#define KMS_DRIVER_MINOR 48
|
||||
#define KMS_DRIVER_MINOR 49
|
||||
#define KMS_DRIVER_PATCHLEVEL 0
|
||||
int radeon_driver_load_kms(struct drm_device *dev, unsigned long flags);
|
||||
int radeon_driver_unload_kms(struct drm_device *dev);
|
||||
|
||||
@@ -220,8 +220,8 @@ int radeon_gem_info_ioctl(struct drm_device *dev, void *data,
|
||||
|
||||
man = &rdev->mman.bdev.man[TTM_PL_VRAM];
|
||||
|
||||
args->vram_size = rdev->mc.real_vram_size;
|
||||
args->vram_visible = (u64)man->size << PAGE_SHIFT;
|
||||
args->vram_size = (u64)man->size << PAGE_SHIFT;
|
||||
args->vram_visible = rdev->mc.visible_vram_size;
|
||||
args->vram_visible -= rdev->vram_pin_size;
|
||||
args->gart_size = rdev->mc.gtt_size;
|
||||
args->gart_size -= rdev->gart_pin_size;
|
||||
|
||||
@@ -6330,7 +6330,7 @@ static inline void si_irq_ack(struct radeon_device *rdev)
|
||||
WREG32(DC_HPD5_INT_CONTROL, tmp);
|
||||
}
|
||||
if (rdev->irq.stat_regs.evergreen.disp_int_cont5 & DC_HPD6_INTERRUPT) {
|
||||
tmp = RREG32(DC_HPD5_INT_CONTROL);
|
||||
tmp = RREG32(DC_HPD6_INT_CONTROL);
|
||||
tmp |= DC_HPDx_INT_ACK;
|
||||
WREG32(DC_HPD6_INT_CONTROL, tmp);
|
||||
}
|
||||
@@ -6361,7 +6361,7 @@ static inline void si_irq_ack(struct radeon_device *rdev)
|
||||
WREG32(DC_HPD5_INT_CONTROL, tmp);
|
||||
}
|
||||
if (rdev->irq.stat_regs.evergreen.disp_int_cont5 & DC_HPD6_RX_INTERRUPT) {
|
||||
tmp = RREG32(DC_HPD5_INT_CONTROL);
|
||||
tmp = RREG32(DC_HPD6_INT_CONTROL);
|
||||
tmp |= DC_HPDx_RX_INT_ACK;
|
||||
WREG32(DC_HPD6_INT_CONTROL, tmp);
|
||||
}
|
||||
|
||||
@@ -1602,7 +1602,14 @@ EXPORT_SYMBOL(ttm_bo_unmap_virtual);
|
||||
int ttm_bo_wait(struct ttm_buffer_object *bo,
|
||||
bool interruptible, bool no_wait)
|
||||
{
|
||||
long timeout = no_wait ? 0 : 15 * HZ;
|
||||
long timeout = 15 * HZ;
|
||||
|
||||
if (no_wait) {
|
||||
if (reservation_object_test_signaled_rcu(bo->resv, true))
|
||||
return 0;
|
||||
else
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
timeout = reservation_object_wait_timeout_rcu(bo->resv, true,
|
||||
interruptible, timeout);
|
||||
|
||||
@@ -368,6 +368,8 @@ static void *vmw_local_fifo_reserve(struct vmw_private *dev_priv,
|
||||
return fifo_state->static_buffer;
|
||||
else {
|
||||
fifo_state->dynamic_buffer = vmalloc(bytes);
|
||||
if (!fifo_state->dynamic_buffer)
|
||||
goto out_err;
|
||||
return fifo_state->dynamic_buffer;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1275,11 +1275,14 @@ int vmw_gb_surface_define_ioctl(struct drm_device *dev, void *data,
|
||||
struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile;
|
||||
int ret;
|
||||
uint32_t size;
|
||||
uint32_t backup_handle;
|
||||
uint32_t backup_handle = 0;
|
||||
|
||||
if (req->multisample_count != 0)
|
||||
return -EINVAL;
|
||||
|
||||
if (req->mip_levels > DRM_VMW_MAX_MIP_LEVELS)
|
||||
return -EINVAL;
|
||||
|
||||
if (unlikely(vmw_user_surface_size == 0))
|
||||
vmw_user_surface_size = ttm_round_pot(sizeof(*user_srf)) +
|
||||
128;
|
||||
@@ -1315,12 +1318,16 @@ int vmw_gb_surface_define_ioctl(struct drm_device *dev, void *data,
|
||||
ret = vmw_user_dmabuf_lookup(tfile, req->buffer_handle,
|
||||
&res->backup,
|
||||
&user_srf->backup_base);
|
||||
if (ret == 0 && res->backup->base.num_pages * PAGE_SIZE <
|
||||
res->backup_size) {
|
||||
DRM_ERROR("Surface backup buffer is too small.\n");
|
||||
vmw_dmabuf_unreference(&res->backup);
|
||||
ret = -EINVAL;
|
||||
goto out_unlock;
|
||||
if (ret == 0) {
|
||||
if (res->backup->base.num_pages * PAGE_SIZE <
|
||||
res->backup_size) {
|
||||
DRM_ERROR("Surface backup buffer is too small.\n");
|
||||
vmw_dmabuf_unreference(&res->backup);
|
||||
ret = -EINVAL;
|
||||
goto out_unlock;
|
||||
} else {
|
||||
backup_handle = req->buffer_handle;
|
||||
}
|
||||
}
|
||||
} else if (req->drm_surface_flags & drm_vmw_surface_flag_create_buffer)
|
||||
ret = vmw_user_dmabuf_alloc(dev_priv, tfile,
|
||||
|
||||
@@ -28,6 +28,8 @@
|
||||
#define UHID_NAME "uhid"
|
||||
#define UHID_BUFSIZE 32
|
||||
|
||||
static DEFINE_MUTEX(uhid_open_mutex);
|
||||
|
||||
struct uhid_device {
|
||||
struct mutex devlock;
|
||||
bool running;
|
||||
@@ -142,15 +144,26 @@ static void uhid_hid_stop(struct hid_device *hid)
|
||||
static int uhid_hid_open(struct hid_device *hid)
|
||||
{
|
||||
struct uhid_device *uhid = hid->driver_data;
|
||||
int retval = 0;
|
||||
|
||||
return uhid_queue_event(uhid, UHID_OPEN);
|
||||
mutex_lock(&uhid_open_mutex);
|
||||
if (!hid->open++) {
|
||||
retval = uhid_queue_event(uhid, UHID_OPEN);
|
||||
if (retval)
|
||||
hid->open--;
|
||||
}
|
||||
mutex_unlock(&uhid_open_mutex);
|
||||
return retval;
|
||||
}
|
||||
|
||||
static void uhid_hid_close(struct hid_device *hid)
|
||||
{
|
||||
struct uhid_device *uhid = hid->driver_data;
|
||||
|
||||
uhid_queue_event(uhid, UHID_CLOSE);
|
||||
mutex_lock(&uhid_open_mutex);
|
||||
if (!--hid->open)
|
||||
uhid_queue_event(uhid, UHID_CLOSE);
|
||||
mutex_unlock(&uhid_open_mutex);
|
||||
}
|
||||
|
||||
static int uhid_hid_parse(struct hid_device *hid)
|
||||
|
||||
@@ -1400,37 +1400,38 @@ static int wacom_tpc_irq(struct wacom_wac *wacom, size_t len)
|
||||
{
|
||||
unsigned char *data = wacom->data;
|
||||
|
||||
if (wacom->pen_input)
|
||||
if (wacom->pen_input) {
|
||||
dev_dbg(wacom->pen_input->dev.parent,
|
||||
"%s: received report #%d\n", __func__, data[0]);
|
||||
else if (wacom->touch_input)
|
||||
|
||||
if (len == WACOM_PKGLEN_PENABLED ||
|
||||
data[0] == WACOM_REPORT_PENABLED)
|
||||
return wacom_tpc_pen(wacom);
|
||||
}
|
||||
else if (wacom->touch_input) {
|
||||
dev_dbg(wacom->touch_input->dev.parent,
|
||||
"%s: received report #%d\n", __func__, data[0]);
|
||||
|
||||
switch (len) {
|
||||
case WACOM_PKGLEN_TPC1FG:
|
||||
return wacom_tpc_single_touch(wacom, len);
|
||||
|
||||
case WACOM_PKGLEN_TPC2FG:
|
||||
return wacom_tpc_mt_touch(wacom);
|
||||
|
||||
case WACOM_PKGLEN_PENABLED:
|
||||
return wacom_tpc_pen(wacom);
|
||||
|
||||
default:
|
||||
switch (data[0]) {
|
||||
case WACOM_REPORT_TPC1FG:
|
||||
case WACOM_REPORT_TPCHID:
|
||||
case WACOM_REPORT_TPCST:
|
||||
case WACOM_REPORT_TPC1FGE:
|
||||
switch (len) {
|
||||
case WACOM_PKGLEN_TPC1FG:
|
||||
return wacom_tpc_single_touch(wacom, len);
|
||||
|
||||
case WACOM_REPORT_TPCMT:
|
||||
case WACOM_REPORT_TPCMT2:
|
||||
return wacom_mt_touch(wacom);
|
||||
case WACOM_PKGLEN_TPC2FG:
|
||||
return wacom_tpc_mt_touch(wacom);
|
||||
|
||||
case WACOM_REPORT_PENABLED:
|
||||
return wacom_tpc_pen(wacom);
|
||||
default:
|
||||
switch (data[0]) {
|
||||
case WACOM_REPORT_TPC1FG:
|
||||
case WACOM_REPORT_TPCHID:
|
||||
case WACOM_REPORT_TPCST:
|
||||
case WACOM_REPORT_TPC1FGE:
|
||||
return wacom_tpc_single_touch(wacom, len);
|
||||
|
||||
case WACOM_REPORT_TPCMT:
|
||||
case WACOM_REPORT_TPCMT2:
|
||||
return wacom_mt_touch(wacom);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -178,22 +178,39 @@ static int usb_read(struct i2c_adapter *adapter, int cmd,
|
||||
int value, int index, void *data, int len)
|
||||
{
|
||||
struct i2c_tiny_usb *dev = (struct i2c_tiny_usb *)adapter->algo_data;
|
||||
void *dmadata = kmalloc(len, GFP_KERNEL);
|
||||
int ret;
|
||||
|
||||
if (!dmadata)
|
||||
return -ENOMEM;
|
||||
|
||||
/* do control transfer */
|
||||
return usb_control_msg(dev->usb_dev, usb_rcvctrlpipe(dev->usb_dev, 0),
|
||||
ret = usb_control_msg(dev->usb_dev, usb_rcvctrlpipe(dev->usb_dev, 0),
|
||||
cmd, USB_TYPE_VENDOR | USB_RECIP_INTERFACE |
|
||||
USB_DIR_IN, value, index, data, len, 2000);
|
||||
USB_DIR_IN, value, index, dmadata, len, 2000);
|
||||
|
||||
memcpy(data, dmadata, len);
|
||||
kfree(dmadata);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int usb_write(struct i2c_adapter *adapter, int cmd,
|
||||
int value, int index, void *data, int len)
|
||||
{
|
||||
struct i2c_tiny_usb *dev = (struct i2c_tiny_usb *)adapter->algo_data;
|
||||
void *dmadata = kmemdup(data, len, GFP_KERNEL);
|
||||
int ret;
|
||||
|
||||
if (!dmadata)
|
||||
return -ENOMEM;
|
||||
|
||||
/* do control transfer */
|
||||
return usb_control_msg(dev->usb_dev, usb_sndctrlpipe(dev->usb_dev, 0),
|
||||
ret = usb_control_msg(dev->usb_dev, usb_sndctrlpipe(dev->usb_dev, 0),
|
||||
cmd, USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
|
||||
value, index, data, len, 2000);
|
||||
value, index, dmadata, len, 2000);
|
||||
|
||||
kfree(dmadata);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void i2c_tiny_usb_free(struct i2c_tiny_usb *dev)
|
||||
|
||||
@@ -143,7 +143,7 @@ static void iproc_adc_reg_dump(struct iio_dev *indio_dev)
|
||||
iproc_adc_dbg_reg(dev, adc_priv, IPROC_SOFT_BYPASS_DATA);
|
||||
}
|
||||
|
||||
static irqreturn_t iproc_adc_interrupt_handler(int irq, void *data)
|
||||
static irqreturn_t iproc_adc_interrupt_thread(int irq, void *data)
|
||||
{
|
||||
u32 channel_intr_status;
|
||||
u32 intr_status;
|
||||
@@ -167,7 +167,7 @@ static irqreturn_t iproc_adc_interrupt_handler(int irq, void *data)
|
||||
return IRQ_NONE;
|
||||
}
|
||||
|
||||
static irqreturn_t iproc_adc_interrupt_thread(int irq, void *data)
|
||||
static irqreturn_t iproc_adc_interrupt_handler(int irq, void *data)
|
||||
{
|
||||
irqreturn_t retval = IRQ_NONE;
|
||||
struct iproc_adc_priv *adc_priv;
|
||||
@@ -181,7 +181,7 @@ static irqreturn_t iproc_adc_interrupt_thread(int irq, void *data)
|
||||
adc_priv = iio_priv(indio_dev);
|
||||
|
||||
regmap_read(adc_priv->regmap, IPROC_INTERRUPT_STATUS, &intr_status);
|
||||
dev_dbg(&indio_dev->dev, "iproc_adc_interrupt_thread(),INTRPT_STS:%x\n",
|
||||
dev_dbg(&indio_dev->dev, "iproc_adc_interrupt_handler(),INTRPT_STS:%x\n",
|
||||
intr_status);
|
||||
|
||||
intr_channels = (intr_status & IPROC_ADC_INTR_MASK) >> IPROC_ADC_INTR;
|
||||
@@ -566,8 +566,8 @@ static int iproc_adc_probe(struct platform_device *pdev)
|
||||
}
|
||||
|
||||
ret = devm_request_threaded_irq(&pdev->dev, adc_priv->irqno,
|
||||
iproc_adc_interrupt_thread,
|
||||
iproc_adc_interrupt_handler,
|
||||
iproc_adc_interrupt_thread,
|
||||
IRQF_SHARED, "iproc-adc", indio_dev);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "request_irq error %d\n", ret);
|
||||
|
||||
@@ -74,9 +74,9 @@ static const int int_time_mapping[] = {100000, 50000, 200000, 400000};
|
||||
static const struct reg_field reg_field_it =
|
||||
REG_FIELD(LTR501_ALS_MEAS_RATE, 3, 4);
|
||||
static const struct reg_field reg_field_als_intr =
|
||||
REG_FIELD(LTR501_INTR, 0, 0);
|
||||
static const struct reg_field reg_field_ps_intr =
|
||||
REG_FIELD(LTR501_INTR, 1, 1);
|
||||
static const struct reg_field reg_field_ps_intr =
|
||||
REG_FIELD(LTR501_INTR, 0, 0);
|
||||
static const struct reg_field reg_field_als_rate =
|
||||
REG_FIELD(LTR501_ALS_MEAS_RATE, 0, 2);
|
||||
static const struct reg_field reg_field_ps_rate =
|
||||
|
||||
@@ -40,9 +40,9 @@
|
||||
#define AS3935_AFE_PWR_BIT BIT(0)
|
||||
|
||||
#define AS3935_INT 0x03
|
||||
#define AS3935_INT_MASK 0x07
|
||||
#define AS3935_INT_MASK 0x0f
|
||||
#define AS3935_EVENT_INT BIT(3)
|
||||
#define AS3935_NOISE_INT BIT(1)
|
||||
#define AS3935_NOISE_INT BIT(0)
|
||||
|
||||
#define AS3935_DATA 0x07
|
||||
#define AS3935_DATA_MASK 0x3F
|
||||
@@ -215,7 +215,7 @@ static irqreturn_t as3935_trigger_handler(int irq, void *private)
|
||||
|
||||
st->buffer[0] = val & AS3935_DATA_MASK;
|
||||
iio_push_to_buffers_with_timestamp(indio_dev, &st->buffer,
|
||||
pf->timestamp);
|
||||
iio_get_time_ns(indio_dev));
|
||||
err_read:
|
||||
iio_trigger_notify_done(indio_dev->trig);
|
||||
|
||||
@@ -244,7 +244,7 @@ static void as3935_event_work(struct work_struct *work)
|
||||
|
||||
switch (val) {
|
||||
case AS3935_EVENT_INT:
|
||||
iio_trigger_poll(st->trig);
|
||||
iio_trigger_poll_chained(st->trig);
|
||||
break;
|
||||
case AS3935_NOISE_INT:
|
||||
dev_warn(&st->spi->dev, "noise level is too high\n");
|
||||
|
||||
@@ -2366,8 +2366,11 @@ send_last:
|
||||
ret = hfi1_rvt_get_rwqe(qp, 1);
|
||||
if (ret < 0)
|
||||
goto nack_op_err;
|
||||
if (!ret)
|
||||
if (!ret) {
|
||||
/* peer will send again */
|
||||
rvt_put_ss(&qp->r_sge);
|
||||
goto rnr_nak;
|
||||
}
|
||||
wc.ex.imm_data = ohdr->u.rc.imm_data;
|
||||
wc.wc_flags = IB_WC_WITH_IMM;
|
||||
goto send_last;
|
||||
|
||||
@@ -2067,8 +2067,10 @@ send_last:
|
||||
ret = qib_get_rwqe(qp, 1);
|
||||
if (ret < 0)
|
||||
goto nack_op_err;
|
||||
if (!ret)
|
||||
if (!ret) {
|
||||
rvt_put_ss(&qp->r_sge);
|
||||
goto rnr_nak;
|
||||
}
|
||||
wc.ex.imm_data = ohdr->u.rc.imm_data;
|
||||
hdrsize += 4;
|
||||
wc.wc_flags = IB_WC_WITH_IMM;
|
||||
|
||||
@@ -1118,8 +1118,10 @@ static int elantech_get_resolution_v4(struct psmouse *psmouse,
|
||||
* Asus UX32VD 0x361f02 00, 15, 0e clickpad
|
||||
* Avatar AVIU-145A2 0x361f00 ? clickpad
|
||||
* Fujitsu LIFEBOOK E544 0x470f00 d0, 12, 09 2 hw buttons
|
||||
* Fujitsu LIFEBOOK E546 0x470f00 50, 12, 09 2 hw buttons
|
||||
* Fujitsu LIFEBOOK E547 0x470f00 50, 12, 09 2 hw buttons
|
||||
* Fujitsu LIFEBOOK E554 0x570f01 40, 14, 0c 2 hw buttons
|
||||
* Fujitsu LIFEBOOK E557 0x570f01 40, 14, 0c 2 hw buttons
|
||||
* Fujitsu T725 0x470f01 05, 12, 09 2 hw buttons
|
||||
* Fujitsu H730 0x570f00 c0, 14, 0c 3 hw buttons (**)
|
||||
* Gigabyte U2442 0x450f01 58, 17, 0c 2 hw buttons
|
||||
@@ -1524,6 +1526,13 @@ static const struct dmi_system_id elantech_dmi_force_crc_enabled[] = {
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "LIFEBOOK E544"),
|
||||
},
|
||||
},
|
||||
{
|
||||
/* Fujitsu LIFEBOOK E546 does not work with crc_enabled == 0 */
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "LIFEBOOK E546"),
|
||||
},
|
||||
},
|
||||
{
|
||||
/* Fujitsu LIFEBOOK E547 does not work with crc_enabled == 0 */
|
||||
.matches = {
|
||||
@@ -1545,6 +1554,13 @@ static const struct dmi_system_id elantech_dmi_force_crc_enabled[] = {
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "LIFEBOOK E556"),
|
||||
},
|
||||
},
|
||||
{
|
||||
/* Fujitsu LIFEBOOK E557 does not work with crc_enabled == 0 */
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "LIFEBOOK E557"),
|
||||
},
|
||||
},
|
||||
{
|
||||
/* Fujitsu LIFEBOOK U745 does not work with crc_enabled == 0 */
|
||||
.matches = {
|
||||
|
||||
@@ -80,8 +80,6 @@ void dm_set_md_type(struct mapped_device *md, unsigned type);
|
||||
unsigned dm_get_md_type(struct mapped_device *md);
|
||||
struct target_type *dm_get_immutable_target_type(struct mapped_device *md);
|
||||
|
||||
int dm_setup_md_queue(struct mapped_device *md, struct dm_table *t);
|
||||
|
||||
/*
|
||||
* To check the return value from dm_table_find_target().
|
||||
*/
|
||||
|
||||
@@ -768,7 +768,7 @@ config PANEL_BOOT_MESSAGE
|
||||
|
||||
config UID_SYS_STATS
|
||||
bool "Per-UID statistics"
|
||||
depends on PROFILING
|
||||
depends on PROFILING && TASK_XACCT && TASK_IO_ACCOUNTING
|
||||
help
|
||||
Per UID based cpu time statistics exported to /proc/uid_cputime
|
||||
Per UID based io statistics exported to /proc/uid_io
|
||||
|
||||
@@ -155,11 +155,8 @@ static long afu_ioctl_start_work(struct cxl_context *ctx,
|
||||
|
||||
/* Do this outside the status_mutex to avoid a circular dependency with
|
||||
* the locking in cxl_mmap_fault() */
|
||||
if (copy_from_user(&work, uwork,
|
||||
sizeof(struct cxl_ioctl_start_work))) {
|
||||
rc = -EFAULT;
|
||||
goto out;
|
||||
}
|
||||
if (copy_from_user(&work, uwork, sizeof(work)))
|
||||
return -EFAULT;
|
||||
|
||||
mutex_lock(&ctx->status_mutex);
|
||||
if (ctx->status != OPENED) {
|
||||
|
||||
@@ -1066,13 +1066,16 @@ int cxl_native_register_psl_err_irq(struct cxl *adapter)
|
||||
|
||||
void cxl_native_release_psl_err_irq(struct cxl *adapter)
|
||||
{
|
||||
if (adapter->native->err_virq != irq_find_mapping(NULL, adapter->native->err_hwirq))
|
||||
if (adapter->native->err_virq == 0 ||
|
||||
adapter->native->err_virq !=
|
||||
irq_find_mapping(NULL, adapter->native->err_hwirq))
|
||||
return;
|
||||
|
||||
cxl_p1_write(adapter, CXL_PSL_ErrIVTE, 0x0000000000000000);
|
||||
cxl_unmap_irq(adapter->native->err_virq, adapter);
|
||||
cxl_ops->release_one_irq(adapter, adapter->native->err_hwirq);
|
||||
kfree(adapter->irq_name);
|
||||
adapter->native->err_virq = 0;
|
||||
}
|
||||
|
||||
int cxl_native_register_serr_irq(struct cxl_afu *afu)
|
||||
@@ -1102,13 +1105,15 @@ int cxl_native_register_serr_irq(struct cxl_afu *afu)
|
||||
|
||||
void cxl_native_release_serr_irq(struct cxl_afu *afu)
|
||||
{
|
||||
if (afu->serr_virq != irq_find_mapping(NULL, afu->serr_hwirq))
|
||||
if (afu->serr_virq == 0 ||
|
||||
afu->serr_virq != irq_find_mapping(NULL, afu->serr_hwirq))
|
||||
return;
|
||||
|
||||
cxl_p1n_write(afu, CXL_PSL_SERR_An, 0x0000000000000000);
|
||||
cxl_unmap_irq(afu->serr_virq, afu);
|
||||
cxl_ops->release_one_irq(afu->adapter, afu->serr_hwirq);
|
||||
kfree(afu->err_irq_name);
|
||||
afu->serr_virq = 0;
|
||||
}
|
||||
|
||||
int cxl_native_register_psl_irq(struct cxl_afu *afu)
|
||||
@@ -1131,12 +1136,15 @@ int cxl_native_register_psl_irq(struct cxl_afu *afu)
|
||||
|
||||
void cxl_native_release_psl_irq(struct cxl_afu *afu)
|
||||
{
|
||||
if (afu->native->psl_virq != irq_find_mapping(NULL, afu->native->psl_hwirq))
|
||||
if (afu->native->psl_virq == 0 ||
|
||||
afu->native->psl_virq !=
|
||||
irq_find_mapping(NULL, afu->native->psl_hwirq))
|
||||
return;
|
||||
|
||||
cxl_unmap_irq(afu->native->psl_virq, afu);
|
||||
cxl_ops->release_one_irq(afu->adapter, afu->native->psl_hwirq);
|
||||
kfree(afu->psl_irq_name);
|
||||
afu->native->psl_virq = 0;
|
||||
}
|
||||
|
||||
static void recover_psl_err(struct cxl_afu *afu, u64 errstat)
|
||||
|
||||
@@ -678,8 +678,10 @@ static ssize_t modalias_show(struct device *dev, struct device_attribute *a,
|
||||
{
|
||||
struct mei_cl_device *cldev = to_mei_cl_device(dev);
|
||||
const uuid_le *uuid = mei_me_cl_uuid(cldev->me_cl);
|
||||
u8 version = mei_me_cl_ver(cldev->me_cl);
|
||||
|
||||
return scnprintf(buf, PAGE_SIZE, "mei:%s:%pUl:", cldev->name, uuid);
|
||||
return scnprintf(buf, PAGE_SIZE, "mei:%s:%pUl:%02X:",
|
||||
cldev->name, uuid, version);
|
||||
}
|
||||
static DEVICE_ATTR_RO(modalias);
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user