Merge remote-tracking branch 'common/android-4.9' into android-hikey-linaro-4.9-aosp
This commit is contained in:
@@ -1397,6 +1397,10 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
|
||||
When zero, profiling data is discarded and associated
|
||||
debugfs files are removed at module unload time.
|
||||
|
||||
goldfish [X86] Enable the goldfish android emulator platform.
|
||||
Don't use this when you are not running on the
|
||||
android emulator
|
||||
|
||||
gpt [EFI] Forces disk with valid GPT signature but
|
||||
invalid Protective MBR to be treated as GPT. If the
|
||||
primary GPT is corrupted, it enables the backup/alternate
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
VERSION = 4
|
||||
PATCHLEVEL = 9
|
||||
SUBLEVEL = 12
|
||||
SUBLEVEL = 15
|
||||
EXTRAVERSION =
|
||||
NAME = Roaring Lionus
|
||||
|
||||
|
||||
@@ -148,6 +148,8 @@
|
||||
uart1: serial@f8020000 {
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&pinctrl_uart1_default>;
|
||||
atmel,use-dma-rx;
|
||||
atmel,use-dma-tx;
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
|
||||
@@ -110,6 +110,8 @@
|
||||
};
|
||||
|
||||
usart3: serial@fc00c000 {
|
||||
atmel,use-dma-rx;
|
||||
atmel,use-dma-tx;
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
|
||||
@@ -150,18 +150,12 @@ static inline void __coherent_cache_guest_page(struct kvm_vcpu *vcpu,
|
||||
* and iterate over the range.
|
||||
*/
|
||||
|
||||
bool need_flush = !vcpu_has_cache_enabled(vcpu) || ipa_uncached;
|
||||
|
||||
VM_BUG_ON(size & ~PAGE_MASK);
|
||||
|
||||
if (!need_flush && !icache_is_pipt())
|
||||
goto vipt_cache;
|
||||
|
||||
while (size) {
|
||||
void *va = kmap_atomic_pfn(pfn);
|
||||
|
||||
if (need_flush)
|
||||
kvm_flush_dcache_to_poc(va, PAGE_SIZE);
|
||||
kvm_flush_dcache_to_poc(va, PAGE_SIZE);
|
||||
|
||||
if (icache_is_pipt())
|
||||
__cpuc_coherent_user_range((unsigned long)va,
|
||||
@@ -173,7 +167,6 @@ static inline void __coherent_cache_guest_page(struct kvm_vcpu *vcpu,
|
||||
kunmap_atomic(va);
|
||||
}
|
||||
|
||||
vipt_cache:
|
||||
if (!icache_is_pipt() && !icache_is_vivt_asid_tagged()) {
|
||||
/* any kind of VIPT cache */
|
||||
__flush_icache_all();
|
||||
|
||||
@@ -77,7 +77,11 @@ static inline void decode_ctrl_reg(u32 reg,
|
||||
/* Lengths */
|
||||
#define ARM_BREAKPOINT_LEN_1 0x1
|
||||
#define ARM_BREAKPOINT_LEN_2 0x3
|
||||
#define ARM_BREAKPOINT_LEN_3 0x7
|
||||
#define ARM_BREAKPOINT_LEN_4 0xf
|
||||
#define ARM_BREAKPOINT_LEN_5 0x1f
|
||||
#define ARM_BREAKPOINT_LEN_6 0x3f
|
||||
#define ARM_BREAKPOINT_LEN_7 0x7f
|
||||
#define ARM_BREAKPOINT_LEN_8 0xff
|
||||
|
||||
/* Kernel stepping */
|
||||
@@ -119,7 +123,7 @@ struct perf_event;
|
||||
struct pmu;
|
||||
|
||||
extern int arch_bp_generic_fields(struct arch_hw_breakpoint_ctrl ctrl,
|
||||
int *gen_len, int *gen_type);
|
||||
int *gen_len, int *gen_type, int *offset);
|
||||
extern int arch_check_bp_in_kernelspace(struct perf_event *bp);
|
||||
extern int arch_validate_hwbkpt_settings(struct perf_event *bp);
|
||||
extern int hw_breakpoint_exceptions_notify(struct notifier_block *unused,
|
||||
|
||||
@@ -241,8 +241,7 @@ static inline void __coherent_cache_guest_page(struct kvm_vcpu *vcpu,
|
||||
{
|
||||
void *va = page_address(pfn_to_page(pfn));
|
||||
|
||||
if (!vcpu_has_cache_enabled(vcpu) || ipa_uncached)
|
||||
kvm_flush_dcache_to_poc(va, size);
|
||||
kvm_flush_dcache_to_poc(va, size);
|
||||
|
||||
if (!icache_is_aliasing()) { /* PIPT */
|
||||
flush_icache_range((unsigned long)va,
|
||||
|
||||
@@ -654,15 +654,15 @@ static u64 __raw_read_system_reg(u32 sys_id)
|
||||
case SYS_ID_ISAR2_EL1: return read_cpuid(ID_ISAR2_EL1);
|
||||
case SYS_ID_ISAR3_EL1: return read_cpuid(ID_ISAR3_EL1);
|
||||
case SYS_ID_ISAR4_EL1: return read_cpuid(ID_ISAR4_EL1);
|
||||
case SYS_ID_ISAR5_EL1: return read_cpuid(ID_ISAR4_EL1);
|
||||
case SYS_ID_ISAR5_EL1: return read_cpuid(ID_ISAR5_EL1);
|
||||
case SYS_MVFR0_EL1: return read_cpuid(MVFR0_EL1);
|
||||
case SYS_MVFR1_EL1: return read_cpuid(MVFR1_EL1);
|
||||
case SYS_MVFR2_EL1: return read_cpuid(MVFR2_EL1);
|
||||
|
||||
case SYS_ID_AA64PFR0_EL1: return read_cpuid(ID_AA64PFR0_EL1);
|
||||
case SYS_ID_AA64PFR1_EL1: return read_cpuid(ID_AA64PFR0_EL1);
|
||||
case SYS_ID_AA64PFR1_EL1: return read_cpuid(ID_AA64PFR1_EL1);
|
||||
case SYS_ID_AA64DFR0_EL1: return read_cpuid(ID_AA64DFR0_EL1);
|
||||
case SYS_ID_AA64DFR1_EL1: return read_cpuid(ID_AA64DFR0_EL1);
|
||||
case SYS_ID_AA64DFR1_EL1: return read_cpuid(ID_AA64DFR1_EL1);
|
||||
case SYS_ID_AA64MMFR0_EL1: return read_cpuid(ID_AA64MMFR0_EL1);
|
||||
case SYS_ID_AA64MMFR1_EL1: return read_cpuid(ID_AA64MMFR1_EL1);
|
||||
case SYS_ID_AA64MMFR2_EL1: return read_cpuid(ID_AA64MMFR2_EL1);
|
||||
|
||||
@@ -317,9 +317,21 @@ static int get_hbp_len(u8 hbp_len)
|
||||
case ARM_BREAKPOINT_LEN_2:
|
||||
len_in_bytes = 2;
|
||||
break;
|
||||
case ARM_BREAKPOINT_LEN_3:
|
||||
len_in_bytes = 3;
|
||||
break;
|
||||
case ARM_BREAKPOINT_LEN_4:
|
||||
len_in_bytes = 4;
|
||||
break;
|
||||
case ARM_BREAKPOINT_LEN_5:
|
||||
len_in_bytes = 5;
|
||||
break;
|
||||
case ARM_BREAKPOINT_LEN_6:
|
||||
len_in_bytes = 6;
|
||||
break;
|
||||
case ARM_BREAKPOINT_LEN_7:
|
||||
len_in_bytes = 7;
|
||||
break;
|
||||
case ARM_BREAKPOINT_LEN_8:
|
||||
len_in_bytes = 8;
|
||||
break;
|
||||
@@ -349,7 +361,7 @@ int arch_check_bp_in_kernelspace(struct perf_event *bp)
|
||||
* to generic breakpoint descriptions.
|
||||
*/
|
||||
int arch_bp_generic_fields(struct arch_hw_breakpoint_ctrl ctrl,
|
||||
int *gen_len, int *gen_type)
|
||||
int *gen_len, int *gen_type, int *offset)
|
||||
{
|
||||
/* Type */
|
||||
switch (ctrl.type) {
|
||||
@@ -369,17 +381,33 @@ int arch_bp_generic_fields(struct arch_hw_breakpoint_ctrl ctrl,
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (!ctrl.len)
|
||||
return -EINVAL;
|
||||
*offset = __ffs(ctrl.len);
|
||||
|
||||
/* Len */
|
||||
switch (ctrl.len) {
|
||||
switch (ctrl.len >> *offset) {
|
||||
case ARM_BREAKPOINT_LEN_1:
|
||||
*gen_len = HW_BREAKPOINT_LEN_1;
|
||||
break;
|
||||
case ARM_BREAKPOINT_LEN_2:
|
||||
*gen_len = HW_BREAKPOINT_LEN_2;
|
||||
break;
|
||||
case ARM_BREAKPOINT_LEN_3:
|
||||
*gen_len = HW_BREAKPOINT_LEN_3;
|
||||
break;
|
||||
case ARM_BREAKPOINT_LEN_4:
|
||||
*gen_len = HW_BREAKPOINT_LEN_4;
|
||||
break;
|
||||
case ARM_BREAKPOINT_LEN_5:
|
||||
*gen_len = HW_BREAKPOINT_LEN_5;
|
||||
break;
|
||||
case ARM_BREAKPOINT_LEN_6:
|
||||
*gen_len = HW_BREAKPOINT_LEN_6;
|
||||
break;
|
||||
case ARM_BREAKPOINT_LEN_7:
|
||||
*gen_len = HW_BREAKPOINT_LEN_7;
|
||||
break;
|
||||
case ARM_BREAKPOINT_LEN_8:
|
||||
*gen_len = HW_BREAKPOINT_LEN_8;
|
||||
break;
|
||||
@@ -423,9 +451,21 @@ static int arch_build_bp_info(struct perf_event *bp)
|
||||
case HW_BREAKPOINT_LEN_2:
|
||||
info->ctrl.len = ARM_BREAKPOINT_LEN_2;
|
||||
break;
|
||||
case HW_BREAKPOINT_LEN_3:
|
||||
info->ctrl.len = ARM_BREAKPOINT_LEN_3;
|
||||
break;
|
||||
case HW_BREAKPOINT_LEN_4:
|
||||
info->ctrl.len = ARM_BREAKPOINT_LEN_4;
|
||||
break;
|
||||
case HW_BREAKPOINT_LEN_5:
|
||||
info->ctrl.len = ARM_BREAKPOINT_LEN_5;
|
||||
break;
|
||||
case HW_BREAKPOINT_LEN_6:
|
||||
info->ctrl.len = ARM_BREAKPOINT_LEN_6;
|
||||
break;
|
||||
case HW_BREAKPOINT_LEN_7:
|
||||
info->ctrl.len = ARM_BREAKPOINT_LEN_7;
|
||||
break;
|
||||
case HW_BREAKPOINT_LEN_8:
|
||||
info->ctrl.len = ARM_BREAKPOINT_LEN_8;
|
||||
break;
|
||||
@@ -517,18 +557,17 @@ int arch_validate_hwbkpt_settings(struct perf_event *bp)
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
info->address &= ~alignment_mask;
|
||||
info->ctrl.len <<= offset;
|
||||
} else {
|
||||
if (info->ctrl.type == ARM_BREAKPOINT_EXECUTE)
|
||||
alignment_mask = 0x3;
|
||||
else
|
||||
alignment_mask = 0x7;
|
||||
if (info->address & alignment_mask)
|
||||
return -EINVAL;
|
||||
offset = info->address & alignment_mask;
|
||||
}
|
||||
|
||||
info->address &= ~alignment_mask;
|
||||
info->ctrl.len <<= offset;
|
||||
|
||||
/*
|
||||
* Disallow per-task kernel breakpoints since these would
|
||||
* complicate the stepping code.
|
||||
@@ -661,12 +700,47 @@ unlock:
|
||||
}
|
||||
NOKPROBE_SYMBOL(breakpoint_handler);
|
||||
|
||||
/*
|
||||
* Arm64 hardware does not always report a watchpoint hit address that matches
|
||||
* one of the watchpoints set. It can also report an address "near" the
|
||||
* watchpoint if a single instruction access both watched and unwatched
|
||||
* addresses. There is no straight-forward way, short of disassembling the
|
||||
* offending instruction, to map that address back to the watchpoint. This
|
||||
* function computes the distance of the memory access from the watchpoint as a
|
||||
* heuristic for the likelyhood that a given access triggered the watchpoint.
|
||||
*
|
||||
* See Section D2.10.5 "Determining the memory location that caused a Watchpoint
|
||||
* exception" of ARMv8 Architecture Reference Manual for details.
|
||||
*
|
||||
* The function returns the distance of the address from the bytes watched by
|
||||
* the watchpoint. In case of an exact match, it returns 0.
|
||||
*/
|
||||
static u64 get_distance_from_watchpoint(unsigned long addr, u64 val,
|
||||
struct arch_hw_breakpoint_ctrl *ctrl)
|
||||
{
|
||||
u64 wp_low, wp_high;
|
||||
u32 lens, lene;
|
||||
|
||||
lens = __ffs(ctrl->len);
|
||||
lene = __fls(ctrl->len);
|
||||
|
||||
wp_low = val + lens;
|
||||
wp_high = val + lene;
|
||||
if (addr < wp_low)
|
||||
return wp_low - addr;
|
||||
else if (addr > wp_high)
|
||||
return addr - wp_high;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int watchpoint_handler(unsigned long addr, unsigned int esr,
|
||||
struct pt_regs *regs)
|
||||
{
|
||||
int i, step = 0, *kernel_step, access;
|
||||
int i, step = 0, *kernel_step, access, closest_match = 0;
|
||||
u64 min_dist = -1, dist;
|
||||
u32 ctrl_reg;
|
||||
u64 val, alignment_mask;
|
||||
u64 val;
|
||||
struct perf_event *wp, **slots;
|
||||
struct debug_info *debug_info;
|
||||
struct arch_hw_breakpoint *info;
|
||||
@@ -675,35 +749,15 @@ static int watchpoint_handler(unsigned long addr, unsigned int esr,
|
||||
slots = this_cpu_ptr(wp_on_reg);
|
||||
debug_info = ¤t->thread.debug;
|
||||
|
||||
/*
|
||||
* Find all watchpoints that match the reported address. If no exact
|
||||
* match is found. Attribute the hit to the closest watchpoint.
|
||||
*/
|
||||
rcu_read_lock();
|
||||
for (i = 0; i < core_num_wrps; ++i) {
|
||||
rcu_read_lock();
|
||||
|
||||
wp = slots[i];
|
||||
|
||||
if (wp == NULL)
|
||||
goto unlock;
|
||||
|
||||
info = counter_arch_bp(wp);
|
||||
/* AArch32 watchpoints are either 4 or 8 bytes aligned. */
|
||||
if (is_compat_task()) {
|
||||
if (info->ctrl.len == ARM_BREAKPOINT_LEN_8)
|
||||
alignment_mask = 0x7;
|
||||
else
|
||||
alignment_mask = 0x3;
|
||||
} else {
|
||||
alignment_mask = 0x7;
|
||||
}
|
||||
|
||||
/* Check if the watchpoint value matches. */
|
||||
val = read_wb_reg(AARCH64_DBG_REG_WVR, i);
|
||||
if (val != (addr & ~alignment_mask))
|
||||
goto unlock;
|
||||
|
||||
/* Possible match, check the byte address select to confirm. */
|
||||
ctrl_reg = read_wb_reg(AARCH64_DBG_REG_WCR, i);
|
||||
decode_ctrl_reg(ctrl_reg, &ctrl);
|
||||
if (!((1 << (addr & alignment_mask)) & ctrl.len))
|
||||
goto unlock;
|
||||
continue;
|
||||
|
||||
/*
|
||||
* Check that the access type matches.
|
||||
@@ -712,18 +766,41 @@ static int watchpoint_handler(unsigned long addr, unsigned int esr,
|
||||
access = (esr & AARCH64_ESR_ACCESS_MASK) ? HW_BREAKPOINT_W :
|
||||
HW_BREAKPOINT_R;
|
||||
if (!(access & hw_breakpoint_type(wp)))
|
||||
goto unlock;
|
||||
continue;
|
||||
|
||||
/* Check if the watchpoint value and byte select match. */
|
||||
val = read_wb_reg(AARCH64_DBG_REG_WVR, i);
|
||||
ctrl_reg = read_wb_reg(AARCH64_DBG_REG_WCR, i);
|
||||
decode_ctrl_reg(ctrl_reg, &ctrl);
|
||||
dist = get_distance_from_watchpoint(addr, val, &ctrl);
|
||||
if (dist < min_dist) {
|
||||
min_dist = dist;
|
||||
closest_match = i;
|
||||
}
|
||||
/* Is this an exact match? */
|
||||
if (dist != 0)
|
||||
continue;
|
||||
|
||||
info = counter_arch_bp(wp);
|
||||
info->trigger = addr;
|
||||
perf_bp_event(wp, regs);
|
||||
|
||||
/* Do we need to handle the stepping? */
|
||||
if (is_default_overflow_handler(wp))
|
||||
step = 1;
|
||||
|
||||
unlock:
|
||||
rcu_read_unlock();
|
||||
}
|
||||
if (min_dist > 0 && min_dist != -1) {
|
||||
/* No exact match found. */
|
||||
wp = slots[closest_match];
|
||||
info = counter_arch_bp(wp);
|
||||
info->trigger = addr;
|
||||
perf_bp_event(wp, regs);
|
||||
|
||||
/* Do we need to handle the stepping? */
|
||||
if (is_default_overflow_handler(wp))
|
||||
step = 1;
|
||||
}
|
||||
rcu_read_unlock();
|
||||
|
||||
if (!step)
|
||||
return 0;
|
||||
|
||||
@@ -327,13 +327,13 @@ static int ptrace_hbp_fill_attr_ctrl(unsigned int note_type,
|
||||
struct arch_hw_breakpoint_ctrl ctrl,
|
||||
struct perf_event_attr *attr)
|
||||
{
|
||||
int err, len, type, disabled = !ctrl.enabled;
|
||||
int err, len, type, offset, disabled = !ctrl.enabled;
|
||||
|
||||
attr->disabled = disabled;
|
||||
if (disabled)
|
||||
return 0;
|
||||
|
||||
err = arch_bp_generic_fields(ctrl, &len, &type);
|
||||
err = arch_bp_generic_fields(ctrl, &len, &type, &offset);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
@@ -352,6 +352,7 @@ static int ptrace_hbp_fill_attr_ctrl(unsigned int note_type,
|
||||
|
||||
attr->bp_len = len;
|
||||
attr->bp_type = type;
|
||||
attr->bp_addr += offset;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -404,7 +405,7 @@ static int ptrace_hbp_get_addr(unsigned int note_type,
|
||||
if (IS_ERR(bp))
|
||||
return PTR_ERR(bp);
|
||||
|
||||
*addr = bp ? bp->attr.bp_addr : 0;
|
||||
*addr = bp ? counter_arch_bp(bp)->address : 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -352,6 +352,13 @@ static int __swiotlb_dma_supported(struct device *hwdev, u64 mask)
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int __swiotlb_dma_mapping_error(struct device *hwdev, dma_addr_t addr)
|
||||
{
|
||||
if (swiotlb)
|
||||
return swiotlb_dma_mapping_error(hwdev, addr);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct dma_map_ops swiotlb_dma_ops = {
|
||||
.alloc = __dma_alloc,
|
||||
.free = __dma_free,
|
||||
@@ -366,7 +373,7 @@ static struct dma_map_ops swiotlb_dma_ops = {
|
||||
.sync_sg_for_cpu = __swiotlb_sync_sg_for_cpu,
|
||||
.sync_sg_for_device = __swiotlb_sync_sg_for_device,
|
||||
.dma_supported = __swiotlb_dma_supported,
|
||||
.mapping_error = swiotlb_dma_mapping_error,
|
||||
.mapping_error = __swiotlb_dma_mapping_error,
|
||||
};
|
||||
|
||||
static int __init atomic_pool_init(void)
|
||||
|
||||
@@ -17,6 +17,12 @@
|
||||
.active_low = 1, \
|
||||
}
|
||||
|
||||
#define BCM47XX_GPIO_KEY_H(_gpio, _code) \
|
||||
{ \
|
||||
.code = _code, \
|
||||
.gpio = _gpio, \
|
||||
}
|
||||
|
||||
/* Asus */
|
||||
|
||||
static const struct gpio_keys_button
|
||||
@@ -79,8 +85,8 @@ bcm47xx_buttons_asus_wl500gpv2[] __initconst = {
|
||||
|
||||
static const struct gpio_keys_button
|
||||
bcm47xx_buttons_asus_wl500w[] __initconst = {
|
||||
BCM47XX_GPIO_KEY(6, KEY_RESTART),
|
||||
BCM47XX_GPIO_KEY(7, KEY_WPS_BUTTON),
|
||||
BCM47XX_GPIO_KEY_H(6, KEY_RESTART),
|
||||
BCM47XX_GPIO_KEY_H(7, KEY_WPS_BUTTON),
|
||||
};
|
||||
|
||||
static const struct gpio_keys_button
|
||||
|
||||
@@ -208,18 +208,18 @@ EXC( STORE t2, UNIT(6)(dst), s_exc_p10u)
|
||||
ADD src, src, 16*NBYTES
|
||||
EXC( STORE t3, UNIT(7)(dst), s_exc_p9u)
|
||||
ADD dst, dst, 16*NBYTES
|
||||
EXC( LOAD t0, UNIT(-8)(src), l_exc_copy)
|
||||
EXC( LOAD t1, UNIT(-7)(src), l_exc_copy)
|
||||
EXC( LOAD t2, UNIT(-6)(src), l_exc_copy)
|
||||
EXC( LOAD t3, UNIT(-5)(src), l_exc_copy)
|
||||
EXC( LOAD t0, UNIT(-8)(src), l_exc_copy_rewind16)
|
||||
EXC( LOAD t1, UNIT(-7)(src), l_exc_copy_rewind16)
|
||||
EXC( LOAD t2, UNIT(-6)(src), l_exc_copy_rewind16)
|
||||
EXC( LOAD t3, UNIT(-5)(src), l_exc_copy_rewind16)
|
||||
EXC( STORE t0, UNIT(-8)(dst), s_exc_p8u)
|
||||
EXC( STORE t1, UNIT(-7)(dst), s_exc_p7u)
|
||||
EXC( STORE t2, UNIT(-6)(dst), s_exc_p6u)
|
||||
EXC( STORE t3, UNIT(-5)(dst), s_exc_p5u)
|
||||
EXC( LOAD t0, UNIT(-4)(src), l_exc_copy)
|
||||
EXC( LOAD t1, UNIT(-3)(src), l_exc_copy)
|
||||
EXC( LOAD t2, UNIT(-2)(src), l_exc_copy)
|
||||
EXC( LOAD t3, UNIT(-1)(src), l_exc_copy)
|
||||
EXC( LOAD t0, UNIT(-4)(src), l_exc_copy_rewind16)
|
||||
EXC( LOAD t1, UNIT(-3)(src), l_exc_copy_rewind16)
|
||||
EXC( LOAD t2, UNIT(-2)(src), l_exc_copy_rewind16)
|
||||
EXC( LOAD t3, UNIT(-1)(src), l_exc_copy_rewind16)
|
||||
EXC( STORE t0, UNIT(-4)(dst), s_exc_p4u)
|
||||
EXC( STORE t1, UNIT(-3)(dst), s_exc_p3u)
|
||||
EXC( STORE t2, UNIT(-2)(dst), s_exc_p2u)
|
||||
@@ -383,6 +383,10 @@ done:
|
||||
nop
|
||||
END(memcpy)
|
||||
|
||||
l_exc_copy_rewind16:
|
||||
/* Rewind src and dst by 16*NBYTES for l_exc_copy */
|
||||
SUB src, src, 16*NBYTES
|
||||
SUB dst, dst, 16*NBYTES
|
||||
l_exc_copy:
|
||||
/*
|
||||
* Copy bytes from src until faulting load address (or until a
|
||||
|
||||
@@ -186,7 +186,9 @@ static inline __wsum csum_tcpudp_nofold(__be32 saddr, __be32 daddr,
|
||||
" daddu %0, %4 \n"
|
||||
" dsll32 $1, %0, 0 \n"
|
||||
" daddu %0, $1 \n"
|
||||
" sltu $1, %0, $1 \n"
|
||||
" dsra32 %0, %0, 0 \n"
|
||||
" addu %0, $1 \n"
|
||||
#endif
|
||||
" .set pop"
|
||||
: "=r" (sum)
|
||||
|
||||
+98
-53
@@ -195,11 +195,9 @@ struct mips_frame_info {
|
||||
#define J_TARGET(pc,target) \
|
||||
(((unsigned long)(pc) & 0xf0000000) | ((target) << 2))
|
||||
|
||||
static inline int is_ra_save_ins(union mips_instruction *ip)
|
||||
static inline int is_ra_save_ins(union mips_instruction *ip, int *poff)
|
||||
{
|
||||
#ifdef CONFIG_CPU_MICROMIPS
|
||||
union mips_instruction mmi;
|
||||
|
||||
/*
|
||||
* swsp ra,offset
|
||||
* swm16 reglist,offset(sp)
|
||||
@@ -209,29 +207,71 @@ static inline int is_ra_save_ins(union mips_instruction *ip)
|
||||
*
|
||||
* microMIPS is way more fun...
|
||||
*/
|
||||
if (mm_insn_16bit(ip->halfword[0])) {
|
||||
mmi.word = (ip->halfword[0] << 16);
|
||||
return (mmi.mm16_r5_format.opcode == mm_swsp16_op &&
|
||||
mmi.mm16_r5_format.rt == 31) ||
|
||||
(mmi.mm16_m_format.opcode == mm_pool16c_op &&
|
||||
mmi.mm16_m_format.func == mm_swm16_op);
|
||||
if (mm_insn_16bit(ip->halfword[1])) {
|
||||
switch (ip->mm16_r5_format.opcode) {
|
||||
case mm_swsp16_op:
|
||||
if (ip->mm16_r5_format.rt != 31)
|
||||
return 0;
|
||||
|
||||
*poff = ip->mm16_r5_format.simmediate;
|
||||
*poff = (*poff << 2) / sizeof(ulong);
|
||||
return 1;
|
||||
|
||||
case mm_pool16c_op:
|
||||
switch (ip->mm16_m_format.func) {
|
||||
case mm_swm16_op:
|
||||
*poff = ip->mm16_m_format.imm;
|
||||
*poff += 1 + ip->mm16_m_format.rlist;
|
||||
*poff = (*poff << 2) / sizeof(ulong);
|
||||
return 1;
|
||||
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
else {
|
||||
mmi.halfword[0] = ip->halfword[1];
|
||||
mmi.halfword[1] = ip->halfword[0];
|
||||
return (mmi.mm_m_format.opcode == mm_pool32b_op &&
|
||||
mmi.mm_m_format.rd > 9 &&
|
||||
mmi.mm_m_format.base == 29 &&
|
||||
mmi.mm_m_format.func == mm_swm32_func) ||
|
||||
(mmi.i_format.opcode == mm_sw32_op &&
|
||||
mmi.i_format.rs == 29 &&
|
||||
mmi.i_format.rt == 31);
|
||||
|
||||
switch (ip->i_format.opcode) {
|
||||
case mm_sw32_op:
|
||||
if (ip->i_format.rs != 29)
|
||||
return 0;
|
||||
if (ip->i_format.rt != 31)
|
||||
return 0;
|
||||
|
||||
*poff = ip->i_format.simmediate / sizeof(ulong);
|
||||
return 1;
|
||||
|
||||
case mm_pool32b_op:
|
||||
switch (ip->mm_m_format.func) {
|
||||
case mm_swm32_func:
|
||||
if (ip->mm_m_format.rd < 0x10)
|
||||
return 0;
|
||||
if (ip->mm_m_format.base != 29)
|
||||
return 0;
|
||||
|
||||
*poff = ip->mm_m_format.simmediate;
|
||||
*poff += (ip->mm_m_format.rd & 0xf) * sizeof(u32);
|
||||
*poff /= sizeof(ulong);
|
||||
return 1;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
/* sw / sd $ra, offset($sp) */
|
||||
return (ip->i_format.opcode == sw_op || ip->i_format.opcode == sd_op) &&
|
||||
ip->i_format.rs == 29 &&
|
||||
ip->i_format.rt == 31;
|
||||
if ((ip->i_format.opcode == sw_op || ip->i_format.opcode == sd_op) &&
|
||||
ip->i_format.rs == 29 && ip->i_format.rt == 31) {
|
||||
*poff = ip->i_format.simmediate / sizeof(ulong);
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -246,13 +286,16 @@ static inline int is_jump_ins(union mips_instruction *ip)
|
||||
*
|
||||
* microMIPS is kind of more fun...
|
||||
*/
|
||||
union mips_instruction mmi;
|
||||
if (mm_insn_16bit(ip->halfword[1])) {
|
||||
if ((ip->mm16_r5_format.opcode == mm_pool16c_op &&
|
||||
(ip->mm16_r5_format.rt & mm_jr16_op) == mm_jr16_op))
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
mmi.word = (ip->halfword[0] << 16);
|
||||
|
||||
if ((mmi.mm16_r5_format.opcode == mm_pool16c_op &&
|
||||
(mmi.mm16_r5_format.rt & mm_jr16_op) == mm_jr16_op) ||
|
||||
ip->j_format.opcode == mm_jal32_op)
|
||||
if (ip->j_format.opcode == mm_j32_op)
|
||||
return 1;
|
||||
if (ip->j_format.opcode == mm_jal32_op)
|
||||
return 1;
|
||||
if (ip->r_format.opcode != mm_pool32a_op ||
|
||||
ip->r_format.func != mm_pool32axf_op)
|
||||
@@ -280,15 +323,13 @@ static inline int is_sp_move_ins(union mips_instruction *ip)
|
||||
*
|
||||
* microMIPS is not more fun...
|
||||
*/
|
||||
if (mm_insn_16bit(ip->halfword[0])) {
|
||||
union mips_instruction mmi;
|
||||
|
||||
mmi.word = (ip->halfword[0] << 16);
|
||||
return (mmi.mm16_r3_format.opcode == mm_pool16d_op &&
|
||||
mmi.mm16_r3_format.simmediate && mm_addiusp_func) ||
|
||||
(mmi.mm16_r5_format.opcode == mm_pool16d_op &&
|
||||
mmi.mm16_r5_format.rt == 29);
|
||||
if (mm_insn_16bit(ip->halfword[1])) {
|
||||
return (ip->mm16_r3_format.opcode == mm_pool16d_op &&
|
||||
ip->mm16_r3_format.simmediate && mm_addiusp_func) ||
|
||||
(ip->mm16_r5_format.opcode == mm_pool16d_op &&
|
||||
ip->mm16_r5_format.rt == 29);
|
||||
}
|
||||
|
||||
return ip->mm_i_format.opcode == mm_addiu32_op &&
|
||||
ip->mm_i_format.rt == 29 && ip->mm_i_format.rs == 29;
|
||||
#else
|
||||
@@ -303,30 +344,36 @@ static inline int is_sp_move_ins(union mips_instruction *ip)
|
||||
|
||||
static int get_frame_info(struct mips_frame_info *info)
|
||||
{
|
||||
#ifdef CONFIG_CPU_MICROMIPS
|
||||
union mips_instruction *ip = (void *) (((char *) info->func) - 1);
|
||||
#else
|
||||
union mips_instruction *ip = info->func;
|
||||
#endif
|
||||
unsigned max_insns = info->func_size / sizeof(union mips_instruction);
|
||||
unsigned i;
|
||||
bool is_mmips = IS_ENABLED(CONFIG_CPU_MICROMIPS);
|
||||
union mips_instruction insn, *ip, *ip_end;
|
||||
const unsigned int max_insns = 128;
|
||||
unsigned int i;
|
||||
|
||||
info->pc_offset = -1;
|
||||
info->frame_size = 0;
|
||||
|
||||
ip = (void *)msk_isa16_mode((ulong)info->func);
|
||||
if (!ip)
|
||||
goto err;
|
||||
|
||||
if (max_insns == 0)
|
||||
max_insns = 128U; /* unknown function size */
|
||||
max_insns = min(128U, max_insns);
|
||||
ip_end = (void *)ip + info->func_size;
|
||||
|
||||
for (i = 0; i < max_insns; i++, ip++) {
|
||||
for (i = 0; i < max_insns && ip < ip_end; i++, ip++) {
|
||||
if (is_mmips && mm_insn_16bit(ip->halfword[0])) {
|
||||
insn.halfword[0] = 0;
|
||||
insn.halfword[1] = ip->halfword[0];
|
||||
} else if (is_mmips) {
|
||||
insn.halfword[0] = ip->halfword[1];
|
||||
insn.halfword[1] = ip->halfword[0];
|
||||
} else {
|
||||
insn.word = ip->word;
|
||||
}
|
||||
|
||||
if (is_jump_ins(ip))
|
||||
if (is_jump_ins(&insn))
|
||||
break;
|
||||
|
||||
if (!info->frame_size) {
|
||||
if (is_sp_move_ins(ip))
|
||||
if (is_sp_move_ins(&insn))
|
||||
{
|
||||
#ifdef CONFIG_CPU_MICROMIPS
|
||||
if (mm_insn_16bit(ip->halfword[0]))
|
||||
@@ -349,11 +396,9 @@ static int get_frame_info(struct mips_frame_info *info)
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (info->pc_offset == -1 && is_ra_save_ins(ip)) {
|
||||
info->pc_offset =
|
||||
ip->i_format.simmediate / sizeof(long);
|
||||
if (info->pc_offset == -1 &&
|
||||
is_ra_save_ins(&insn, &info->pc_offset))
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (info->frame_size && info->pc_offset >= 0) /* nested */
|
||||
return 0;
|
||||
|
||||
@@ -545,7 +545,7 @@ void __init ltq_soc_init(void)
|
||||
clkdev_add_pmu("1a800000.pcie", "msi", 1, 1, PMU1_PCIE2_MSI);
|
||||
clkdev_add_pmu("1a800000.pcie", "pdi", 1, 1, PMU1_PCIE2_PDI);
|
||||
clkdev_add_pmu("1a800000.pcie", "ctl", 1, 1, PMU1_PCIE2_CTL);
|
||||
clkdev_add_pmu("1e108000.eth", NULL, 1, 0, PMU_SWITCH | PMU_PPE_DP);
|
||||
clkdev_add_pmu("1e108000.eth", NULL, 0, 0, PMU_SWITCH | PMU_PPE_DP);
|
||||
clkdev_add_pmu("1da00000.usif", "NULL", 1, 0, PMU_USIF);
|
||||
clkdev_add_pmu("1e103100.deu", NULL, 1, 0, PMU_DEU);
|
||||
} else if (of_machine_is_compatible("lantiq,ar10")) {
|
||||
@@ -553,7 +553,7 @@ void __init ltq_soc_init(void)
|
||||
ltq_ar10_fpi_hz(), ltq_ar10_pp32_hz());
|
||||
clkdev_add_pmu("1e101000.usb", "ctl", 1, 0, PMU_USB0);
|
||||
clkdev_add_pmu("1e106000.usb", "ctl", 1, 0, PMU_USB1);
|
||||
clkdev_add_pmu("1e108000.eth", NULL, 1, 0, PMU_SWITCH |
|
||||
clkdev_add_pmu("1e108000.eth", NULL, 0, 0, PMU_SWITCH |
|
||||
PMU_PPE_DP | PMU_PPE_TC);
|
||||
clkdev_add_pmu("1da00000.usif", "NULL", 1, 0, PMU_USIF);
|
||||
clkdev_add_pmu("1f203000.rcu", "gphy", 1, 0, PMU_GPHY);
|
||||
@@ -575,11 +575,11 @@ void __init ltq_soc_init(void)
|
||||
clkdev_add_pmu(NULL, "ahb", 1, 0, PMU_AHBM | PMU_AHBS);
|
||||
|
||||
clkdev_add_pmu("1da00000.usif", "NULL", 1, 0, PMU_USIF);
|
||||
clkdev_add_pmu("1e108000.eth", NULL, 1, 0,
|
||||
clkdev_add_pmu("1e108000.eth", NULL, 0, 0,
|
||||
PMU_SWITCH | PMU_PPE_DPLUS | PMU_PPE_DPLUM |
|
||||
PMU_PPE_EMA | PMU_PPE_TC | PMU_PPE_SLL01 |
|
||||
PMU_PPE_QSB | PMU_PPE_TOP);
|
||||
clkdev_add_pmu("1f203000.rcu", "gphy", 1, 0, PMU_GPHY);
|
||||
clkdev_add_pmu("1f203000.rcu", "gphy", 0, 0, PMU_GPHY);
|
||||
clkdev_add_pmu("1e103000.sdio", NULL, 1, 0, PMU_SDIO);
|
||||
clkdev_add_pmu("1e103100.deu", NULL, 1, 0, PMU_DEU);
|
||||
clkdev_add_pmu("1e116000.mei", "dfe", 1, 0, PMU_DFE);
|
||||
|
||||
+34
-20
@@ -31,26 +31,40 @@ static inline void indy_sc_wipe(unsigned long first, unsigned long last)
|
||||
unsigned long tmp;
|
||||
|
||||
__asm__ __volatile__(
|
||||
".set\tpush\t\t\t# indy_sc_wipe\n\t"
|
||||
".set\tnoreorder\n\t"
|
||||
".set\tmips3\n\t"
|
||||
".set\tnoat\n\t"
|
||||
"mfc0\t%2, $12\n\t"
|
||||
"li\t$1, 0x80\t\t\t# Go 64 bit\n\t"
|
||||
"mtc0\t$1, $12\n\t"
|
||||
|
||||
"dli\t$1, 0x9000000080000000\n\t"
|
||||
"or\t%0, $1\t\t\t# first line to flush\n\t"
|
||||
"or\t%1, $1\t\t\t# last line to flush\n\t"
|
||||
".set\tat\n\t"
|
||||
|
||||
"1:\tsw\t$0, 0(%0)\n\t"
|
||||
"bne\t%0, %1, 1b\n\t"
|
||||
" daddu\t%0, 32\n\t"
|
||||
|
||||
"mtc0\t%2, $12\t\t\t# Back to 32 bit\n\t"
|
||||
"nop; nop; nop; nop;\n\t"
|
||||
".set\tpop"
|
||||
" .set push # indy_sc_wipe \n"
|
||||
" .set noreorder \n"
|
||||
" .set mips3 \n"
|
||||
" .set noat \n"
|
||||
" mfc0 %2, $12 \n"
|
||||
" li $1, 0x80 # Go 64 bit \n"
|
||||
" mtc0 $1, $12 \n"
|
||||
" \n"
|
||||
" # \n"
|
||||
" # Open code a dli $1, 0x9000000080000000 \n"
|
||||
" # \n"
|
||||
" # Required because binutils 2.25 will happily accept \n"
|
||||
" # 64 bit instructions in .set mips3 mode but puke on \n"
|
||||
" # 64 bit constants when generating 32 bit ELF \n"
|
||||
" # \n"
|
||||
" lui $1,0x9000 \n"
|
||||
" dsll $1,$1,0x10 \n"
|
||||
" ori $1,$1,0x8000 \n"
|
||||
" dsll $1,$1,0x10 \n"
|
||||
" \n"
|
||||
" or %0, $1 # first line to flush \n"
|
||||
" or %1, $1 # last line to flush \n"
|
||||
" .set at \n"
|
||||
" \n"
|
||||
"1: sw $0, 0(%0) \n"
|
||||
" bne %0, %1, 1b \n"
|
||||
" daddu %0, 32 \n"
|
||||
" \n"
|
||||
" mtc0 %2, $12 # Back to 32 bit \n"
|
||||
" nop # pipeline hazard \n"
|
||||
" nop \n"
|
||||
" nop \n"
|
||||
" nop \n"
|
||||
" .set pop \n"
|
||||
: "=r" (first), "=r" (last), "=&r" (tmp)
|
||||
: "0" (first), "1" (last));
|
||||
}
|
||||
|
||||
@@ -2,8 +2,7 @@
|
||||
# Joshua Henderson, <joshua.henderson@microchip.com>
|
||||
# Copyright (C) 2015 Microchip Technology, Inc. All rights reserved.
|
||||
#
|
||||
obj-y := init.o time.o config.o
|
||||
obj-y := config.o early_clk.o init.o time.o
|
||||
|
||||
obj-$(CONFIG_EARLY_PRINTK) += early_console.o \
|
||||
early_pin.o \
|
||||
early_clk.o
|
||||
early_pin.o
|
||||
|
||||
@@ -136,6 +136,7 @@ enum {
|
||||
MMU_FTR_NO_SLBIE_B | MMU_FTR_16M_PAGE | MMU_FTR_TLBIEL |
|
||||
MMU_FTR_LOCKLESS_TLBIE | MMU_FTR_CI_LARGE_PAGE |
|
||||
MMU_FTR_1T_SEGMENT | MMU_FTR_TLBIE_CROP_VA |
|
||||
MMU_FTR_KERNEL_RO |
|
||||
#ifdef CONFIG_PPC_RADIX_MMU
|
||||
MMU_FTR_TYPE_RADIX |
|
||||
#endif
|
||||
|
||||
@@ -100,6 +100,8 @@ _GLOBAL(__setup_cpu_power9)
|
||||
mfspr r3,SPRN_LPCR
|
||||
LOAD_REG_IMMEDIATE(r4, LPCR_PECEDH | LPCR_PECE_HVEE | LPCR_HVICE)
|
||||
or r3, r3, r4
|
||||
LOAD_REG_IMMEDIATE(r4, LPCR_UPRT | LPCR_HR)
|
||||
andc r3, r3, r4
|
||||
bl __init_LPCR
|
||||
bl __init_HFSCR
|
||||
bl __init_tlb_power9
|
||||
@@ -120,6 +122,8 @@ _GLOBAL(__restore_cpu_power9)
|
||||
mfspr r3,SPRN_LPCR
|
||||
LOAD_REG_IMMEDIATE(r4, LPCR_PECEDH | LPCR_PECE_HVEE | LPCR_HVICE)
|
||||
or r3, r3, r4
|
||||
LOAD_REG_IMMEDIATE(r4, LPCR_UPRT | LPCR_HR)
|
||||
andc r3, r3, r4
|
||||
bl __init_LPCR
|
||||
bl __init_HFSCR
|
||||
bl __init_tlb_power9
|
||||
|
||||
@@ -228,8 +228,10 @@ int hw_breakpoint_handler(struct die_args *args)
|
||||
rcu_read_lock();
|
||||
|
||||
bp = __this_cpu_read(bp_per_reg);
|
||||
if (!bp)
|
||||
if (!bp) {
|
||||
rc = NOTIFY_DONE;
|
||||
goto out;
|
||||
}
|
||||
info = counter_arch_bp(bp);
|
||||
|
||||
/*
|
||||
|
||||
@@ -89,7 +89,8 @@ extern void execve_tail(void);
|
||||
* User space process size: 2GB for 31 bit, 4TB or 8PT for 64 bit.
|
||||
*/
|
||||
|
||||
#define TASK_SIZE_OF(tsk) ((tsk)->mm->context.asce_limit)
|
||||
#define TASK_SIZE_OF(tsk) ((tsk)->mm ? \
|
||||
(tsk)->mm->context.asce_limit : TASK_MAX_SIZE)
|
||||
#define TASK_UNMAPPED_BASE (test_thread_flag(TIF_31BIT) ? \
|
||||
(1UL << 30) : (1UL << 41))
|
||||
#define TASK_SIZE TASK_SIZE_OF(current)
|
||||
|
||||
@@ -329,7 +329,11 @@ static void *nt_init_name(void *buf, Elf64_Word type, void *desc, int d_len,
|
||||
|
||||
static inline void *nt_init(void *buf, Elf64_Word type, void *desc, int d_len)
|
||||
{
|
||||
return nt_init_name(buf, type, desc, d_len, KEXEC_CORE_NOTE_NAME);
|
||||
const char *note_name = "LINUX";
|
||||
|
||||
if (type == NT_PRPSINFO || type == NT_PRSTATUS || type == NT_PRFPREG)
|
||||
note_name = KEXEC_CORE_NOTE_NAME;
|
||||
return nt_init_name(buf, type, desc, d_len, note_name);
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -819,10 +819,10 @@ static void __init setup_randomness(void)
|
||||
{
|
||||
struct sysinfo_3_2_2 *vmms;
|
||||
|
||||
vmms = (struct sysinfo_3_2_2 *) alloc_page(GFP_KERNEL);
|
||||
if (vmms && stsi(vmms, 3, 2, 2) == 0 && vmms->count)
|
||||
add_device_randomness(&vmms, vmms->count);
|
||||
free_page((unsigned long) vmms);
|
||||
vmms = (struct sysinfo_3_2_2 *) memblock_alloc(PAGE_SIZE, PAGE_SIZE);
|
||||
if (stsi(vmms, 3, 2, 2) == 0 && vmms->count)
|
||||
add_device_randomness(&vmms->vm, sizeof(vmms->vm[0]) * vmms->count);
|
||||
memblock_free((unsigned long) vmms, PAGE_SIZE);
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -442,6 +442,9 @@ int kvm_vm_ioctl_get_dirty_log(struct kvm *kvm,
|
||||
struct kvm_memory_slot *memslot;
|
||||
int is_dirty = 0;
|
||||
|
||||
if (kvm_is_ucontrol(kvm))
|
||||
return -EINVAL;
|
||||
|
||||
mutex_lock(&kvm->slots_lock);
|
||||
|
||||
r = -EINVAL;
|
||||
|
||||
@@ -46,6 +46,15 @@ extern int __arch_set_user_pkey_access(struct task_struct *tsk, int pkey,
|
||||
static inline
|
||||
bool mm_pkey_is_allocated(struct mm_struct *mm, int pkey)
|
||||
{
|
||||
/*
|
||||
* "Allocated" pkeys are those that have been returned
|
||||
* from pkey_alloc(). pkey 0 is special, and never
|
||||
* returned from pkey_alloc().
|
||||
*/
|
||||
if (pkey <= 0)
|
||||
return false;
|
||||
if (pkey >= arch_max_pkey())
|
||||
return false;
|
||||
return mm_pkey_allocation_map(mm) & (1U << pkey);
|
||||
}
|
||||
|
||||
@@ -82,12 +91,6 @@ int mm_pkey_alloc(struct mm_struct *mm)
|
||||
static inline
|
||||
int mm_pkey_free(struct mm_struct *mm, int pkey)
|
||||
{
|
||||
/*
|
||||
* pkey 0 is special, always allocated and can never
|
||||
* be freed.
|
||||
*/
|
||||
if (!pkey)
|
||||
return -EINVAL;
|
||||
if (!mm_pkey_is_allocated(mm, pkey))
|
||||
return -EINVAL;
|
||||
|
||||
|
||||
@@ -188,7 +188,7 @@ static inline void __native_flush_tlb_single(unsigned long addr)
|
||||
|
||||
static inline void __flush_tlb_all(void)
|
||||
{
|
||||
if (static_cpu_has(X86_FEATURE_PGE))
|
||||
if (boot_cpu_has(X86_FEATURE_PGE))
|
||||
__flush_tlb_global();
|
||||
else
|
||||
__flush_tlb();
|
||||
|
||||
+2
-2
@@ -3693,7 +3693,7 @@ static void fix_rmode_seg(int seg, struct kvm_segment *save)
|
||||
}
|
||||
|
||||
vmcs_write16(sf->selector, var.selector);
|
||||
vmcs_write32(sf->base, var.base);
|
||||
vmcs_writel(sf->base, var.base);
|
||||
vmcs_write32(sf->limit, var.limit);
|
||||
vmcs_write32(sf->ar_bytes, vmx_segment_access_rights(&var));
|
||||
}
|
||||
@@ -8202,7 +8202,7 @@ static void kvm_flush_pml_buffers(struct kvm *kvm)
|
||||
static void vmx_dump_sel(char *name, uint32_t sel)
|
||||
{
|
||||
pr_err("%s sel=0x%04x, attr=0x%05x, limit=0x%08x, base=0x%016lx\n",
|
||||
name, vmcs_read32(sel),
|
||||
name, vmcs_read16(sel),
|
||||
vmcs_read32(sel + GUEST_ES_AR_BYTES - GUEST_ES_SELECTOR),
|
||||
vmcs_read32(sel + GUEST_ES_LIMIT - GUEST_ES_SELECTOR),
|
||||
vmcs_readl(sel + GUEST_ES_BASE - GUEST_ES_SELECTOR));
|
||||
|
||||
+6
-2
@@ -120,6 +120,11 @@ static noinline int gup_pte_range(pmd_t pmd, unsigned long addr,
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!pte_allows_gup(pte_val(pte), write)) {
|
||||
pte_unmap(ptep);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (pte_devmap(pte)) {
|
||||
pgmap = get_dev_pagemap(pte_pfn(pte), pgmap);
|
||||
if (unlikely(!pgmap)) {
|
||||
@@ -127,8 +132,7 @@ static noinline int gup_pte_range(pmd_t pmd, unsigned long addr,
|
||||
pte_unmap(ptep);
|
||||
return 0;
|
||||
}
|
||||
} else if (!pte_allows_gup(pte_val(pte), write) ||
|
||||
pte_special(pte)) {
|
||||
} else if (pte_special(pte)) {
|
||||
pte_unmap(ptep);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -42,10 +42,22 @@ static struct resource goldfish_pdev_bus_resources[] = {
|
||||
}
|
||||
};
|
||||
|
||||
static bool goldfish_enable __initdata;
|
||||
|
||||
static int __init goldfish_setup(char *str)
|
||||
{
|
||||
goldfish_enable = true;
|
||||
return 0;
|
||||
}
|
||||
__setup("goldfish", goldfish_setup);
|
||||
|
||||
static int __init goldfish_init(void)
|
||||
{
|
||||
if (!goldfish_enable)
|
||||
return -ENODEV;
|
||||
|
||||
platform_device_register_simple("goldfish_pdev_bus", -1,
|
||||
goldfish_pdev_bus_resources, 2);
|
||||
goldfish_pdev_bus_resources, 2);
|
||||
return 0;
|
||||
}
|
||||
device_initcall(goldfish_init);
|
||||
|
||||
@@ -133,6 +133,8 @@ static int __init parse_tag_initrd(const bp_tag_t* tag)
|
||||
|
||||
__tagtable(BP_TAG_INITRD, parse_tag_initrd);
|
||||
|
||||
#endif /* CONFIG_BLK_DEV_INITRD */
|
||||
|
||||
#ifdef CONFIG_OF
|
||||
|
||||
static int __init parse_tag_fdt(const bp_tag_t *tag)
|
||||
@@ -145,8 +147,6 @@ __tagtable(BP_TAG_FDT, parse_tag_fdt);
|
||||
|
||||
#endif /* CONFIG_OF */
|
||||
|
||||
#endif /* CONFIG_BLK_DEV_INITRD */
|
||||
|
||||
static int __init parse_tag_cmdline(const bp_tag_t* tag)
|
||||
{
|
||||
strlcpy(command_line, (char *)(tag->data), COMMAND_LINE_SIZE);
|
||||
|
||||
+1
-1
@@ -22813,7 +22813,7 @@ static struct aead_testvec aes_ccm_enc_tv_template[] = {
|
||||
"\x09\x75\x9a\x9b\x3c\x9b\x27\x39",
|
||||
.klen = 32,
|
||||
.iv = "\x03\xf9\xd9\x4e\x63\xb5\x3d\x9d"
|
||||
"\x43\xf6\x1e\x50",
|
||||
"\x43\xf6\x1e\x50\0\0\0\0",
|
||||
.assoc = "\x57\xf5\x6b\x8b\x57\x5c\x3d\x3b"
|
||||
"\x13\x02\x01\x0c\x83\x4c\x96\x35"
|
||||
"\x8e\xd6\x39\xcf\x7d\x14\x9b\x94"
|
||||
|
||||
@@ -1603,7 +1603,7 @@ static size_t sizeof_nfit_set_info(int num_mappings)
|
||||
+ num_mappings * sizeof(struct nfit_set_info_map);
|
||||
}
|
||||
|
||||
static int cmp_map(const void *m0, const void *m1)
|
||||
static int cmp_map_compat(const void *m0, const void *m1)
|
||||
{
|
||||
const struct nfit_set_info_map *map0 = m0;
|
||||
const struct nfit_set_info_map *map1 = m1;
|
||||
@@ -1612,6 +1612,14 @@ static int cmp_map(const void *m0, const void *m1)
|
||||
sizeof(u64));
|
||||
}
|
||||
|
||||
static int cmp_map(const void *m0, const void *m1)
|
||||
{
|
||||
const struct nfit_set_info_map *map0 = m0;
|
||||
const struct nfit_set_info_map *map1 = m1;
|
||||
|
||||
return map0->region_offset - map1->region_offset;
|
||||
}
|
||||
|
||||
/* Retrieve the nth entry referencing this spa */
|
||||
static struct acpi_nfit_memory_map *memdev_from_spa(
|
||||
struct acpi_nfit_desc *acpi_desc, u16 range_index, int n)
|
||||
@@ -1667,6 +1675,12 @@ static int acpi_nfit_init_interleave_set(struct acpi_nfit_desc *acpi_desc,
|
||||
sort(&info->mapping[0], nr, sizeof(struct nfit_set_info_map),
|
||||
cmp_map, NULL);
|
||||
nd_set->cookie = nd_fletcher64(info, sizeof_nfit_set_info(nr), 0);
|
||||
|
||||
/* support namespaces created with the wrong sort order */
|
||||
sort(&info->mapping[0], nr, sizeof(struct nfit_set_info_map),
|
||||
cmp_map_compat, NULL);
|
||||
nd_set->altcookie = nd_fletcher64(info, sizeof_nfit_set_info(nr), 0);
|
||||
|
||||
ndr_desc->nd_set = nd_set;
|
||||
devm_kfree(dev, info);
|
||||
|
||||
|
||||
@@ -633,8 +633,11 @@ static int bcma_device_probe(struct device *dev)
|
||||
drv);
|
||||
int err = 0;
|
||||
|
||||
get_device(dev);
|
||||
if (adrv->probe)
|
||||
err = adrv->probe(core);
|
||||
if (err)
|
||||
put_device(dev);
|
||||
|
||||
return err;
|
||||
}
|
||||
@@ -647,6 +650,7 @@ static int bcma_device_remove(struct device *dev)
|
||||
|
||||
if (adrv->remove)
|
||||
adrv->remove(core);
|
||||
put_device(dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
+20
-12
@@ -1097,9 +1097,12 @@ loop_set_status(struct loop_device *lo, const struct loop_info64 *info)
|
||||
if ((unsigned int) info->lo_encrypt_key_size > LO_KEY_SIZE)
|
||||
return -EINVAL;
|
||||
|
||||
/* I/O need to be drained during transfer transition */
|
||||
blk_mq_freeze_queue(lo->lo_queue);
|
||||
|
||||
err = loop_release_xfer(lo);
|
||||
if (err)
|
||||
return err;
|
||||
goto exit;
|
||||
|
||||
if (info->lo_encrypt_type) {
|
||||
unsigned int type = info->lo_encrypt_type;
|
||||
@@ -1114,12 +1117,14 @@ loop_set_status(struct loop_device *lo, const struct loop_info64 *info)
|
||||
|
||||
err = loop_init_xfer(lo, xfer, info);
|
||||
if (err)
|
||||
return err;
|
||||
goto exit;
|
||||
|
||||
if (lo->lo_offset != info->lo_offset ||
|
||||
lo->lo_sizelimit != info->lo_sizelimit)
|
||||
if (figure_loop_size(lo, info->lo_offset, info->lo_sizelimit))
|
||||
return -EFBIG;
|
||||
if (figure_loop_size(lo, info->lo_offset, info->lo_sizelimit)) {
|
||||
err = -EFBIG;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
loop_config_discard(lo);
|
||||
|
||||
@@ -1137,13 +1142,6 @@ loop_set_status(struct loop_device *lo, const struct loop_info64 *info)
|
||||
(info->lo_flags & LO_FLAGS_AUTOCLEAR))
|
||||
lo->lo_flags ^= LO_FLAGS_AUTOCLEAR;
|
||||
|
||||
if ((info->lo_flags & LO_FLAGS_PARTSCAN) &&
|
||||
!(lo->lo_flags & LO_FLAGS_PARTSCAN)) {
|
||||
lo->lo_flags |= LO_FLAGS_PARTSCAN;
|
||||
lo->lo_disk->flags &= ~GENHD_FL_NO_PART_SCAN;
|
||||
loop_reread_partitions(lo, lo->lo_device);
|
||||
}
|
||||
|
||||
lo->lo_encrypt_key_size = info->lo_encrypt_key_size;
|
||||
lo->lo_init[0] = info->lo_init[0];
|
||||
lo->lo_init[1] = info->lo_init[1];
|
||||
@@ -1156,7 +1154,17 @@ loop_set_status(struct loop_device *lo, const struct loop_info64 *info)
|
||||
/* update dio if lo_offset or transfer is changed */
|
||||
__loop_update_dio(lo, lo->use_dio);
|
||||
|
||||
return 0;
|
||||
exit:
|
||||
blk_mq_unfreeze_queue(lo->lo_queue);
|
||||
|
||||
if (!err && (info->lo_flags & LO_FLAGS_PARTSCAN) &&
|
||||
!(lo->lo_flags & LO_FLAGS_PARTSCAN)) {
|
||||
lo->lo_flags |= LO_FLAGS_PARTSCAN;
|
||||
lo->lo_disk->flags &= ~GENHD_FL_NO_PART_SCAN;
|
||||
loop_reread_partitions(lo, lo->lo_device);
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static int
|
||||
|
||||
@@ -94,6 +94,7 @@ static const struct usb_device_id ath3k_table[] = {
|
||||
{ USB_DEVICE(0x04CA, 0x300f) },
|
||||
{ USB_DEVICE(0x04CA, 0x3010) },
|
||||
{ USB_DEVICE(0x04CA, 0x3014) },
|
||||
{ USB_DEVICE(0x04CA, 0x3018) },
|
||||
{ USB_DEVICE(0x0930, 0x0219) },
|
||||
{ USB_DEVICE(0x0930, 0x021c) },
|
||||
{ USB_DEVICE(0x0930, 0x0220) },
|
||||
@@ -162,6 +163,7 @@ static const struct usb_device_id ath3k_blist_tbl[] = {
|
||||
{ USB_DEVICE(0x04ca, 0x300f), .driver_info = BTUSB_ATH3012 },
|
||||
{ USB_DEVICE(0x04ca, 0x3010), .driver_info = BTUSB_ATH3012 },
|
||||
{ USB_DEVICE(0x04ca, 0x3014), .driver_info = BTUSB_ATH3012 },
|
||||
{ USB_DEVICE(0x04ca, 0x3018), .driver_info = BTUSB_ATH3012 },
|
||||
{ USB_DEVICE(0x0930, 0x0219), .driver_info = BTUSB_ATH3012 },
|
||||
{ USB_DEVICE(0x0930, 0x021c), .driver_info = BTUSB_ATH3012 },
|
||||
{ USB_DEVICE(0x0930, 0x0220), .driver_info = BTUSB_ATH3012 },
|
||||
|
||||
@@ -209,6 +209,7 @@ static const struct usb_device_id blacklist_table[] = {
|
||||
{ USB_DEVICE(0x04ca, 0x300f), .driver_info = BTUSB_ATH3012 },
|
||||
{ USB_DEVICE(0x04ca, 0x3010), .driver_info = BTUSB_ATH3012 },
|
||||
{ USB_DEVICE(0x04ca, 0x3014), .driver_info = BTUSB_ATH3012 },
|
||||
{ USB_DEVICE(0x04ca, 0x3018), .driver_info = BTUSB_ATH3012 },
|
||||
{ USB_DEVICE(0x0930, 0x0219), .driver_info = BTUSB_ATH3012 },
|
||||
{ USB_DEVICE(0x0930, 0x021c), .driver_info = BTUSB_ATH3012 },
|
||||
{ USB_DEVICE(0x0930, 0x0220), .driver_info = BTUSB_ATH3012 },
|
||||
|
||||
@@ -421,7 +421,7 @@ err_pnp:
|
||||
acpi_bus_unregister_driver(&tis_acpi_driver);
|
||||
err_acpi:
|
||||
#endif
|
||||
platform_device_unregister(force_pdev);
|
||||
platform_driver_unregister(&tis_drv);
|
||||
err_platform:
|
||||
if (force_pdev)
|
||||
platform_device_unregister(force_pdev);
|
||||
|
||||
@@ -130,7 +130,7 @@ static void devfreq_set_freq_table(struct devfreq *devfreq)
|
||||
* @devfreq: the devfreq instance
|
||||
* @freq: the update target frequency
|
||||
*/
|
||||
static int devfreq_update_status(struct devfreq *devfreq, unsigned long freq)
|
||||
int devfreq_update_status(struct devfreq *devfreq, unsigned long freq)
|
||||
{
|
||||
int lev, prev_lev, ret = 0;
|
||||
unsigned long cur_time;
|
||||
@@ -166,6 +166,7 @@ out:
|
||||
devfreq->last_stat_updated = cur_time;
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(devfreq_update_status);
|
||||
|
||||
/**
|
||||
* find_devfreq_governor() - find devfreq governor from name
|
||||
@@ -939,6 +940,9 @@ static ssize_t governor_store(struct device *dev, struct device_attribute *attr,
|
||||
if (df->governor == governor) {
|
||||
ret = 0;
|
||||
goto out;
|
||||
} else if (df->governor->immutable || governor->immutable) {
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (df->governor) {
|
||||
@@ -968,13 +972,33 @@ static ssize_t available_governors_show(struct device *d,
|
||||
struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
struct devfreq_governor *tmp_governor;
|
||||
struct devfreq *df = to_devfreq(d);
|
||||
ssize_t count = 0;
|
||||
|
||||
mutex_lock(&devfreq_list_lock);
|
||||
list_for_each_entry(tmp_governor, &devfreq_governor_list, node)
|
||||
count += scnprintf(&buf[count], (PAGE_SIZE - count - 2),
|
||||
"%s ", tmp_governor->name);
|
||||
|
||||
/*
|
||||
* The devfreq with immutable governor (e.g., passive) shows
|
||||
* only own governor.
|
||||
*/
|
||||
if (df->governor->immutable) {
|
||||
count = scnprintf(&buf[count], DEVFREQ_NAME_LEN,
|
||||
"%s ", df->governor_name);
|
||||
/*
|
||||
* The devfreq device shows the registered governor except for
|
||||
* immutable governors such as passive governor .
|
||||
*/
|
||||
} else {
|
||||
struct devfreq_governor *governor;
|
||||
|
||||
list_for_each_entry(governor, &devfreq_governor_list, node) {
|
||||
if (governor->immutable)
|
||||
continue;
|
||||
count += scnprintf(&buf[count], (PAGE_SIZE - count - 2),
|
||||
"%s ", governor->name);
|
||||
}
|
||||
}
|
||||
|
||||
mutex_unlock(&devfreq_list_lock);
|
||||
|
||||
/* Truncate the trailing space */
|
||||
|
||||
@@ -38,4 +38,6 @@ extern void devfreq_interval_update(struct devfreq *devfreq,
|
||||
extern int devfreq_add_governor(struct devfreq_governor *governor);
|
||||
extern int devfreq_remove_governor(struct devfreq_governor *governor);
|
||||
|
||||
extern int devfreq_update_status(struct devfreq *devfreq, unsigned long freq);
|
||||
|
||||
#endif /* _GOVERNOR_H */
|
||||
|
||||
@@ -112,6 +112,11 @@ static int update_devfreq_passive(struct devfreq *devfreq, unsigned long freq)
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
|
||||
if (devfreq->profile->freq_table
|
||||
&& (devfreq_update_status(devfreq, freq)))
|
||||
dev_err(&devfreq->dev,
|
||||
"Couldn't update frequency transition information.\n");
|
||||
|
||||
devfreq->previous_freq = freq;
|
||||
|
||||
out:
|
||||
@@ -179,6 +184,7 @@ static int devfreq_passive_event_handler(struct devfreq *devfreq,
|
||||
|
||||
static struct devfreq_governor devfreq_passive = {
|
||||
.name = "passive",
|
||||
.immutable = 1,
|
||||
.get_target_freq = devfreq_passive_get_target_freq,
|
||||
.event_handler = devfreq_passive_event_handler,
|
||||
};
|
||||
|
||||
@@ -298,6 +298,7 @@ struct sdma_engine;
|
||||
* @event_id1 for channels that use 2 events
|
||||
* @word_size peripheral access size
|
||||
* @buf_tail ID of the buffer that was processed
|
||||
* @buf_ptail ID of the previous buffer that was processed
|
||||
* @num_bd max NUM_BD. number of descriptors currently handling
|
||||
*/
|
||||
struct sdma_channel {
|
||||
@@ -309,6 +310,7 @@ struct sdma_channel {
|
||||
unsigned int event_id1;
|
||||
enum dma_slave_buswidth word_size;
|
||||
unsigned int buf_tail;
|
||||
unsigned int buf_ptail;
|
||||
unsigned int num_bd;
|
||||
unsigned int period_len;
|
||||
struct sdma_buffer_descriptor *bd;
|
||||
@@ -700,6 +702,8 @@ static void sdma_update_channel_loop(struct sdma_channel *sdmac)
|
||||
sdmac->chn_real_count = bd->mode.count;
|
||||
bd->mode.status |= BD_DONE;
|
||||
bd->mode.count = sdmac->period_len;
|
||||
sdmac->buf_ptail = sdmac->buf_tail;
|
||||
sdmac->buf_tail = (sdmac->buf_tail + 1) % sdmac->num_bd;
|
||||
|
||||
/*
|
||||
* The callback is called from the interrupt context in order
|
||||
@@ -710,9 +714,6 @@ static void sdma_update_channel_loop(struct sdma_channel *sdmac)
|
||||
|
||||
dmaengine_desc_get_callback_invoke(&sdmac->desc, NULL);
|
||||
|
||||
sdmac->buf_tail++;
|
||||
sdmac->buf_tail %= sdmac->num_bd;
|
||||
|
||||
if (error)
|
||||
sdmac->status = old_status;
|
||||
}
|
||||
@@ -1186,6 +1187,8 @@ static struct dma_async_tx_descriptor *sdma_prep_slave_sg(
|
||||
sdmac->flags = 0;
|
||||
|
||||
sdmac->buf_tail = 0;
|
||||
sdmac->buf_ptail = 0;
|
||||
sdmac->chn_real_count = 0;
|
||||
|
||||
dev_dbg(sdma->dev, "setting up %d entries for channel %d.\n",
|
||||
sg_len, channel);
|
||||
@@ -1288,6 +1291,8 @@ static struct dma_async_tx_descriptor *sdma_prep_dma_cyclic(
|
||||
sdmac->status = DMA_IN_PROGRESS;
|
||||
|
||||
sdmac->buf_tail = 0;
|
||||
sdmac->buf_ptail = 0;
|
||||
sdmac->chn_real_count = 0;
|
||||
sdmac->period_len = period_len;
|
||||
|
||||
sdmac->flags |= IMX_DMA_SG_LOOP;
|
||||
@@ -1385,7 +1390,7 @@ static enum dma_status sdma_tx_status(struct dma_chan *chan,
|
||||
u32 residue;
|
||||
|
||||
if (sdmac->flags & IMX_DMA_SG_LOOP)
|
||||
residue = (sdmac->num_bd - sdmac->buf_tail) *
|
||||
residue = (sdmac->num_bd - sdmac->buf_ptail) *
|
||||
sdmac->period_len - sdmac->chn_real_count;
|
||||
else
|
||||
residue = sdmac->chn_count - sdmac->chn_real_count;
|
||||
|
||||
@@ -272,7 +272,7 @@ static void ipu_irq_handler(struct irq_desc *desc)
|
||||
u32 status;
|
||||
int i, line;
|
||||
|
||||
for (i = IPU_IRQ_NR_FN_BANKS; i < IPU_IRQ_NR_BANKS; i++) {
|
||||
for (i = 0; i < IPU_IRQ_NR_BANKS; i++) {
|
||||
struct ipu_irq_bank *bank = irq_bank + i;
|
||||
|
||||
raw_spin_lock(&bank_lock);
|
||||
|
||||
@@ -3814,9 +3814,15 @@ static void dce_v11_0_encoder_add(struct amdgpu_device *adev,
|
||||
default:
|
||||
encoder->possible_crtcs = 0x3;
|
||||
break;
|
||||
case 3:
|
||||
encoder->possible_crtcs = 0x7;
|
||||
break;
|
||||
case 4:
|
||||
encoder->possible_crtcs = 0xf;
|
||||
break;
|
||||
case 5:
|
||||
encoder->possible_crtcs = 0x1f;
|
||||
break;
|
||||
case 6:
|
||||
encoder->possible_crtcs = 0x3f;
|
||||
break;
|
||||
|
||||
@@ -58,13 +58,9 @@ bool ast_is_vga_enabled(struct drm_device *dev)
|
||||
/* TODO 1180 */
|
||||
} else {
|
||||
ch = ast_io_read8(ast, AST_IO_VGA_ENABLE_PORT);
|
||||
if (ch) {
|
||||
ast_open_key(ast);
|
||||
ch = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xb6, 0xff);
|
||||
return ch & 0x04;
|
||||
}
|
||||
return !!(ch & 0x01);
|
||||
}
|
||||
return 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
static const u8 extreginfo[] = { 0x0f, 0x04, 0x1c, 0xff };
|
||||
@@ -375,8 +371,8 @@ void ast_post_gpu(struct drm_device *dev)
|
||||
pci_write_config_dword(ast->dev->pdev, 0x04, reg);
|
||||
|
||||
ast_enable_vga(dev);
|
||||
ast_enable_mmio(dev);
|
||||
ast_open_key(ast);
|
||||
ast_enable_mmio(dev);
|
||||
ast_set_def_ext_reg(dev);
|
||||
|
||||
if (ast->chip == AST2300 || ast->chip == AST2400)
|
||||
@@ -1630,12 +1626,44 @@ static void ast_init_dram_2300(struct drm_device *dev)
|
||||
temp |= 0x73;
|
||||
ast_write32(ast, 0x12008, temp);
|
||||
|
||||
param.dram_freq = 396;
|
||||
param.dram_type = AST_DDR3;
|
||||
temp = ast_mindwm(ast, 0x1e6e2070);
|
||||
if (temp & 0x01000000)
|
||||
param.dram_type = AST_DDR2;
|
||||
param.dram_chipid = ast->dram_type;
|
||||
param.dram_freq = ast->mclk;
|
||||
param.vram_size = ast->vram_size;
|
||||
switch (temp & 0x18000000) {
|
||||
case 0:
|
||||
param.dram_chipid = AST_DRAM_512Mx16;
|
||||
break;
|
||||
default:
|
||||
case 0x08000000:
|
||||
param.dram_chipid = AST_DRAM_1Gx16;
|
||||
break;
|
||||
case 0x10000000:
|
||||
param.dram_chipid = AST_DRAM_2Gx16;
|
||||
break;
|
||||
case 0x18000000:
|
||||
param.dram_chipid = AST_DRAM_4Gx16;
|
||||
break;
|
||||
}
|
||||
switch (temp & 0x0c) {
|
||||
default:
|
||||
case 0x00:
|
||||
param.vram_size = AST_VIDMEM_SIZE_8M;
|
||||
break;
|
||||
|
||||
case 0x04:
|
||||
param.vram_size = AST_VIDMEM_SIZE_16M;
|
||||
break;
|
||||
|
||||
case 0x08:
|
||||
param.vram_size = AST_VIDMEM_SIZE_32M;
|
||||
break;
|
||||
|
||||
case 0x0c:
|
||||
param.vram_size = AST_VIDMEM_SIZE_64M;
|
||||
break;
|
||||
}
|
||||
|
||||
if (param.dram_type == AST_DDR3) {
|
||||
get_ddr3_info(ast, ¶m);
|
||||
|
||||
@@ -362,7 +362,7 @@ mode_fixup(struct drm_atomic_state *state)
|
||||
struct drm_connector *connector;
|
||||
struct drm_connector_state *conn_state;
|
||||
int i;
|
||||
bool ret;
|
||||
int ret;
|
||||
|
||||
for_each_crtc_in_state(state, crtc, crtc_state, i) {
|
||||
if (!crtc_state->mode_changed &&
|
||||
|
||||
@@ -145,6 +145,9 @@ static struct edid_quirk {
|
||||
|
||||
/* Panel in Samsung NP700G7A-S01PL notebook reports 6bpc */
|
||||
{ "SEC", 0xd033, EDID_QUIRK_FORCE_8BPC },
|
||||
|
||||
/* Rotel RSX-1058 forwards sink's EDID but only does HDMI 1.1*/
|
||||
{ "ETR", 13896, EDID_QUIRK_FORCE_8BPC },
|
||||
};
|
||||
|
||||
/*
|
||||
|
||||
@@ -848,6 +848,9 @@ void drm_fb_helper_fini(struct drm_fb_helper *fb_helper)
|
||||
if (!drm_fbdev_emulation)
|
||||
return;
|
||||
|
||||
cancel_work_sync(&fb_helper->resume_work);
|
||||
cancel_work_sync(&fb_helper->dirty_work);
|
||||
|
||||
if (!list_empty(&fb_helper->kernel_fb_list)) {
|
||||
list_del(&fb_helper->kernel_fb_list);
|
||||
if (list_empty(&kernel_fb_helper_list)) {
|
||||
|
||||
@@ -415,6 +415,11 @@ int i915_gem_init_stolen(struct drm_device *dev)
|
||||
|
||||
mutex_init(&dev_priv->mm.stolen_lock);
|
||||
|
||||
if (intel_vgpu_active(dev_priv)) {
|
||||
DRM_INFO("iGVT-g active, disabling use of stolen memory\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_INTEL_IOMMU
|
||||
if (intel_iommu_gfx_mapped && INTEL_INFO(dev)->gen < 8) {
|
||||
DRM_INFO("DMAR active, disabling use of stolen memory\n");
|
||||
|
||||
@@ -2832,6 +2832,9 @@ static void vlv_detach_power_sequencer(struct intel_dp *intel_dp)
|
||||
enum pipe pipe = intel_dp->pps_pipe;
|
||||
i915_reg_t pp_on_reg = PP_ON_DELAYS(pipe);
|
||||
|
||||
if (WARN_ON(pipe != PIPE_A && pipe != PIPE_B))
|
||||
return;
|
||||
|
||||
edp_panel_vdd_off_sync(intel_dp);
|
||||
|
||||
/*
|
||||
@@ -2859,9 +2862,6 @@ static void vlv_steal_power_sequencer(struct drm_device *dev,
|
||||
|
||||
lockdep_assert_held(&dev_priv->pps_mutex);
|
||||
|
||||
if (WARN_ON(pipe != PIPE_A && pipe != PIPE_B))
|
||||
return;
|
||||
|
||||
for_each_intel_encoder(dev, encoder) {
|
||||
struct intel_dp *intel_dp;
|
||||
enum port port;
|
||||
|
||||
@@ -1031,7 +1031,18 @@ int intel_opregion_setup(struct drm_i915_private *dev_priv)
|
||||
opregion->vbt_size = vbt_size;
|
||||
} else {
|
||||
vbt = base + OPREGION_VBT_OFFSET;
|
||||
vbt_size = OPREGION_ASLE_EXT_OFFSET - OPREGION_VBT_OFFSET;
|
||||
/*
|
||||
* The VBT specification says that if the ASLE ext
|
||||
* mailbox is not used its area is reserved, but
|
||||
* on some CHT boards the VBT extends into the
|
||||
* ASLE ext area. Allow this even though it is
|
||||
* against the spec, so we do not end up rejecting
|
||||
* the VBT on those boards (and end up not finding the
|
||||
* LCD panel because of this).
|
||||
*/
|
||||
vbt_size = (mboxes & MBOX_ASLE_EXT) ?
|
||||
OPREGION_ASLE_EXT_OFFSET : OPREGION_SIZE;
|
||||
vbt_size -= OPREGION_VBT_OFFSET;
|
||||
if (intel_bios_is_valid_vbt(vbt, vbt_size)) {
|
||||
DRM_DEBUG_KMS("Found valid VBT in ACPI OpRegion (Mailbox #4)\n");
|
||||
opregion->vbt = vbt;
|
||||
|
||||
@@ -98,6 +98,8 @@
|
||||
/* TVE_TST_MODE_REG */
|
||||
#define TVE_TVDAC_TEST_MODE_MASK (0x7 << 0)
|
||||
|
||||
#define IMX_TVE_DAC_VOLTAGE 2750000
|
||||
|
||||
enum {
|
||||
TVE_MODE_TVOUT,
|
||||
TVE_MODE_VGA,
|
||||
@@ -628,9 +630,8 @@ static int imx_tve_bind(struct device *dev, struct device *master, void *data)
|
||||
|
||||
tve->dac_reg = devm_regulator_get(dev, "dac");
|
||||
if (!IS_ERR(tve->dac_reg)) {
|
||||
ret = regulator_set_voltage(tve->dac_reg, 2750000, 2750000);
|
||||
if (ret)
|
||||
return ret;
|
||||
if (regulator_get_voltage(tve->dac_reg) != IMX_TVE_DAC_VOLTAGE)
|
||||
dev_warn(dev, "dac voltage is not %d uV\n", IMX_TVE_DAC_VOLTAGE);
|
||||
ret = regulator_enable(tve->dac_reg);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
@@ -1654,7 +1654,6 @@ static int ttm_bo_swapout(struct ttm_mem_shrink *shrink)
|
||||
struct ttm_buffer_object *bo;
|
||||
int ret = -EBUSY;
|
||||
int put_count;
|
||||
uint32_t swap_placement = (TTM_PL_FLAG_CACHED | TTM_PL_FLAG_SYSTEM);
|
||||
|
||||
spin_lock(&glob->lru_lock);
|
||||
list_for_each_entry(bo, &glob->swap_lru, swap) {
|
||||
@@ -1685,7 +1684,8 @@ static int ttm_bo_swapout(struct ttm_mem_shrink *shrink)
|
||||
* Move to system cached
|
||||
*/
|
||||
|
||||
if ((bo->mem.placement & swap_placement) != swap_placement) {
|
||||
if (bo->mem.mem_type != TTM_PL_SYSTEM ||
|
||||
bo->ttm->caching_state != tt_cached) {
|
||||
struct ttm_mem_reg evict_mem;
|
||||
|
||||
evict_mem = bo->mem;
|
||||
|
||||
@@ -199,9 +199,14 @@ static const struct drm_ioctl_desc vmw_ioctls[] = {
|
||||
VMW_IOCTL_DEF(VMW_PRESENT_READBACK,
|
||||
vmw_present_readback_ioctl,
|
||||
DRM_MASTER | DRM_AUTH),
|
||||
/*
|
||||
* The permissions of the below ioctl are overridden in
|
||||
* vmw_generic_ioctl(). We require either
|
||||
* DRM_MASTER or capable(CAP_SYS_ADMIN).
|
||||
*/
|
||||
VMW_IOCTL_DEF(VMW_UPDATE_LAYOUT,
|
||||
vmw_kms_update_layout_ioctl,
|
||||
DRM_MASTER | DRM_CONTROL_ALLOW),
|
||||
DRM_RENDER_ALLOW),
|
||||
VMW_IOCTL_DEF(VMW_CREATE_SHADER,
|
||||
vmw_shader_define_ioctl,
|
||||
DRM_AUTH | DRM_RENDER_ALLOW),
|
||||
@@ -1125,6 +1130,10 @@ static long vmw_generic_ioctl(struct file *filp, unsigned int cmd,
|
||||
|
||||
return (long) vmw_execbuf_ioctl(dev, arg, file_priv,
|
||||
_IOC_SIZE(cmd));
|
||||
} else if (nr == DRM_COMMAND_BASE + DRM_VMW_UPDATE_LAYOUT) {
|
||||
if (!drm_is_current_master(file_priv) &&
|
||||
!capable(CAP_SYS_ADMIN))
|
||||
return -EACCES;
|
||||
}
|
||||
|
||||
if (unlikely(ioctl->cmd != cmd))
|
||||
|
||||
@@ -41,9 +41,9 @@
|
||||
#include <drm/ttm/ttm_module.h>
|
||||
#include "vmwgfx_fence.h"
|
||||
|
||||
#define VMWGFX_DRIVER_DATE "20160210"
|
||||
#define VMWGFX_DRIVER_DATE "20170221"
|
||||
#define VMWGFX_DRIVER_MAJOR 2
|
||||
#define VMWGFX_DRIVER_MINOR 11
|
||||
#define VMWGFX_DRIVER_MINOR 12
|
||||
#define VMWGFX_DRIVER_PATCHLEVEL 0
|
||||
#define VMWGFX_FILE_PAGE_OFFSET 0x00100000
|
||||
#define VMWGFX_FIFO_STATIC_SIZE (1024*1024)
|
||||
|
||||
+27
-8
@@ -157,6 +157,7 @@ int vmbus_open(struct vmbus_channel *newchannel, u32 send_ringbuffer_size,
|
||||
}
|
||||
|
||||
init_completion(&open_info->waitevent);
|
||||
open_info->waiting_channel = newchannel;
|
||||
|
||||
open_msg = (struct vmbus_channel_open_channel *)open_info->msg;
|
||||
open_msg->header.msgtype = CHANNELMSG_OPENCHANNEL;
|
||||
@@ -181,7 +182,7 @@ int vmbus_open(struct vmbus_channel *newchannel, u32 send_ringbuffer_size,
|
||||
spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock, flags);
|
||||
|
||||
ret = vmbus_post_msg(open_msg,
|
||||
sizeof(struct vmbus_channel_open_channel));
|
||||
sizeof(struct vmbus_channel_open_channel), true);
|
||||
|
||||
if (ret != 0) {
|
||||
err = ret;
|
||||
@@ -194,6 +195,11 @@ int vmbus_open(struct vmbus_channel *newchannel, u32 send_ringbuffer_size,
|
||||
list_del(&open_info->msglistentry);
|
||||
spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock, flags);
|
||||
|
||||
if (newchannel->rescind) {
|
||||
err = -ENODEV;
|
||||
goto error_free_gpadl;
|
||||
}
|
||||
|
||||
if (open_info->response.open_result.status) {
|
||||
err = -EAGAIN;
|
||||
goto error_free_gpadl;
|
||||
@@ -233,7 +239,7 @@ int vmbus_send_tl_connect_request(const uuid_le *shv_guest_servie_id,
|
||||
conn_msg.guest_endpoint_id = *shv_guest_servie_id;
|
||||
conn_msg.host_service_id = *shv_host_servie_id;
|
||||
|
||||
return vmbus_post_msg(&conn_msg, sizeof(conn_msg));
|
||||
return vmbus_post_msg(&conn_msg, sizeof(conn_msg), true);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(vmbus_send_tl_connect_request);
|
||||
|
||||
@@ -405,6 +411,7 @@ int vmbus_establish_gpadl(struct vmbus_channel *channel, void *kbuffer,
|
||||
return ret;
|
||||
|
||||
init_completion(&msginfo->waitevent);
|
||||
msginfo->waiting_channel = channel;
|
||||
|
||||
gpadlmsg = (struct vmbus_channel_gpadl_header *)msginfo->msg;
|
||||
gpadlmsg->header.msgtype = CHANNELMSG_GPADL_HEADER;
|
||||
@@ -419,7 +426,7 @@ int vmbus_establish_gpadl(struct vmbus_channel *channel, void *kbuffer,
|
||||
spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock, flags);
|
||||
|
||||
ret = vmbus_post_msg(gpadlmsg, msginfo->msgsize -
|
||||
sizeof(*msginfo));
|
||||
sizeof(*msginfo), true);
|
||||
if (ret != 0)
|
||||
goto cleanup;
|
||||
|
||||
@@ -433,14 +440,19 @@ int vmbus_establish_gpadl(struct vmbus_channel *channel, void *kbuffer,
|
||||
gpadl_body->gpadl = next_gpadl_handle;
|
||||
|
||||
ret = vmbus_post_msg(gpadl_body,
|
||||
submsginfo->msgsize -
|
||||
sizeof(*submsginfo));
|
||||
submsginfo->msgsize - sizeof(*submsginfo),
|
||||
true);
|
||||
if (ret != 0)
|
||||
goto cleanup;
|
||||
|
||||
}
|
||||
wait_for_completion(&msginfo->waitevent);
|
||||
|
||||
if (channel->rescind) {
|
||||
ret = -ENODEV;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/* At this point, we received the gpadl created msg */
|
||||
*gpadl_handle = gpadlmsg->gpadl;
|
||||
|
||||
@@ -474,6 +486,7 @@ int vmbus_teardown_gpadl(struct vmbus_channel *channel, u32 gpadl_handle)
|
||||
return -ENOMEM;
|
||||
|
||||
init_completion(&info->waitevent);
|
||||
info->waiting_channel = channel;
|
||||
|
||||
msg = (struct vmbus_channel_gpadl_teardown *)info->msg;
|
||||
|
||||
@@ -485,14 +498,19 @@ int vmbus_teardown_gpadl(struct vmbus_channel *channel, u32 gpadl_handle)
|
||||
list_add_tail(&info->msglistentry,
|
||||
&vmbus_connection.chn_msg_list);
|
||||
spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock, flags);
|
||||
ret = vmbus_post_msg(msg,
|
||||
sizeof(struct vmbus_channel_gpadl_teardown));
|
||||
ret = vmbus_post_msg(msg, sizeof(struct vmbus_channel_gpadl_teardown),
|
||||
true);
|
||||
|
||||
if (ret)
|
||||
goto post_msg_err;
|
||||
|
||||
wait_for_completion(&info->waitevent);
|
||||
|
||||
if (channel->rescind) {
|
||||
ret = -ENODEV;
|
||||
goto post_msg_err;
|
||||
}
|
||||
|
||||
post_msg_err:
|
||||
spin_lock_irqsave(&vmbus_connection.channelmsg_lock, flags);
|
||||
list_del(&info->msglistentry);
|
||||
@@ -557,7 +575,8 @@ static int vmbus_close_internal(struct vmbus_channel *channel)
|
||||
msg->header.msgtype = CHANNELMSG_CLOSECHANNEL;
|
||||
msg->child_relid = channel->offermsg.child_relid;
|
||||
|
||||
ret = vmbus_post_msg(msg, sizeof(struct vmbus_channel_close_channel));
|
||||
ret = vmbus_post_msg(msg, sizeof(struct vmbus_channel_close_channel),
|
||||
true);
|
||||
|
||||
if (ret) {
|
||||
pr_err("Close failed: close post msg return is %d\n", ret);
|
||||
|
||||
@@ -147,6 +147,29 @@ static const struct {
|
||||
{ HV_RDV_GUID },
|
||||
};
|
||||
|
||||
/*
|
||||
* The rescinded channel may be blocked waiting for a response from the host;
|
||||
* take care of that.
|
||||
*/
|
||||
static void vmbus_rescind_cleanup(struct vmbus_channel *channel)
|
||||
{
|
||||
struct vmbus_channel_msginfo *msginfo;
|
||||
unsigned long flags;
|
||||
|
||||
|
||||
spin_lock_irqsave(&vmbus_connection.channelmsg_lock, flags);
|
||||
|
||||
list_for_each_entry(msginfo, &vmbus_connection.chn_msg_list,
|
||||
msglistentry) {
|
||||
|
||||
if (msginfo->waiting_channel == channel) {
|
||||
complete(&msginfo->waitevent);
|
||||
break;
|
||||
}
|
||||
}
|
||||
spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock, flags);
|
||||
}
|
||||
|
||||
static bool is_unsupported_vmbus_devs(const uuid_le *guid)
|
||||
{
|
||||
int i;
|
||||
@@ -321,7 +344,8 @@ static void vmbus_release_relid(u32 relid)
|
||||
memset(&msg, 0, sizeof(struct vmbus_channel_relid_released));
|
||||
msg.child_relid = relid;
|
||||
msg.header.msgtype = CHANNELMSG_RELID_RELEASED;
|
||||
vmbus_post_msg(&msg, sizeof(struct vmbus_channel_relid_released));
|
||||
vmbus_post_msg(&msg, sizeof(struct vmbus_channel_relid_released),
|
||||
true);
|
||||
}
|
||||
|
||||
void hv_event_tasklet_disable(struct vmbus_channel *channel)
|
||||
@@ -728,7 +752,8 @@ void vmbus_initiate_unload(bool crash)
|
||||
init_completion(&vmbus_connection.unload_event);
|
||||
memset(&hdr, 0, sizeof(struct vmbus_channel_message_header));
|
||||
hdr.msgtype = CHANNELMSG_UNLOAD;
|
||||
vmbus_post_msg(&hdr, sizeof(struct vmbus_channel_message_header));
|
||||
vmbus_post_msg(&hdr, sizeof(struct vmbus_channel_message_header),
|
||||
!crash);
|
||||
|
||||
/*
|
||||
* vmbus_initiate_unload() is also called on crash and the crash can be
|
||||
@@ -823,6 +848,8 @@ static void vmbus_onoffer_rescind(struct vmbus_channel_message_header *hdr)
|
||||
channel->rescind = true;
|
||||
spin_unlock_irqrestore(&channel->lock, flags);
|
||||
|
||||
vmbus_rescind_cleanup(channel);
|
||||
|
||||
if (channel->device_obj) {
|
||||
if (channel->chn_rescind_callback) {
|
||||
channel->chn_rescind_callback(channel);
|
||||
@@ -1116,8 +1143,8 @@ int vmbus_request_offers(void)
|
||||
msg->msgtype = CHANNELMSG_REQUESTOFFERS;
|
||||
|
||||
|
||||
ret = vmbus_post_msg(msg,
|
||||
sizeof(struct vmbus_channel_message_header));
|
||||
ret = vmbus_post_msg(msg, sizeof(struct vmbus_channel_message_header),
|
||||
true);
|
||||
if (ret != 0) {
|
||||
pr_err("Unable to request offers - %d\n", ret);
|
||||
|
||||
|
||||
+12
-5
@@ -110,7 +110,8 @@ static int vmbus_negotiate_version(struct vmbus_channel_msginfo *msginfo,
|
||||
spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock, flags);
|
||||
|
||||
ret = vmbus_post_msg(msg,
|
||||
sizeof(struct vmbus_channel_initiate_contact));
|
||||
sizeof(struct vmbus_channel_initiate_contact),
|
||||
true);
|
||||
if (ret != 0) {
|
||||
spin_lock_irqsave(&vmbus_connection.channelmsg_lock, flags);
|
||||
list_del(&msginfo->msglistentry);
|
||||
@@ -434,7 +435,7 @@ void vmbus_on_event(unsigned long data)
|
||||
/*
|
||||
* vmbus_post_msg - Send a msg on the vmbus's message connection
|
||||
*/
|
||||
int vmbus_post_msg(void *buffer, size_t buflen)
|
||||
int vmbus_post_msg(void *buffer, size_t buflen, bool can_sleep)
|
||||
{
|
||||
union hv_connection_id conn_id;
|
||||
int ret = 0;
|
||||
@@ -449,7 +450,7 @@ int vmbus_post_msg(void *buffer, size_t buflen)
|
||||
* insufficient resources. Retry the operation a couple of
|
||||
* times before giving up.
|
||||
*/
|
||||
while (retries < 20) {
|
||||
while (retries < 100) {
|
||||
ret = hv_post_message(conn_id, 1, buffer, buflen);
|
||||
|
||||
switch (ret) {
|
||||
@@ -472,8 +473,14 @@ int vmbus_post_msg(void *buffer, size_t buflen)
|
||||
}
|
||||
|
||||
retries++;
|
||||
udelay(usec);
|
||||
if (usec < 2048)
|
||||
if (can_sleep && usec > 1000)
|
||||
msleep(usec / 1000);
|
||||
else if (usec < MAX_UDELAY_MS * 1000)
|
||||
udelay(usec);
|
||||
else
|
||||
mdelay(usec / 1000);
|
||||
|
||||
if (usec < 256000)
|
||||
usec *= 2;
|
||||
}
|
||||
return ret;
|
||||
|
||||
+8
-7
@@ -220,7 +220,7 @@ int hv_init(void)
|
||||
/* See if the hypercall page is already set */
|
||||
rdmsrl(HV_X64_MSR_HYPERCALL, hypercall_msr.as_uint64);
|
||||
|
||||
virtaddr = __vmalloc(PAGE_SIZE, GFP_KERNEL, PAGE_KERNEL_EXEC);
|
||||
virtaddr = __vmalloc(PAGE_SIZE, GFP_KERNEL, PAGE_KERNEL_RX);
|
||||
|
||||
if (!virtaddr)
|
||||
goto cleanup;
|
||||
@@ -309,9 +309,10 @@ void hv_cleanup(bool crash)
|
||||
|
||||
hypercall_msr.as_uint64 = 0;
|
||||
wrmsrl(HV_X64_MSR_REFERENCE_TSC, hypercall_msr.as_uint64);
|
||||
if (!crash)
|
||||
if (!crash) {
|
||||
vfree(hv_context.tsc_page);
|
||||
hv_context.tsc_page = NULL;
|
||||
hv_context.tsc_page = NULL;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
@@ -411,7 +412,7 @@ int hv_synic_alloc(void)
|
||||
goto err;
|
||||
}
|
||||
|
||||
for_each_online_cpu(cpu) {
|
||||
for_each_present_cpu(cpu) {
|
||||
hv_context.event_dpc[cpu] = kmalloc(size, GFP_ATOMIC);
|
||||
if (hv_context.event_dpc[cpu] == NULL) {
|
||||
pr_err("Unable to allocate event dpc\n");
|
||||
@@ -457,6 +458,8 @@ int hv_synic_alloc(void)
|
||||
pr_err("Unable to allocate post msg page\n");
|
||||
goto err;
|
||||
}
|
||||
|
||||
INIT_LIST_HEAD(&hv_context.percpu_list[cpu]);
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -482,7 +485,7 @@ void hv_synic_free(void)
|
||||
int cpu;
|
||||
|
||||
kfree(hv_context.hv_numa_map);
|
||||
for_each_online_cpu(cpu)
|
||||
for_each_present_cpu(cpu)
|
||||
hv_synic_free_cpu(cpu);
|
||||
}
|
||||
|
||||
@@ -552,8 +555,6 @@ void hv_synic_init(void *arg)
|
||||
rdmsrl(HV_X64_MSR_VP_INDEX, vp_index);
|
||||
hv_context.vp_index[cpu] = (u32)vp_index;
|
||||
|
||||
INIT_LIST_HEAD(&hv_context.percpu_list[cpu]);
|
||||
|
||||
/*
|
||||
* Register the per-cpu clockevent source.
|
||||
*/
|
||||
|
||||
@@ -61,6 +61,7 @@ static DECLARE_WORK(fcopy_send_work, fcopy_send_data);
|
||||
static const char fcopy_devname[] = "vmbus/hv_fcopy";
|
||||
static u8 *recv_buffer;
|
||||
static struct hvutil_transport *hvt;
|
||||
static struct completion release_event;
|
||||
/*
|
||||
* This state maintains the version number registered by the daemon.
|
||||
*/
|
||||
@@ -317,6 +318,7 @@ static void fcopy_on_reset(void)
|
||||
|
||||
if (cancel_delayed_work_sync(&fcopy_timeout_work))
|
||||
fcopy_respond_to_host(HV_E_FAIL);
|
||||
complete(&release_event);
|
||||
}
|
||||
|
||||
int hv_fcopy_init(struct hv_util_service *srv)
|
||||
@@ -324,6 +326,7 @@ int hv_fcopy_init(struct hv_util_service *srv)
|
||||
recv_buffer = srv->recv_buffer;
|
||||
fcopy_transaction.recv_channel = srv->channel;
|
||||
|
||||
init_completion(&release_event);
|
||||
/*
|
||||
* When this driver loads, the user level daemon that
|
||||
* processes the host requests may not yet be running.
|
||||
@@ -345,4 +348,5 @@ void hv_fcopy_deinit(void)
|
||||
fcopy_transaction.state = HVUTIL_DEVICE_DYING;
|
||||
cancel_delayed_work_sync(&fcopy_timeout_work);
|
||||
hvutil_transport_destroy(hvt);
|
||||
wait_for_completion(&release_event);
|
||||
}
|
||||
|
||||
@@ -88,6 +88,7 @@ static DECLARE_WORK(kvp_sendkey_work, kvp_send_key);
|
||||
static const char kvp_devname[] = "vmbus/hv_kvp";
|
||||
static u8 *recv_buffer;
|
||||
static struct hvutil_transport *hvt;
|
||||
static struct completion release_event;
|
||||
/*
|
||||
* Register the kernel component with the user-level daemon.
|
||||
* As part of this registration, pass the LIC version number.
|
||||
@@ -716,6 +717,7 @@ static void kvp_on_reset(void)
|
||||
if (cancel_delayed_work_sync(&kvp_timeout_work))
|
||||
kvp_respond_to_host(NULL, HV_E_FAIL);
|
||||
kvp_transaction.state = HVUTIL_DEVICE_INIT;
|
||||
complete(&release_event);
|
||||
}
|
||||
|
||||
int
|
||||
@@ -724,6 +726,7 @@ hv_kvp_init(struct hv_util_service *srv)
|
||||
recv_buffer = srv->recv_buffer;
|
||||
kvp_transaction.recv_channel = srv->channel;
|
||||
|
||||
init_completion(&release_event);
|
||||
/*
|
||||
* When this driver loads, the user level daemon that
|
||||
* processes the host requests may not yet be running.
|
||||
@@ -747,4 +750,5 @@ void hv_kvp_deinit(void)
|
||||
cancel_delayed_work_sync(&kvp_timeout_work);
|
||||
cancel_work_sync(&kvp_sendkey_work);
|
||||
hvutil_transport_destroy(hvt);
|
||||
wait_for_completion(&release_event);
|
||||
}
|
||||
|
||||
@@ -66,6 +66,7 @@ static int dm_reg_value;
|
||||
static const char vss_devname[] = "vmbus/hv_vss";
|
||||
static __u8 *recv_buffer;
|
||||
static struct hvutil_transport *hvt;
|
||||
static struct completion release_event;
|
||||
|
||||
static void vss_timeout_func(struct work_struct *dummy);
|
||||
static void vss_handle_request(struct work_struct *dummy);
|
||||
@@ -330,11 +331,13 @@ static void vss_on_reset(void)
|
||||
if (cancel_delayed_work_sync(&vss_timeout_work))
|
||||
vss_respond_to_host(HV_E_FAIL);
|
||||
vss_transaction.state = HVUTIL_DEVICE_INIT;
|
||||
complete(&release_event);
|
||||
}
|
||||
|
||||
int
|
||||
hv_vss_init(struct hv_util_service *srv)
|
||||
{
|
||||
init_completion(&release_event);
|
||||
if (vmbus_proto_version < VERSION_WIN8_1) {
|
||||
pr_warn("Integration service 'Backup (volume snapshot)'"
|
||||
" not supported on this host version.\n");
|
||||
@@ -365,4 +368,5 @@ void hv_vss_deinit(void)
|
||||
cancel_delayed_work_sync(&vss_timeout_work);
|
||||
cancel_work_sync(&vss_handle_request_work);
|
||||
hvutil_transport_destroy(hvt);
|
||||
wait_for_completion(&release_event);
|
||||
}
|
||||
|
||||
@@ -683,7 +683,7 @@ void vmbus_free_channels(void);
|
||||
int vmbus_connect(void);
|
||||
void vmbus_disconnect(void);
|
||||
|
||||
int vmbus_post_msg(void *buffer, size_t buflen);
|
||||
int vmbus_post_msg(void *buffer, size_t buflen, bool can_sleep);
|
||||
|
||||
void vmbus_on_event(unsigned long data);
|
||||
void vmbus_on_msg_dpc(unsigned long data);
|
||||
|
||||
@@ -298,6 +298,9 @@ int hv_ringbuffer_write(struct vmbus_channel *channel,
|
||||
unsigned long flags = 0;
|
||||
struct hv_ring_buffer_info *outring_info = &channel->outbound;
|
||||
|
||||
if (channel->rescind)
|
||||
return -ENODEV;
|
||||
|
||||
for (i = 0; i < kv_count; i++)
|
||||
totalbytes_towrite += kv_list[i].iov_len;
|
||||
|
||||
@@ -350,6 +353,10 @@ int hv_ringbuffer_write(struct vmbus_channel *channel,
|
||||
spin_unlock_irqrestore(&outring_info->ring_lock, flags);
|
||||
|
||||
hv_signal_on_write(old_write, channel, kick_q);
|
||||
|
||||
if (channel->rescind)
|
||||
return -ENODEV;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
+26
-13
@@ -1300,25 +1300,35 @@ static ssize_t set_pwm_enable(struct device *dev, struct device_attribute *attr,
|
||||
it87_write_value(data, IT87_REG_FAN_MAIN_CTRL,
|
||||
data->fan_main_ctrl);
|
||||
} else {
|
||||
u8 ctrl;
|
||||
|
||||
/* No on/off mode, set maximum pwm value */
|
||||
data->pwm_duty[nr] = pwm_to_reg(data, 0xff);
|
||||
it87_write_value(data, IT87_REG_PWM_DUTY[nr],
|
||||
data->pwm_duty[nr]);
|
||||
/* and set manual mode */
|
||||
data->pwm_ctrl[nr] = has_newer_autopwm(data) ?
|
||||
data->pwm_temp_map[nr] :
|
||||
data->pwm_duty[nr];
|
||||
it87_write_value(data, IT87_REG_PWM[nr],
|
||||
data->pwm_ctrl[nr]);
|
||||
if (has_newer_autopwm(data)) {
|
||||
ctrl = (data->pwm_ctrl[nr] & 0x7c) |
|
||||
data->pwm_temp_map[nr];
|
||||
} else {
|
||||
ctrl = data->pwm_duty[nr];
|
||||
}
|
||||
data->pwm_ctrl[nr] = ctrl;
|
||||
it87_write_value(data, IT87_REG_PWM[nr], ctrl);
|
||||
}
|
||||
} else {
|
||||
if (val == 1) /* Manual mode */
|
||||
data->pwm_ctrl[nr] = has_newer_autopwm(data) ?
|
||||
data->pwm_temp_map[nr] :
|
||||
data->pwm_duty[nr];
|
||||
else /* Automatic mode */
|
||||
data->pwm_ctrl[nr] = 0x80 | data->pwm_temp_map[nr];
|
||||
it87_write_value(data, IT87_REG_PWM[nr], data->pwm_ctrl[nr]);
|
||||
u8 ctrl;
|
||||
|
||||
if (has_newer_autopwm(data)) {
|
||||
ctrl = (data->pwm_ctrl[nr] & 0x7c) |
|
||||
data->pwm_temp_map[nr];
|
||||
if (val != 1)
|
||||
ctrl |= 0x80;
|
||||
} else {
|
||||
ctrl = (val == 1 ? data->pwm_duty[nr] : 0x80);
|
||||
}
|
||||
data->pwm_ctrl[nr] = ctrl;
|
||||
it87_write_value(data, IT87_REG_PWM[nr], ctrl);
|
||||
|
||||
if (data->type != it8603 && nr < 3) {
|
||||
/* set SmartGuardian mode */
|
||||
@@ -1344,6 +1354,7 @@ static ssize_t set_pwm(struct device *dev, struct device_attribute *attr,
|
||||
return -EINVAL;
|
||||
|
||||
mutex_lock(&data->update_lock);
|
||||
it87_update_pwm_ctrl(data, nr);
|
||||
if (has_newer_autopwm(data)) {
|
||||
/*
|
||||
* If we are in automatic mode, the PWM duty cycle register
|
||||
@@ -1456,13 +1467,15 @@ static ssize_t set_pwm_temp_map(struct device *dev,
|
||||
}
|
||||
|
||||
mutex_lock(&data->update_lock);
|
||||
it87_update_pwm_ctrl(data, nr);
|
||||
data->pwm_temp_map[nr] = reg;
|
||||
/*
|
||||
* If we are in automatic mode, write the temp mapping immediately;
|
||||
* otherwise, just store it for later use.
|
||||
*/
|
||||
if (data->pwm_ctrl[nr] & 0x80) {
|
||||
data->pwm_ctrl[nr] = 0x80 | data->pwm_temp_map[nr];
|
||||
data->pwm_ctrl[nr] = (data->pwm_ctrl[nr] & 0xfc) |
|
||||
data->pwm_temp_map[nr];
|
||||
it87_write_value(data, IT87_REG_PWM[nr], data->pwm_ctrl[nr]);
|
||||
}
|
||||
mutex_unlock(&data->update_lock);
|
||||
|
||||
@@ -356,7 +356,7 @@ static void stm_generic_unlink(struct stm_data *stm_data,
|
||||
if (!drvdata || !drvdata->csdev)
|
||||
return;
|
||||
|
||||
stm_disable(drvdata->csdev, NULL);
|
||||
coresight_disable(drvdata->csdev);
|
||||
}
|
||||
|
||||
static phys_addr_t
|
||||
|
||||
@@ -137,6 +137,7 @@ static const struct iio_chan_spec mpl115_channels[] = {
|
||||
{
|
||||
.type = IIO_TEMP,
|
||||
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
|
||||
.info_mask_shared_by_type =
|
||||
BIT(IIO_CHAN_INFO_OFFSET) | BIT(IIO_CHAN_INFO_SCALE),
|
||||
},
|
||||
};
|
||||
|
||||
@@ -182,7 +182,7 @@ static const struct iio_chan_spec mpl3115_channels[] = {
|
||||
{
|
||||
.type = IIO_PRESSURE,
|
||||
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
|
||||
BIT(IIO_CHAN_INFO_SCALE),
|
||||
.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),
|
||||
.scan_index = 0,
|
||||
.scan_type = {
|
||||
.sign = 'u',
|
||||
@@ -195,7 +195,7 @@ static const struct iio_chan_spec mpl3115_channels[] = {
|
||||
{
|
||||
.type = IIO_TEMP,
|
||||
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
|
||||
BIT(IIO_CHAN_INFO_SCALE),
|
||||
.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),
|
||||
.scan_index = 1,
|
||||
.scan_type = {
|
||||
.sign = 's',
|
||||
|
||||
@@ -3540,6 +3540,9 @@ static int cma_accept_iw(struct rdma_id_private *id_priv,
|
||||
struct iw_cm_conn_param iw_param;
|
||||
int ret;
|
||||
|
||||
if (!conn_param)
|
||||
return -EINVAL;
|
||||
|
||||
ret = cma_modify_qp_rtr(id_priv, conn_param);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
@@ -165,8 +165,6 @@ static int create_srq_kernel(struct mlx5_ib_dev *dev, struct mlx5_ib_srq *srq,
|
||||
int err;
|
||||
int i;
|
||||
struct mlx5_wqe_srq_next_seg *next;
|
||||
int page_shift;
|
||||
int npages;
|
||||
|
||||
err = mlx5_db_alloc(dev->mdev, &srq->db);
|
||||
if (err) {
|
||||
@@ -179,7 +177,6 @@ static int create_srq_kernel(struct mlx5_ib_dev *dev, struct mlx5_ib_srq *srq,
|
||||
err = -ENOMEM;
|
||||
goto err_db;
|
||||
}
|
||||
page_shift = srq->buf.page_shift;
|
||||
|
||||
srq->head = 0;
|
||||
srq->tail = srq->msrq.max - 1;
|
||||
@@ -191,10 +188,8 @@ static int create_srq_kernel(struct mlx5_ib_dev *dev, struct mlx5_ib_srq *srq,
|
||||
cpu_to_be16((i + 1) & (srq->msrq.max - 1));
|
||||
}
|
||||
|
||||
npages = DIV_ROUND_UP(srq->buf.npages, 1 << (page_shift - PAGE_SHIFT));
|
||||
mlx5_ib_dbg(dev, "buf_size %d, page_shift %d, npages %d, calc npages %d\n",
|
||||
buf_size, page_shift, srq->buf.npages, npages);
|
||||
in->pas = mlx5_vzalloc(sizeof(*in->pas) * npages);
|
||||
mlx5_ib_dbg(dev, "srq->buf.page_shift = %d\n", srq->buf.page_shift);
|
||||
in->pas = mlx5_vzalloc(sizeof(*in->pas) * srq->buf.npages);
|
||||
if (!in->pas) {
|
||||
err = -ENOMEM;
|
||||
goto err_buf;
|
||||
@@ -210,7 +205,7 @@ static int create_srq_kernel(struct mlx5_ib_dev *dev, struct mlx5_ib_srq *srq,
|
||||
}
|
||||
srq->wq_sig = !!srq_signature;
|
||||
|
||||
in->log_page_size = page_shift - MLX5_ADAPTER_PAGE_SHIFT;
|
||||
in->log_page_size = srq->buf.page_shift - MLX5_ADAPTER_PAGE_SHIFT;
|
||||
if (MLX5_CAP_GEN(dev->mdev, cqe_version) == MLX5_CQE_VERSION_V1 &&
|
||||
in->type == IB_SRQT_XRC)
|
||||
in->user_index = MLX5_IB_DEFAULT_UIDX;
|
||||
|
||||
@@ -1511,12 +1511,14 @@ static ssize_t set_mode(struct device *d, struct device_attribute *attr,
|
||||
|
||||
ret = ipoib_set_mode(dev, buf);
|
||||
|
||||
rtnl_unlock();
|
||||
/* The assumption is that the function ipoib_set_mode returned
|
||||
* with the rtnl held by it, if not the value -EBUSY returned,
|
||||
* then no need to rtnl_unlock
|
||||
*/
|
||||
if (ret != -EBUSY)
|
||||
rtnl_unlock();
|
||||
|
||||
if (!ret)
|
||||
return count;
|
||||
|
||||
return ret;
|
||||
return (!ret || ret == -EBUSY) ? count : ret;
|
||||
}
|
||||
|
||||
static DEVICE_ATTR(mode, S_IWUSR | S_IRUGO, show_mode, set_mode);
|
||||
|
||||
@@ -468,8 +468,7 @@ int ipoib_set_mode(struct net_device *dev, const char *buf)
|
||||
priv->tx_wr.wr.send_flags &= ~IB_SEND_IP_CSUM;
|
||||
|
||||
ipoib_flush_paths(dev);
|
||||
rtnl_lock();
|
||||
return 0;
|
||||
return (!rtnl_trylock()) ? -EBUSY : 0;
|
||||
}
|
||||
|
||||
if (!strcmp(buf, "datagram\n")) {
|
||||
@@ -478,8 +477,7 @@ int ipoib_set_mode(struct net_device *dev, const char *buf)
|
||||
dev_set_mtu(dev, min(priv->mcast_mtu, dev->mtu));
|
||||
rtnl_unlock();
|
||||
ipoib_flush_paths(dev);
|
||||
rtnl_lock();
|
||||
return 0;
|
||||
return (!rtnl_trylock()) ? -EBUSY : 0;
|
||||
}
|
||||
|
||||
return -EINVAL;
|
||||
@@ -703,6 +701,14 @@ int ipoib_check_sm_sendonly_fullmember_support(struct ipoib_dev_priv *priv)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void push_pseudo_header(struct sk_buff *skb, const char *daddr)
|
||||
{
|
||||
struct ipoib_pseudo_header *phdr;
|
||||
|
||||
phdr = (struct ipoib_pseudo_header *)skb_push(skb, sizeof(*phdr));
|
||||
memcpy(phdr->hwaddr, daddr, INFINIBAND_ALEN);
|
||||
}
|
||||
|
||||
void ipoib_flush_paths(struct net_device *dev)
|
||||
{
|
||||
struct ipoib_dev_priv *priv = netdev_priv(dev);
|
||||
@@ -927,8 +933,7 @@ static void neigh_add_path(struct sk_buff *skb, u8 *daddr,
|
||||
}
|
||||
if (skb_queue_len(&neigh->queue) <
|
||||
IPOIB_MAX_PATH_REC_QUEUE) {
|
||||
/* put pseudoheader back on for next time */
|
||||
skb_push(skb, IPOIB_PSEUDO_LEN);
|
||||
push_pseudo_header(skb, neigh->daddr);
|
||||
__skb_queue_tail(&neigh->queue, skb);
|
||||
} else {
|
||||
ipoib_warn(priv, "queue length limit %d. Packet drop.\n",
|
||||
@@ -946,10 +951,12 @@ static void neigh_add_path(struct sk_buff *skb, u8 *daddr,
|
||||
|
||||
if (!path->query && path_rec_start(dev, path))
|
||||
goto err_path;
|
||||
if (skb_queue_len(&neigh->queue) < IPOIB_MAX_PATH_REC_QUEUE)
|
||||
if (skb_queue_len(&neigh->queue) < IPOIB_MAX_PATH_REC_QUEUE) {
|
||||
push_pseudo_header(skb, neigh->daddr);
|
||||
__skb_queue_tail(&neigh->queue, skb);
|
||||
else
|
||||
} else {
|
||||
goto err_drop;
|
||||
}
|
||||
}
|
||||
|
||||
spin_unlock_irqrestore(&priv->lock, flags);
|
||||
@@ -985,8 +992,7 @@ static void unicast_arp_send(struct sk_buff *skb, struct net_device *dev,
|
||||
}
|
||||
if (path) {
|
||||
if (skb_queue_len(&path->queue) < IPOIB_MAX_PATH_REC_QUEUE) {
|
||||
/* put pseudoheader back on for next time */
|
||||
skb_push(skb, IPOIB_PSEUDO_LEN);
|
||||
push_pseudo_header(skb, phdr->hwaddr);
|
||||
__skb_queue_tail(&path->queue, skb);
|
||||
} else {
|
||||
++dev->stats.tx_dropped;
|
||||
@@ -1018,8 +1024,7 @@ static void unicast_arp_send(struct sk_buff *skb, struct net_device *dev,
|
||||
return;
|
||||
} else if ((path->query || !path_rec_start(dev, path)) &&
|
||||
skb_queue_len(&path->queue) < IPOIB_MAX_PATH_REC_QUEUE) {
|
||||
/* put pseudoheader back on for next time */
|
||||
skb_push(skb, IPOIB_PSEUDO_LEN);
|
||||
push_pseudo_header(skb, phdr->hwaddr);
|
||||
__skb_queue_tail(&path->queue, skb);
|
||||
} else {
|
||||
++dev->stats.tx_dropped;
|
||||
@@ -1100,8 +1105,7 @@ send_using_neigh:
|
||||
}
|
||||
|
||||
if (skb_queue_len(&neigh->queue) < IPOIB_MAX_PATH_REC_QUEUE) {
|
||||
/* put pseudoheader back on for next time */
|
||||
skb_push(skb, sizeof(*phdr));
|
||||
push_pseudo_header(skb, phdr->hwaddr);
|
||||
spin_lock_irqsave(&priv->lock, flags);
|
||||
__skb_queue_tail(&neigh->queue, skb);
|
||||
spin_unlock_irqrestore(&priv->lock, flags);
|
||||
@@ -1133,7 +1137,6 @@ static int ipoib_hard_header(struct sk_buff *skb,
|
||||
unsigned short type,
|
||||
const void *daddr, const void *saddr, unsigned len)
|
||||
{
|
||||
struct ipoib_pseudo_header *phdr;
|
||||
struct ipoib_header *header;
|
||||
|
||||
header = (struct ipoib_header *) skb_push(skb, sizeof *header);
|
||||
@@ -1146,8 +1149,7 @@ static int ipoib_hard_header(struct sk_buff *skb,
|
||||
* destination address into skb hard header so we can figure out where
|
||||
* to send the packet later.
|
||||
*/
|
||||
phdr = (struct ipoib_pseudo_header *) skb_push(skb, sizeof(*phdr));
|
||||
memcpy(phdr->hwaddr, daddr, INFINIBAND_ALEN);
|
||||
push_pseudo_header(skb, daddr);
|
||||
|
||||
return IPOIB_HARD_LEN;
|
||||
}
|
||||
|
||||
@@ -366,7 +366,6 @@ static struct srp_fr_pool *srp_create_fr_pool(struct ib_device *device,
|
||||
struct srp_fr_desc *d;
|
||||
struct ib_mr *mr;
|
||||
int i, ret = -EINVAL;
|
||||
enum ib_mr_type mr_type;
|
||||
|
||||
if (pool_size <= 0)
|
||||
goto err;
|
||||
@@ -380,13 +379,9 @@ static struct srp_fr_pool *srp_create_fr_pool(struct ib_device *device,
|
||||
spin_lock_init(&pool->lock);
|
||||
INIT_LIST_HEAD(&pool->free_list);
|
||||
|
||||
if (device->attrs.device_cap_flags & IB_DEVICE_SG_GAPS_REG)
|
||||
mr_type = IB_MR_TYPE_SG_GAPS;
|
||||
else
|
||||
mr_type = IB_MR_TYPE_MEM_REG;
|
||||
|
||||
for (i = 0, d = &pool->desc[0]; i < pool->size; i++, d++) {
|
||||
mr = ib_alloc_mr(pd, mr_type, max_page_list_len);
|
||||
mr = ib_alloc_mr(pd, IB_MR_TYPE_MEM_REG,
|
||||
max_page_list_len);
|
||||
if (IS_ERR(mr)) {
|
||||
ret = PTR_ERR(mr);
|
||||
goto destroy_pool;
|
||||
@@ -1877,17 +1872,24 @@ static void srp_process_rsp(struct srp_rdma_ch *ch, struct srp_rsp *rsp)
|
||||
if (unlikely(rsp->tag & SRP_TAG_TSK_MGMT)) {
|
||||
spin_lock_irqsave(&ch->lock, flags);
|
||||
ch->req_lim += be32_to_cpu(rsp->req_lim_delta);
|
||||
if (rsp->tag == ch->tsk_mgmt_tag) {
|
||||
ch->tsk_mgmt_status = -1;
|
||||
if (be32_to_cpu(rsp->resp_data_len) >= 4)
|
||||
ch->tsk_mgmt_status = rsp->data[3];
|
||||
complete(&ch->tsk_mgmt_done);
|
||||
} else {
|
||||
shost_printk(KERN_ERR, target->scsi_host,
|
||||
"Received tsk mgmt response too late for tag %#llx\n",
|
||||
rsp->tag);
|
||||
}
|
||||
spin_unlock_irqrestore(&ch->lock, flags);
|
||||
|
||||
ch->tsk_mgmt_status = -1;
|
||||
if (be32_to_cpu(rsp->resp_data_len) >= 4)
|
||||
ch->tsk_mgmt_status = rsp->data[3];
|
||||
complete(&ch->tsk_mgmt_done);
|
||||
} else {
|
||||
scmnd = scsi_host_find_tag(target->scsi_host, rsp->tag);
|
||||
if (scmnd) {
|
||||
if (scmnd && scmnd->host_scribble) {
|
||||
req = (void *)scmnd->host_scribble;
|
||||
scmnd = srp_claim_req(ch, req, NULL, scmnd);
|
||||
} else {
|
||||
scmnd = NULL;
|
||||
}
|
||||
if (!scmnd) {
|
||||
shost_printk(KERN_ERR, target->scsi_host,
|
||||
@@ -2519,19 +2521,18 @@ srp_change_queue_depth(struct scsi_device *sdev, int qdepth)
|
||||
}
|
||||
|
||||
static int srp_send_tsk_mgmt(struct srp_rdma_ch *ch, u64 req_tag, u64 lun,
|
||||
u8 func)
|
||||
u8 func, u8 *status)
|
||||
{
|
||||
struct srp_target_port *target = ch->target;
|
||||
struct srp_rport *rport = target->rport;
|
||||
struct ib_device *dev = target->srp_host->srp_dev->dev;
|
||||
struct srp_iu *iu;
|
||||
struct srp_tsk_mgmt *tsk_mgmt;
|
||||
int res;
|
||||
|
||||
if (!ch->connected || target->qp_in_error)
|
||||
return -1;
|
||||
|
||||
init_completion(&ch->tsk_mgmt_done);
|
||||
|
||||
/*
|
||||
* Lock the rport mutex to avoid that srp_create_ch_ib() is
|
||||
* invoked while a task management function is being sent.
|
||||
@@ -2554,10 +2555,16 @@ static int srp_send_tsk_mgmt(struct srp_rdma_ch *ch, u64 req_tag, u64 lun,
|
||||
|
||||
tsk_mgmt->opcode = SRP_TSK_MGMT;
|
||||
int_to_scsilun(lun, &tsk_mgmt->lun);
|
||||
tsk_mgmt->tag = req_tag | SRP_TAG_TSK_MGMT;
|
||||
tsk_mgmt->tsk_mgmt_func = func;
|
||||
tsk_mgmt->task_tag = req_tag;
|
||||
|
||||
spin_lock_irq(&ch->lock);
|
||||
ch->tsk_mgmt_tag = (ch->tsk_mgmt_tag + 1) | SRP_TAG_TSK_MGMT;
|
||||
tsk_mgmt->tag = ch->tsk_mgmt_tag;
|
||||
spin_unlock_irq(&ch->lock);
|
||||
|
||||
init_completion(&ch->tsk_mgmt_done);
|
||||
|
||||
ib_dma_sync_single_for_device(dev, iu->dma, sizeof *tsk_mgmt,
|
||||
DMA_TO_DEVICE);
|
||||
if (srp_post_send(ch, iu, sizeof(*tsk_mgmt))) {
|
||||
@@ -2566,13 +2573,15 @@ static int srp_send_tsk_mgmt(struct srp_rdma_ch *ch, u64 req_tag, u64 lun,
|
||||
|
||||
return -1;
|
||||
}
|
||||
res = wait_for_completion_timeout(&ch->tsk_mgmt_done,
|
||||
msecs_to_jiffies(SRP_ABORT_TIMEOUT_MS));
|
||||
if (res > 0 && status)
|
||||
*status = ch->tsk_mgmt_status;
|
||||
mutex_unlock(&rport->mutex);
|
||||
|
||||
if (!wait_for_completion_timeout(&ch->tsk_mgmt_done,
|
||||
msecs_to_jiffies(SRP_ABORT_TIMEOUT_MS)))
|
||||
return -1;
|
||||
WARN_ON_ONCE(res < 0);
|
||||
|
||||
return 0;
|
||||
return res > 0 ? 0 : -1;
|
||||
}
|
||||
|
||||
static int srp_abort(struct scsi_cmnd *scmnd)
|
||||
@@ -2598,7 +2607,7 @@ static int srp_abort(struct scsi_cmnd *scmnd)
|
||||
shost_printk(KERN_ERR, target->scsi_host,
|
||||
"Sending SRP abort for tag %#x\n", tag);
|
||||
if (srp_send_tsk_mgmt(ch, tag, scmnd->device->lun,
|
||||
SRP_TSK_ABORT_TASK) == 0)
|
||||
SRP_TSK_ABORT_TASK, NULL) == 0)
|
||||
ret = SUCCESS;
|
||||
else if (target->rport->state == SRP_RPORT_LOST)
|
||||
ret = FAST_IO_FAIL;
|
||||
@@ -2616,14 +2625,15 @@ static int srp_reset_device(struct scsi_cmnd *scmnd)
|
||||
struct srp_target_port *target = host_to_target(scmnd->device->host);
|
||||
struct srp_rdma_ch *ch;
|
||||
int i;
|
||||
u8 status;
|
||||
|
||||
shost_printk(KERN_ERR, target->scsi_host, "SRP reset_device called\n");
|
||||
|
||||
ch = &target->ch[0];
|
||||
if (srp_send_tsk_mgmt(ch, SRP_TAG_NO_REQ, scmnd->device->lun,
|
||||
SRP_TSK_LUN_RESET))
|
||||
SRP_TSK_LUN_RESET, &status))
|
||||
return FAILED;
|
||||
if (ch->tsk_mgmt_status)
|
||||
if (status)
|
||||
return FAILED;
|
||||
|
||||
for (i = 0; i < target->ch_count; i++) {
|
||||
@@ -2652,9 +2662,8 @@ static int srp_slave_alloc(struct scsi_device *sdev)
|
||||
struct Scsi_Host *shost = sdev->host;
|
||||
struct srp_target_port *target = host_to_target(shost);
|
||||
struct srp_device *srp_dev = target->srp_host->srp_dev;
|
||||
struct ib_device *ibdev = srp_dev->dev;
|
||||
|
||||
if (!(ibdev->attrs.device_cap_flags & IB_DEVICE_SG_GAPS_REG))
|
||||
if (true)
|
||||
blk_queue_virt_boundary(sdev->request_queue,
|
||||
~srp_dev->mr_page_mask);
|
||||
|
||||
|
||||
@@ -163,6 +163,7 @@ struct srp_rdma_ch {
|
||||
int max_ti_iu_len;
|
||||
int comp_vector;
|
||||
|
||||
u64 tsk_mgmt_tag;
|
||||
struct completion tsk_mgmt_done;
|
||||
u8 tsk_mgmt_status;
|
||||
bool connected;
|
||||
|
||||
@@ -3325,13 +3325,14 @@ static int __init init_dmars(void)
|
||||
iommu_identity_mapping |= IDENTMAP_GFX;
|
||||
#endif
|
||||
|
||||
check_tylersburg_isoch();
|
||||
|
||||
if (iommu_identity_mapping) {
|
||||
ret = si_domain_init(hw_pass_through);
|
||||
if (ret)
|
||||
goto free_iommu;
|
||||
}
|
||||
|
||||
check_tylersburg_isoch();
|
||||
|
||||
/*
|
||||
* If we copied translations from a previous kernel in the kdump
|
||||
|
||||
@@ -115,6 +115,12 @@ static inline bool is_userdebug(void)
|
||||
return !strncmp(buildvariant, typeuserdebug, sizeof(typeuserdebug));
|
||||
}
|
||||
|
||||
static inline bool is_unlocked(void)
|
||||
{
|
||||
static const char unlocked[] = "orange";
|
||||
|
||||
return !strncmp(verifiedbootstate, unlocked, sizeof(unlocked));
|
||||
}
|
||||
|
||||
static int table_extract_mpi_array(struct public_key_signature *pks,
|
||||
const void *data, size_t len)
|
||||
@@ -585,6 +591,8 @@ static int verify_verity_signature(char *key_id,
|
||||
|
||||
if (IS_ERR(pks)) {
|
||||
DMERR("hashing failed");
|
||||
retval = PTR_ERR(pks);
|
||||
pks = NULL;
|
||||
goto error;
|
||||
}
|
||||
|
||||
@@ -649,6 +657,28 @@ static int add_as_linear_device(struct dm_target *ti, char *dev)
|
||||
return err;
|
||||
}
|
||||
|
||||
static int create_linear_device(struct dm_target *ti, dev_t dev,
|
||||
char *target_device)
|
||||
{
|
||||
u64 device_size = 0;
|
||||
int err = find_size(dev, &device_size);
|
||||
|
||||
if (err) {
|
||||
DMERR("error finding bdev size");
|
||||
handle_error();
|
||||
return err;
|
||||
}
|
||||
|
||||
ti->len = device_size;
|
||||
err = add_as_linear_device(ti, target_device);
|
||||
if (err) {
|
||||
handle_error();
|
||||
return err;
|
||||
}
|
||||
verity_enabled = false;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Target parameters:
|
||||
* <key id> Key id of the public key in the system keyring.
|
||||
@@ -672,7 +702,6 @@ static int android_verity_ctr(struct dm_target *ti, unsigned argc, char **argv)
|
||||
struct fec_ecc_metadata uninitialized_var(ecc);
|
||||
char buf[FEC_ARG_LENGTH], *buf_ptr;
|
||||
unsigned long long tmpll;
|
||||
u64 uninitialized_var(device_size);
|
||||
|
||||
if (argc == 1) {
|
||||
/* Use the default keyid */
|
||||
@@ -700,23 +729,8 @@ static int android_verity_ctr(struct dm_target *ti, unsigned argc, char **argv)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (is_eng()) {
|
||||
err = find_size(dev, &device_size);
|
||||
if (err) {
|
||||
DMERR("error finding bdev size");
|
||||
handle_error();
|
||||
return err;
|
||||
}
|
||||
|
||||
ti->len = device_size;
|
||||
err = add_as_linear_device(ti, target_device);
|
||||
if (err) {
|
||||
handle_error();
|
||||
return err;
|
||||
}
|
||||
verity_enabled = false;
|
||||
return 0;
|
||||
}
|
||||
if (is_eng())
|
||||
return create_linear_device(ti, dev, target_device);
|
||||
|
||||
strreplace(key_id, '#', ' ');
|
||||
|
||||
@@ -731,6 +745,11 @@ static int android_verity_ctr(struct dm_target *ti, unsigned argc, char **argv)
|
||||
err = extract_metadata(dev, &fec, &metadata, &verity_enabled);
|
||||
|
||||
if (err) {
|
||||
/* Allow invalid metadata when the device is unlocked */
|
||||
if (is_unlocked()) {
|
||||
DMWARN("Allow invalid metadata when unlocked");
|
||||
return create_linear_device(ti, dev, target_device);
|
||||
}
|
||||
DMERR("Error while extracting metadata");
|
||||
handle_error();
|
||||
goto free_metadata;
|
||||
|
||||
@@ -248,7 +248,7 @@ struct cache {
|
||||
/*
|
||||
* Fields for converting from sectors to blocks.
|
||||
*/
|
||||
uint32_t sectors_per_block;
|
||||
sector_t sectors_per_block;
|
||||
int sectors_per_block_shift;
|
||||
|
||||
spinlock_t lock;
|
||||
@@ -3546,11 +3546,11 @@ static void cache_status(struct dm_target *ti, status_type_t type,
|
||||
|
||||
residency = policy_residency(cache->policy);
|
||||
|
||||
DMEMIT("%u %llu/%llu %u %llu/%llu %u %u %u %u %u %u %lu ",
|
||||
DMEMIT("%u %llu/%llu %llu %llu/%llu %u %u %u %u %u %u %lu ",
|
||||
(unsigned)DM_CACHE_METADATA_BLOCK_SIZE,
|
||||
(unsigned long long)(nr_blocks_metadata - nr_free_blocks_metadata),
|
||||
(unsigned long long)nr_blocks_metadata,
|
||||
cache->sectors_per_block,
|
||||
(unsigned long long)cache->sectors_per_block,
|
||||
(unsigned long long) from_cblock(residency),
|
||||
(unsigned long long) from_cblock(cache->cache_size),
|
||||
(unsigned) atomic_read(&cache->stats.read_hit),
|
||||
|
||||
+11
-1
@@ -3621,6 +3621,8 @@ static int raid_preresume(struct dm_target *ti)
|
||||
return r;
|
||||
}
|
||||
|
||||
#define RESUME_STAY_FROZEN_FLAGS (CTR_FLAG_DELTA_DISKS | CTR_FLAG_DATA_OFFSET)
|
||||
|
||||
static void raid_resume(struct dm_target *ti)
|
||||
{
|
||||
struct raid_set *rs = ti->private;
|
||||
@@ -3638,7 +3640,15 @@ static void raid_resume(struct dm_target *ti)
|
||||
mddev->ro = 0;
|
||||
mddev->in_sync = 0;
|
||||
|
||||
clear_bit(MD_RECOVERY_FROZEN, &mddev->recovery);
|
||||
/*
|
||||
* Keep the RAID set frozen if reshape/rebuild flags are set.
|
||||
* The RAID set is unfrozen once the next table load/resume,
|
||||
* which clears the reshape/rebuild flags, occurs.
|
||||
* This ensures that the constructor for the inactive table
|
||||
* retrieves an up-to-date reshape_position.
|
||||
*/
|
||||
if (!(rs->ctr_flags & RESUME_STAY_FROZEN_FLAGS))
|
||||
clear_bit(MD_RECOVERY_FROZEN, &mddev->recovery);
|
||||
|
||||
if (mddev->suspended)
|
||||
mddev_resume(mddev);
|
||||
|
||||
+14
-53
@@ -17,8 +17,8 @@
|
||||
#include <linux/module.h>
|
||||
|
||||
#define DM_MSG_PREFIX "multipath round-robin"
|
||||
#define RR_MIN_IO 1000
|
||||
#define RR_VERSION "1.1.0"
|
||||
#define RR_MIN_IO 1
|
||||
#define RR_VERSION "1.2.0"
|
||||
|
||||
/*-----------------------------------------------------------------
|
||||
* Path-handling code, paths are held in lists
|
||||
@@ -47,44 +47,19 @@ struct selector {
|
||||
struct list_head valid_paths;
|
||||
struct list_head invalid_paths;
|
||||
spinlock_t lock;
|
||||
struct dm_path * __percpu *current_path;
|
||||
struct percpu_counter repeat_count;
|
||||
};
|
||||
|
||||
static void set_percpu_current_path(struct selector *s, struct dm_path *path)
|
||||
{
|
||||
int cpu;
|
||||
|
||||
for_each_possible_cpu(cpu)
|
||||
*per_cpu_ptr(s->current_path, cpu) = path;
|
||||
}
|
||||
|
||||
static struct selector *alloc_selector(void)
|
||||
{
|
||||
struct selector *s = kmalloc(sizeof(*s), GFP_KERNEL);
|
||||
|
||||
if (!s)
|
||||
return NULL;
|
||||
|
||||
INIT_LIST_HEAD(&s->valid_paths);
|
||||
INIT_LIST_HEAD(&s->invalid_paths);
|
||||
spin_lock_init(&s->lock);
|
||||
|
||||
s->current_path = alloc_percpu(struct dm_path *);
|
||||
if (!s->current_path)
|
||||
goto out_current_path;
|
||||
set_percpu_current_path(s, NULL);
|
||||
|
||||
if (percpu_counter_init(&s->repeat_count, 0, GFP_KERNEL))
|
||||
goto out_repeat_count;
|
||||
if (s) {
|
||||
INIT_LIST_HEAD(&s->valid_paths);
|
||||
INIT_LIST_HEAD(&s->invalid_paths);
|
||||
spin_lock_init(&s->lock);
|
||||
}
|
||||
|
||||
return s;
|
||||
|
||||
out_repeat_count:
|
||||
free_percpu(s->current_path);
|
||||
out_current_path:
|
||||
kfree(s);
|
||||
return NULL;;
|
||||
}
|
||||
|
||||
static int rr_create(struct path_selector *ps, unsigned argc, char **argv)
|
||||
@@ -105,8 +80,6 @@ static void rr_destroy(struct path_selector *ps)
|
||||
|
||||
free_paths(&s->valid_paths);
|
||||
free_paths(&s->invalid_paths);
|
||||
free_percpu(s->current_path);
|
||||
percpu_counter_destroy(&s->repeat_count);
|
||||
kfree(s);
|
||||
ps->context = NULL;
|
||||
}
|
||||
@@ -157,6 +130,11 @@ static int rr_add_path(struct path_selector *ps, struct dm_path *path,
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (repeat_count > 1) {
|
||||
DMWARN_LIMIT("repeat_count > 1 is deprecated, using 1 instead");
|
||||
repeat_count = 1;
|
||||
}
|
||||
|
||||
/* allocate the path */
|
||||
pi = kmalloc(sizeof(*pi), GFP_KERNEL);
|
||||
if (!pi) {
|
||||
@@ -183,9 +161,6 @@ static void rr_fail_path(struct path_selector *ps, struct dm_path *p)
|
||||
struct path_info *pi = p->pscontext;
|
||||
|
||||
spin_lock_irqsave(&s->lock, flags);
|
||||
if (p == *this_cpu_ptr(s->current_path))
|
||||
set_percpu_current_path(s, NULL);
|
||||
|
||||
list_move(&pi->list, &s->invalid_paths);
|
||||
spin_unlock_irqrestore(&s->lock, flags);
|
||||
}
|
||||
@@ -208,29 +183,15 @@ static struct dm_path *rr_select_path(struct path_selector *ps, size_t nr_bytes)
|
||||
unsigned long flags;
|
||||
struct selector *s = ps->context;
|
||||
struct path_info *pi = NULL;
|
||||
struct dm_path *current_path = NULL;
|
||||
|
||||
local_irq_save(flags);
|
||||
current_path = *this_cpu_ptr(s->current_path);
|
||||
if (current_path) {
|
||||
percpu_counter_dec(&s->repeat_count);
|
||||
if (percpu_counter_read_positive(&s->repeat_count) > 0) {
|
||||
local_irq_restore(flags);
|
||||
return current_path;
|
||||
}
|
||||
}
|
||||
|
||||
spin_lock(&s->lock);
|
||||
spin_lock_irqsave(&s->lock, flags);
|
||||
if (!list_empty(&s->valid_paths)) {
|
||||
pi = list_entry(s->valid_paths.next, struct path_info, list);
|
||||
list_move_tail(&pi->list, &s->valid_paths);
|
||||
percpu_counter_set(&s->repeat_count, pi->repeat_count);
|
||||
set_percpu_current_path(s, pi->path);
|
||||
current_path = pi->path;
|
||||
}
|
||||
spin_unlock_irqrestore(&s->lock, flags);
|
||||
|
||||
return current_path;
|
||||
return pi ? pi->path : NULL;
|
||||
}
|
||||
|
||||
static struct path_selector_type rr_ps = {
|
||||
|
||||
@@ -175,6 +175,7 @@ static void dm_stat_free(struct rcu_head *head)
|
||||
int cpu;
|
||||
struct dm_stat *s = container_of(head, struct dm_stat, rcu_head);
|
||||
|
||||
kfree(s->histogram_boundaries);
|
||||
kfree(s->program_id);
|
||||
kfree(s->aux_data);
|
||||
for_each_possible_cpu(cpu) {
|
||||
|
||||
+34
-5
@@ -52,18 +52,26 @@ static inline struct dev_info *which_dev(struct mddev *mddev, sector_t sector)
|
||||
return conf->disks + lo;
|
||||
}
|
||||
|
||||
/*
|
||||
* In linear_congested() conf->raid_disks is used as a copy of
|
||||
* mddev->raid_disks to iterate conf->disks[], because conf->raid_disks
|
||||
* and conf->disks[] are created in linear_conf(), they are always
|
||||
* consitent with each other, but mddev->raid_disks does not.
|
||||
*/
|
||||
static int linear_congested(struct mddev *mddev, int bits)
|
||||
{
|
||||
struct linear_conf *conf;
|
||||
int i, ret = 0;
|
||||
|
||||
conf = mddev->private;
|
||||
rcu_read_lock();
|
||||
conf = rcu_dereference(mddev->private);
|
||||
|
||||
for (i = 0; i < mddev->raid_disks && !ret ; i++) {
|
||||
for (i = 0; i < conf->raid_disks && !ret ; i++) {
|
||||
struct request_queue *q = bdev_get_queue(conf->disks[i].rdev->bdev);
|
||||
ret |= bdi_congested(&q->backing_dev_info, bits);
|
||||
}
|
||||
|
||||
rcu_read_unlock();
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -143,6 +151,19 @@ static struct linear_conf *linear_conf(struct mddev *mddev, int raid_disks)
|
||||
conf->disks[i-1].end_sector +
|
||||
conf->disks[i].rdev->sectors;
|
||||
|
||||
/*
|
||||
* conf->raid_disks is copy of mddev->raid_disks. The reason to
|
||||
* keep a copy of mddev->raid_disks in struct linear_conf is,
|
||||
* mddev->raid_disks may not be consistent with pointers number of
|
||||
* conf->disks[] when it is updated in linear_add() and used to
|
||||
* iterate old conf->disks[] earray in linear_congested().
|
||||
* Here conf->raid_disks is always consitent with number of
|
||||
* pointers in conf->disks[] array, and mddev->private is updated
|
||||
* with rcu_assign_pointer() in linear_addr(), such race can be
|
||||
* avoided.
|
||||
*/
|
||||
conf->raid_disks = raid_disks;
|
||||
|
||||
return conf;
|
||||
|
||||
out:
|
||||
@@ -195,15 +216,23 @@ static int linear_add(struct mddev *mddev, struct md_rdev *rdev)
|
||||
if (!newconf)
|
||||
return -ENOMEM;
|
||||
|
||||
/* newconf->raid_disks already keeps a copy of * the increased
|
||||
* value of mddev->raid_disks, WARN_ONCE() is just used to make
|
||||
* sure of this. It is possible that oldconf is still referenced
|
||||
* in linear_congested(), therefore kfree_rcu() is used to free
|
||||
* oldconf until no one uses it anymore.
|
||||
*/
|
||||
mddev_suspend(mddev);
|
||||
oldconf = mddev->private;
|
||||
oldconf = rcu_dereference(mddev->private);
|
||||
mddev->raid_disks++;
|
||||
mddev->private = newconf;
|
||||
WARN_ONCE(mddev->raid_disks != newconf->raid_disks,
|
||||
"copied raid_disks doesn't match mddev->raid_disks");
|
||||
rcu_assign_pointer(mddev->private, newconf);
|
||||
md_set_array_sectors(mddev, linear_size(mddev, 0, 0));
|
||||
set_capacity(mddev->gendisk, mddev->array_sectors);
|
||||
mddev_resume(mddev);
|
||||
revalidate_disk(mddev->gendisk);
|
||||
kfree(oldconf);
|
||||
kfree_rcu(oldconf, rcu);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -10,6 +10,7 @@ struct linear_conf
|
||||
{
|
||||
struct rcu_head rcu;
|
||||
sector_t array_sectors;
|
||||
int raid_disks; /* a copy of mddev->raid_disks */
|
||||
struct dev_info disks[0];
|
||||
};
|
||||
#endif
|
||||
|
||||
@@ -615,6 +615,7 @@ static int cxd2820r_probe(struct i2c_client *client,
|
||||
}
|
||||
|
||||
priv->client[0] = client;
|
||||
priv->fe.demodulator_priv = priv;
|
||||
priv->i2c = client->adapter;
|
||||
priv->ts_mode = pdata->ts_mode;
|
||||
priv->ts_clk_inv = pdata->ts_clk_inv;
|
||||
@@ -697,7 +698,6 @@ static int cxd2820r_probe(struct i2c_client *client,
|
||||
memcpy(&priv->fe.ops, &cxd2820r_ops, sizeof(priv->fe.ops));
|
||||
if (!pdata->attach_in_use)
|
||||
priv->fe.ops.release = NULL;
|
||||
priv->fe.demodulator_priv = priv;
|
||||
i2c_set_clientdata(client, priv);
|
||||
|
||||
/* Setup callbacks */
|
||||
|
||||
@@ -130,7 +130,7 @@ static long media_device_enum_entities(struct media_device *mdev,
|
||||
* old range.
|
||||
*/
|
||||
if (ent->function < MEDIA_ENT_F_OLD_BASE ||
|
||||
ent->function > MEDIA_ENT_T_DEVNODE_UNKNOWN) {
|
||||
ent->function > MEDIA_ENT_F_TUNER) {
|
||||
if (is_media_entity_v4l2_subdev(ent))
|
||||
entd->type = MEDIA_ENT_F_V4L2_SUBDEV_UNKNOWN;
|
||||
else if (ent->function != MEDIA_ENT_F_IO_V4L)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
config DVB_DM1105
|
||||
tristate "SDMC DM1105 based PCI cards"
|
||||
depends on DVB_CORE && PCI && I2C
|
||||
depends on DVB_CORE && PCI && I2C && I2C_ALGOBIT
|
||||
select DVB_PLL if MEDIA_SUBDRV_AUTOSELECT
|
||||
select DVB_STV0299 if MEDIA_SUBDRV_AUTOSELECT
|
||||
select DVB_STV0288 if MEDIA_SUBDRV_AUTOSELECT
|
||||
|
||||
@@ -1576,7 +1576,7 @@ static int vpfe_s_fmt(struct file *file, void *priv,
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
ret = vpfe_try_fmt(file, priv, &format);
|
||||
ret = __vpfe_get_format(vpfe, &format, &bpp);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
|
||||
@@ -589,7 +589,7 @@ long lirc_dev_fop_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
|
||||
result = put_user(ir->d.features, (__u32 __user *)arg);
|
||||
break;
|
||||
case LIRC_GET_REC_MODE:
|
||||
if (LIRC_CAN_REC(ir->d.features)) {
|
||||
if (!LIRC_CAN_REC(ir->d.features)) {
|
||||
result = -ENOTTY;
|
||||
break;
|
||||
}
|
||||
@@ -599,7 +599,7 @@ long lirc_dev_fop_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
|
||||
(__u32 __user *)arg);
|
||||
break;
|
||||
case LIRC_SET_REC_MODE:
|
||||
if (LIRC_CAN_REC(ir->d.features)) {
|
||||
if (!LIRC_CAN_REC(ir->d.features)) {
|
||||
result = -ENOTTY;
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -412,7 +412,7 @@ struct uvc_buffer *uvc_queue_next_buffer(struct uvc_video_queue *queue,
|
||||
nextbuf = NULL;
|
||||
spin_unlock_irqrestore(&queue->irqlock, flags);
|
||||
|
||||
buf->state = buf->error ? VB2_BUF_STATE_ERROR : UVC_BUF_STATE_DONE;
|
||||
buf->state = buf->error ? UVC_BUF_STATE_ERROR : UVC_BUF_STATE_DONE;
|
||||
vb2_set_plane_payload(&buf->buf.vb2_buf, 0, buf->bytesused);
|
||||
vb2_buffer_done(&buf->buf.vb2_buf, VB2_BUF_STATE_DONE);
|
||||
|
||||
|
||||
+14
-13
@@ -93,7 +93,7 @@ static void at91sam9_ebi_get_config(struct at91_ebi_dev *ebid,
|
||||
struct at91_ebi_dev_config *conf)
|
||||
{
|
||||
struct at91sam9_smc_generic_fields *fields = &ebid->ebi->sam9;
|
||||
unsigned int clk_rate = clk_get_rate(ebid->ebi->clk);
|
||||
unsigned int clk_period = NSEC_PER_SEC / clk_get_rate(ebid->ebi->clk);
|
||||
struct at91sam9_ebi_dev_config *config = &conf->sam9;
|
||||
struct at91sam9_smc_timings *timings = &config->timings;
|
||||
unsigned int val;
|
||||
@@ -102,43 +102,43 @@ static void at91sam9_ebi_get_config(struct at91_ebi_dev *ebid,
|
||||
config->mode = val & ~AT91_SMC_TDF;
|
||||
|
||||
val = (val & AT91_SMC_TDF) >> 16;
|
||||
timings->tdf_ns = clk_rate * val;
|
||||
timings->tdf_ns = clk_period * val;
|
||||
|
||||
regmap_fields_read(fields->setup, conf->cs, &val);
|
||||
timings->ncs_rd_setup_ns = (val >> 24) & 0x1f;
|
||||
timings->ncs_rd_setup_ns += ((val >> 29) & 0x1) * 128;
|
||||
timings->ncs_rd_setup_ns *= clk_rate;
|
||||
timings->ncs_rd_setup_ns *= clk_period;
|
||||
timings->nrd_setup_ns = (val >> 16) & 0x1f;
|
||||
timings->nrd_setup_ns += ((val >> 21) & 0x1) * 128;
|
||||
timings->nrd_setup_ns *= clk_rate;
|
||||
timings->nrd_setup_ns *= clk_period;
|
||||
timings->ncs_wr_setup_ns = (val >> 8) & 0x1f;
|
||||
timings->ncs_wr_setup_ns += ((val >> 13) & 0x1) * 128;
|
||||
timings->ncs_wr_setup_ns *= clk_rate;
|
||||
timings->ncs_wr_setup_ns *= clk_period;
|
||||
timings->nwe_setup_ns = val & 0x1f;
|
||||
timings->nwe_setup_ns += ((val >> 5) & 0x1) * 128;
|
||||
timings->nwe_setup_ns *= clk_rate;
|
||||
timings->nwe_setup_ns *= clk_period;
|
||||
|
||||
regmap_fields_read(fields->pulse, conf->cs, &val);
|
||||
timings->ncs_rd_pulse_ns = (val >> 24) & 0x3f;
|
||||
timings->ncs_rd_pulse_ns += ((val >> 30) & 0x1) * 256;
|
||||
timings->ncs_rd_pulse_ns *= clk_rate;
|
||||
timings->ncs_rd_pulse_ns *= clk_period;
|
||||
timings->nrd_pulse_ns = (val >> 16) & 0x3f;
|
||||
timings->nrd_pulse_ns += ((val >> 22) & 0x1) * 256;
|
||||
timings->nrd_pulse_ns *= clk_rate;
|
||||
timings->nrd_pulse_ns *= clk_period;
|
||||
timings->ncs_wr_pulse_ns = (val >> 8) & 0x3f;
|
||||
timings->ncs_wr_pulse_ns += ((val >> 14) & 0x1) * 256;
|
||||
timings->ncs_wr_pulse_ns *= clk_rate;
|
||||
timings->ncs_wr_pulse_ns *= clk_period;
|
||||
timings->nwe_pulse_ns = val & 0x3f;
|
||||
timings->nwe_pulse_ns += ((val >> 6) & 0x1) * 256;
|
||||
timings->nwe_pulse_ns *= clk_rate;
|
||||
timings->nwe_pulse_ns *= clk_period;
|
||||
|
||||
regmap_fields_read(fields->cycle, conf->cs, &val);
|
||||
timings->nrd_cycle_ns = (val >> 16) & 0x7f;
|
||||
timings->nrd_cycle_ns += ((val >> 23) & 0x3) * 256;
|
||||
timings->nrd_cycle_ns *= clk_rate;
|
||||
timings->nrd_cycle_ns *= clk_period;
|
||||
timings->nwe_cycle_ns = val & 0x7f;
|
||||
timings->nwe_cycle_ns += ((val >> 7) & 0x3) * 256;
|
||||
timings->nwe_cycle_ns *= clk_rate;
|
||||
timings->nwe_cycle_ns *= clk_period;
|
||||
}
|
||||
|
||||
static int at91_xlate_timing(struct device_node *np, const char *prop,
|
||||
@@ -334,6 +334,7 @@ static int at91sam9_ebi_apply_config(struct at91_ebi_dev *ebid,
|
||||
struct at91_ebi_dev_config *conf)
|
||||
{
|
||||
unsigned int clk_rate = clk_get_rate(ebid->ebi->clk);
|
||||
unsigned int clk_period = NSEC_PER_SEC / clk_rate;
|
||||
struct at91sam9_ebi_dev_config *config = &conf->sam9;
|
||||
struct at91sam9_smc_timings *timings = &config->timings;
|
||||
struct at91sam9_smc_generic_fields *fields = &ebid->ebi->sam9;
|
||||
@@ -376,7 +377,7 @@ static int at91sam9_ebi_apply_config(struct at91_ebi_dev *ebid,
|
||||
val |= AT91SAM9_SMC_NWECYCLE(coded_val);
|
||||
regmap_fields_write(fields->cycle, conf->cs, val);
|
||||
|
||||
val = DIV_ROUND_UP(timings->tdf_ns, clk_rate);
|
||||
val = DIV_ROUND_UP(timings->tdf_ns, clk_period);
|
||||
if (val > AT91_SMC_TDF_MAX)
|
||||
val = AT91_SMC_TDF_MAX;
|
||||
regmap_fields_write(fields->mode, conf->cs,
|
||||
|
||||
@@ -766,11 +766,13 @@ config PANEL_BOOT_MESSAGE
|
||||
An empty message will only clear the display at driver init time. Any other
|
||||
printf()-formatted message is valid with newline and escape codes.
|
||||
|
||||
config UID_CPUTIME
|
||||
bool "Per-UID cpu time statistics"
|
||||
config UID_SYS_STATS
|
||||
bool "Per-UID statistics"
|
||||
depends on PROFILING
|
||||
help
|
||||
Per UID based cpu time statistics exported to /proc/uid_cputime
|
||||
Per UID based io statistics exported to /proc/uid_io
|
||||
Per UID based procstat control in /proc/uid_procstat
|
||||
|
||||
config MEMORY_STATE_TIME
|
||||
tristate "Memory freq/bandwidth time statistics"
|
||||
|
||||
@@ -54,7 +54,7 @@ obj-$(CONFIG_VEXPRESS_SYSCFG) += vexpress-syscfg.o
|
||||
obj-$(CONFIG_CXL_BASE) += cxl/
|
||||
obj-$(CONFIG_PANEL) += panel.o
|
||||
|
||||
obj-$(CONFIG_UID_CPUTIME) += uid_cputime.o
|
||||
obj-$(CONFIG_UID_SYS_STATS) += uid_sys_stats.o
|
||||
obj-$(CONFIG_MEMORY_STATE_TIME) += memory_state_time.o
|
||||
|
||||
lkdtm-$(CONFIG_LKDTM) += lkdtm_core.o
|
||||
|
||||
@@ -419,6 +419,9 @@ struct cxl_afu {
|
||||
struct mutex contexts_lock;
|
||||
spinlock_t afu_cntl_lock;
|
||||
|
||||
/* -1: AFU deconfigured/locked, >= 0: number of readers */
|
||||
atomic_t configured_state;
|
||||
|
||||
/* AFU error buffer fields and bin attribute for sysfs */
|
||||
u64 eb_len, eb_offset;
|
||||
struct bin_attribute attr_eb;
|
||||
|
||||
@@ -268,7 +268,7 @@ struct cxl_afu *cxl_alloc_afu(struct cxl *adapter, int slice)
|
||||
idr_init(&afu->contexts_idr);
|
||||
mutex_init(&afu->contexts_lock);
|
||||
spin_lock_init(&afu->afu_cntl_lock);
|
||||
|
||||
atomic_set(&afu->configured_state, -1);
|
||||
afu->prefault_mode = CXL_PREFAULT_NONE;
|
||||
afu->irqs_max = afu->adapter->user_irqs;
|
||||
|
||||
|
||||
@@ -1129,6 +1129,7 @@ static int pci_configure_afu(struct cxl_afu *afu, struct cxl *adapter, struct pc
|
||||
if ((rc = cxl_native_register_psl_irq(afu)))
|
||||
goto err2;
|
||||
|
||||
atomic_set(&afu->configured_state, 0);
|
||||
return 0;
|
||||
|
||||
err2:
|
||||
@@ -1141,6 +1142,14 @@ err1:
|
||||
|
||||
static void pci_deconfigure_afu(struct cxl_afu *afu)
|
||||
{
|
||||
/*
|
||||
* It's okay to deconfigure when AFU is already locked, otherwise wait
|
||||
* until there are no readers
|
||||
*/
|
||||
if (atomic_read(&afu->configured_state) != -1) {
|
||||
while (atomic_cmpxchg(&afu->configured_state, 0, -1) != -1)
|
||||
schedule();
|
||||
}
|
||||
cxl_native_release_psl_irq(afu);
|
||||
if (afu->adapter->native->sl_ops->release_serr_irq)
|
||||
afu->adapter->native->sl_ops->release_serr_irq(afu);
|
||||
|
||||
+39
-22
@@ -76,23 +76,32 @@ static int cxl_pcie_cfg_record(u8 bus, u8 devfn)
|
||||
return (bus << 8) + devfn;
|
||||
}
|
||||
|
||||
static int cxl_pcie_config_info(struct pci_bus *bus, unsigned int devfn,
|
||||
struct cxl_afu **_afu, int *_record)
|
||||
static inline struct cxl_afu *pci_bus_to_afu(struct pci_bus *bus)
|
||||
{
|
||||
struct pci_controller *phb = bus ? pci_bus_to_host(bus) : NULL;
|
||||
|
||||
return phb ? phb->private_data : NULL;
|
||||
}
|
||||
|
||||
static void cxl_afu_configured_put(struct cxl_afu *afu)
|
||||
{
|
||||
atomic_dec_if_positive(&afu->configured_state);
|
||||
}
|
||||
|
||||
static bool cxl_afu_configured_get(struct cxl_afu *afu)
|
||||
{
|
||||
return atomic_inc_unless_negative(&afu->configured_state);
|
||||
}
|
||||
|
||||
static inline int cxl_pcie_config_info(struct pci_bus *bus, unsigned int devfn,
|
||||
struct cxl_afu *afu, int *_record)
|
||||
{
|
||||
struct pci_controller *phb;
|
||||
struct cxl_afu *afu;
|
||||
int record;
|
||||
|
||||
phb = pci_bus_to_host(bus);
|
||||
if (phb == NULL)
|
||||
return PCIBIOS_DEVICE_NOT_FOUND;
|
||||
|
||||
afu = (struct cxl_afu *)phb->private_data;
|
||||
record = cxl_pcie_cfg_record(bus->number, devfn);
|
||||
if (record > afu->crs_num)
|
||||
return PCIBIOS_DEVICE_NOT_FOUND;
|
||||
|
||||
*_afu = afu;
|
||||
*_record = record;
|
||||
return 0;
|
||||
}
|
||||
@@ -106,9 +115,14 @@ static int cxl_pcie_read_config(struct pci_bus *bus, unsigned int devfn,
|
||||
u16 val16;
|
||||
u32 val32;
|
||||
|
||||
rc = cxl_pcie_config_info(bus, devfn, &afu, &record);
|
||||
afu = pci_bus_to_afu(bus);
|
||||
/* Grab a reader lock on afu. */
|
||||
if (afu == NULL || !cxl_afu_configured_get(afu))
|
||||
return PCIBIOS_DEVICE_NOT_FOUND;
|
||||
|
||||
rc = cxl_pcie_config_info(bus, devfn, afu, &record);
|
||||
if (rc)
|
||||
return rc;
|
||||
goto out;
|
||||
|
||||
switch (len) {
|
||||
case 1:
|
||||
@@ -127,10 +141,9 @@ static int cxl_pcie_read_config(struct pci_bus *bus, unsigned int devfn,
|
||||
WARN_ON(1);
|
||||
}
|
||||
|
||||
if (rc)
|
||||
return PCIBIOS_DEVICE_NOT_FOUND;
|
||||
|
||||
return PCIBIOS_SUCCESSFUL;
|
||||
out:
|
||||
cxl_afu_configured_put(afu);
|
||||
return rc ? PCIBIOS_DEVICE_NOT_FOUND : PCIBIOS_SUCCESSFUL;
|
||||
}
|
||||
|
||||
static int cxl_pcie_write_config(struct pci_bus *bus, unsigned int devfn,
|
||||
@@ -139,9 +152,14 @@ static int cxl_pcie_write_config(struct pci_bus *bus, unsigned int devfn,
|
||||
int rc, record;
|
||||
struct cxl_afu *afu;
|
||||
|
||||
rc = cxl_pcie_config_info(bus, devfn, &afu, &record);
|
||||
afu = pci_bus_to_afu(bus);
|
||||
/* Grab a reader lock on afu. */
|
||||
if (afu == NULL || !cxl_afu_configured_get(afu))
|
||||
return PCIBIOS_DEVICE_NOT_FOUND;
|
||||
|
||||
rc = cxl_pcie_config_info(bus, devfn, afu, &record);
|
||||
if (rc)
|
||||
return rc;
|
||||
goto out;
|
||||
|
||||
switch (len) {
|
||||
case 1:
|
||||
@@ -157,10 +175,9 @@ static int cxl_pcie_write_config(struct pci_bus *bus, unsigned int devfn,
|
||||
WARN_ON(1);
|
||||
}
|
||||
|
||||
if (rc)
|
||||
return PCIBIOS_SET_FAILED;
|
||||
|
||||
return PCIBIOS_SUCCESSFUL;
|
||||
out:
|
||||
cxl_afu_configured_put(afu);
|
||||
return rc ? PCIBIOS_SET_FAILED : PCIBIOS_SUCCESSFUL;
|
||||
}
|
||||
|
||||
static struct pci_ops cxl_pcie_pci_ops =
|
||||
|
||||
+26
-22
@@ -182,32 +182,36 @@ static ssize_t mei_read(struct file *file, char __user *ubuf,
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (rets == -EBUSY &&
|
||||
!mei_cl_enqueue_ctrl_wr_cb(cl, length, MEI_FOP_READ, file)) {
|
||||
rets = -ENOMEM;
|
||||
|
||||
again:
|
||||
mutex_unlock(&dev->device_lock);
|
||||
if (wait_event_interruptible(cl->rx_wait,
|
||||
!list_empty(&cl->rd_completed) ||
|
||||
!mei_cl_is_connected(cl))) {
|
||||
if (signal_pending(current))
|
||||
return -EINTR;
|
||||
return -ERESTARTSYS;
|
||||
}
|
||||
mutex_lock(&dev->device_lock);
|
||||
|
||||
if (!mei_cl_is_connected(cl)) {
|
||||
rets = -ENODEV;
|
||||
goto out;
|
||||
}
|
||||
|
||||
do {
|
||||
mutex_unlock(&dev->device_lock);
|
||||
cb = mei_cl_read_cb(cl, file);
|
||||
if (!cb) {
|
||||
/*
|
||||
* For amthif all the waiters are woken up,
|
||||
* but only fp with matching cb->fp get the cb,
|
||||
* the others have to return to wait on read.
|
||||
*/
|
||||
if (cl == &dev->iamthif_cl)
|
||||
goto again;
|
||||
|
||||
if (wait_event_interruptible(cl->rx_wait,
|
||||
(!list_empty(&cl->rd_completed)) ||
|
||||
(!mei_cl_is_connected(cl)))) {
|
||||
|
||||
if (signal_pending(current))
|
||||
return -EINTR;
|
||||
return -ERESTARTSYS;
|
||||
}
|
||||
|
||||
mutex_lock(&dev->device_lock);
|
||||
if (!mei_cl_is_connected(cl)) {
|
||||
rets = -ENODEV;
|
||||
goto out;
|
||||
}
|
||||
|
||||
cb = mei_cl_read_cb(cl, file);
|
||||
} while (!cb);
|
||||
rets = 0;
|
||||
goto out;
|
||||
}
|
||||
|
||||
copy_buffer:
|
||||
/* now copy the data to user space */
|
||||
|
||||
@@ -1,240 +0,0 @@
|
||||
/* drivers/misc/uid_cputime.c
|
||||
*
|
||||
* Copyright (C) 2014 - 2015 Google, Inc.
|
||||
*
|
||||
* This software is licensed under the terms of the GNU General Public
|
||||
* License version 2, as published by the Free Software Foundation, and
|
||||
* may be copied, distributed, and modified under those terms.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/atomic.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/hashtable.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/list.h>
|
||||
#include <linux/proc_fs.h>
|
||||
#include <linux/profile.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/seq_file.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/uaccess.h>
|
||||
|
||||
#define UID_HASH_BITS 10
|
||||
DECLARE_HASHTABLE(hash_table, UID_HASH_BITS);
|
||||
|
||||
static DEFINE_MUTEX(uid_lock);
|
||||
static struct proc_dir_entry *parent;
|
||||
|
||||
struct uid_entry {
|
||||
uid_t uid;
|
||||
cputime_t utime;
|
||||
cputime_t stime;
|
||||
cputime_t active_utime;
|
||||
cputime_t active_stime;
|
||||
struct hlist_node hash;
|
||||
};
|
||||
|
||||
static struct uid_entry *find_uid_entry(uid_t uid)
|
||||
{
|
||||
struct uid_entry *uid_entry;
|
||||
hash_for_each_possible(hash_table, uid_entry, hash, uid) {
|
||||
if (uid_entry->uid == uid)
|
||||
return uid_entry;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static struct uid_entry *find_or_register_uid(uid_t uid)
|
||||
{
|
||||
struct uid_entry *uid_entry;
|
||||
|
||||
uid_entry = find_uid_entry(uid);
|
||||
if (uid_entry)
|
||||
return uid_entry;
|
||||
|
||||
uid_entry = kzalloc(sizeof(struct uid_entry), GFP_ATOMIC);
|
||||
if (!uid_entry)
|
||||
return NULL;
|
||||
|
||||
uid_entry->uid = uid;
|
||||
|
||||
hash_add(hash_table, &uid_entry->hash, uid);
|
||||
|
||||
return uid_entry;
|
||||
}
|
||||
|
||||
static int uid_stat_show(struct seq_file *m, void *v)
|
||||
{
|
||||
struct uid_entry *uid_entry;
|
||||
struct task_struct *task, *temp;
|
||||
cputime_t utime;
|
||||
cputime_t stime;
|
||||
unsigned long bkt;
|
||||
|
||||
mutex_lock(&uid_lock);
|
||||
|
||||
hash_for_each(hash_table, bkt, uid_entry, hash) {
|
||||
uid_entry->active_stime = 0;
|
||||
uid_entry->active_utime = 0;
|
||||
}
|
||||
|
||||
read_lock(&tasklist_lock);
|
||||
do_each_thread(temp, task) {
|
||||
uid_entry = find_or_register_uid(from_kuid_munged(
|
||||
current_user_ns(), task_uid(task)));
|
||||
if (!uid_entry) {
|
||||
read_unlock(&tasklist_lock);
|
||||
mutex_unlock(&uid_lock);
|
||||
pr_err("%s: failed to find the uid_entry for uid %d\n",
|
||||
__func__, from_kuid_munged(current_user_ns(),
|
||||
task_uid(task)));
|
||||
return -ENOMEM;
|
||||
}
|
||||
task_cputime_adjusted(task, &utime, &stime);
|
||||
uid_entry->active_utime += utime;
|
||||
uid_entry->active_stime += stime;
|
||||
} while_each_thread(temp, task);
|
||||
read_unlock(&tasklist_lock);
|
||||
|
||||
hash_for_each(hash_table, bkt, uid_entry, hash) {
|
||||
cputime_t total_utime = uid_entry->utime +
|
||||
uid_entry->active_utime;
|
||||
cputime_t total_stime = uid_entry->stime +
|
||||
uid_entry->active_stime;
|
||||
seq_printf(m, "%d: %llu %llu\n", uid_entry->uid,
|
||||
(unsigned long long)jiffies_to_msecs(
|
||||
cputime_to_jiffies(total_utime)) * USEC_PER_MSEC,
|
||||
(unsigned long long)jiffies_to_msecs(
|
||||
cputime_to_jiffies(total_stime)) * USEC_PER_MSEC);
|
||||
}
|
||||
|
||||
mutex_unlock(&uid_lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int uid_stat_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
return single_open(file, uid_stat_show, PDE_DATA(inode));
|
||||
}
|
||||
|
||||
static const struct file_operations uid_stat_fops = {
|
||||
.open = uid_stat_open,
|
||||
.read = seq_read,
|
||||
.llseek = seq_lseek,
|
||||
.release = single_release,
|
||||
};
|
||||
|
||||
static int uid_remove_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
return single_open(file, NULL, NULL);
|
||||
}
|
||||
|
||||
static ssize_t uid_remove_write(struct file *file,
|
||||
const char __user *buffer, size_t count, loff_t *ppos)
|
||||
{
|
||||
struct uid_entry *uid_entry;
|
||||
struct hlist_node *tmp;
|
||||
char uids[128];
|
||||
char *start_uid, *end_uid = NULL;
|
||||
long int uid_start = 0, uid_end = 0;
|
||||
|
||||
if (count >= sizeof(uids))
|
||||
count = sizeof(uids) - 1;
|
||||
|
||||
if (copy_from_user(uids, buffer, count))
|
||||
return -EFAULT;
|
||||
|
||||
uids[count] = '\0';
|
||||
end_uid = uids;
|
||||
start_uid = strsep(&end_uid, "-");
|
||||
|
||||
if (!start_uid || !end_uid)
|
||||
return -EINVAL;
|
||||
|
||||
if (kstrtol(start_uid, 10, &uid_start) != 0 ||
|
||||
kstrtol(end_uid, 10, &uid_end) != 0) {
|
||||
return -EINVAL;
|
||||
}
|
||||
mutex_lock(&uid_lock);
|
||||
|
||||
for (; uid_start <= uid_end; uid_start++) {
|
||||
hash_for_each_possible_safe(hash_table, uid_entry, tmp,
|
||||
hash, (uid_t)uid_start) {
|
||||
if (uid_start == uid_entry->uid) {
|
||||
hash_del(&uid_entry->hash);
|
||||
kfree(uid_entry);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mutex_unlock(&uid_lock);
|
||||
return count;
|
||||
}
|
||||
|
||||
static const struct file_operations uid_remove_fops = {
|
||||
.open = uid_remove_open,
|
||||
.release = single_release,
|
||||
.write = uid_remove_write,
|
||||
};
|
||||
|
||||
static int process_notifier(struct notifier_block *self,
|
||||
unsigned long cmd, void *v)
|
||||
{
|
||||
struct task_struct *task = v;
|
||||
struct uid_entry *uid_entry;
|
||||
cputime_t utime, stime;
|
||||
uid_t uid;
|
||||
|
||||
if (!task)
|
||||
return NOTIFY_OK;
|
||||
|
||||
mutex_lock(&uid_lock);
|
||||
uid = from_kuid_munged(current_user_ns(), task_uid(task));
|
||||
uid_entry = find_or_register_uid(uid);
|
||||
if (!uid_entry) {
|
||||
pr_err("%s: failed to find uid %d\n", __func__, uid);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
task_cputime_adjusted(task, &utime, &stime);
|
||||
uid_entry->utime += utime;
|
||||
uid_entry->stime += stime;
|
||||
|
||||
exit:
|
||||
mutex_unlock(&uid_lock);
|
||||
return NOTIFY_OK;
|
||||
}
|
||||
|
||||
static struct notifier_block process_notifier_block = {
|
||||
.notifier_call = process_notifier,
|
||||
};
|
||||
|
||||
static int __init proc_uid_cputime_init(void)
|
||||
{
|
||||
hash_init(hash_table);
|
||||
|
||||
parent = proc_mkdir("uid_cputime", NULL);
|
||||
if (!parent) {
|
||||
pr_err("%s: failed to create proc entry\n", __func__);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
proc_create_data("remove_uid_range", S_IWUGO, parent, &uid_remove_fops,
|
||||
NULL);
|
||||
|
||||
proc_create_data("show_uid_stat", S_IRUGO, parent, &uid_stat_fops,
|
||||
NULL);
|
||||
|
||||
profile_event_register(PROFILE_TASK_EXIT, &process_notifier_block);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
early_initcall(proc_uid_cputime_init);
|
||||
@@ -0,0 +1,464 @@
|
||||
/* drivers/misc/uid_cputime.c
|
||||
*
|
||||
* Copyright (C) 2014 - 2015 Google, Inc.
|
||||
*
|
||||
* This software is licensed under the terms of the GNU General Public
|
||||
* License version 2, as published by the Free Software Foundation, and
|
||||
* may be copied, distributed, and modified under those terms.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/atomic.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/hashtable.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/list.h>
|
||||
#include <linux/proc_fs.h>
|
||||
#include <linux/profile.h>
|
||||
#include <linux/rtmutex.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/seq_file.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/uaccess.h>
|
||||
|
||||
|
||||
#define UID_HASH_BITS 10
|
||||
DECLARE_HASHTABLE(hash_table, UID_HASH_BITS);
|
||||
|
||||
static DEFINE_RT_MUTEX(uid_lock);
|
||||
static struct proc_dir_entry *cpu_parent;
|
||||
static struct proc_dir_entry *io_parent;
|
||||
static struct proc_dir_entry *proc_parent;
|
||||
|
||||
struct io_stats {
|
||||
u64 read_bytes;
|
||||
u64 write_bytes;
|
||||
u64 rchar;
|
||||
u64 wchar;
|
||||
u64 fsync;
|
||||
};
|
||||
|
||||
#define UID_STATE_FOREGROUND 0
|
||||
#define UID_STATE_BACKGROUND 1
|
||||
#define UID_STATE_BUCKET_SIZE 2
|
||||
|
||||
#define UID_STATE_TOTAL_CURR 2
|
||||
#define UID_STATE_TOTAL_LAST 3
|
||||
#define UID_STATE_SIZE 4
|
||||
|
||||
struct uid_entry {
|
||||
uid_t uid;
|
||||
cputime_t utime;
|
||||
cputime_t stime;
|
||||
cputime_t active_utime;
|
||||
cputime_t active_stime;
|
||||
int state;
|
||||
struct io_stats io[UID_STATE_SIZE];
|
||||
struct hlist_node hash;
|
||||
};
|
||||
|
||||
static struct uid_entry *find_uid_entry(uid_t uid)
|
||||
{
|
||||
struct uid_entry *uid_entry;
|
||||
hash_for_each_possible(hash_table, uid_entry, hash, uid) {
|
||||
if (uid_entry->uid == uid)
|
||||
return uid_entry;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static struct uid_entry *find_or_register_uid(uid_t uid)
|
||||
{
|
||||
struct uid_entry *uid_entry;
|
||||
|
||||
uid_entry = find_uid_entry(uid);
|
||||
if (uid_entry)
|
||||
return uid_entry;
|
||||
|
||||
uid_entry = kzalloc(sizeof(struct uid_entry), GFP_ATOMIC);
|
||||
if (!uid_entry)
|
||||
return NULL;
|
||||
|
||||
uid_entry->uid = uid;
|
||||
|
||||
hash_add(hash_table, &uid_entry->hash, uid);
|
||||
|
||||
return uid_entry;
|
||||
}
|
||||
|
||||
static int uid_cputime_show(struct seq_file *m, void *v)
|
||||
{
|
||||
struct uid_entry *uid_entry;
|
||||
struct task_struct *task, *temp;
|
||||
cputime_t utime;
|
||||
cputime_t stime;
|
||||
unsigned long bkt;
|
||||
|
||||
rt_mutex_lock(&uid_lock);
|
||||
|
||||
hash_for_each(hash_table, bkt, uid_entry, hash) {
|
||||
uid_entry->active_stime = 0;
|
||||
uid_entry->active_utime = 0;
|
||||
}
|
||||
|
||||
read_lock(&tasklist_lock);
|
||||
do_each_thread(temp, task) {
|
||||
uid_entry = find_or_register_uid(from_kuid_munged(
|
||||
current_user_ns(), task_uid(task)));
|
||||
if (!uid_entry) {
|
||||
read_unlock(&tasklist_lock);
|
||||
rt_mutex_unlock(&uid_lock);
|
||||
pr_err("%s: failed to find the uid_entry for uid %d\n",
|
||||
__func__, from_kuid_munged(current_user_ns(),
|
||||
task_uid(task)));
|
||||
return -ENOMEM;
|
||||
}
|
||||
task_cputime_adjusted(task, &utime, &stime);
|
||||
uid_entry->active_utime += utime;
|
||||
uid_entry->active_stime += stime;
|
||||
} while_each_thread(temp, task);
|
||||
read_unlock(&tasklist_lock);
|
||||
|
||||
hash_for_each(hash_table, bkt, uid_entry, hash) {
|
||||
cputime_t total_utime = uid_entry->utime +
|
||||
uid_entry->active_utime;
|
||||
cputime_t total_stime = uid_entry->stime +
|
||||
uid_entry->active_stime;
|
||||
seq_printf(m, "%d: %llu %llu\n", uid_entry->uid,
|
||||
(unsigned long long)jiffies_to_msecs(
|
||||
cputime_to_jiffies(total_utime)) * USEC_PER_MSEC,
|
||||
(unsigned long long)jiffies_to_msecs(
|
||||
cputime_to_jiffies(total_stime)) * USEC_PER_MSEC);
|
||||
}
|
||||
|
||||
rt_mutex_unlock(&uid_lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int uid_cputime_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
return single_open(file, uid_cputime_show, PDE_DATA(inode));
|
||||
}
|
||||
|
||||
static const struct file_operations uid_cputime_fops = {
|
||||
.open = uid_cputime_open,
|
||||
.read = seq_read,
|
||||
.llseek = seq_lseek,
|
||||
.release = single_release,
|
||||
};
|
||||
|
||||
static int uid_remove_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
return single_open(file, NULL, NULL);
|
||||
}
|
||||
|
||||
static ssize_t uid_remove_write(struct file *file,
|
||||
const char __user *buffer, size_t count, loff_t *ppos)
|
||||
{
|
||||
struct uid_entry *uid_entry;
|
||||
struct hlist_node *tmp;
|
||||
char uids[128];
|
||||
char *start_uid, *end_uid = NULL;
|
||||
long int uid_start = 0, uid_end = 0;
|
||||
|
||||
if (count >= sizeof(uids))
|
||||
count = sizeof(uids) - 1;
|
||||
|
||||
if (copy_from_user(uids, buffer, count))
|
||||
return -EFAULT;
|
||||
|
||||
uids[count] = '\0';
|
||||
end_uid = uids;
|
||||
start_uid = strsep(&end_uid, "-");
|
||||
|
||||
if (!start_uid || !end_uid)
|
||||
return -EINVAL;
|
||||
|
||||
if (kstrtol(start_uid, 10, &uid_start) != 0 ||
|
||||
kstrtol(end_uid, 10, &uid_end) != 0) {
|
||||
return -EINVAL;
|
||||
}
|
||||
rt_mutex_lock(&uid_lock);
|
||||
|
||||
for (; uid_start <= uid_end; uid_start++) {
|
||||
hash_for_each_possible_safe(hash_table, uid_entry, tmp,
|
||||
hash, (uid_t)uid_start) {
|
||||
if (uid_start == uid_entry->uid) {
|
||||
hash_del(&uid_entry->hash);
|
||||
kfree(uid_entry);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
rt_mutex_unlock(&uid_lock);
|
||||
return count;
|
||||
}
|
||||
|
||||
static const struct file_operations uid_remove_fops = {
|
||||
.open = uid_remove_open,
|
||||
.release = single_release,
|
||||
.write = uid_remove_write,
|
||||
};
|
||||
|
||||
static u64 compute_write_bytes(struct task_struct *task)
|
||||
{
|
||||
if (task->ioac.write_bytes <= task->ioac.cancelled_write_bytes)
|
||||
return 0;
|
||||
|
||||
return task->ioac.write_bytes - task->ioac.cancelled_write_bytes;
|
||||
}
|
||||
|
||||
static void add_uid_io_curr_stats(struct uid_entry *uid_entry,
|
||||
struct task_struct *task)
|
||||
{
|
||||
struct io_stats *io_curr = &uid_entry->io[UID_STATE_TOTAL_CURR];
|
||||
|
||||
io_curr->read_bytes += task->ioac.read_bytes;
|
||||
io_curr->write_bytes += compute_write_bytes(task);
|
||||
io_curr->rchar += task->ioac.rchar;
|
||||
io_curr->wchar += task->ioac.wchar;
|
||||
io_curr->fsync += task->ioac.syscfs;
|
||||
}
|
||||
|
||||
static void clean_uid_io_last_stats(struct uid_entry *uid_entry,
|
||||
struct task_struct *task)
|
||||
{
|
||||
struct io_stats *io_last = &uid_entry->io[UID_STATE_TOTAL_LAST];
|
||||
|
||||
io_last->read_bytes -= task->ioac.read_bytes;
|
||||
io_last->write_bytes -= compute_write_bytes(task);
|
||||
io_last->rchar -= task->ioac.rchar;
|
||||
io_last->wchar -= task->ioac.wchar;
|
||||
io_last->fsync -= task->ioac.syscfs;
|
||||
}
|
||||
|
||||
static void update_io_stats_locked(void)
|
||||
{
|
||||
struct uid_entry *uid_entry;
|
||||
struct task_struct *task, *temp;
|
||||
struct io_stats *io_bucket, *io_curr, *io_last;
|
||||
unsigned long bkt;
|
||||
|
||||
BUG_ON(!rt_mutex_is_locked(&uid_lock));
|
||||
|
||||
hash_for_each(hash_table, bkt, uid_entry, hash)
|
||||
memset(&uid_entry->io[UID_STATE_TOTAL_CURR], 0,
|
||||
sizeof(struct io_stats));
|
||||
|
||||
read_lock(&tasklist_lock);
|
||||
do_each_thread(temp, task) {
|
||||
uid_entry = find_or_register_uid(from_kuid_munged(
|
||||
current_user_ns(), task_uid(task)));
|
||||
if (!uid_entry)
|
||||
continue;
|
||||
add_uid_io_curr_stats(uid_entry, task);
|
||||
} while_each_thread(temp, task);
|
||||
read_unlock(&tasklist_lock);
|
||||
|
||||
hash_for_each(hash_table, bkt, uid_entry, hash) {
|
||||
io_bucket = &uid_entry->io[uid_entry->state];
|
||||
io_curr = &uid_entry->io[UID_STATE_TOTAL_CURR];
|
||||
io_last = &uid_entry->io[UID_STATE_TOTAL_LAST];
|
||||
|
||||
io_bucket->read_bytes +=
|
||||
io_curr->read_bytes - io_last->read_bytes;
|
||||
io_bucket->write_bytes +=
|
||||
io_curr->write_bytes - io_last->write_bytes;
|
||||
io_bucket->rchar += io_curr->rchar - io_last->rchar;
|
||||
io_bucket->wchar += io_curr->wchar - io_last->wchar;
|
||||
io_bucket->fsync += io_curr->fsync - io_last->fsync;
|
||||
|
||||
io_last->read_bytes = io_curr->read_bytes;
|
||||
io_last->write_bytes = io_curr->write_bytes;
|
||||
io_last->rchar = io_curr->rchar;
|
||||
io_last->wchar = io_curr->wchar;
|
||||
io_last->fsync = io_curr->fsync;
|
||||
}
|
||||
}
|
||||
|
||||
static int uid_io_show(struct seq_file *m, void *v)
|
||||
{
|
||||
struct uid_entry *uid_entry;
|
||||
unsigned long bkt;
|
||||
|
||||
rt_mutex_lock(&uid_lock);
|
||||
|
||||
update_io_stats_locked();
|
||||
|
||||
hash_for_each(hash_table, bkt, uid_entry, hash) {
|
||||
seq_printf(m, "%d %llu %llu %llu %llu %llu %llu %llu %llu %llu %llu\n",
|
||||
uid_entry->uid,
|
||||
uid_entry->io[UID_STATE_FOREGROUND].rchar,
|
||||
uid_entry->io[UID_STATE_FOREGROUND].wchar,
|
||||
uid_entry->io[UID_STATE_FOREGROUND].read_bytes,
|
||||
uid_entry->io[UID_STATE_FOREGROUND].write_bytes,
|
||||
uid_entry->io[UID_STATE_BACKGROUND].rchar,
|
||||
uid_entry->io[UID_STATE_BACKGROUND].wchar,
|
||||
uid_entry->io[UID_STATE_BACKGROUND].read_bytes,
|
||||
uid_entry->io[UID_STATE_BACKGROUND].write_bytes,
|
||||
uid_entry->io[UID_STATE_FOREGROUND].fsync,
|
||||
uid_entry->io[UID_STATE_BACKGROUND].fsync);
|
||||
}
|
||||
|
||||
rt_mutex_unlock(&uid_lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int uid_io_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
return single_open(file, uid_io_show, PDE_DATA(inode));
|
||||
}
|
||||
|
||||
static const struct file_operations uid_io_fops = {
|
||||
.open = uid_io_open,
|
||||
.read = seq_read,
|
||||
.llseek = seq_lseek,
|
||||
.release = single_release,
|
||||
};
|
||||
|
||||
static int uid_procstat_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
return single_open(file, NULL, NULL);
|
||||
}
|
||||
|
||||
static ssize_t uid_procstat_write(struct file *file,
|
||||
const char __user *buffer, size_t count, loff_t *ppos)
|
||||
{
|
||||
struct uid_entry *uid_entry;
|
||||
uid_t uid;
|
||||
int argc, state;
|
||||
char input[128];
|
||||
|
||||
if (count >= sizeof(input))
|
||||
return -EINVAL;
|
||||
|
||||
if (copy_from_user(input, buffer, count))
|
||||
return -EFAULT;
|
||||
|
||||
input[count] = '\0';
|
||||
|
||||
argc = sscanf(input, "%u %d", &uid, &state);
|
||||
if (argc != 2)
|
||||
return -EINVAL;
|
||||
|
||||
if (state != UID_STATE_BACKGROUND && state != UID_STATE_FOREGROUND)
|
||||
return -EINVAL;
|
||||
|
||||
rt_mutex_lock(&uid_lock);
|
||||
|
||||
uid_entry = find_or_register_uid(uid);
|
||||
if (!uid_entry) {
|
||||
rt_mutex_unlock(&uid_lock);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (uid_entry->state == state) {
|
||||
rt_mutex_unlock(&uid_lock);
|
||||
return count;
|
||||
}
|
||||
|
||||
update_io_stats_locked();
|
||||
|
||||
uid_entry->state = state;
|
||||
|
||||
rt_mutex_unlock(&uid_lock);
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static const struct file_operations uid_procstat_fops = {
|
||||
.open = uid_procstat_open,
|
||||
.release = single_release,
|
||||
.write = uid_procstat_write,
|
||||
};
|
||||
|
||||
static int process_notifier(struct notifier_block *self,
|
||||
unsigned long cmd, void *v)
|
||||
{
|
||||
struct task_struct *task = v;
|
||||
struct uid_entry *uid_entry;
|
||||
cputime_t utime, stime;
|
||||
uid_t uid;
|
||||
|
||||
if (!task)
|
||||
return NOTIFY_OK;
|
||||
|
||||
rt_mutex_lock(&uid_lock);
|
||||
uid = from_kuid_munged(current_user_ns(), task_uid(task));
|
||||
uid_entry = find_or_register_uid(uid);
|
||||
if (!uid_entry) {
|
||||
pr_err("%s: failed to find uid %d\n", __func__, uid);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
task_cputime_adjusted(task, &utime, &stime);
|
||||
uid_entry->utime += utime;
|
||||
uid_entry->stime += stime;
|
||||
|
||||
update_io_stats_locked();
|
||||
clean_uid_io_last_stats(uid_entry, task);
|
||||
|
||||
exit:
|
||||
rt_mutex_unlock(&uid_lock);
|
||||
return NOTIFY_OK;
|
||||
}
|
||||
|
||||
static struct notifier_block process_notifier_block = {
|
||||
.notifier_call = process_notifier,
|
||||
};
|
||||
|
||||
static int __init proc_uid_sys_stats_init(void)
|
||||
{
|
||||
hash_init(hash_table);
|
||||
|
||||
cpu_parent = proc_mkdir("uid_cputime", NULL);
|
||||
if (!cpu_parent) {
|
||||
pr_err("%s: failed to create uid_cputime proc entry\n",
|
||||
__func__);
|
||||
goto err;
|
||||
}
|
||||
|
||||
proc_create_data("remove_uid_range", 0222, cpu_parent,
|
||||
&uid_remove_fops, NULL);
|
||||
proc_create_data("show_uid_stat", 0444, cpu_parent,
|
||||
&uid_cputime_fops, NULL);
|
||||
|
||||
io_parent = proc_mkdir("uid_io", NULL);
|
||||
if (!io_parent) {
|
||||
pr_err("%s: failed to create uid_io proc entry\n",
|
||||
__func__);
|
||||
goto err;
|
||||
}
|
||||
|
||||
proc_create_data("stats", 0444, io_parent,
|
||||
&uid_io_fops, NULL);
|
||||
|
||||
proc_parent = proc_mkdir("uid_procstat", NULL);
|
||||
if (!proc_parent) {
|
||||
pr_err("%s: failed to create uid_procstat proc entry\n",
|
||||
__func__);
|
||||
goto err;
|
||||
}
|
||||
|
||||
proc_create_data("set", 0222, proc_parent,
|
||||
&uid_procstat_fops, NULL);
|
||||
|
||||
profile_event_register(PROFILE_TASK_EXIT, &process_notifier_block);
|
||||
|
||||
return 0;
|
||||
|
||||
err:
|
||||
remove_proc_subtree("uid_cputime", NULL);
|
||||
remove_proc_subtree("uid_io", NULL);
|
||||
remove_proc_subtree("uid_procstat", NULL);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
early_initcall(proc_uid_sys_stats_init);
|
||||
@@ -466,7 +466,10 @@ static int sdhci_acpi_probe(struct platform_device *pdev)
|
||||
if (sdhci_acpi_flag(c, SDHCI_ACPI_SD_CD)) {
|
||||
bool v = sdhci_acpi_flag(c, SDHCI_ACPI_SD_CD_OVERRIDE_LEVEL);
|
||||
|
||||
if (mmc_gpiod_request_cd(host->mmc, NULL, 0, v, 0, NULL)) {
|
||||
err = mmc_gpiod_request_cd(host->mmc, NULL, 0, v, 0, NULL);
|
||||
if (err) {
|
||||
if (err == -EPROBE_DEFER)
|
||||
goto err_free;
|
||||
dev_warn(dev, "failed to setup card detect gpio\n");
|
||||
c->use_runtime_pm = false;
|
||||
}
|
||||
|
||||
@@ -258,9 +258,15 @@ static void fsl_ifc_run_command(struct mtd_info *mtd)
|
||||
int bufnum = nctrl->page & priv->bufnum_mask;
|
||||
int sector = bufnum * chip->ecc.steps;
|
||||
int sector_end = sector + chip->ecc.steps - 1;
|
||||
__be32 *eccstat_regs;
|
||||
|
||||
if (ctrl->version >= FSL_IFC_VERSION_2_0_0)
|
||||
eccstat_regs = ifc->ifc_nand.v2_nand_eccstat;
|
||||
else
|
||||
eccstat_regs = ifc->ifc_nand.v1_nand_eccstat;
|
||||
|
||||
for (i = sector / 4; i <= sector_end / 4; i++)
|
||||
eccstat[i] = ifc_in32(&ifc->ifc_nand.nand_eccstat[i]);
|
||||
eccstat[i] = ifc_in32(&eccstat_regs[i]);
|
||||
|
||||
for (i = sector; i <= sector_end; i++) {
|
||||
errors = check_read_ecc(mtd, ctrl, eccstat, i);
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user