Merge 5.10.69 into android12-5.10-lts

Changes in 5.10.69
	PCI: pci-bridge-emul: Add PCIe Root Capabilities Register
	PCI: aardvark: Fix reporting CRS value
	console: consume APC, DM, DCS
	s390/pci_mmio: fully validate the VMA before calling follow_pte()
	ARM: Qualify enabling of swiotlb_init()
	ARM: 9077/1: PLT: Move struct plt_entries definition to header
	ARM: 9078/1: Add warn suppress parameter to arm_gen_branch_link()
	ARM: 9079/1: ftrace: Add MODULE_PLTS support
	ARM: 9098/1: ftrace: MODULE_PLT: Fix build problem without DYNAMIC_FTRACE
	Revert "net/mlx5: Register to devlink ingress VLAN filter trap"
	sctp: validate chunk size in __rcv_asconf_lookup
	sctp: add param size validation for SCTP_PARAM_SET_PRIMARY
	staging: rtl8192u: Fix bitwise vs logical operator in TranslateRxSignalStuff819xUsb()
	coredump: fix memleak in dump_vma_snapshot()
	um: virtio_uml: fix memory leak on init failures
	dmaengine: acpi: Avoid comparison GSI with Linux vIRQ
	perf test: Fix bpf test sample mismatch reporting
	tools lib: Adopt memchr_inv() from kernel
	perf tools: Allow build-id with trailing zeros
	thermal/drivers/exynos: Fix an error code in exynos_tmu_probe()
	9p/trans_virtio: Remove sysfs file on probe failure
	prctl: allow to setup brk for et_dyn executables
	nilfs2: use refcount_dec_and_lock() to fix potential UAF
	profiling: fix shift-out-of-bounds bugs
	PM: sleep: core: Avoid setting power.must_resume to false
	pwm: lpc32xx: Don't modify HW state in .probe() after the PWM chip was registered
	pwm: mxs: Don't modify HW state in .probe() after the PWM chip was registered
	dmaengine: idxd: fix wq slot allocation index check
	platform/chrome: sensorhub: Add trace events for sample
	platform/chrome: cros_ec_trace: Fix format warnings
	ceph: allow ceph_put_mds_session to take NULL or ERR_PTR
	ceph: cancel delayed work instead of flushing on mdsc teardown
	Kconfig.debug: drop selecting non-existing HARDLOCKUP_DETECTOR_ARCH
	tools/bootconfig: Fix tracing_on option checking in ftrace2bconf.sh
	thermal/core: Fix thermal_cooling_device_register() prototype
	drm/amdgpu: Disable PCIE_DPM on Intel RKL Platform
	drivers: base: cacheinfo: Get rid of DEFINE_SMP_CALL_CACHE_FUNCTION()
	dma-buf: DMABUF_MOVE_NOTIFY should depend on DMA_SHARED_BUFFER
	parisc: Move pci_dev_is_behind_card_dino to where it is used
	iommu/amd: Relocate GAMSup check to early_enable_iommus
	dmaengine: idxd: depends on !UML
	dmaengine: sprd: Add missing MODULE_DEVICE_TABLE
	dmaengine: ioat: depends on !UML
	dmaengine: xilinx_dma: Set DMA mask for coherent APIs
	ceph: request Fw caps before updating the mtime in ceph_write_iter
	ceph: remove the capsnaps when removing caps
	ceph: lockdep annotations for try_nonblocking_invalidate
	btrfs: update the bdev time directly when closing
	btrfs: fix lockdep warning while mounting sprout fs
	nilfs2: fix memory leak in nilfs_sysfs_create_device_group
	nilfs2: fix NULL pointer in nilfs_##name##_attr_release
	nilfs2: fix memory leak in nilfs_sysfs_create_##name##_group
	nilfs2: fix memory leak in nilfs_sysfs_delete_##name##_group
	nilfs2: fix memory leak in nilfs_sysfs_create_snapshot_group
	nilfs2: fix memory leak in nilfs_sysfs_delete_snapshot_group
	habanalabs: add validity check for event ID received from F/W
	pwm: img: Don't modify HW state in .remove() callback
	pwm: rockchip: Don't modify HW state in .remove() callback
	pwm: stm32-lp: Don't modify HW state in .remove() callback
	blk-throttle: fix UAF by deleteing timer in blk_throtl_exit()
	blk-mq: allow 4x BLK_MAX_REQUEST_COUNT at blk_plug for multiple_queues
	rtc: rx8010: select REGMAP_I2C
	sched/idle: Make the idle timer expire in hard interrupt context
	drm/nouveau/nvkm: Replace -ENOSYS with -ENODEV
	Linux 5.10.69

Signed-off-by: Greg Kroah-Hartman <gregkh@google.com>
Change-Id: I982349e3a65b83e92e9b808154bf8c84d094f1d6
This commit is contained in:
Greg Kroah-Hartman
2021-09-30 18:36:17 +02:00
69 changed files with 677 additions and 316 deletions

View File

@@ -1,7 +1,7 @@
# SPDX-License-Identifier: GPL-2.0 # SPDX-License-Identifier: GPL-2.0
VERSION = 5 VERSION = 5
PATCHLEVEL = 10 PATCHLEVEL = 10
SUBLEVEL = 68 SUBLEVEL = 69
EXTRAVERSION = EXTRAVERSION =
NAME = Dare mighty things NAME = Dare mighty things

View File

@@ -15,6 +15,9 @@ extern void __gnu_mcount_nc(void);
#ifdef CONFIG_DYNAMIC_FTRACE #ifdef CONFIG_DYNAMIC_FTRACE
struct dyn_arch_ftrace { struct dyn_arch_ftrace {
#ifdef CONFIG_ARM_MODULE_PLTS
struct module *mod;
#endif
}; };
static inline unsigned long ftrace_call_adjust(unsigned long addr) static inline unsigned long ftrace_call_adjust(unsigned long addr)

View File

@@ -13,18 +13,18 @@ arm_gen_nop(void)
} }
unsigned long unsigned long
__arm_gen_branch(unsigned long pc, unsigned long addr, bool link); __arm_gen_branch(unsigned long pc, unsigned long addr, bool link, bool warn);
static inline unsigned long static inline unsigned long
arm_gen_branch(unsigned long pc, unsigned long addr) arm_gen_branch(unsigned long pc, unsigned long addr)
{ {
return __arm_gen_branch(pc, addr, false); return __arm_gen_branch(pc, addr, false, true);
} }
static inline unsigned long static inline unsigned long
arm_gen_branch_link(unsigned long pc, unsigned long addr) arm_gen_branch_link(unsigned long pc, unsigned long addr, bool warn)
{ {
return __arm_gen_branch(pc, addr, true); return __arm_gen_branch(pc, addr, true, warn);
} }
#endif #endif

View File

@@ -19,8 +19,18 @@ enum {
}; };
#endif #endif
#define PLT_ENT_STRIDE L1_CACHE_BYTES
#define PLT_ENT_COUNT (PLT_ENT_STRIDE / sizeof(u32))
#define PLT_ENT_SIZE (sizeof(struct plt_entries) / PLT_ENT_COUNT)
struct plt_entries {
u32 ldr[PLT_ENT_COUNT];
u32 lit[PLT_ENT_COUNT];
};
struct mod_plt_sec { struct mod_plt_sec {
struct elf32_shdr *plt; struct elf32_shdr *plt;
struct plt_entries *plt_ent;
int plt_count; int plt_count;
}; };

View File

@@ -68,9 +68,10 @@ int ftrace_arch_code_modify_post_process(void)
return 0; return 0;
} }
static unsigned long ftrace_call_replace(unsigned long pc, unsigned long addr) static unsigned long ftrace_call_replace(unsigned long pc, unsigned long addr,
bool warn)
{ {
return arm_gen_branch_link(pc, addr); return arm_gen_branch_link(pc, addr, warn);
} }
static int ftrace_modify_code(unsigned long pc, unsigned long old, static int ftrace_modify_code(unsigned long pc, unsigned long old,
@@ -104,14 +105,14 @@ int ftrace_update_ftrace_func(ftrace_func_t func)
int ret; int ret;
pc = (unsigned long)&ftrace_call; pc = (unsigned long)&ftrace_call;
new = ftrace_call_replace(pc, (unsigned long)func); new = ftrace_call_replace(pc, (unsigned long)func, true);
ret = ftrace_modify_code(pc, 0, new, false); ret = ftrace_modify_code(pc, 0, new, false);
#ifdef CONFIG_DYNAMIC_FTRACE_WITH_REGS #ifdef CONFIG_DYNAMIC_FTRACE_WITH_REGS
if (!ret) { if (!ret) {
pc = (unsigned long)&ftrace_regs_call; pc = (unsigned long)&ftrace_regs_call;
new = ftrace_call_replace(pc, (unsigned long)func); new = ftrace_call_replace(pc, (unsigned long)func, true);
ret = ftrace_modify_code(pc, 0, new, false); ret = ftrace_modify_code(pc, 0, new, false);
} }
@@ -124,10 +125,22 @@ int ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr)
{ {
unsigned long new, old; unsigned long new, old;
unsigned long ip = rec->ip; unsigned long ip = rec->ip;
unsigned long aaddr = adjust_address(rec, addr);
struct module *mod = NULL;
#ifdef CONFIG_ARM_MODULE_PLTS
mod = rec->arch.mod;
#endif
old = ftrace_nop_replace(rec); old = ftrace_nop_replace(rec);
new = ftrace_call_replace(ip, adjust_address(rec, addr)); new = ftrace_call_replace(ip, aaddr, !mod);
#ifdef CONFIG_ARM_MODULE_PLTS
if (!new && mod) {
aaddr = get_module_plt(mod, ip, aaddr);
new = ftrace_call_replace(ip, aaddr, true);
}
#endif
return ftrace_modify_code(rec->ip, old, new, true); return ftrace_modify_code(rec->ip, old, new, true);
} }
@@ -140,9 +153,9 @@ int ftrace_modify_call(struct dyn_ftrace *rec, unsigned long old_addr,
unsigned long new, old; unsigned long new, old;
unsigned long ip = rec->ip; unsigned long ip = rec->ip;
old = ftrace_call_replace(ip, adjust_address(rec, old_addr)); old = ftrace_call_replace(ip, adjust_address(rec, old_addr), true);
new = ftrace_call_replace(ip, adjust_address(rec, addr)); new = ftrace_call_replace(ip, adjust_address(rec, addr), true);
return ftrace_modify_code(rec->ip, old, new, true); return ftrace_modify_code(rec->ip, old, new, true);
} }
@@ -152,12 +165,29 @@ int ftrace_modify_call(struct dyn_ftrace *rec, unsigned long old_addr,
int ftrace_make_nop(struct module *mod, int ftrace_make_nop(struct module *mod,
struct dyn_ftrace *rec, unsigned long addr) struct dyn_ftrace *rec, unsigned long addr)
{ {
unsigned long aaddr = adjust_address(rec, addr);
unsigned long ip = rec->ip; unsigned long ip = rec->ip;
unsigned long old; unsigned long old;
unsigned long new; unsigned long new;
int ret; int ret;
old = ftrace_call_replace(ip, adjust_address(rec, addr)); #ifdef CONFIG_ARM_MODULE_PLTS
/* mod is only supplied during module loading */
if (!mod)
mod = rec->arch.mod;
else
rec->arch.mod = mod;
#endif
old = ftrace_call_replace(ip, aaddr,
!IS_ENABLED(CONFIG_ARM_MODULE_PLTS) || !mod);
#ifdef CONFIG_ARM_MODULE_PLTS
if (!old && mod) {
aaddr = get_module_plt(mod, ip, aaddr);
old = ftrace_call_replace(ip, aaddr, true);
}
#endif
new = ftrace_nop_replace(rec); new = ftrace_nop_replace(rec);
ret = ftrace_modify_code(ip, old, new, true); ret = ftrace_modify_code(ip, old, new, true);

View File

@@ -3,8 +3,9 @@
#include <linux/kernel.h> #include <linux/kernel.h>
#include <asm/opcodes.h> #include <asm/opcodes.h>
static unsigned long static unsigned long __arm_gen_branch_thumb2(unsigned long pc,
__arm_gen_branch_thumb2(unsigned long pc, unsigned long addr, bool link) unsigned long addr, bool link,
bool warn)
{ {
unsigned long s, j1, j2, i1, i2, imm10, imm11; unsigned long s, j1, j2, i1, i2, imm10, imm11;
unsigned long first, second; unsigned long first, second;
@@ -12,7 +13,7 @@ __arm_gen_branch_thumb2(unsigned long pc, unsigned long addr, bool link)
offset = (long)addr - (long)(pc + 4); offset = (long)addr - (long)(pc + 4);
if (offset < -16777216 || offset > 16777214) { if (offset < -16777216 || offset > 16777214) {
WARN_ON_ONCE(1); WARN_ON_ONCE(warn);
return 0; return 0;
} }
@@ -33,8 +34,8 @@ __arm_gen_branch_thumb2(unsigned long pc, unsigned long addr, bool link)
return __opcode_thumb32_compose(first, second); return __opcode_thumb32_compose(first, second);
} }
static unsigned long static unsigned long __arm_gen_branch_arm(unsigned long pc, unsigned long addr,
__arm_gen_branch_arm(unsigned long pc, unsigned long addr, bool link) bool link, bool warn)
{ {
unsigned long opcode = 0xea000000; unsigned long opcode = 0xea000000;
long offset; long offset;
@@ -44,7 +45,7 @@ __arm_gen_branch_arm(unsigned long pc, unsigned long addr, bool link)
offset = (long)addr - (long)(pc + 8); offset = (long)addr - (long)(pc + 8);
if (unlikely(offset < -33554432 || offset > 33554428)) { if (unlikely(offset < -33554432 || offset > 33554428)) {
WARN_ON_ONCE(1); WARN_ON_ONCE(warn);
return 0; return 0;
} }
@@ -54,10 +55,10 @@ __arm_gen_branch_arm(unsigned long pc, unsigned long addr, bool link)
} }
unsigned long unsigned long
__arm_gen_branch(unsigned long pc, unsigned long addr, bool link) __arm_gen_branch(unsigned long pc, unsigned long addr, bool link, bool warn)
{ {
if (IS_ENABLED(CONFIG_THUMB2_KERNEL)) if (IS_ENABLED(CONFIG_THUMB2_KERNEL))
return __arm_gen_branch_thumb2(pc, addr, link); return __arm_gen_branch_thumb2(pc, addr, link, warn);
else else
return __arm_gen_branch_arm(pc, addr, link); return __arm_gen_branch_arm(pc, addr, link, warn);
} }

View File

@@ -4,6 +4,7 @@
*/ */
#include <linux/elf.h> #include <linux/elf.h>
#include <linux/ftrace.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/sort.h> #include <linux/sort.h>
@@ -12,10 +13,6 @@
#include <asm/cache.h> #include <asm/cache.h>
#include <asm/opcodes.h> #include <asm/opcodes.h>
#define PLT_ENT_STRIDE L1_CACHE_BYTES
#define PLT_ENT_COUNT (PLT_ENT_STRIDE / sizeof(u32))
#define PLT_ENT_SIZE (sizeof(struct plt_entries) / PLT_ENT_COUNT)
#ifdef CONFIG_THUMB2_KERNEL #ifdef CONFIG_THUMB2_KERNEL
#define PLT_ENT_LDR __opcode_to_mem_thumb32(0xf8dff000 | \ #define PLT_ENT_LDR __opcode_to_mem_thumb32(0xf8dff000 | \
(PLT_ENT_STRIDE - 4)) (PLT_ENT_STRIDE - 4))
@@ -24,9 +21,11 @@
(PLT_ENT_STRIDE - 8)) (PLT_ENT_STRIDE - 8))
#endif #endif
struct plt_entries { static const u32 fixed_plts[] = {
u32 ldr[PLT_ENT_COUNT]; #ifdef CONFIG_DYNAMIC_FTRACE
u32 lit[PLT_ENT_COUNT]; FTRACE_ADDR,
MCOUNT_ADDR,
#endif
}; };
static bool in_init(const struct module *mod, unsigned long loc) static bool in_init(const struct module *mod, unsigned long loc)
@@ -34,14 +33,40 @@ static bool in_init(const struct module *mod, unsigned long loc)
return loc - (u32)mod->init_layout.base < mod->init_layout.size; return loc - (u32)mod->init_layout.base < mod->init_layout.size;
} }
static void prealloc_fixed(struct mod_plt_sec *pltsec, struct plt_entries *plt)
{
int i;
if (!ARRAY_SIZE(fixed_plts) || pltsec->plt_count)
return;
pltsec->plt_count = ARRAY_SIZE(fixed_plts);
for (i = 0; i < ARRAY_SIZE(plt->ldr); ++i)
plt->ldr[i] = PLT_ENT_LDR;
BUILD_BUG_ON(sizeof(fixed_plts) > sizeof(plt->lit));
memcpy(plt->lit, fixed_plts, sizeof(fixed_plts));
}
u32 get_module_plt(struct module *mod, unsigned long loc, Elf32_Addr val) u32 get_module_plt(struct module *mod, unsigned long loc, Elf32_Addr val)
{ {
struct mod_plt_sec *pltsec = !in_init(mod, loc) ? &mod->arch.core : struct mod_plt_sec *pltsec = !in_init(mod, loc) ? &mod->arch.core :
&mod->arch.init; &mod->arch.init;
struct plt_entries *plt;
int idx;
struct plt_entries *plt = (struct plt_entries *)pltsec->plt->sh_addr; /* cache the address, ELF header is available only during module load */
int idx = 0; if (!pltsec->plt_ent)
pltsec->plt_ent = (struct plt_entries *)pltsec->plt->sh_addr;
plt = pltsec->plt_ent;
prealloc_fixed(pltsec, plt);
for (idx = 0; idx < ARRAY_SIZE(fixed_plts); ++idx)
if (plt->lit[idx] == val)
return (u32)&plt->ldr[idx];
idx = 0;
/* /*
* Look for an existing entry pointing to 'val'. Given that the * Look for an existing entry pointing to 'val'. Given that the
* relocations are sorted, this will be the last entry we allocated. * relocations are sorted, this will be the last entry we allocated.
@@ -189,8 +214,8 @@ static unsigned int count_plts(const Elf32_Sym *syms, Elf32_Addr base,
int module_frob_arch_sections(Elf_Ehdr *ehdr, Elf_Shdr *sechdrs, int module_frob_arch_sections(Elf_Ehdr *ehdr, Elf_Shdr *sechdrs,
char *secstrings, struct module *mod) char *secstrings, struct module *mod)
{ {
unsigned long core_plts = 0; unsigned long core_plts = ARRAY_SIZE(fixed_plts);
unsigned long init_plts = 0; unsigned long init_plts = ARRAY_SIZE(fixed_plts);
Elf32_Shdr *s, *sechdrs_end = sechdrs + ehdr->e_shnum; Elf32_Shdr *s, *sechdrs_end = sechdrs + ehdr->e_shnum;
Elf32_Sym *syms = NULL; Elf32_Sym *syms = NULL;
@@ -245,6 +270,7 @@ int module_frob_arch_sections(Elf_Ehdr *ehdr, Elf_Shdr *sechdrs,
mod->arch.core.plt->sh_size = round_up(core_plts * PLT_ENT_SIZE, mod->arch.core.plt->sh_size = round_up(core_plts * PLT_ENT_SIZE,
sizeof(struct plt_entries)); sizeof(struct plt_entries));
mod->arch.core.plt_count = 0; mod->arch.core.plt_count = 0;
mod->arch.core.plt_ent = NULL;
mod->arch.init.plt->sh_type = SHT_NOBITS; mod->arch.init.plt->sh_type = SHT_NOBITS;
mod->arch.init.plt->sh_flags = SHF_EXECINSTR | SHF_ALLOC; mod->arch.init.plt->sh_flags = SHF_EXECINSTR | SHF_ALLOC;
@@ -252,6 +278,7 @@ int module_frob_arch_sections(Elf_Ehdr *ehdr, Elf_Shdr *sechdrs,
mod->arch.init.plt->sh_size = round_up(init_plts * PLT_ENT_SIZE, mod->arch.init.plt->sh_size = round_up(init_plts * PLT_ENT_SIZE,
sizeof(struct plt_entries)); sizeof(struct plt_entries));
mod->arch.init.plt_count = 0; mod->arch.init.plt_count = 0;
mod->arch.init.plt_ent = NULL;
pr_debug("%s: plt=%x, init.plt=%x\n", __func__, pr_debug("%s: plt=%x, init.plt=%x\n", __func__,
mod->arch.core.plt->sh_size, mod->arch.init.plt->sh_size); mod->arch.core.plt->sh_size, mod->arch.init.plt->sh_size);

View File

@@ -378,7 +378,11 @@ static void __init free_highpages(void)
void __init mem_init(void) void __init mem_init(void)
{ {
#ifdef CONFIG_ARM_LPAE #ifdef CONFIG_ARM_LPAE
if (swiotlb_force == SWIOTLB_FORCE ||
max_pfn > arm_dma_pfn_limit)
swiotlb_init(1); swiotlb_init(1);
else
swiotlb_force = SWIOTLB_NO_FORCE;
#endif #endif
set_max_mapnr(pfn_to_page(max_pfn) - mem_map); set_max_mapnr(pfn_to_page(max_pfn) - mem_map);

View File

@@ -43,7 +43,7 @@ static void ci_leaf_init(struct cacheinfo *this_leaf,
this_leaf->type = type; this_leaf->type = type;
} }
static int __init_cache_level(unsigned int cpu) int init_cache_level(unsigned int cpu)
{ {
unsigned int ctype, level, leaves, fw_level; unsigned int ctype, level, leaves, fw_level;
struct cpu_cacheinfo *this_cpu_ci = get_cpu_cacheinfo(cpu); struct cpu_cacheinfo *this_cpu_ci = get_cpu_cacheinfo(cpu);
@@ -78,7 +78,7 @@ static int __init_cache_level(unsigned int cpu)
return 0; return 0;
} }
static int __populate_cache_leaves(unsigned int cpu) int populate_cache_leaves(unsigned int cpu)
{ {
unsigned int level, idx; unsigned int level, idx;
enum cache_type type; enum cache_type type;
@@ -97,6 +97,3 @@ static int __populate_cache_leaves(unsigned int cpu)
} }
return 0; return 0;
} }
DEFINE_SMP_CALL_CACHE_FUNCTION(init_cache_level)
DEFINE_SMP_CALL_CACHE_FUNCTION(populate_cache_leaves)

View File

@@ -17,7 +17,7 @@ do { \
leaf++; \ leaf++; \
} while (0) } while (0)
static int __init_cache_level(unsigned int cpu) int init_cache_level(unsigned int cpu)
{ {
struct cpuinfo_mips *c = &current_cpu_data; struct cpuinfo_mips *c = &current_cpu_data;
struct cpu_cacheinfo *this_cpu_ci = get_cpu_cacheinfo(cpu); struct cpu_cacheinfo *this_cpu_ci = get_cpu_cacheinfo(cpu);
@@ -69,7 +69,7 @@ static void fill_cpumask_cluster(int cpu, cpumask_t *cpu_map)
cpumask_set_cpu(cpu1, cpu_map); cpumask_set_cpu(cpu1, cpu_map);
} }
static int __populate_cache_leaves(unsigned int cpu) int populate_cache_leaves(unsigned int cpu)
{ {
struct cpuinfo_mips *c = &current_cpu_data; struct cpuinfo_mips *c = &current_cpu_data;
struct cpu_cacheinfo *this_cpu_ci = get_cpu_cacheinfo(cpu); struct cpu_cacheinfo *this_cpu_ci = get_cpu_cacheinfo(cpu);
@@ -98,6 +98,3 @@ static int __populate_cache_leaves(unsigned int cpu)
return 0; return 0;
} }
DEFINE_SMP_CALL_CACHE_FUNCTION(init_cache_level)
DEFINE_SMP_CALL_CACHE_FUNCTION(populate_cache_leaves)

View File

@@ -113,7 +113,7 @@ static void fill_cacheinfo(struct cacheinfo **this_leaf,
} }
} }
static int __init_cache_level(unsigned int cpu) int init_cache_level(unsigned int cpu)
{ {
struct cpu_cacheinfo *this_cpu_ci = get_cpu_cacheinfo(cpu); struct cpu_cacheinfo *this_cpu_ci = get_cpu_cacheinfo(cpu);
struct device_node *np = of_cpu_device_node_get(cpu); struct device_node *np = of_cpu_device_node_get(cpu);
@@ -155,7 +155,7 @@ static int __init_cache_level(unsigned int cpu)
return 0; return 0;
} }
static int __populate_cache_leaves(unsigned int cpu) int populate_cache_leaves(unsigned int cpu)
{ {
struct cpu_cacheinfo *this_cpu_ci = get_cpu_cacheinfo(cpu); struct cpu_cacheinfo *this_cpu_ci = get_cpu_cacheinfo(cpu);
struct cacheinfo *this_leaf = this_cpu_ci->info_list; struct cacheinfo *this_leaf = this_cpu_ci->info_list;
@@ -187,6 +187,3 @@ static int __populate_cache_leaves(unsigned int cpu)
return 0; return 0;
} }
DEFINE_SMP_CALL_CACHE_FUNCTION(init_cache_level)
DEFINE_SMP_CALL_CACHE_FUNCTION(populate_cache_leaves)

View File

@@ -128,7 +128,7 @@ static long get_pfn(unsigned long user_addr, unsigned long access,
mmap_read_lock(current->mm); mmap_read_lock(current->mm);
ret = -EINVAL; ret = -EINVAL;
vma = find_vma(current->mm, user_addr); vma = find_vma(current->mm, user_addr);
if (!vma) if (!vma || user_addr < vma->vm_start)
goto out; goto out;
ret = -EACCES; ret = -EACCES;
if (!(vma->vm_flags & access)) if (!(vma->vm_flags & access))

View File

@@ -1113,7 +1113,7 @@ static int virtio_uml_probe(struct platform_device *pdev)
rc = os_connect_socket(pdata->socket_path); rc = os_connect_socket(pdata->socket_path);
} while (rc == -EINTR); } while (rc == -EINTR);
if (rc < 0) if (rc < 0)
return rc; goto error_free;
vu_dev->sock = rc; vu_dev->sock = rc;
spin_lock_init(&vu_dev->sock_lock); spin_lock_init(&vu_dev->sock_lock);
@@ -1132,6 +1132,8 @@ static int virtio_uml_probe(struct platform_device *pdev)
error_init: error_init:
os_close_file(vu_dev->sock); os_close_file(vu_dev->sock);
error_free:
kfree(vu_dev);
return rc; return rc;
} }

View File

@@ -985,7 +985,7 @@ static void ci_leaf_init(struct cacheinfo *this_leaf,
this_leaf->priv = base->nb; this_leaf->priv = base->nb;
} }
static int __init_cache_level(unsigned int cpu) int init_cache_level(unsigned int cpu)
{ {
struct cpu_cacheinfo *this_cpu_ci = get_cpu_cacheinfo(cpu); struct cpu_cacheinfo *this_cpu_ci = get_cpu_cacheinfo(cpu);
@@ -1014,7 +1014,7 @@ static void get_cache_id(int cpu, struct _cpuid4_info_regs *id4_regs)
id4_regs->id = c->apicid >> index_msb; id4_regs->id = c->apicid >> index_msb;
} }
static int __populate_cache_leaves(unsigned int cpu) int populate_cache_leaves(unsigned int cpu)
{ {
unsigned int idx, ret; unsigned int idx, ret;
struct cpu_cacheinfo *this_cpu_ci = get_cpu_cacheinfo(cpu); struct cpu_cacheinfo *this_cpu_ci = get_cpu_cacheinfo(cpu);
@@ -1033,6 +1033,3 @@ static int __populate_cache_leaves(unsigned int cpu)
return 0; return 0;
} }
DEFINE_SMP_CALL_CACHE_FUNCTION(init_cache_level)
DEFINE_SMP_CALL_CACHE_FUNCTION(populate_cache_leaves)

View File

@@ -2167,6 +2167,18 @@ static void blk_add_rq_to_plug(struct blk_plug *plug, struct request *rq)
} }
} }
/*
* Allow 4x BLK_MAX_REQUEST_COUNT requests on plug queue for multiple
* queues. This is important for md arrays to benefit from merging
* requests.
*/
static inline unsigned short blk_plug_max_rq_count(struct blk_plug *plug)
{
if (plug->multiple_queues)
return BLK_MAX_REQUEST_COUNT * 4;
return BLK_MAX_REQUEST_COUNT;
}
/** /**
* blk_mq_submit_bio - Create and send a request to block device. * blk_mq_submit_bio - Create and send a request to block device.
* @bio: Bio pointer. * @bio: Bio pointer.
@@ -2260,7 +2272,7 @@ blk_qc_t blk_mq_submit_bio(struct bio *bio)
else else
last = list_entry_rq(plug->mq_list.prev); last = list_entry_rq(plug->mq_list.prev);
if (request_count >= BLK_MAX_REQUEST_COUNT || (last && if (request_count >= blk_plug_max_rq_count(plug) || (last &&
blk_rq_bytes(last) >= BLK_PLUG_FLUSH_SIZE)) { blk_rq_bytes(last) >= BLK_PLUG_FLUSH_SIZE)) {
blk_flush_plug_list(plug, false); blk_flush_plug_list(plug, false);
trace_block_plug(q); trace_block_plug(q);

View File

@@ -2452,6 +2452,7 @@ int blk_throtl_init(struct request_queue *q)
void blk_throtl_exit(struct request_queue *q) void blk_throtl_exit(struct request_queue *q)
{ {
BUG_ON(!q->td); BUG_ON(!q->td);
del_timer_sync(&q->td->service_queue.pending_timer);
throtl_shutdown_wq(q); throtl_shutdown_wq(q);
blkcg_deactivate_policy(q, &blkcg_policy_throtl); blkcg_deactivate_policy(q, &blkcg_policy_throtl);
free_percpu(q->td->latency_buckets[READ]); free_percpu(q->td->latency_buckets[READ]);

View File

@@ -1649,7 +1649,7 @@ static int __device_suspend(struct device *dev, pm_message_t state, bool async)
} }
dev->power.may_skip_resume = true; dev->power.may_skip_resume = true;
dev->power.must_resume = false; dev->power.must_resume = !dev_pm_test_driver_flags(dev, DPM_FLAG_MAY_SKIP_RESUME);
dpm_watchdog_set(&wd, dev); dpm_watchdog_set(&wd, dev);
device_lock(dev); device_lock(dev);

View File

@@ -42,6 +42,7 @@ config UDMABUF
config DMABUF_MOVE_NOTIFY config DMABUF_MOVE_NOTIFY
bool "Move notify between drivers (EXPERIMENTAL)" bool "Move notify between drivers (EXPERIMENTAL)"
default n default n
depends on DMA_SHARED_BUFFER
help help
Don't pin buffers if the dynamic DMA-buf interface is available on Don't pin buffers if the dynamic DMA-buf interface is available on
both the exporter as well as the importer. This fixes a security both the exporter as well as the importer. This fixes a security

View File

@@ -285,7 +285,7 @@ config INTEL_IDMA64
config INTEL_IDXD config INTEL_IDXD
tristate "Intel Data Accelerators support" tristate "Intel Data Accelerators support"
depends on PCI && X86_64 depends on PCI && X86_64 && !UML
depends on PCI_MSI depends on PCI_MSI
depends on SBITMAP depends on SBITMAP
select DMA_ENGINE select DMA_ENGINE
@@ -299,7 +299,7 @@ config INTEL_IDXD
config INTEL_IOATDMA config INTEL_IOATDMA
tristate "Intel I/OAT DMA support" tristate "Intel I/OAT DMA support"
depends on PCI && X86_64 depends on PCI && X86_64 && !UML
select DMA_ENGINE select DMA_ENGINE
select DMA_ENGINE_RAID select DMA_ENGINE_RAID
select DCA select DCA

View File

@@ -70,10 +70,14 @@ static int acpi_dma_parse_resource_group(const struct acpi_csrt_group *grp,
si = (const struct acpi_csrt_shared_info *)&grp[1]; si = (const struct acpi_csrt_shared_info *)&grp[1];
/* Match device by MMIO and IRQ */ /* Match device by MMIO */
if (si->mmio_base_low != lower_32_bits(mem) || if (si->mmio_base_low != lower_32_bits(mem) ||
si->mmio_base_high != upper_32_bits(mem) || si->mmio_base_high != upper_32_bits(mem))
si->gsi_interrupt != irq) return 0;
/* Match device by Linux vIRQ */
ret = acpi_register_gsi(NULL, si->gsi_interrupt, si->interrupt_mode, si->interrupt_polarity);
if (ret != irq)
return 0; return 0;
dev_dbg(&adev->dev, "matches with %.4s%04X (rev %u)\n", dev_dbg(&adev->dev, "matches with %.4s%04X (rev %u)\n",

View File

@@ -45,7 +45,7 @@ struct idxd_desc *idxd_alloc_desc(struct idxd_wq *wq, enum idxd_op_type optype)
if (signal_pending_state(TASK_INTERRUPTIBLE, current)) if (signal_pending_state(TASK_INTERRUPTIBLE, current))
break; break;
idx = sbitmap_queue_get(sbq, &cpu); idx = sbitmap_queue_get(sbq, &cpu);
if (idx > 0) if (idx >= 0)
break; break;
schedule(); schedule();
} }

View File

@@ -1265,6 +1265,7 @@ static const struct of_device_id sprd_dma_match[] = {
{ .compatible = "sprd,sc9860-dma", }, { .compatible = "sprd,sc9860-dma", },
{}, {},
}; };
MODULE_DEVICE_TABLE(of, sprd_dma_match);
static int __maybe_unused sprd_dma_runtime_suspend(struct device *dev) static int __maybe_unused sprd_dma_runtime_suspend(struct device *dev)
{ {

View File

@@ -3070,7 +3070,7 @@ static int xilinx_dma_probe(struct platform_device *pdev)
xdev->ext_addr = false; xdev->ext_addr = false;
/* Set the dma mask bits */ /* Set the dma mask bits */
dma_set_mask(xdev->dev, DMA_BIT_MASK(addr_width)); dma_set_mask_and_coherent(xdev->dev, DMA_BIT_MASK(addr_width));
/* Initialize the DMA engine */ /* Initialize the DMA engine */
xdev->common.dev = &pdev->dev; xdev->common.dev = &pdev->dev;

View File

@@ -27,6 +27,9 @@
#include <linux/pci.h> #include <linux/pci.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <asm/div64.h> #include <asm/div64.h>
#if IS_ENABLED(CONFIG_X86_64)
#include <asm/intel-family.h>
#endif
#include <drm/amdgpu_drm.h> #include <drm/amdgpu_drm.h>
#include "ppatomctrl.h" #include "ppatomctrl.h"
#include "atombios.h" #include "atombios.h"
@@ -1606,6 +1609,17 @@ static int smu7_disable_dpm_tasks(struct pp_hwmgr *hwmgr)
return result; return result;
} }
static bool intel_core_rkl_chk(void)
{
#if IS_ENABLED(CONFIG_X86_64)
struct cpuinfo_x86 *c = &cpu_data(0);
return (c->x86 == 6 && c->x86_model == INTEL_FAM6_ROCKETLAKE);
#else
return false;
#endif
}
static void smu7_init_dpm_defaults(struct pp_hwmgr *hwmgr) static void smu7_init_dpm_defaults(struct pp_hwmgr *hwmgr)
{ {
struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
@@ -1629,7 +1643,8 @@ static void smu7_init_dpm_defaults(struct pp_hwmgr *hwmgr)
data->mclk_dpm_key_disabled = hwmgr->feature_mask & PP_MCLK_DPM_MASK ? false : true; data->mclk_dpm_key_disabled = hwmgr->feature_mask & PP_MCLK_DPM_MASK ? false : true;
data->sclk_dpm_key_disabled = hwmgr->feature_mask & PP_SCLK_DPM_MASK ? false : true; data->sclk_dpm_key_disabled = hwmgr->feature_mask & PP_SCLK_DPM_MASK ? false : true;
data->pcie_dpm_key_disabled = hwmgr->feature_mask & PP_PCIE_DPM_MASK ? false : true; data->pcie_dpm_key_disabled =
intel_core_rkl_chk() || !(hwmgr->feature_mask & PP_PCIE_DPM_MASK);
/* need to set voltage control types before EVV patching */ /* need to set voltage control types before EVV patching */
data->voltage_control = SMU7_VOLTAGE_CONTROL_NONE; data->voltage_control = SMU7_VOLTAGE_CONTROL_NONE;
data->vddci_control = SMU7_VOLTAGE_CONTROL_NONE; data->vddci_control = SMU7_VOLTAGE_CONTROL_NONE;

View File

@@ -57,7 +57,7 @@ nvkm_control_mthd_pstate_info(struct nvkm_control *ctrl, void *data, u32 size)
args->v0.count = 0; args->v0.count = 0;
args->v0.ustate_ac = NVIF_CONTROL_PSTATE_INFO_V0_USTATE_DISABLE; args->v0.ustate_ac = NVIF_CONTROL_PSTATE_INFO_V0_USTATE_DISABLE;
args->v0.ustate_dc = NVIF_CONTROL_PSTATE_INFO_V0_USTATE_DISABLE; args->v0.ustate_dc = NVIF_CONTROL_PSTATE_INFO_V0_USTATE_DISABLE;
args->v0.pwrsrc = -ENOSYS; args->v0.pwrsrc = -ENODEV;
args->v0.pstate = NVIF_CONTROL_PSTATE_INFO_V0_PSTATE_UNKNOWN; args->v0.pstate = NVIF_CONTROL_PSTATE_INFO_V0_PSTATE_UNKNOWN;
} }

View File

@@ -298,6 +298,22 @@ int amd_iommu_get_num_iommus(void)
return amd_iommus_present; return amd_iommus_present;
} }
#ifdef CONFIG_IRQ_REMAP
static bool check_feature_on_all_iommus(u64 mask)
{
bool ret = false;
struct amd_iommu *iommu;
for_each_iommu(iommu) {
ret = iommu_feature(iommu, mask);
if (!ret)
return false;
}
return true;
}
#endif
/* /*
* For IVHD type 0x11/0x40, EFR is also available via IVHD. * For IVHD type 0x11/0x40, EFR is also available via IVHD.
* Default to IVHD EFR since it is available sooner * Default to IVHD EFR since it is available sooner
@@ -854,13 +870,6 @@ static int iommu_init_ga(struct amd_iommu *iommu)
int ret = 0; int ret = 0;
#ifdef CONFIG_IRQ_REMAP #ifdef CONFIG_IRQ_REMAP
/* Note: We have already checked GASup from IVRS table.
* Now, we need to make sure that GAMSup is set.
*/
if (AMD_IOMMU_GUEST_IR_VAPIC(amd_iommu_guest_ir) &&
!iommu_feature(iommu, FEATURE_GAM_VAPIC))
amd_iommu_guest_ir = AMD_IOMMU_GUEST_IR_LEGACY_GA;
ret = iommu_init_ga_log(iommu); ret = iommu_init_ga_log(iommu);
#endif /* CONFIG_IRQ_REMAP */ #endif /* CONFIG_IRQ_REMAP */
@@ -2396,6 +2405,14 @@ static void early_enable_iommus(void)
} }
#ifdef CONFIG_IRQ_REMAP #ifdef CONFIG_IRQ_REMAP
/*
* Note: We have already checked GASup from IVRS table.
* Now, we need to make sure that GAMSup is set.
*/
if (AMD_IOMMU_GUEST_IR_VAPIC(amd_iommu_guest_ir) &&
!check_feature_on_all_iommus(FEATURE_GAM_VAPIC))
amd_iommu_guest_ir = AMD_IOMMU_GUEST_IR_LEGACY_GA;
if (AMD_IOMMU_GUEST_IR_VAPIC(amd_iommu_guest_ir)) if (AMD_IOMMU_GUEST_IR_VAPIC(amd_iommu_guest_ir))
amd_iommu_irq_ops.capability |= (1 << IRQ_POSTING_CAP); amd_iommu_irq_ops.capability |= (1 << IRQ_POSTING_CAP);
#endif #endif

View File

@@ -5723,6 +5723,12 @@ static void gaudi_handle_eqe(struct hl_device *hdev,
u8 cause; u8 cause;
bool reset_required; bool reset_required;
if (event_type >= GAUDI_EVENT_SIZE) {
dev_err(hdev->dev, "Event type %u exceeds maximum of %u",
event_type, GAUDI_EVENT_SIZE - 1);
return;
}
gaudi->events_stat[event_type]++; gaudi->events_stat[event_type]++;
gaudi->events_stat_aggregate[event_type]++; gaudi->events_stat_aggregate[event_type]++;

View File

@@ -4623,6 +4623,12 @@ void goya_handle_eqe(struct hl_device *hdev, struct hl_eq_entry *eq_entry)
>> EQ_CTL_EVENT_TYPE_SHIFT); >> EQ_CTL_EVENT_TYPE_SHIFT);
struct goya_device *goya = hdev->asic_specific; struct goya_device *goya = hdev->asic_specific;
if (event_type >= GOYA_ASYNC_EVENT_ID_SIZE) {
dev_err(hdev->dev, "Event type %u exceeds maximum of %u",
event_type, GOYA_ASYNC_EVENT_ID_SIZE - 1);
return;
}
goya->events_stat[event_type]++; goya->events_stat[event_type]++;
goya->events_stat_aggregate[event_type]++; goya->events_stat_aggregate[event_type]++;

View File

@@ -376,48 +376,6 @@ static void mlx5_devlink_set_params_init_values(struct devlink *devlink)
#endif #endif
} }
#define MLX5_TRAP_DROP(_id, _group_id) \
DEVLINK_TRAP_GENERIC(DROP, DROP, _id, \
DEVLINK_TRAP_GROUP_GENERIC_ID_##_group_id, \
DEVLINK_TRAP_METADATA_TYPE_F_IN_PORT)
static const struct devlink_trap mlx5_traps_arr[] = {
MLX5_TRAP_DROP(INGRESS_VLAN_FILTER, L2_DROPS),
};
static const struct devlink_trap_group mlx5_trap_groups_arr[] = {
DEVLINK_TRAP_GROUP_GENERIC(L2_DROPS, 0),
};
static int mlx5_devlink_traps_register(struct devlink *devlink)
{
struct mlx5_core_dev *core_dev = devlink_priv(devlink);
int err;
err = devlink_trap_groups_register(devlink, mlx5_trap_groups_arr,
ARRAY_SIZE(mlx5_trap_groups_arr));
if (err)
return err;
err = devlink_traps_register(devlink, mlx5_traps_arr, ARRAY_SIZE(mlx5_traps_arr),
&core_dev->priv);
if (err)
goto err_trap_group;
return 0;
err_trap_group:
devlink_trap_groups_unregister(devlink, mlx5_trap_groups_arr,
ARRAY_SIZE(mlx5_trap_groups_arr));
return err;
}
static void mlx5_devlink_traps_unregister(struct devlink *devlink)
{
devlink_traps_unregister(devlink, mlx5_traps_arr, ARRAY_SIZE(mlx5_traps_arr));
devlink_trap_groups_unregister(devlink, mlx5_trap_groups_arr,
ARRAY_SIZE(mlx5_trap_groups_arr));
}
int mlx5_devlink_register(struct devlink *devlink, struct device *dev) int mlx5_devlink_register(struct devlink *devlink, struct device *dev)
{ {
int err; int err;
@@ -432,16 +390,8 @@ int mlx5_devlink_register(struct devlink *devlink, struct device *dev)
goto params_reg_err; goto params_reg_err;
mlx5_devlink_set_params_init_values(devlink); mlx5_devlink_set_params_init_values(devlink);
devlink_params_publish(devlink); devlink_params_publish(devlink);
err = mlx5_devlink_traps_register(devlink);
if (err)
goto traps_reg_err;
return 0; return 0;
traps_reg_err:
devlink_params_unregister(devlink, mlx5_devlink_params,
ARRAY_SIZE(mlx5_devlink_params));
params_reg_err: params_reg_err:
devlink_unregister(devlink); devlink_unregister(devlink);
return err; return err;
@@ -449,7 +399,6 @@ params_reg_err:
void mlx5_devlink_unregister(struct devlink *devlink) void mlx5_devlink_unregister(struct devlink *devlink)
{ {
mlx5_devlink_traps_unregister(devlink);
devlink_params_unpublish(devlink); devlink_params_unpublish(devlink);
devlink_params_unregister(devlink, mlx5_devlink_params, devlink_params_unregister(devlink, mlx5_devlink_params,
ARRAY_SIZE(mlx5_devlink_params)); ARRAY_SIZE(mlx5_devlink_params));

View File

@@ -156,15 +156,6 @@ static inline struct dino_device *DINO_DEV(struct pci_hba_data *hba)
return container_of(hba, struct dino_device, hba); return container_of(hba, struct dino_device, hba);
} }
/* Check if PCI device is behind a Card-mode Dino. */
static int pci_dev_is_behind_card_dino(struct pci_dev *dev)
{
struct dino_device *dino_dev;
dino_dev = DINO_DEV(parisc_walk_tree(dev->bus->bridge));
return is_card_dino(&dino_dev->hba.dev->id);
}
/* /*
* Dino Configuration Space Accessor Functions * Dino Configuration Space Accessor Functions
*/ */
@@ -447,6 +438,15 @@ static void quirk_cirrus_cardbus(struct pci_dev *dev)
DECLARE_PCI_FIXUP_ENABLE(PCI_VENDOR_ID_CIRRUS, PCI_DEVICE_ID_CIRRUS_6832, quirk_cirrus_cardbus ); DECLARE_PCI_FIXUP_ENABLE(PCI_VENDOR_ID_CIRRUS, PCI_DEVICE_ID_CIRRUS_6832, quirk_cirrus_cardbus );
#ifdef CONFIG_TULIP #ifdef CONFIG_TULIP
/* Check if PCI device is behind a Card-mode Dino. */
static int pci_dev_is_behind_card_dino(struct pci_dev *dev)
{
struct dino_device *dino_dev;
dino_dev = DINO_DEV(parisc_walk_tree(dev->bus->bridge));
return is_card_dino(&dino_dev->hba.dev->id);
}
static void pci_fixup_tulip(struct pci_dev *dev) static void pci_fixup_tulip(struct pci_dev *dev)
{ {
if (!pci_dev_is_behind_card_dino(dev)) if (!pci_dev_is_behind_card_dino(dev))

View File

@@ -225,6 +225,8 @@
#define MSI_IRQ_NUM 32 #define MSI_IRQ_NUM 32
#define CFG_RD_CRS_VAL 0xffff0001
struct advk_pcie { struct advk_pcie {
struct platform_device *pdev; struct platform_device *pdev;
void __iomem *base; void __iomem *base;
@@ -587,7 +589,7 @@ static void advk_pcie_setup_hw(struct advk_pcie *pcie)
advk_writel(pcie, reg, PCIE_CORE_CMD_STATUS_REG); advk_writel(pcie, reg, PCIE_CORE_CMD_STATUS_REG);
} }
static int advk_pcie_check_pio_status(struct advk_pcie *pcie, u32 *val) static int advk_pcie_check_pio_status(struct advk_pcie *pcie, bool allow_crs, u32 *val)
{ {
struct device *dev = &pcie->pdev->dev; struct device *dev = &pcie->pdev->dev;
u32 reg; u32 reg;
@@ -629,9 +631,30 @@ static int advk_pcie_check_pio_status(struct advk_pcie *pcie, u32 *val)
strcomp_status = "UR"; strcomp_status = "UR";
break; break;
case PIO_COMPLETION_STATUS_CRS: case PIO_COMPLETION_STATUS_CRS:
if (allow_crs && val) {
/* PCIe r4.0, sec 2.3.2, says:
* If CRS Software Visibility is enabled:
* For a Configuration Read Request that includes both
* bytes of the Vendor ID field of a device Function's
* Configuration Space Header, the Root Complex must
* complete the Request to the host by returning a
* read-data value of 0001h for the Vendor ID field and
* all '1's for any additional bytes included in the
* request.
*
* So CRS in this case is not an error status.
*/
*val = CFG_RD_CRS_VAL;
strcomp_status = NULL;
break;
}
/* PCIe r4.0, sec 2.3.2, says: /* PCIe r4.0, sec 2.3.2, says:
* If CRS Software Visibility is not enabled, the Root Complex * If CRS Software Visibility is not enabled, the Root Complex
* must re-issue the Configuration Request as a new Request. * must re-issue the Configuration Request as a new Request.
* If CRS Software Visibility is enabled: For a Configuration
* Write Request or for any other Configuration Read Request,
* the Root Complex must re-issue the Configuration Request as
* a new Request.
* A Root Complex implementation may choose to limit the number * A Root Complex implementation may choose to limit the number
* of Configuration Request/CRS Completion Status loops before * of Configuration Request/CRS Completion Status loops before
* determining that something is wrong with the target of the * determining that something is wrong with the target of the
@@ -700,6 +723,7 @@ advk_pci_bridge_emul_pcie_conf_read(struct pci_bridge_emul *bridge,
case PCI_EXP_RTCTL: { case PCI_EXP_RTCTL: {
u32 val = advk_readl(pcie, PCIE_ISR0_MASK_REG); u32 val = advk_readl(pcie, PCIE_ISR0_MASK_REG);
*value = (val & PCIE_MSG_PM_PME_MASK) ? 0 : PCI_EXP_RTCTL_PMEIE; *value = (val & PCIE_MSG_PM_PME_MASK) ? 0 : PCI_EXP_RTCTL_PMEIE;
*value |= PCI_EXP_RTCAP_CRSVIS << 16;
return PCI_BRIDGE_EMUL_HANDLED; return PCI_BRIDGE_EMUL_HANDLED;
} }
@@ -781,6 +805,7 @@ static struct pci_bridge_emul_ops advk_pci_bridge_emul_ops = {
static int advk_sw_pci_bridge_init(struct advk_pcie *pcie) static int advk_sw_pci_bridge_init(struct advk_pcie *pcie)
{ {
struct pci_bridge_emul *bridge = &pcie->bridge; struct pci_bridge_emul *bridge = &pcie->bridge;
int ret;
bridge->conf.vendor = bridge->conf.vendor =
cpu_to_le16(advk_readl(pcie, PCIE_CORE_DEV_ID_REG) & 0xffff); cpu_to_le16(advk_readl(pcie, PCIE_CORE_DEV_ID_REG) & 0xffff);
@@ -804,7 +829,15 @@ static int advk_sw_pci_bridge_init(struct advk_pcie *pcie)
bridge->data = pcie; bridge->data = pcie;
bridge->ops = &advk_pci_bridge_emul_ops; bridge->ops = &advk_pci_bridge_emul_ops;
return pci_bridge_emul_init(bridge, 0); /* PCIe config space can be initialized after pci_bridge_emul_init() */
ret = pci_bridge_emul_init(bridge, 0);
if (ret < 0)
return ret;
/* Indicates supports for Completion Retry Status */
bridge->pcie_conf.rootcap = cpu_to_le16(PCI_EXP_RTCAP_CRSVIS);
return 0;
} }
static bool advk_pcie_valid_device(struct advk_pcie *pcie, struct pci_bus *bus, static bool advk_pcie_valid_device(struct advk_pcie *pcie, struct pci_bus *bus,
@@ -856,6 +889,7 @@ static int advk_pcie_rd_conf(struct pci_bus *bus, u32 devfn,
int where, int size, u32 *val) int where, int size, u32 *val)
{ {
struct advk_pcie *pcie = bus->sysdata; struct advk_pcie *pcie = bus->sysdata;
bool allow_crs;
u32 reg; u32 reg;
int ret; int ret;
@@ -868,7 +902,24 @@ static int advk_pcie_rd_conf(struct pci_bus *bus, u32 devfn,
return pci_bridge_emul_conf_read(&pcie->bridge, where, return pci_bridge_emul_conf_read(&pcie->bridge, where,
size, val); size, val);
/*
* Completion Retry Status is possible to return only when reading all
* 4 bytes from PCI_VENDOR_ID and PCI_DEVICE_ID registers at once and
* CRSSVE flag on Root Bridge is enabled.
*/
allow_crs = (where == PCI_VENDOR_ID) && (size == 4) &&
(le16_to_cpu(pcie->bridge.pcie_conf.rootctl) &
PCI_EXP_RTCTL_CRSSVE);
if (advk_pcie_pio_is_running(pcie)) { if (advk_pcie_pio_is_running(pcie)) {
/*
* If it is possible return Completion Retry Status so caller
* tries to issue the request again instead of failing.
*/
if (allow_crs) {
*val = CFG_RD_CRS_VAL;
return PCIBIOS_SUCCESSFUL;
}
*val = 0xffffffff; *val = 0xffffffff;
return PCIBIOS_SET_FAILED; return PCIBIOS_SET_FAILED;
} }
@@ -896,12 +947,20 @@ static int advk_pcie_rd_conf(struct pci_bus *bus, u32 devfn,
ret = advk_pcie_wait_pio(pcie); ret = advk_pcie_wait_pio(pcie);
if (ret < 0) { if (ret < 0) {
/*
* If it is possible return Completion Retry Status so caller
* tries to issue the request again instead of failing.
*/
if (allow_crs) {
*val = CFG_RD_CRS_VAL;
return PCIBIOS_SUCCESSFUL;
}
*val = 0xffffffff; *val = 0xffffffff;
return PCIBIOS_SET_FAILED; return PCIBIOS_SET_FAILED;
} }
/* Check PIO status and get the read result */ /* Check PIO status and get the read result */
ret = advk_pcie_check_pio_status(pcie, val); ret = advk_pcie_check_pio_status(pcie, allow_crs, val);
if (ret < 0) { if (ret < 0) {
*val = 0xffffffff; *val = 0xffffffff;
return PCIBIOS_SET_FAILED; return PCIBIOS_SET_FAILED;
@@ -970,7 +1029,7 @@ static int advk_pcie_wr_conf(struct pci_bus *bus, u32 devfn,
if (ret < 0) if (ret < 0)
return PCIBIOS_SET_FAILED; return PCIBIOS_SET_FAILED;
ret = advk_pcie_check_pio_status(pcie, NULL); ret = advk_pcie_check_pio_status(pcie, false, NULL);
if (ret < 0) if (ret < 0)
return PCIBIOS_SET_FAILED; return PCIBIOS_SET_FAILED;

View File

@@ -54,7 +54,7 @@ struct pci_bridge_emul_pcie_conf {
__le16 slotctl; __le16 slotctl;
__le16 slotsta; __le16 slotsta;
__le16 rootctl; __le16 rootctl;
__le16 rsvd; __le16 rootcap;
__le32 rootsta; __le32 rootsta;
__le32 devcap2; __le32 devcap2;
__le16 devctl2; __le16 devctl2;

View File

@@ -20,7 +20,7 @@ obj-$(CONFIG_CROS_EC_CHARDEV) += cros_ec_chardev.o
obj-$(CONFIG_CROS_EC_LIGHTBAR) += cros_ec_lightbar.o obj-$(CONFIG_CROS_EC_LIGHTBAR) += cros_ec_lightbar.o
obj-$(CONFIG_CROS_EC_VBC) += cros_ec_vbc.o obj-$(CONFIG_CROS_EC_VBC) += cros_ec_vbc.o
obj-$(CONFIG_CROS_EC_DEBUGFS) += cros_ec_debugfs.o obj-$(CONFIG_CROS_EC_DEBUGFS) += cros_ec_debugfs.o
cros-ec-sensorhub-objs := cros_ec_sensorhub.o cros_ec_sensorhub_ring.o cros-ec-sensorhub-objs := cros_ec_sensorhub.o cros_ec_sensorhub_ring.o cros_ec_trace.o
obj-$(CONFIG_CROS_EC_SENSORHUB) += cros-ec-sensorhub.o obj-$(CONFIG_CROS_EC_SENSORHUB) += cros-ec-sensorhub.o
obj-$(CONFIG_CROS_EC_SYSFS) += cros_ec_sysfs.o obj-$(CONFIG_CROS_EC_SYSFS) += cros_ec_sysfs.o
obj-$(CONFIG_CROS_USBPD_LOGGER) += cros_usbpd_logger.o obj-$(CONFIG_CROS_USBPD_LOGGER) += cros_usbpd_logger.o

View File

@@ -17,6 +17,8 @@
#include <linux/sort.h> #include <linux/sort.h>
#include <linux/slab.h> #include <linux/slab.h>
#include "cros_ec_trace.h"
/* Precision of fixed point for the m values from the filter */ /* Precision of fixed point for the m values from the filter */
#define M_PRECISION BIT(23) #define M_PRECISION BIT(23)
@@ -291,6 +293,7 @@ cros_ec_sensor_ring_ts_filter_update(struct cros_ec_sensors_ts_filter_state
state->median_m = 0; state->median_m = 0;
state->median_error = 0; state->median_error = 0;
} }
trace_cros_ec_sensorhub_filter(state, dx, dy);
} }
/** /**
@@ -427,6 +430,11 @@ cros_ec_sensor_ring_process_event(struct cros_ec_sensorhub *sensorhub,
if (new_timestamp - *current_timestamp > 0) if (new_timestamp - *current_timestamp > 0)
*current_timestamp = new_timestamp; *current_timestamp = new_timestamp;
} }
trace_cros_ec_sensorhub_timestamp(in->timestamp,
fifo_info->timestamp,
fifo_timestamp,
*current_timestamp,
now);
} }
if (in->flags & MOTIONSENSE_SENSOR_FLAG_ODR) { if (in->flags & MOTIONSENSE_SENSOR_FLAG_ODR) {
@@ -460,6 +468,12 @@ cros_ec_sensor_ring_process_event(struct cros_ec_sensorhub *sensorhub,
/* Regular sample */ /* Regular sample */
out->sensor_id = in->sensor_num; out->sensor_id = in->sensor_num;
trace_cros_ec_sensorhub_data(in->sensor_num,
fifo_info->timestamp,
fifo_timestamp,
*current_timestamp,
now);
if (*current_timestamp - now > 0) { if (*current_timestamp - now > 0) {
/* /*
* This fix is needed to overcome the timestamp filter putting * This fix is needed to overcome the timestamp filter putting

View File

@@ -15,6 +15,7 @@
#include <linux/types.h> #include <linux/types.h>
#include <linux/platform_data/cros_ec_commands.h> #include <linux/platform_data/cros_ec_commands.h>
#include <linux/platform_data/cros_ec_proto.h> #include <linux/platform_data/cros_ec_proto.h>
#include <linux/platform_data/cros_ec_sensorhub.h>
#include <linux/tracepoint.h> #include <linux/tracepoint.h>
@@ -70,6 +71,99 @@ TRACE_EVENT(cros_ec_request_done,
__entry->retval) __entry->retval)
); );
TRACE_EVENT(cros_ec_sensorhub_timestamp,
TP_PROTO(u32 ec_sample_timestamp, u32 ec_fifo_timestamp, s64 fifo_timestamp,
s64 current_timestamp, s64 current_time),
TP_ARGS(ec_sample_timestamp, ec_fifo_timestamp, fifo_timestamp, current_timestamp,
current_time),
TP_STRUCT__entry(
__field(u32, ec_sample_timestamp)
__field(u32, ec_fifo_timestamp)
__field(s64, fifo_timestamp)
__field(s64, current_timestamp)
__field(s64, current_time)
__field(s64, delta)
),
TP_fast_assign(
__entry->ec_sample_timestamp = ec_sample_timestamp;
__entry->ec_fifo_timestamp = ec_fifo_timestamp;
__entry->fifo_timestamp = fifo_timestamp;
__entry->current_timestamp = current_timestamp;
__entry->current_time = current_time;
__entry->delta = current_timestamp - current_time;
),
TP_printk("ec_ts: %9u, ec_fifo_ts: %9u, fifo_ts: %12lld, curr_ts: %12lld, curr_time: %12lld, delta %12lld",
__entry->ec_sample_timestamp,
__entry->ec_fifo_timestamp,
__entry->fifo_timestamp,
__entry->current_timestamp,
__entry->current_time,
__entry->delta
)
);
TRACE_EVENT(cros_ec_sensorhub_data,
TP_PROTO(u32 ec_sensor_num, u32 ec_fifo_timestamp, s64 fifo_timestamp,
s64 current_timestamp, s64 current_time),
TP_ARGS(ec_sensor_num, ec_fifo_timestamp, fifo_timestamp, current_timestamp, current_time),
TP_STRUCT__entry(
__field(u32, ec_sensor_num)
__field(u32, ec_fifo_timestamp)
__field(s64, fifo_timestamp)
__field(s64, current_timestamp)
__field(s64, current_time)
__field(s64, delta)
),
TP_fast_assign(
__entry->ec_sensor_num = ec_sensor_num;
__entry->ec_fifo_timestamp = ec_fifo_timestamp;
__entry->fifo_timestamp = fifo_timestamp;
__entry->current_timestamp = current_timestamp;
__entry->current_time = current_time;
__entry->delta = current_timestamp - current_time;
),
TP_printk("ec_num: %4u, ec_fifo_ts: %9u, fifo_ts: %12lld, curr_ts: %12lld, curr_time: %12lld, delta %12lld",
__entry->ec_sensor_num,
__entry->ec_fifo_timestamp,
__entry->fifo_timestamp,
__entry->current_timestamp,
__entry->current_time,
__entry->delta
)
);
TRACE_EVENT(cros_ec_sensorhub_filter,
TP_PROTO(struct cros_ec_sensors_ts_filter_state *state, s64 dx, s64 dy),
TP_ARGS(state, dx, dy),
TP_STRUCT__entry(
__field(s64, dx)
__field(s64, dy)
__field(s64, median_m)
__field(s64, median_error)
__field(s64, history_len)
__field(s64, x)
__field(s64, y)
),
TP_fast_assign(
__entry->dx = dx;
__entry->dy = dy;
__entry->median_m = state->median_m;
__entry->median_error = state->median_error;
__entry->history_len = state->history_len;
__entry->x = state->x_offset;
__entry->y = state->y_offset;
),
TP_printk("dx: %12lld. dy: %12lld median_m: %12lld median_error: %12lld len: %lld x: %12lld y: %12lld",
__entry->dx,
__entry->dy,
__entry->median_m,
__entry->median_error,
__entry->history_len,
__entry->x,
__entry->y
)
);
#endif /* _CROS_EC_TRACE_H_ */ #endif /* _CROS_EC_TRACE_H_ */

View File

@@ -329,23 +329,7 @@ err_pm_disable:
static int img_pwm_remove(struct platform_device *pdev) static int img_pwm_remove(struct platform_device *pdev)
{ {
struct img_pwm_chip *pwm_chip = platform_get_drvdata(pdev); struct img_pwm_chip *pwm_chip = platform_get_drvdata(pdev);
u32 val;
unsigned int i;
int ret;
ret = pm_runtime_get_sync(&pdev->dev);
if (ret < 0) {
pm_runtime_put(&pdev->dev);
return ret;
}
for (i = 0; i < pwm_chip->chip.npwm; i++) {
val = img_pwm_readl(pwm_chip, PWM_CTRL_CFG);
val &= ~BIT(i);
img_pwm_writel(pwm_chip, PWM_CTRL_CFG, val);
}
pm_runtime_put(&pdev->dev);
pm_runtime_disable(&pdev->dev); pm_runtime_disable(&pdev->dev);
if (!pm_runtime_status_suspended(&pdev->dev)) if (!pm_runtime_status_suspended(&pdev->dev))
img_pwm_runtime_suspend(&pdev->dev); img_pwm_runtime_suspend(&pdev->dev);

View File

@@ -120,17 +120,17 @@ static int lpc32xx_pwm_probe(struct platform_device *pdev)
lpc32xx->chip.npwm = 1; lpc32xx->chip.npwm = 1;
lpc32xx->chip.base = -1; lpc32xx->chip.base = -1;
/* If PWM is disabled, configure the output to the default value */
val = readl(lpc32xx->base + (lpc32xx->chip.pwms[0].hwpwm << 2));
val &= ~PWM_PIN_LEVEL;
writel(val, lpc32xx->base + (lpc32xx->chip.pwms[0].hwpwm << 2));
ret = pwmchip_add(&lpc32xx->chip); ret = pwmchip_add(&lpc32xx->chip);
if (ret < 0) { if (ret < 0) {
dev_err(&pdev->dev, "failed to add PWM chip, error %d\n", ret); dev_err(&pdev->dev, "failed to add PWM chip, error %d\n", ret);
return ret; return ret;
} }
/* When PWM is disable, configure the output to the default value */
val = readl(lpc32xx->base + (lpc32xx->chip.pwms[0].hwpwm << 2));
val &= ~PWM_PIN_LEVEL;
writel(val, lpc32xx->base + (lpc32xx->chip.pwms[0].hwpwm << 2));
platform_set_drvdata(pdev, lpc32xx); platform_set_drvdata(pdev, lpc32xx);
return 0; return 0;

View File

@@ -148,6 +148,11 @@ static int mxs_pwm_probe(struct platform_device *pdev)
return ret; return ret;
} }
/* FIXME: Only do this if the PWM isn't already running */
ret = stmp_reset_block(mxs->base);
if (ret)
return dev_err_probe(&pdev->dev, ret, "failed to reset PWM\n");
ret = pwmchip_add(&mxs->chip); ret = pwmchip_add(&mxs->chip);
if (ret < 0) { if (ret < 0) {
dev_err(&pdev->dev, "failed to add pwm chip %d\n", ret); dev_err(&pdev->dev, "failed to add pwm chip %d\n", ret);
@@ -156,15 +161,7 @@ static int mxs_pwm_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, mxs); platform_set_drvdata(pdev, mxs);
ret = stmp_reset_block(mxs->base);
if (ret)
goto pwm_remove;
return 0; return 0;
pwm_remove:
pwmchip_remove(&mxs->chip);
return ret;
} }
static int mxs_pwm_remove(struct platform_device *pdev) static int mxs_pwm_remove(struct platform_device *pdev)

View File

@@ -382,20 +382,6 @@ static int rockchip_pwm_remove(struct platform_device *pdev)
{ {
struct rockchip_pwm_chip *pc = platform_get_drvdata(pdev); struct rockchip_pwm_chip *pc = platform_get_drvdata(pdev);
/*
* Disable the PWM clk before unpreparing it if the PWM device is still
* running. This should only happen when the last PWM user left it
* enabled, or when nobody requested a PWM that was previously enabled
* by the bootloader.
*
* FIXME: Maybe the core should disable all PWM devices in
* pwmchip_remove(). In this case we'd only have to call
* clk_unprepare() after pwmchip_remove().
*
*/
if (pwm_is_enabled(pc->chip.pwms))
clk_disable(pc->clk);
clk_unprepare(pc->pclk); clk_unprepare(pc->pclk);
clk_unprepare(pc->clk); clk_unprepare(pc->clk);

View File

@@ -225,8 +225,6 @@ static int stm32_pwm_lp_remove(struct platform_device *pdev)
{ {
struct stm32_pwm_lp *priv = platform_get_drvdata(pdev); struct stm32_pwm_lp *priv = platform_get_drvdata(pdev);
pwm_disable(&priv->chip.pwms[0]);
return pwmchip_remove(&priv->chip); return pwmchip_remove(&priv->chip);
} }

View File

@@ -624,6 +624,7 @@ config RTC_DRV_FM3130
config RTC_DRV_RX8010 config RTC_DRV_RX8010
tristate "Epson RX8010SJ" tristate "Epson RX8010SJ"
select REGMAP_I2C
help help
If you say yes here you get support for the Epson RX8010SJ RTC If you say yes here you get support for the Epson RX8010SJ RTC
chip. chip.

View File

@@ -4271,7 +4271,7 @@ static void TranslateRxSignalStuff819xUsb(struct sk_buff *skb,
bpacket_match_bssid = (type != IEEE80211_FTYPE_CTL) && bpacket_match_bssid = (type != IEEE80211_FTYPE_CTL) &&
(ether_addr_equal(priv->ieee80211->current_network.bssid, (fc & IEEE80211_FCTL_TODS) ? hdr->addr1 : (fc & IEEE80211_FCTL_FROMDS) ? hdr->addr2 : hdr->addr3)) (ether_addr_equal(priv->ieee80211->current_network.bssid, (fc & IEEE80211_FCTL_TODS) ? hdr->addr1 : (fc & IEEE80211_FCTL_FROMDS) ? hdr->addr2 : hdr->addr3))
&& (!pstats->bHwError) && (!pstats->bCRC) && (!pstats->bICV); && (!pstats->bHwError) && (!pstats->bCRC) && (!pstats->bICV);
bpacket_toself = bpacket_match_bssid & bpacket_toself = bpacket_match_bssid &&
(ether_addr_equal(praddr, priv->ieee80211->dev->dev_addr)); (ether_addr_equal(praddr, priv->ieee80211->dev->dev_addr));
if (WLAN_FC_GET_FRAMETYPE(fc) == IEEE80211_STYPE_BEACON) if (WLAN_FC_GET_FRAMETYPE(fc) == IEEE80211_STYPE_BEACON)

View File

@@ -1073,6 +1073,7 @@ static int exynos_tmu_probe(struct platform_device *pdev)
data->sclk = devm_clk_get(&pdev->dev, "tmu_sclk"); data->sclk = devm_clk_get(&pdev->dev, "tmu_sclk");
if (IS_ERR(data->sclk)) { if (IS_ERR(data->sclk)) {
dev_err(&pdev->dev, "Failed to get sclk\n"); dev_err(&pdev->dev, "Failed to get sclk\n");
ret = PTR_ERR(data->sclk);
goto err_clk; goto err_clk;
} else { } else {
ret = clk_prepare_enable(data->sclk); ret = clk_prepare_enable(data->sclk);

View File

@@ -2060,7 +2060,7 @@ static void restore_cur(struct vc_data *vc)
enum { ESnormal, ESesc, ESsquare, ESgetpars, ESfunckey, enum { ESnormal, ESesc, ESsquare, ESgetpars, ESfunckey,
EShash, ESsetG0, ESsetG1, ESpercent, EScsiignore, ESnonstd, EShash, ESsetG0, ESsetG1, ESpercent, EScsiignore, ESnonstd,
ESpalette, ESosc }; ESpalette, ESosc, ESapc, ESpm, ESdcs };
/* console_lock is held (except via vc_init()) */ /* console_lock is held (except via vc_init()) */
static void reset_terminal(struct vc_data *vc, int do_clear) static void reset_terminal(struct vc_data *vc, int do_clear)
@@ -2134,20 +2134,28 @@ static void vc_setGx(struct vc_data *vc, unsigned int which, int c)
vc->vc_translate = set_translate(*charset, vc); vc->vc_translate = set_translate(*charset, vc);
} }
/* is this state an ANSI control string? */
static bool ansi_control_string(unsigned int state)
{
if (state == ESosc || state == ESapc || state == ESpm || state == ESdcs)
return true;
return false;
}
/* console_lock is held */ /* console_lock is held */
static void do_con_trol(struct tty_struct *tty, struct vc_data *vc, int c) static void do_con_trol(struct tty_struct *tty, struct vc_data *vc, int c)
{ {
/* /*
* Control characters can be used in the _middle_ * Control characters can be used in the _middle_
* of an escape sequence. * of an escape sequence, aside from ANSI control strings.
*/ */
if (vc->vc_state == ESosc && c>=8 && c<=13) /* ... except for OSC */ if (ansi_control_string(vc->vc_state) && c >= 8 && c <= 13)
return; return;
switch (c) { switch (c) {
case 0: case 0:
return; return;
case 7: case 7:
if (vc->vc_state == ESosc) if (ansi_control_string(vc->vc_state))
vc->vc_state = ESnormal; vc->vc_state = ESnormal;
else if (vc->vc_bell_duration) else if (vc->vc_bell_duration)
kd_mksound(vc->vc_bell_pitch, vc->vc_bell_duration); kd_mksound(vc->vc_bell_pitch, vc->vc_bell_duration);
@@ -2208,6 +2216,12 @@ static void do_con_trol(struct tty_struct *tty, struct vc_data *vc, int c)
case ']': case ']':
vc->vc_state = ESnonstd; vc->vc_state = ESnonstd;
return; return;
case '_':
vc->vc_state = ESapc;
return;
case '^':
vc->vc_state = ESpm;
return;
case '%': case '%':
vc->vc_state = ESpercent; vc->vc_state = ESpercent;
return; return;
@@ -2225,6 +2239,9 @@ static void do_con_trol(struct tty_struct *tty, struct vc_data *vc, int c)
if (vc->state.x < VC_TABSTOPS_COUNT) if (vc->state.x < VC_TABSTOPS_COUNT)
set_bit(vc->state.x, vc->vc_tab_stop); set_bit(vc->state.x, vc->vc_tab_stop);
return; return;
case 'P':
vc->vc_state = ESdcs;
return;
case 'Z': case 'Z':
respond_ID(tty); respond_ID(tty);
return; return;
@@ -2521,8 +2538,14 @@ static void do_con_trol(struct tty_struct *tty, struct vc_data *vc, int c)
vc_setGx(vc, 1, c); vc_setGx(vc, 1, c);
vc->vc_state = ESnormal; vc->vc_state = ESnormal;
return; return;
case ESapc:
return;
case ESosc: case ESosc:
return; return;
case ESpm:
return;
case ESdcs:
return;
default: default:
vc->vc_state = ESnormal; vc->vc_state = ESnormal;
} }

View File

@@ -568,6 +568,8 @@ static int btrfs_free_stale_devices(const char *path,
struct btrfs_device *device, *tmp_device; struct btrfs_device *device, *tmp_device;
int ret = 0; int ret = 0;
lockdep_assert_held(&uuid_mutex);
if (path) if (path)
ret = -ENOENT; ret = -ENOENT;
@@ -999,11 +1001,12 @@ static struct btrfs_fs_devices *clone_fs_devices(struct btrfs_fs_devices *orig)
struct btrfs_device *orig_dev; struct btrfs_device *orig_dev;
int ret = 0; int ret = 0;
lockdep_assert_held(&uuid_mutex);
fs_devices = alloc_fs_devices(orig->fsid, NULL); fs_devices = alloc_fs_devices(orig->fsid, NULL);
if (IS_ERR(fs_devices)) if (IS_ERR(fs_devices))
return fs_devices; return fs_devices;
mutex_lock(&orig->device_list_mutex);
fs_devices->total_devices = orig->total_devices; fs_devices->total_devices = orig->total_devices;
list_for_each_entry(orig_dev, &orig->devices, dev_list) { list_for_each_entry(orig_dev, &orig->devices, dev_list) {
@@ -1035,10 +1038,8 @@ static struct btrfs_fs_devices *clone_fs_devices(struct btrfs_fs_devices *orig)
device->fs_devices = fs_devices; device->fs_devices = fs_devices;
fs_devices->num_devices++; fs_devices->num_devices++;
} }
mutex_unlock(&orig->device_list_mutex);
return fs_devices; return fs_devices;
error: error:
mutex_unlock(&orig->device_list_mutex);
free_fs_devices(fs_devices); free_fs_devices(fs_devices);
return ERR_PTR(ret); return ERR_PTR(ret);
} }
@@ -1855,15 +1856,17 @@ out:
* Function to update ctime/mtime for a given device path. * Function to update ctime/mtime for a given device path.
* Mainly used for ctime/mtime based probe like libblkid. * Mainly used for ctime/mtime based probe like libblkid.
*/ */
static void update_dev_time(const char *path_name) static void update_dev_time(struct block_device *bdev)
{ {
struct file *filp; struct inode *inode = bdev->bd_inode;
struct timespec64 now;
filp = filp_open(path_name, O_RDWR, 0); /* Shouldn't happen but just in case. */
if (IS_ERR(filp)) if (!inode)
return; return;
file_update_time(filp);
filp_close(filp, NULL); now = current_time(inode);
generic_update_time(inode, &now, S_MTIME | S_CTIME);
} }
static int btrfs_rm_dev_item(struct btrfs_device *device) static int btrfs_rm_dev_item(struct btrfs_device *device)
@@ -2038,7 +2041,7 @@ void btrfs_scratch_superblocks(struct btrfs_fs_info *fs_info,
btrfs_kobject_uevent(bdev, KOBJ_CHANGE); btrfs_kobject_uevent(bdev, KOBJ_CHANGE);
/* Update ctime/mtime for device path for libblkid */ /* Update ctime/mtime for device path for libblkid */
update_dev_time(device_path); update_dev_time(bdev);
} }
int btrfs_rm_device(struct btrfs_fs_info *fs_info, const char *device_path, int btrfs_rm_device(struct btrfs_fs_info *fs_info, const char *device_path,
@@ -2681,7 +2684,7 @@ int btrfs_init_new_device(struct btrfs_fs_info *fs_info, const char *device_path
btrfs_forget_devices(device_path); btrfs_forget_devices(device_path);
/* Update ctime/mtime for blkid or udev */ /* Update ctime/mtime for blkid or udev */
update_dev_time(device_path); update_dev_time(bdev);
return ret; return ret;

View File

@@ -1868,6 +1868,8 @@ static u64 __mark_caps_flushing(struct inode *inode,
* try to invalidate mapping pages without blocking. * try to invalidate mapping pages without blocking.
*/ */
static int try_nonblocking_invalidate(struct inode *inode) static int try_nonblocking_invalidate(struct inode *inode)
__releases(ci->i_ceph_lock)
__acquires(ci->i_ceph_lock)
{ {
struct ceph_inode_info *ci = ceph_inode(inode); struct ceph_inode_info *ci = ceph_inode(inode);
u32 invalidating_gen = ci->i_rdcache_gen; u32 invalidating_gen = ci->i_rdcache_gen;
@@ -3169,7 +3171,16 @@ void ceph_put_wrbuffer_cap_refs(struct ceph_inode_info *ci, int nr,
break; break;
} }
} }
BUG_ON(!found);
if (!found) {
/*
* The capsnap should already be removed when removing
* auth cap in the case of a forced unmount.
*/
WARN_ON_ONCE(ci->i_auth_cap);
goto unlock;
}
capsnap->dirty_pages -= nr; capsnap->dirty_pages -= nr;
if (capsnap->dirty_pages == 0) { if (capsnap->dirty_pages == 0) {
complete_capsnap = true; complete_capsnap = true;
@@ -3191,6 +3202,7 @@ void ceph_put_wrbuffer_cap_refs(struct ceph_inode_info *ci, int nr,
complete_capsnap ? " (complete capsnap)" : ""); complete_capsnap ? " (complete capsnap)" : "");
} }
unlock:
spin_unlock(&ci->i_ceph_lock); spin_unlock(&ci->i_ceph_lock);
if (last) { if (last) {
@@ -3657,6 +3669,43 @@ out:
iput(inode); iput(inode);
} }
void __ceph_remove_capsnap(struct inode *inode, struct ceph_cap_snap *capsnap,
bool *wake_ci, bool *wake_mdsc)
{
struct ceph_inode_info *ci = ceph_inode(inode);
struct ceph_mds_client *mdsc = ceph_sb_to_client(inode->i_sb)->mdsc;
bool ret;
lockdep_assert_held(&ci->i_ceph_lock);
dout("removing capsnap %p, inode %p ci %p\n", capsnap, inode, ci);
list_del_init(&capsnap->ci_item);
ret = __detach_cap_flush_from_ci(ci, &capsnap->cap_flush);
if (wake_ci)
*wake_ci = ret;
spin_lock(&mdsc->cap_dirty_lock);
if (list_empty(&ci->i_cap_flush_list))
list_del_init(&ci->i_flushing_item);
ret = __detach_cap_flush_from_mdsc(mdsc, &capsnap->cap_flush);
if (wake_mdsc)
*wake_mdsc = ret;
spin_unlock(&mdsc->cap_dirty_lock);
}
void ceph_remove_capsnap(struct inode *inode, struct ceph_cap_snap *capsnap,
bool *wake_ci, bool *wake_mdsc)
{
struct ceph_inode_info *ci = ceph_inode(inode);
lockdep_assert_held(&ci->i_ceph_lock);
WARN_ON_ONCE(capsnap->dirty_pages || capsnap->writing);
__ceph_remove_capsnap(inode, capsnap, wake_ci, wake_mdsc);
}
/* /*
* Handle FLUSHSNAP_ACK. MDS has flushed snap data to disk and we can * Handle FLUSHSNAP_ACK. MDS has flushed snap data to disk and we can
* throw away our cap_snap. * throw away our cap_snap.
@@ -3694,23 +3743,10 @@ static void handle_cap_flushsnap_ack(struct inode *inode, u64 flush_tid,
capsnap, capsnap->follows); capsnap, capsnap->follows);
} }
} }
if (flushed) { if (flushed)
WARN_ON(capsnap->dirty_pages || capsnap->writing); ceph_remove_capsnap(inode, capsnap, &wake_ci, &wake_mdsc);
dout(" removing %p cap_snap %p follows %lld\n",
inode, capsnap, follows);
list_del(&capsnap->ci_item);
wake_ci |= __detach_cap_flush_from_ci(ci, &capsnap->cap_flush);
spin_lock(&mdsc->cap_dirty_lock);
if (list_empty(&ci->i_cap_flush_list))
list_del_init(&ci->i_flushing_item);
wake_mdsc |= __detach_cap_flush_from_mdsc(mdsc,
&capsnap->cap_flush);
spin_unlock(&mdsc->cap_dirty_lock);
}
spin_unlock(&ci->i_ceph_lock); spin_unlock(&ci->i_ceph_lock);
if (flushed) { if (flushed) {
ceph_put_snap_context(capsnap->context); ceph_put_snap_context(capsnap->context);
ceph_put_cap_snap(capsnap); ceph_put_cap_snap(capsnap);

View File

@@ -1797,7 +1797,6 @@ static void ceph_d_release(struct dentry *dentry)
dentry->d_fsdata = NULL; dentry->d_fsdata = NULL;
spin_unlock(&dentry->d_lock); spin_unlock(&dentry->d_lock);
if (di->lease_session)
ceph_put_mds_session(di->lease_session); ceph_put_mds_session(di->lease_session);
kmem_cache_free(ceph_dentry_cachep, di); kmem_cache_free(ceph_dentry_cachep, di);
} }

View File

@@ -1723,22 +1723,6 @@ retry_snap:
goto out; goto out;
} }
err = file_remove_privs(file);
if (err)
goto out;
err = file_update_time(file);
if (err)
goto out;
inode_inc_iversion_raw(inode);
if (ci->i_inline_version != CEPH_INLINE_NONE) {
err = ceph_uninline_data(file, NULL);
if (err < 0)
goto out;
}
down_read(&osdc->lock); down_read(&osdc->lock);
map_flags = osdc->osdmap->flags; map_flags = osdc->osdmap->flags;
pool_flags = ceph_pg_pool_flags(osdc->osdmap, ci->i_layout.pool_id); pool_flags = ceph_pg_pool_flags(osdc->osdmap, ci->i_layout.pool_id);
@@ -1749,6 +1733,16 @@ retry_snap:
goto out; goto out;
} }
err = file_remove_privs(file);
if (err)
goto out;
if (ci->i_inline_version != CEPH_INLINE_NONE) {
err = ceph_uninline_data(file, NULL);
if (err < 0)
goto out;
}
dout("aio_write %p %llx.%llx %llu~%zd getting caps. i_size %llu\n", dout("aio_write %p %llx.%llx %llu~%zd getting caps. i_size %llu\n",
inode, ceph_vinop(inode), pos, count, i_size_read(inode)); inode, ceph_vinop(inode), pos, count, i_size_read(inode));
if (fi->fmode & CEPH_FILE_MODE_LAZY) if (fi->fmode & CEPH_FILE_MODE_LAZY)
@@ -1761,6 +1755,12 @@ retry_snap:
if (err < 0) if (err < 0)
goto out; goto out;
err = file_update_time(file);
if (err)
goto out_caps;
inode_inc_iversion_raw(inode);
dout("aio_write %p %llx.%llx %llu~%zd got cap refs on %s\n", dout("aio_write %p %llx.%llx %llu~%zd got cap refs on %s\n",
inode, ceph_vinop(inode), pos, count, ceph_cap_string(got)); inode, ceph_vinop(inode), pos, count, ceph_cap_string(got));
@@ -1844,6 +1844,8 @@ retry_snap:
} }
goto out_unlocked; goto out_unlocked;
out_caps:
ceph_put_cap_refs(ci, got);
out: out:
if (direct_lock) if (direct_lock)
ceph_end_io_direct(inode); ceph_end_io_direct(inode);

View File

@@ -1121,7 +1121,6 @@ static inline void update_dentry_lease(struct inode *dir, struct dentry *dentry,
__update_dentry_lease(dir, dentry, lease, session, from_time, __update_dentry_lease(dir, dentry, lease, session, from_time,
&old_lease_session); &old_lease_session);
spin_unlock(&dentry->d_lock); spin_unlock(&dentry->d_lock);
if (old_lease_session)
ceph_put_mds_session(old_lease_session); ceph_put_mds_session(old_lease_session);
} }
@@ -1167,7 +1166,6 @@ static void update_dentry_lease_careful(struct dentry *dentry,
from_time, &old_lease_session); from_time, &old_lease_session);
out_unlock: out_unlock:
spin_unlock(&dentry->d_lock); spin_unlock(&dentry->d_lock);
if (old_lease_session)
ceph_put_mds_session(old_lease_session); ceph_put_mds_session(old_lease_session);
} }

View File

@@ -661,6 +661,9 @@ struct ceph_mds_session *ceph_get_mds_session(struct ceph_mds_session *s)
void ceph_put_mds_session(struct ceph_mds_session *s) void ceph_put_mds_session(struct ceph_mds_session *s)
{ {
if (IS_ERR_OR_NULL(s))
return;
dout("mdsc put_session %p %d -> %d\n", s, dout("mdsc put_session %p %d -> %d\n", s,
refcount_read(&s->s_ref), refcount_read(&s->s_ref)-1); refcount_read(&s->s_ref), refcount_read(&s->s_ref)-1);
if (refcount_dec_and_test(&s->s_ref)) { if (refcount_dec_and_test(&s->s_ref)) {
@@ -1435,7 +1438,6 @@ static void __open_export_target_sessions(struct ceph_mds_client *mdsc,
for (i = 0; i < mi->num_export_targets; i++) { for (i = 0; i < mi->num_export_targets; i++) {
ts = __open_export_target_session(mdsc, mi->export_targets[i]); ts = __open_export_target_session(mdsc, mi->export_targets[i]);
if (!IS_ERR(ts))
ceph_put_mds_session(ts); ceph_put_mds_session(ts);
} }
} }
@@ -1585,14 +1587,39 @@ out:
return ret; return ret;
} }
static int remove_capsnaps(struct ceph_mds_client *mdsc, struct inode *inode)
{
struct ceph_inode_info *ci = ceph_inode(inode);
struct ceph_cap_snap *capsnap;
int capsnap_release = 0;
lockdep_assert_held(&ci->i_ceph_lock);
dout("removing capsnaps, ci is %p, inode is %p\n", ci, inode);
while (!list_empty(&ci->i_cap_snaps)) {
capsnap = list_first_entry(&ci->i_cap_snaps,
struct ceph_cap_snap, ci_item);
__ceph_remove_capsnap(inode, capsnap, NULL, NULL);
ceph_put_snap_context(capsnap->context);
ceph_put_cap_snap(capsnap);
capsnap_release++;
}
wake_up_all(&ci->i_cap_wq);
wake_up_all(&mdsc->cap_flushing_wq);
return capsnap_release;
}
static int remove_session_caps_cb(struct inode *inode, struct ceph_cap *cap, static int remove_session_caps_cb(struct inode *inode, struct ceph_cap *cap,
void *arg) void *arg)
{ {
struct ceph_fs_client *fsc = (struct ceph_fs_client *)arg; struct ceph_fs_client *fsc = (struct ceph_fs_client *)arg;
struct ceph_mds_client *mdsc = fsc->mdsc;
struct ceph_inode_info *ci = ceph_inode(inode); struct ceph_inode_info *ci = ceph_inode(inode);
LIST_HEAD(to_remove); LIST_HEAD(to_remove);
bool dirty_dropped = false; bool dirty_dropped = false;
bool invalidate = false; bool invalidate = false;
int capsnap_release = 0;
dout("removing cap %p, ci is %p, inode is %p\n", dout("removing cap %p, ci is %p, inode is %p\n",
cap, ci, &ci->vfs_inode); cap, ci, &ci->vfs_inode);
@@ -1600,7 +1627,6 @@ static int remove_session_caps_cb(struct inode *inode, struct ceph_cap *cap,
__ceph_remove_cap(cap, false); __ceph_remove_cap(cap, false);
if (!ci->i_auth_cap) { if (!ci->i_auth_cap) {
struct ceph_cap_flush *cf; struct ceph_cap_flush *cf;
struct ceph_mds_client *mdsc = fsc->mdsc;
if (READ_ONCE(fsc->mount_state) == CEPH_MOUNT_SHUTDOWN) { if (READ_ONCE(fsc->mount_state) == CEPH_MOUNT_SHUTDOWN) {
if (inode->i_data.nrpages > 0) if (inode->i_data.nrpages > 0)
@@ -1664,6 +1690,9 @@ static int remove_session_caps_cb(struct inode *inode, struct ceph_cap *cap,
list_add(&ci->i_prealloc_cap_flush->i_list, &to_remove); list_add(&ci->i_prealloc_cap_flush->i_list, &to_remove);
ci->i_prealloc_cap_flush = NULL; ci->i_prealloc_cap_flush = NULL;
} }
if (!list_empty(&ci->i_cap_snaps))
capsnap_release = remove_capsnaps(mdsc, inode);
} }
spin_unlock(&ci->i_ceph_lock); spin_unlock(&ci->i_ceph_lock);
while (!list_empty(&to_remove)) { while (!list_empty(&to_remove)) {
@@ -1680,6 +1709,8 @@ static int remove_session_caps_cb(struct inode *inode, struct ceph_cap *cap,
ceph_queue_invalidate(inode); ceph_queue_invalidate(inode);
if (dirty_dropped) if (dirty_dropped)
iput(inode); iput(inode);
while (capsnap_release--)
iput(inode);
return 0; return 0;
} }
@@ -4857,7 +4888,6 @@ void ceph_mdsc_destroy(struct ceph_fs_client *fsc)
ceph_metric_destroy(&mdsc->metric); ceph_metric_destroy(&mdsc->metric);
flush_delayed_work(&mdsc->metric.delayed_work);
fsc->mdsc = NULL; fsc->mdsc = NULL;
kfree(mdsc); kfree(mdsc);
dout("mdsc_destroy %p done\n", mdsc); dout("mdsc_destroy %p done\n", mdsc);

View File

@@ -224,6 +224,8 @@ void ceph_metric_destroy(struct ceph_client_metric *m)
if (!m) if (!m)
return; return;
cancel_delayed_work_sync(&m->delayed_work);
percpu_counter_destroy(&m->total_inodes); percpu_counter_destroy(&m->total_inodes);
percpu_counter_destroy(&m->opened_inodes); percpu_counter_destroy(&m->opened_inodes);
percpu_counter_destroy(&m->i_caps_mis); percpu_counter_destroy(&m->i_caps_mis);
@@ -231,9 +233,6 @@ void ceph_metric_destroy(struct ceph_client_metric *m)
percpu_counter_destroy(&m->d_lease_mis); percpu_counter_destroy(&m->d_lease_mis);
percpu_counter_destroy(&m->d_lease_hit); percpu_counter_destroy(&m->d_lease_hit);
cancel_delayed_work_sync(&m->delayed_work);
if (m->session)
ceph_put_mds_session(m->session); ceph_put_mds_session(m->session);
} }

View File

@@ -1134,6 +1134,12 @@ extern void ceph_put_cap_refs_no_check_caps(struct ceph_inode_info *ci,
int had); int had);
extern void ceph_put_wrbuffer_cap_refs(struct ceph_inode_info *ci, int nr, extern void ceph_put_wrbuffer_cap_refs(struct ceph_inode_info *ci, int nr,
struct ceph_snap_context *snapc); struct ceph_snap_context *snapc);
extern void __ceph_remove_capsnap(struct inode *inode,
struct ceph_cap_snap *capsnap,
bool *wake_ci, bool *wake_mdsc);
extern void ceph_remove_capsnap(struct inode *inode,
struct ceph_cap_snap *capsnap,
bool *wake_ci, bool *wake_mdsc);
extern void ceph_flush_snaps(struct ceph_inode_info *ci, extern void ceph_flush_snaps(struct ceph_inode_info *ci,
struct ceph_mds_session **psession); struct ceph_mds_session **psession);
extern bool __ceph_should_report_size(struct ceph_inode_info *ci); extern bool __ceph_should_report_size(struct ceph_inode_info *ci);

View File

@@ -1111,8 +1111,10 @@ int dump_vma_snapshot(struct coredump_params *cprm, int *vma_count,
mmap_write_unlock(mm); mmap_write_unlock(mm);
if (WARN_ON(i != *vma_count)) if (WARN_ON(i != *vma_count)) {
kvfree(*vma_meta);
return -EFAULT; return -EFAULT;
}
*vma_data_size_ptr = vma_data_size; *vma_data_size_ptr = vma_data_size;
return 0; return 0;

View File

@@ -64,11 +64,9 @@ static const struct sysfs_ops nilfs_##name##_attr_ops = { \
#define NILFS_DEV_INT_GROUP_TYPE(name, parent_name) \ #define NILFS_DEV_INT_GROUP_TYPE(name, parent_name) \
static void nilfs_##name##_attr_release(struct kobject *kobj) \ static void nilfs_##name##_attr_release(struct kobject *kobj) \
{ \ { \
struct nilfs_sysfs_##parent_name##_subgroups *subgroups; \ struct nilfs_sysfs_##parent_name##_subgroups *subgroups = container_of(kobj, \
struct the_nilfs *nilfs = container_of(kobj->parent, \ struct nilfs_sysfs_##parent_name##_subgroups, \
struct the_nilfs, \ sg_##name##_kobj); \
ns_##parent_name##_kobj); \
subgroups = nilfs->ns_##parent_name##_subgroups; \
complete(&subgroups->sg_##name##_kobj_unregister); \ complete(&subgroups->sg_##name##_kobj_unregister); \
} \ } \
static struct kobj_type nilfs_##name##_ktype = { \ static struct kobj_type nilfs_##name##_ktype = { \
@@ -94,12 +92,12 @@ static int nilfs_sysfs_create_##name##_group(struct the_nilfs *nilfs) \
err = kobject_init_and_add(kobj, &nilfs_##name##_ktype, parent, \ err = kobject_init_and_add(kobj, &nilfs_##name##_ktype, parent, \
#name); \ #name); \
if (err) \ if (err) \
kobject_put(kobj); \
return err; \ return err; \
return 0; \
} \ } \
static void nilfs_sysfs_delete_##name##_group(struct the_nilfs *nilfs) \ static void nilfs_sysfs_delete_##name##_group(struct the_nilfs *nilfs) \
{ \ { \
kobject_del(&nilfs->ns_##parent_name##_subgroups->sg_##name##_kobj); \ kobject_put(&nilfs->ns_##parent_name##_subgroups->sg_##name##_kobj); \
} }
/************************************************************************ /************************************************************************
@@ -210,14 +208,14 @@ int nilfs_sysfs_create_snapshot_group(struct nilfs_root *root)
} }
if (err) if (err)
return err; kobject_put(&root->snapshot_kobj);
return 0; return err;
} }
void nilfs_sysfs_delete_snapshot_group(struct nilfs_root *root) void nilfs_sysfs_delete_snapshot_group(struct nilfs_root *root)
{ {
kobject_del(&root->snapshot_kobj); kobject_put(&root->snapshot_kobj);
} }
/************************************************************************ /************************************************************************
@@ -999,7 +997,7 @@ int nilfs_sysfs_create_device_group(struct super_block *sb)
err = kobject_init_and_add(&nilfs->ns_dev_kobj, &nilfs_dev_ktype, NULL, err = kobject_init_and_add(&nilfs->ns_dev_kobj, &nilfs_dev_ktype, NULL,
"%s", sb->s_id); "%s", sb->s_id);
if (err) if (err)
goto free_dev_subgroups; goto cleanup_dev_kobject;
err = nilfs_sysfs_create_mounted_snapshots_group(nilfs); err = nilfs_sysfs_create_mounted_snapshots_group(nilfs);
if (err) if (err)
@@ -1036,9 +1034,7 @@ delete_mounted_snapshots_group:
nilfs_sysfs_delete_mounted_snapshots_group(nilfs); nilfs_sysfs_delete_mounted_snapshots_group(nilfs);
cleanup_dev_kobject: cleanup_dev_kobject:
kobject_del(&nilfs->ns_dev_kobj); kobject_put(&nilfs->ns_dev_kobj);
free_dev_subgroups:
kfree(nilfs->ns_dev_subgroups); kfree(nilfs->ns_dev_subgroups);
failed_create_device_group: failed_create_device_group:

View File

@@ -792,14 +792,13 @@ nilfs_find_or_create_root(struct the_nilfs *nilfs, __u64 cno)
void nilfs_put_root(struct nilfs_root *root) void nilfs_put_root(struct nilfs_root *root)
{ {
if (refcount_dec_and_test(&root->count)) {
struct the_nilfs *nilfs = root->nilfs; struct the_nilfs *nilfs = root->nilfs;
nilfs_sysfs_delete_snapshot_group(root); if (refcount_dec_and_lock(&root->count, &nilfs->ns_cptree_lock)) {
spin_lock(&nilfs->ns_cptree_lock);
rb_erase(&root->rb_node, &nilfs->ns_cptree); rb_erase(&root->rb_node, &nilfs->ns_cptree);
spin_unlock(&nilfs->ns_cptree_lock); spin_unlock(&nilfs->ns_cptree_lock);
nilfs_sysfs_delete_snapshot_group(root);
iput(root->ifile); iput(root->ifile);
kfree(root); kfree(root);

View File

@@ -79,24 +79,6 @@ struct cpu_cacheinfo {
bool cpu_map_populated; bool cpu_map_populated;
}; };
/*
* Helpers to make sure "func" is executed on the cpu whose cache
* attributes are being detected
*/
#define DEFINE_SMP_CALL_CACHE_FUNCTION(func) \
static inline void _##func(void *ret) \
{ \
int cpu = smp_processor_id(); \
*(int *)ret = __##func(cpu); \
} \
\
int func(unsigned int cpu) \
{ \
int ret; \
smp_call_function_single(cpu, _##func, &ret, true); \
return ret; \
}
struct cpu_cacheinfo *get_cpu_cacheinfo(unsigned int cpu); struct cpu_cacheinfo *get_cpu_cacheinfo(unsigned int cpu);
int init_cache_level(unsigned int cpu); int init_cache_level(unsigned int cpu);
int populate_cache_leaves(unsigned int cpu); int populate_cache_leaves(unsigned int cpu);

View File

@@ -427,12 +427,13 @@ static inline void thermal_zone_device_unregister(
struct thermal_zone_device *tz) struct thermal_zone_device *tz)
{ } { }
static inline struct thermal_cooling_device * static inline struct thermal_cooling_device *
thermal_cooling_device_register(char *type, void *devdata, thermal_cooling_device_register(const char *type, void *devdata,
const struct thermal_cooling_device_ops *ops) const struct thermal_cooling_device_ops *ops)
{ return ERR_PTR(-ENODEV); } { return ERR_PTR(-ENODEV); }
static inline struct thermal_cooling_device * static inline struct thermal_cooling_device *
thermal_of_cooling_device_register(struct device_node *np, thermal_of_cooling_device_register(struct device_node *np,
char *type, void *devdata, const struct thermal_cooling_device_ops *ops) const char *type, void *devdata,
const struct thermal_cooling_device_ops *ops)
{ return ERR_PTR(-ENODEV); } { return ERR_PTR(-ENODEV); }
static inline struct thermal_cooling_device * static inline struct thermal_cooling_device *
devm_thermal_of_cooling_device_register(struct device *dev, devm_thermal_of_cooling_device_register(struct device *dev,

View File

@@ -41,7 +41,8 @@ struct profile_hit {
#define NR_PROFILE_GRP (NR_PROFILE_HIT/PROFILE_GRPSZ) #define NR_PROFILE_GRP (NR_PROFILE_HIT/PROFILE_GRPSZ)
static atomic_t *prof_buffer; static atomic_t *prof_buffer;
static unsigned long prof_len, prof_shift; static unsigned long prof_len;
static unsigned short int prof_shift;
int prof_on __read_mostly; int prof_on __read_mostly;
EXPORT_SYMBOL_GPL(prof_on); EXPORT_SYMBOL_GPL(prof_on);
@@ -67,8 +68,8 @@ int profile_setup(char *str)
if (str[strlen(sleepstr)] == ',') if (str[strlen(sleepstr)] == ',')
str += strlen(sleepstr) + 1; str += strlen(sleepstr) + 1;
if (get_option(&str, &par)) if (get_option(&str, &par))
prof_shift = par; prof_shift = clamp(par, 0, BITS_PER_LONG - 1);
pr_info("kernel sleep profiling enabled (shift: %ld)\n", pr_info("kernel sleep profiling enabled (shift: %u)\n",
prof_shift); prof_shift);
#else #else
pr_warn("kernel sleep profiling requires CONFIG_SCHEDSTATS\n"); pr_warn("kernel sleep profiling requires CONFIG_SCHEDSTATS\n");
@@ -78,21 +79,21 @@ int profile_setup(char *str)
if (str[strlen(schedstr)] == ',') if (str[strlen(schedstr)] == ',')
str += strlen(schedstr) + 1; str += strlen(schedstr) + 1;
if (get_option(&str, &par)) if (get_option(&str, &par))
prof_shift = par; prof_shift = clamp(par, 0, BITS_PER_LONG - 1);
pr_info("kernel schedule profiling enabled (shift: %ld)\n", pr_info("kernel schedule profiling enabled (shift: %u)\n",
prof_shift); prof_shift);
} else if (!strncmp(str, kvmstr, strlen(kvmstr))) { } else if (!strncmp(str, kvmstr, strlen(kvmstr))) {
prof_on = KVM_PROFILING; prof_on = KVM_PROFILING;
if (str[strlen(kvmstr)] == ',') if (str[strlen(kvmstr)] == ',')
str += strlen(kvmstr) + 1; str += strlen(kvmstr) + 1;
if (get_option(&str, &par)) if (get_option(&str, &par))
prof_shift = par; prof_shift = clamp(par, 0, BITS_PER_LONG - 1);
pr_info("kernel KVM profiling enabled (shift: %ld)\n", pr_info("kernel KVM profiling enabled (shift: %u)\n",
prof_shift); prof_shift);
} else if (get_option(&str, &par)) { } else if (get_option(&str, &par)) {
prof_shift = par; prof_shift = clamp(par, 0, BITS_PER_LONG - 1);
prof_on = CPU_PROFILING; prof_on = CPU_PROFILING;
pr_info("kernel profiling enabled (shift: %ld)\n", pr_info("kernel profiling enabled (shift: %u)\n",
prof_shift); prof_shift);
} }
return 1; return 1;
@@ -468,7 +469,7 @@ read_profile(struct file *file, char __user *buf, size_t count, loff_t *ppos)
unsigned long p = *ppos; unsigned long p = *ppos;
ssize_t read; ssize_t read;
char *pnt; char *pnt;
unsigned int sample_step = 1 << prof_shift; unsigned long sample_step = 1UL << prof_shift;
profile_flip_buffers(); profile_flip_buffers();
if (p >= (prof_len+1)*sizeof(unsigned int)) if (p >= (prof_len+1)*sizeof(unsigned int))

View File

@@ -374,10 +374,10 @@ void play_idle_precise(u64 duration_ns, u64 latency_ns)
cpuidle_use_deepest_state(latency_ns); cpuidle_use_deepest_state(latency_ns);
it.done = 0; it.done = 0;
hrtimer_init_on_stack(&it.timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); hrtimer_init_on_stack(&it.timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL_HARD);
it.timer.function = idle_inject_timer_fn; it.timer.function = idle_inject_timer_fn;
hrtimer_start(&it.timer, ns_to_ktime(duration_ns), hrtimer_start(&it.timer, ns_to_ktime(duration_ns),
HRTIMER_MODE_REL_PINNED); HRTIMER_MODE_REL_PINNED_HARD);
while (!READ_ONCE(it.done)) while (!READ_ONCE(it.done))
do_idle(); do_idle();

View File

@@ -1951,13 +1951,6 @@ static int validate_prctl_map_addr(struct prctl_mm_map *prctl_map)
error = -EINVAL; error = -EINVAL;
/*
* @brk should be after @end_data in traditional maps.
*/
if (prctl_map->start_brk <= prctl_map->end_data ||
prctl_map->brk <= prctl_map->end_data)
goto out;
/* /*
* Neither we should allow to override limits if they set. * Neither we should allow to override limits if they set.
*/ */

View File

@@ -982,7 +982,6 @@ config HARDLOCKUP_DETECTOR
depends on HAVE_HARDLOCKUP_DETECTOR_PERF || HAVE_HARDLOCKUP_DETECTOR_ARCH depends on HAVE_HARDLOCKUP_DETECTOR_PERF || HAVE_HARDLOCKUP_DETECTOR_ARCH
select LOCKUP_DETECTOR select LOCKUP_DETECTOR
select HARDLOCKUP_DETECTOR_PERF if HAVE_HARDLOCKUP_DETECTOR_PERF select HARDLOCKUP_DETECTOR_PERF if HAVE_HARDLOCKUP_DETECTOR_PERF
select HARDLOCKUP_DETECTOR_ARCH if HAVE_HARDLOCKUP_DETECTOR_ARCH
help help
Say Y here to enable the kernel to act as a watchdog to detect Say Y here to enable the kernel to act as a watchdog to detect
hard lockups. hard lockups.

View File

@@ -605,7 +605,7 @@ static int p9_virtio_probe(struct virtio_device *vdev)
chan->vc_wq = kmalloc(sizeof(wait_queue_head_t), GFP_KERNEL); chan->vc_wq = kmalloc(sizeof(wait_queue_head_t), GFP_KERNEL);
if (!chan->vc_wq) { if (!chan->vc_wq) {
err = -ENOMEM; err = -ENOMEM;
goto out_free_tag; goto out_remove_file;
} }
init_waitqueue_head(chan->vc_wq); init_waitqueue_head(chan->vc_wq);
chan->ring_bufs_avail = 1; chan->ring_bufs_avail = 1;
@@ -623,6 +623,8 @@ static int p9_virtio_probe(struct virtio_device *vdev)
return 0; return 0;
out_remove_file:
sysfs_remove_file(&vdev->dev.kobj, &dev_attr_mount_tag.attr);
out_free_tag: out_free_tag:
kfree(tag); kfree(tag);
out_free_vq: out_free_vq:

View File

@@ -1168,6 +1168,9 @@ static struct sctp_association *__sctp_rcv_asconf_lookup(
union sctp_addr_param *param; union sctp_addr_param *param;
union sctp_addr paddr; union sctp_addr paddr;
if (ntohs(ch->length) < sizeof(*asconf) + sizeof(struct sctp_paramhdr))
return NULL;
/* Skip over the ADDIP header and find the Address parameter */ /* Skip over the ADDIP header and find the Address parameter */
param = (union sctp_addr_param *)(asconf + 1); param = (union sctp_addr_param *)(asconf + 1);

View File

@@ -2150,10 +2150,17 @@ static enum sctp_ierror sctp_verify_param(struct net *net,
break; break;
case SCTP_PARAM_SET_PRIMARY: case SCTP_PARAM_SET_PRIMARY:
if (ep->asconf_enable) if (!ep->asconf_enable)
break;
goto unhandled; goto unhandled;
if (ntohs(param.p->length) < sizeof(struct sctp_addip_param) +
sizeof(struct sctp_paramhdr)) {
sctp_process_inv_paramlength(asoc, param.p,
chunk, err_chunk);
retval = SCTP_IERROR_ABORT;
}
break;
case SCTP_PARAM_HOST_NAME_ADDRESS: case SCTP_PARAM_HOST_NAME_ADDRESS:
/* Tell the peer, we won't support this param. */ /* Tell the peer, we won't support this param. */
sctp_process_hn_param(asoc, param, chunk, err_chunk); sctp_process_hn_param(asoc, param, chunk, err_chunk);

View File

@@ -222,8 +222,8 @@ instance_options() { # [instance-name]
emit_kv $PREFIX.cpumask = $val emit_kv $PREFIX.cpumask = $val
fi fi
val=`cat $INSTANCE/tracing_on` val=`cat $INSTANCE/tracing_on`
if [ `echo $val | sed -e s/f//g`x != x ]; then if [ "$val" = "0" ]; then
emit_kv $PREFIX.tracing_on = $val emit_kv $PREFIX.tracing_on = 0
fi fi
val= val=

View File

@@ -46,4 +46,5 @@ extern char * __must_check skip_spaces(const char *);
extern char *strim(char *); extern char *strim(char *);
extern void *memchr_inv(const void *start, int c, size_t bytes);
#endif /* _TOOLS_LINUX_STRING_H_ */ #endif /* _TOOLS_LINUX_STRING_H_ */

View File

@@ -168,3 +168,61 @@ char *strreplace(char *s, char old, char new)
*s = new; *s = new;
return s; return s;
} }
static void *check_bytes8(const u8 *start, u8 value, unsigned int bytes)
{
while (bytes) {
if (*start != value)
return (void *)start;
start++;
bytes--;
}
return NULL;
}
/**
* memchr_inv - Find an unmatching character in an area of memory.
* @start: The memory area
* @c: Find a character other than c
* @bytes: The size of the area.
*
* returns the address of the first character other than @c, or %NULL
* if the whole buffer contains just @c.
*/
void *memchr_inv(const void *start, int c, size_t bytes)
{
u8 value = c;
u64 value64;
unsigned int words, prefix;
if (bytes <= 16)
return check_bytes8(start, value, bytes);
value64 = value;
value64 |= value64 << 8;
value64 |= value64 << 16;
value64 |= value64 << 32;
prefix = (unsigned long)start % 8;
if (prefix) {
u8 *r;
prefix = 8 - prefix;
r = check_bytes8(start, value, prefix);
if (r)
return r;
start += prefix;
bytes -= prefix;
}
words = bytes / 8;
while (words) {
if (*(u64 *)start != value64)
return check_bytes8(start, value, 8);
start += 8;
words--;
}
return check_bytes8(start, value, bytes % 8);
}

View File

@@ -199,7 +199,7 @@ static int do_test(struct bpf_object *obj, int (*func)(void),
} }
if (count != expect * evlist->core.nr_entries) { if (count != expect * evlist->core.nr_entries) {
pr_debug("BPF filter result incorrect, expected %d, got %d samples\n", expect, count); pr_debug("BPF filter result incorrect, expected %d, got %d samples\n", expect * evlist->core.nr_entries, count);
goto out_delete_evlist; goto out_delete_evlist;
} }

View File

@@ -1336,6 +1336,16 @@ void dso__set_build_id(struct dso *dso, struct build_id *bid)
bool dso__build_id_equal(const struct dso *dso, struct build_id *bid) bool dso__build_id_equal(const struct dso *dso, struct build_id *bid)
{ {
if (dso->bid.size > bid->size && dso->bid.size == BUILD_ID_SIZE) {
/*
* For the backward compatibility, it allows a build-id has
* trailing zeros.
*/
return !memcmp(dso->bid.data, bid->data, bid->size) &&
!memchr_inv(&dso->bid.data[bid->size], 0,
dso->bid.size - bid->size);
}
return dso->bid.size == bid->size && return dso->bid.size == bid->size &&
memcmp(dso->bid.data, bid->data, dso->bid.size) == 0; memcmp(dso->bid.data, bid->data, dso->bid.size) == 0;
} }