Merge 8379d0cbd5 ("mmc: core: Add SD card quirk for broken poweroff notification") into android14-6.1-lts

Steps on the way to 6.1.121

Resolved merge conflicts in:
	drivers/mmc/core/card.h
	include/linux/mmc/card.h

Change-Id: I0f59989030d630651cfd6bc28c45db5f313db1fe
Signed-off-by: Greg Kroah-Hartman <gregkh@google.com>
This commit is contained in:
Greg Kroah-Hartman
2024-12-16 10:29:18 +00:00
83 changed files with 1133 additions and 412 deletions

View File

@@ -1342,7 +1342,7 @@ static int tagged_addr_ctrl_get(struct task_struct *target,
{
long ctrl = get_tagged_addr_ctrl(target);
if (IS_ERR_VALUE(ctrl))
if (WARN_ON_ONCE(IS_ERR_VALUE(ctrl)))
return ctrl;
return membuf_write(&to, &ctrl, sizeof(ctrl));
@@ -1356,6 +1356,10 @@ static int tagged_addr_ctrl_set(struct task_struct *target, const struct
int ret;
long ctrl;
ctrl = get_tagged_addr_ctrl(target);
if (WARN_ON_ONCE(IS_ERR_VALUE(ctrl)))
return ctrl;
ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, &ctrl, 0, -1);
if (ret)
return ret;

View File

@@ -32,9 +32,9 @@ static unsigned long nr_pinned_asids;
static unsigned long *pinned_asid_map;
#define ASID_MASK (~GENMASK(asid_bits - 1, 0))
#define ASID_FIRST_VERSION (1UL << asid_bits)
#define ASID_FIRST_VERSION (1UL << 16)
#define NUM_USER_ASIDS ASID_FIRST_VERSION
#define NUM_USER_ASIDS (1UL << asid_bits)
#define ctxid2asid(asid) ((asid) & ~ASID_MASK)
#define asid2ctxid(asid, genid) ((asid) | (genid))

View File

@@ -29,6 +29,16 @@ static inline int prepare_hugepage_range(struct file *file,
return 0;
}
#define __HAVE_ARCH_HUGE_PTE_CLEAR
static inline void huge_pte_clear(struct mm_struct *mm, unsigned long addr,
pte_t *ptep, unsigned long sz)
{
pte_t clear;
pte_val(clear) = (unsigned long)invalid_pte_table;
set_pte_at(mm, addr, ptep, clear);
}
#define __HAVE_ARCH_HUGE_PTEP_GET_AND_CLEAR
static inline pte_t huge_ptep_get_and_clear(struct mm_struct *mm,
unsigned long addr, pte_t *ptep)

View File

@@ -10,23 +10,11 @@ obj-vdso64 = sigtramp64-64.o gettimeofday-64.o datapage-64.o cacheflush-64.o not
ifneq ($(c-gettimeofday-y),)
CFLAGS_vgettimeofday-32.o += -include $(c-gettimeofday-y)
CFLAGS_vgettimeofday-32.o += $(DISABLE_LATENT_ENTROPY_PLUGIN)
CFLAGS_vgettimeofday-32.o += $(call cc-option, -fno-stack-protector)
CFLAGS_vgettimeofday-32.o += -DDISABLE_BRANCH_PROFILING
CFLAGS_vgettimeofday-32.o += -ffreestanding -fasynchronous-unwind-tables
CFLAGS_REMOVE_vgettimeofday-32.o = $(CC_FLAGS_FTRACE)
CFLAGS_REMOVE_vgettimeofday-32.o += -mcmodel=medium -mabi=elfv1 -mabi=elfv2 -mcall-aixdesc
CFLAGS_vgettimeofday-64.o += -include $(c-gettimeofday-y)
CFLAGS_vgettimeofday-64.o += $(DISABLE_LATENT_ENTROPY_PLUGIN)
CFLAGS_vgettimeofday-64.o += $(call cc-option, -fno-stack-protector)
CFLAGS_vgettimeofday-64.o += -DDISABLE_BRANCH_PROFILING
CFLAGS_vgettimeofday-64.o += -ffreestanding -fasynchronous-unwind-tables
CFLAGS_REMOVE_vgettimeofday-64.o = $(CC_FLAGS_FTRACE)
# Go prior to 1.16.x assumes r30 is not clobbered by any VDSO code. That used to be true
# by accident when the VDSO was hand-written asm code, but may not be now that the VDSO is
# compiler generated. To avoid breaking Go tell GCC not to use r30. Impact on code
# generation is minimal, it will just use r29 instead.
CFLAGS_vgettimeofday-64.o += $(call cc-option, -ffixed-r30)
CFLAGS_vgettimeofday-64.o += -include $(c-gettimeofday-y) $(call cc-option, -ffixed-r30)
endif
# Build rules
@@ -47,14 +35,33 @@ KCOV_INSTRUMENT := n
UBSAN_SANITIZE := n
KASAN_SANITIZE := n
ccflags-y := -shared -fno-common -fno-builtin -nostdlib -Wl,--hash-style=both
ccflags-$(CONFIG_LD_IS_LLD) += $(call cc-option,--ld-path=$(LD),-fuse-ld=lld)
ccflags-y := -fno-common -fno-builtin
ccflags-y += $(DISABLE_LATENT_ENTROPY_PLUGIN)
ccflags-y += $(call cc-option, -fno-stack-protector)
ccflags-y += -DDISABLE_BRANCH_PROFILING
ccflags-y += -ffreestanding -fasynchronous-unwind-tables
ccflags-remove-y := $(CC_FLAGS_FTRACE)
ldflags-y := -Wl,--hash-style=both -nostdlib -shared -z noexecstack $(CLANG_FLAGS)
ldflags-$(CONFIG_LD_IS_LLD) += $(call cc-option,--ld-path=$(LD),-fuse-ld=lld)
# Filter flags that clang will warn are unused for linking
ldflags-y += $(filter-out $(CC_FLAGS_FTRACE) -Wa$(comma)%, $(KBUILD_CFLAGS))
CC32FLAGS := -Wl,-soname=linux-vdso32.so.1 -m32
AS32FLAGS := -D__VDSO32__ -s
CC32FLAGS := -m32
CC32FLAGSREMOVE := -mcmodel=medium -mabi=elfv1 -mabi=elfv2 -mcall-aixdesc
ifdef CONFIG_CC_IS_CLANG
# This flag is supported by clang for 64-bit but not 32-bit so it will cause
# an unused command line flag warning for this file.
CC32FLAGSREMOVE += -fno-stack-clash-protection
# -mstack-protector-guard values from the 64-bit build are not valid for the
# 32-bit one. clang validates the values passed to these arguments during
# parsing, even when -fno-stack-protector is passed afterwards.
CC32FLAGSREMOVE += -mstack-protector-guard%
endif
LD32FLAGS := -Wl,-soname=linux-vdso32.so.1
AS32FLAGS := -D__VDSO32__
CC64FLAGS := -Wl,-soname=linux-vdso64.so.1
AS64FLAGS := -D__VDSO64__ -s
LD64FLAGS := -Wl,-soname=linux-vdso64.so.1
AS64FLAGS := -D__VDSO64__
targets += vdso32.lds
CPPFLAGS_vdso32.lds += -P -C -Upowerpc
@@ -92,13 +99,15 @@ include/generated/vdso64-offsets.h: $(obj)/vdso64.so.dbg FORCE
# actual build commands
quiet_cmd_vdso32ld_and_check = VDSO32L $@
cmd_vdso32ld_and_check = $(VDSOCC) $(c_flags) $(CC32FLAGS) -o $@ -Wl,-T$(filter %.lds,$^) $(filter %.o,$^) -z noexecstack ; $(cmd_vdso_check)
cmd_vdso32ld_and_check = $(VDSOCC) $(ldflags-y) $(CC32FLAGS) $(LD32FLAGS) -o $@ -Wl,-T$(filter %.lds,$^) $(filter %.o,$^); $(cmd_vdso_check)
quiet_cmd_vdso32as = VDSO32A $@
cmd_vdso32as = $(VDSOCC) $(a_flags) $(CC32FLAGS) $(AS32FLAGS) -c -o $@ $<
quiet_cmd_vdso32cc = VDSO32C $@
cmd_vdso32cc = $(VDSOCC) $(c_flags) $(CC32FLAGS) -c -o $@ $<
cmd_vdso32cc = $(VDSOCC) $(filter-out $(CC32FLAGSREMOVE), $(c_flags)) $(CC32FLAGS) -c -o $@ $<
quiet_cmd_vdso64ld_and_check = VDSO64L $@
cmd_vdso64ld_and_check = $(VDSOCC) $(c_flags) $(CC64FLAGS) -o $@ -Wl,-T$(filter %.lds,$^) $(filter %.o,$^) -z noexecstack ; $(cmd_vdso_check)
cmd_vdso64ld_and_check = $(VDSOCC) $(ldflags-y) $(LD64FLAGS) -o $@ -Wl,-T$(filter %.lds,$^) $(filter %.o,$^); $(cmd_vdso_check)
quiet_cmd_vdso64as = VDSO64A $@
cmd_vdso64as = $(VDSOCC) $(a_flags) $(CC64FLAGS) $(AS64FLAGS) -c -o $@ $<
cmd_vdso64as = $(VDSOCC) $(a_flags) $(AS64FLAGS) -c -o $@ $<
OBJECT_FILES_NON_STANDARD := y

View File

@@ -1896,7 +1896,9 @@ static void cpumsf_pmu_stop(struct perf_event *event, int flags)
event->hw.state |= PERF_HES_STOPPED;
if ((flags & PERF_EF_UPDATE) && !(event->hw.state & PERF_HES_UPTODATE)) {
hw_perf_event_update(event, 1);
/* CPU hotplug off removes SDBs. No samples to extract. */
if (cpuhw->flags & PMU_F_RESERVED)
hw_perf_event_update(event, 1);
event->hw.state |= PERF_HES_UPTODATE;
}
perf_pmu_enable(event->pmu);

View File

@@ -881,11 +881,12 @@ static int amd_pmu_handle_irq(struct pt_regs *regs)
static int amd_pmu_v2_handle_irq(struct pt_regs *regs)
{
struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events);
static atomic64_t status_warned = ATOMIC64_INIT(0);
u64 reserved, status, mask, new_bits, prev_bits;
struct perf_sample_data data;
struct hw_perf_event *hwc;
struct perf_event *event;
int handled = 0, idx;
u64 reserved, status, mask;
bool pmu_enabled;
/*
@@ -952,7 +953,12 @@ static int amd_pmu_v2_handle_irq(struct pt_regs *regs)
* the corresponding PMCs are expected to be inactive according to the
* active_mask
*/
WARN_ON(status > 0);
if (status > 0) {
prev_bits = atomic64_fetch_or(status, &status_warned);
// A new bit was set for the very first time.
new_bits = status & ~prev_bits;
WARN(new_bits, "New overflows for inactive PMCs: %llx\n", new_bits);
}
/* Clear overflow and freeze bits */
amd_pmu_ack_global_status(~status);

View File

@@ -137,7 +137,7 @@ static void __fwnode_link_del(struct fwnode_link *link)
*/
static void __fwnode_link_cycle(struct fwnode_link *link)
{
pr_debug("%pfwf: Relaxing link with %pfwf\n",
pr_debug("%pfwf: cycle: depends on %pfwf\n",
link->consumer, link->supplier);
link->flags |= FWLINK_FLAG_CYCLE;
}
@@ -1082,7 +1082,8 @@ static struct fwnode_handle *fwnode_links_check_suppliers(
return NULL;
list_for_each_entry(link, &fwnode->suppliers, c_hook)
if (!(link->flags & FWLINK_FLAG_CYCLE))
if (!(link->flags &
(FWLINK_FLAG_CYCLE | FWLINK_FLAG_IGNORE)))
return link->supplier;
return NULL;
@@ -1932,10 +1933,10 @@ static bool fwnode_ancestor_init_without_drv(struct fwnode_handle *fwnode)
*
* Return true if one or more cycles were found. Otherwise, return false.
*/
static bool __fw_devlink_relax_cycles(struct device *con,
static bool __fw_devlink_relax_cycles(struct fwnode_handle *con_handle,
struct fwnode_handle *sup_handle)
{
struct device *sup_dev = NULL, *par_dev = NULL;
struct device *sup_dev = NULL, *par_dev = NULL, *con_dev = NULL;
struct fwnode_link *link;
struct device_link *dev_link;
bool ret = false;
@@ -1952,27 +1953,31 @@ static bool __fw_devlink_relax_cycles(struct device *con,
sup_handle->flags |= FWNODE_FLAG_VISITED;
sup_dev = get_dev_from_fwnode(sup_handle);
/* Termination condition. */
if (sup_dev == con) {
if (sup_handle == con_handle) {
pr_debug("----- cycle: start -----\n");
ret = true;
goto out;
}
sup_dev = get_dev_from_fwnode(sup_handle);
con_dev = get_dev_from_fwnode(con_handle);
/*
* If sup_dev is bound to a driver and @con hasn't started binding to a
* driver, sup_dev can't be a consumer of @con. So, no need to check
* further.
*/
if (sup_dev && sup_dev->links.status == DL_DEV_DRIVER_BOUND &&
con->links.status == DL_DEV_NO_DRIVER) {
con_dev && con_dev->links.status == DL_DEV_NO_DRIVER) {
ret = false;
goto out;
}
list_for_each_entry(link, &sup_handle->suppliers, c_hook) {
if (__fw_devlink_relax_cycles(con, link->supplier)) {
if (link->flags & FWLINK_FLAG_IGNORE)
continue;
if (__fw_devlink_relax_cycles(con_handle, link->supplier)) {
__fwnode_link_cycle(link);
ret = true;
}
@@ -1987,8 +1992,11 @@ static bool __fw_devlink_relax_cycles(struct device *con,
else
par_dev = fwnode_get_next_parent_dev(sup_handle);
if (par_dev && __fw_devlink_relax_cycles(con, par_dev->fwnode))
if (par_dev && __fw_devlink_relax_cycles(con_handle, par_dev->fwnode)) {
pr_debug("%pfwf: cycle: child of %pfwf\n", sup_handle,
par_dev->fwnode);
ret = true;
}
if (!sup_dev)
goto out;
@@ -2002,8 +2010,10 @@ static bool __fw_devlink_relax_cycles(struct device *con,
!(dev_link->flags & DL_FLAG_CYCLE))
continue;
if (__fw_devlink_relax_cycles(con,
if (__fw_devlink_relax_cycles(con_handle,
dev_link->supplier->fwnode)) {
pr_debug("%pfwf: cycle: depends on %pfwf\n", sup_handle,
dev_link->supplier->fwnode);
fw_devlink_relax_link(dev_link);
dev_link->flags |= DL_FLAG_CYCLE;
ret = true;
@@ -2045,10 +2055,8 @@ static int fw_devlink_create_devlink(struct device *con,
int ret = 0;
u32 flags;
if (con->fwnode == link->consumer)
flags = fw_devlink_get_flags(link->flags);
else
flags = FW_DEVLINK_FLAGS_PERMISSIVE;
if (link->flags & FWLINK_FLAG_IGNORE)
return 0;
/*
* In some cases, a device P might also be a supplier to its child node
@@ -2070,24 +2078,23 @@ static int fw_devlink_create_devlink(struct device *con,
return -EINVAL;
/*
* SYNC_STATE_ONLY device links don't block probing and supports cycles.
* So, one might expect that cycle detection isn't necessary for them.
* However, if the device link was marked as SYNC_STATE_ONLY because
* it's part of a cycle, then we still need to do cycle detection. This
* is because the consumer and supplier might be part of multiple cycles
* and we need to detect all those cycles.
* Don't try to optimize by not calling the cycle detection logic under
* certain conditions. There's always some corner case that won't get
* detected.
*/
if (!device_link_flag_is_sync_state_only(flags) ||
flags & DL_FLAG_CYCLE) {
device_links_write_lock();
if (__fw_devlink_relax_cycles(con, sup_handle)) {
__fwnode_link_cycle(link);
flags = fw_devlink_get_flags(link->flags);
dev_info(con, "Fixed dependency cycle(s) with %pfwf\n",
sup_handle);
}
device_links_write_unlock();
device_links_write_lock();
if (__fw_devlink_relax_cycles(link->consumer, sup_handle)) {
__fwnode_link_cycle(link);
pr_debug("----- cycle: end -----\n");
pr_info("%pfwf: Fixed dependency cycle(s) with %pfwf\n",
link->consumer, sup_handle);
}
device_links_write_unlock();
if (con->fwnode == link->consumer)
flags = fw_devlink_get_flags(link->flags);
else
flags = FW_DEVLINK_FLAGS_PERMISSIVE;
if (sup_handle->flags & FWNODE_FLAG_NOT_DEVICE)
sup_dev = fwnode_get_next_parent_dev(sup_handle);

View File

@@ -783,7 +783,7 @@ EXPORT_SYMBOL_GPL(fwnode_get_next_available_child_node);
* fwnode pointer. Note that this function also puts a reference to @child
* unconditionally.
*/
struct fwnode_handle *device_get_next_child_node(struct device *dev,
struct fwnode_handle *device_get_next_child_node(const struct device *dev,
struct fwnode_handle *child)
{
const struct fwnode_handle *fwnode = dev_fwnode(dev);
@@ -826,7 +826,7 @@ EXPORT_SYMBOL_GPL(fwnode_get_named_child_node);
* The caller is responsible for calling fwnode_handle_put() on the returned
* fwnode pointer.
*/
struct fwnode_handle *device_get_named_child_node(struct device *dev,
struct fwnode_handle *device_get_named_child_node(const struct device *dev,
const char *childname)
{
return fwnode_get_named_child_node(dev_fwnode(dev), childname);
@@ -892,7 +892,7 @@ EXPORT_SYMBOL_GPL(fwnode_device_is_available);
*
* Return: the number of child nodes for a given device.
*/
unsigned int device_get_child_node_count(struct device *dev)
unsigned int device_get_child_node_count(const struct device *dev)
{
struct fwnode_handle *child;
unsigned int count = 0;

View File

@@ -652,6 +652,17 @@ int regmap_attach_dev(struct device *dev, struct regmap *map,
}
EXPORT_SYMBOL_GPL(regmap_attach_dev);
static int dev_get_regmap_match(struct device *dev, void *res, void *data);
static int regmap_detach_dev(struct device *dev, struct regmap *map)
{
if (!dev)
return 0;
return devres_release(dev, dev_get_regmap_release,
dev_get_regmap_match, (void *)map->name);
}
static enum regmap_endian regmap_get_reg_endian(const struct regmap_bus *bus,
const struct regmap_config *config)
{
@@ -1502,6 +1513,7 @@ int regmap_reinit_cache(struct regmap *map, const struct regmap_config *config)
{
int ret;
regmap_detach_dev(map->dev, map);
regcache_exit(map);
regmap_debugfs_exit(map);

View File

@@ -103,10 +103,36 @@ static bool dma_fence_array_enable_signaling(struct dma_fence *fence)
static bool dma_fence_array_signaled(struct dma_fence *fence)
{
struct dma_fence_array *array = to_dma_fence_array(fence);
int num_pending;
unsigned int i;
if (atomic_read(&array->num_pending) > 0)
/*
* We need to read num_pending before checking the enable_signal bit
* to avoid racing with the enable_signaling() implementation, which
* might decrement the counter, and cause a partial check.
* atomic_read_acquire() pairs with atomic_dec_and_test() in
* dma_fence_array_enable_signaling()
*
* The !--num_pending check is here to account for the any_signaled case
* if we race with enable_signaling(), that means the !num_pending check
* in the is_signalling_enabled branch might be outdated (num_pending
* might have been decremented), but that's fine. The user will get the
* right value when testing again later.
*/
num_pending = atomic_read_acquire(&array->num_pending);
if (test_bit(DMA_FENCE_FLAG_ENABLE_SIGNAL_BIT, &array->base.flags)) {
if (num_pending <= 0)
goto signal;
return false;
}
for (i = 0; i < array->num_fences; ++i) {
if (dma_fence_is_signaled(array->fences[i]) && !--num_pending)
goto signal;
}
return false;
signal:
dma_fence_array_clear_pending_error(array);
return true;
}

View File

@@ -12,6 +12,7 @@
#include <linux/dma-fence-chain.h>
#include <linux/dma-fence-unwrap.h>
#include <linux/slab.h>
#include <linux/sort.h>
/* Internal helper to start new array iteration, don't use directly */
static struct dma_fence *
@@ -59,6 +60,25 @@ struct dma_fence *dma_fence_unwrap_next(struct dma_fence_unwrap *cursor)
}
EXPORT_SYMBOL_GPL(dma_fence_unwrap_next);
static int fence_cmp(const void *_a, const void *_b)
{
struct dma_fence *a = *(struct dma_fence **)_a;
struct dma_fence *b = *(struct dma_fence **)_b;
if (a->context < b->context)
return -1;
else if (a->context > b->context)
return 1;
if (dma_fence_is_later(b, a))
return 1;
else if (dma_fence_is_later(a, b))
return -1;
return 0;
}
/* Implementation for the dma_fence_merge() marco, don't use directly */
struct dma_fence *__dma_fence_unwrap_merge(unsigned int num_fences,
struct dma_fence **fences,
@@ -67,8 +87,7 @@ struct dma_fence *__dma_fence_unwrap_merge(unsigned int num_fences,
struct dma_fence_array *result;
struct dma_fence *tmp, **array;
ktime_t timestamp;
unsigned int i;
size_t count;
int i, j, count;
count = 0;
timestamp = ns_to_ktime(0);
@@ -96,78 +115,55 @@ struct dma_fence *__dma_fence_unwrap_merge(unsigned int num_fences,
if (!array)
return NULL;
/*
* This trashes the input fence array and uses it as position for the
* following merge loop. This works because the dma_fence_merge()
* wrapper macro is creating this temporary array on the stack together
* with the iterators.
*/
for (i = 0; i < num_fences; ++i)
fences[i] = dma_fence_unwrap_first(fences[i], &iter[i]);
count = 0;
do {
unsigned int sel;
restart:
tmp = NULL;
for (i = 0; i < num_fences; ++i) {
struct dma_fence *next;
while (fences[i] && dma_fence_is_signaled(fences[i]))
fences[i] = dma_fence_unwrap_next(&iter[i]);
next = fences[i];
if (!next)
continue;
/*
* We can't guarantee that inpute fences are ordered by
* context, but it is still quite likely when this
* function is used multiple times. So attempt to order
* the fences by context as we pass over them and merge
* fences with the same context.
*/
if (!tmp || tmp->context > next->context) {
tmp = next;
sel = i;
} else if (tmp->context < next->context) {
continue;
} else if (dma_fence_is_later(tmp, next)) {
fences[i] = dma_fence_unwrap_next(&iter[i]);
goto restart;
for (i = 0; i < num_fences; ++i) {
dma_fence_unwrap_for_each(tmp, &iter[i], fences[i]) {
if (!dma_fence_is_signaled(tmp)) {
array[count++] = dma_fence_get(tmp);
} else {
fences[sel] = dma_fence_unwrap_next(&iter[sel]);
goto restart;
ktime_t t = dma_fence_timestamp(tmp);
if (ktime_after(t, timestamp))
timestamp = t;
}
}
}
if (tmp) {
array[count++] = dma_fence_get(tmp);
fences[sel] = dma_fence_unwrap_next(&iter[sel]);
if (count == 0 || count == 1)
goto return_fastpath;
sort(array, count, sizeof(*array), fence_cmp, NULL);
/*
* Only keep the most recent fence for each context.
*/
j = 0;
for (i = 1; i < count; i++) {
if (array[i]->context == array[j]->context)
dma_fence_put(array[i]);
else
array[++j] = array[i];
}
count = ++j;
if (count > 1) {
result = dma_fence_array_create(count, array,
dma_fence_context_alloc(1),
1, false);
if (!result) {
for (i = 0; i < count; i++)
dma_fence_put(array[i]);
tmp = NULL;
goto return_tmp;
}
} while (tmp);
if (count == 0) {
tmp = dma_fence_allocate_private_stub(ktime_get());
goto return_tmp;
return &result->base;
}
if (count == 1) {
return_fastpath:
if (count == 0)
tmp = dma_fence_allocate_private_stub(timestamp);
else
tmp = array[0];
goto return_tmp;
}
result = dma_fence_array_create(count, array,
dma_fence_context_alloc(1),
1, false);
if (!result) {
tmp = NULL;
goto return_tmp;
}
return &result->base;
return_tmp:
kfree(array);

View File

@@ -31,13 +31,15 @@
static void hdp_v5_2_flush_hdp(struct amdgpu_device *adev,
struct amdgpu_ring *ring)
{
if (!ring || !ring->funcs->emit_wreg)
if (!ring || !ring->funcs->emit_wreg) {
WREG32_NO_KIQ((adev->rmmio_remap.reg_offset + KFD_MMIO_REMAP_HDP_MEM_FLUSH_CNTL) >> 2,
0);
else
RREG32_NO_KIQ((adev->rmmio_remap.reg_offset + KFD_MMIO_REMAP_HDP_MEM_FLUSH_CNTL) >> 2);
} else {
amdgpu_ring_emit_wreg(ring,
(adev->rmmio_remap.reg_offset + KFD_MMIO_REMAP_HDP_MEM_FLUSH_CNTL) >> 2,
0);
}
}
static void hdp_v5_2_update_mem_power_gating(struct amdgpu_device *adev,

View File

@@ -2560,10 +2560,10 @@ static int it6505_poweron(struct it6505 *it6505)
/* time interval between OVDD and SYSRSTN at least be 10ms */
if (pdata->gpiod_reset) {
usleep_range(10000, 20000);
gpiod_set_value_cansleep(pdata->gpiod_reset, 0);
usleep_range(1000, 2000);
gpiod_set_value_cansleep(pdata->gpiod_reset, 1);
usleep_range(10000, 20000);
usleep_range(1000, 2000);
gpiod_set_value_cansleep(pdata->gpiod_reset, 0);
usleep_range(25000, 35000);
}
it6505->powered = true;
@@ -2589,7 +2589,7 @@ static int it6505_poweroff(struct it6505 *it6505)
}
if (pdata->gpiod_reset)
gpiod_set_value_cansleep(pdata->gpiod_reset, 0);
gpiod_set_value_cansleep(pdata->gpiod_reset, 1);
if (pdata->pwr18) {
err = regulator_disable(pdata->pwr18);
@@ -3050,7 +3050,7 @@ static int it6505_init_pdata(struct it6505 *it6505)
return PTR_ERR(pdata->ovdd);
}
pdata->gpiod_reset = devm_gpiod_get(dev, "reset", GPIOD_OUT_LOW);
pdata->gpiod_reset = devm_gpiod_get(dev, "reset", GPIOD_OUT_HIGH);
if (IS_ERR(pdata->gpiod_reset)) {
dev_err(dev, "gpiod_reset gpio not found");
return PTR_ERR(pdata->gpiod_reset);

View File

@@ -319,6 +319,9 @@ static bool drm_dp_decode_sideband_msg_hdr(const struct drm_dp_mst_topology_mgr
hdr->broadcast = (buf[idx] >> 7) & 0x1;
hdr->path_msg = (buf[idx] >> 6) & 0x1;
hdr->msg_len = buf[idx] & 0x3f;
if (hdr->msg_len < 1) /* min space for body CRC */
return false;
idx++;
hdr->somt = (buf[idx] >> 7) & 0x1;
hdr->eomt = (buf[idx] >> 6) & 0x1;
@@ -3652,8 +3655,7 @@ int drm_dp_mst_topology_mgr_set_mst(struct drm_dp_mst_topology_mgr *mgr, bool ms
ret = 0;
mgr->payload_id_table_cleared = false;
memset(&mgr->down_rep_recv, 0, sizeof(mgr->down_rep_recv));
memset(&mgr->up_req_recv, 0, sizeof(mgr->up_req_recv));
mgr->reset_rx_state = true;
}
out_unlock:
@@ -3781,6 +3783,11 @@ out_fail:
}
EXPORT_SYMBOL(drm_dp_mst_topology_mgr_resume);
static void reset_msg_rx_state(struct drm_dp_sideband_msg_rx *msg)
{
memset(msg, 0, sizeof(*msg));
}
static bool
drm_dp_get_one_sb_msg(struct drm_dp_mst_topology_mgr *mgr, bool up,
struct drm_dp_mst_branch **mstb)
@@ -3859,6 +3866,34 @@ drm_dp_get_one_sb_msg(struct drm_dp_mst_topology_mgr *mgr, bool up,
return true;
}
static int get_msg_request_type(u8 data)
{
return data & 0x7f;
}
static bool verify_rx_request_type(struct drm_dp_mst_topology_mgr *mgr,
const struct drm_dp_sideband_msg_tx *txmsg,
const struct drm_dp_sideband_msg_rx *rxmsg)
{
const struct drm_dp_sideband_msg_hdr *hdr = &rxmsg->initial_hdr;
const struct drm_dp_mst_branch *mstb = txmsg->dst;
int tx_req_type = get_msg_request_type(txmsg->msg[0]);
int rx_req_type = get_msg_request_type(rxmsg->msg[0]);
char rad_str[64];
if (tx_req_type == rx_req_type)
return true;
drm_dp_mst_rad_to_str(mstb->rad, mstb->lct, rad_str, sizeof(rad_str));
drm_dbg_kms(mgr->dev,
"Got unexpected MST reply, mstb: %p seqno: %d lct: %d rad: %s rx_req_type: %s (%02x) != tx_req_type: %s (%02x)\n",
mstb, hdr->seqno, mstb->lct, rad_str,
drm_dp_mst_req_type_str(rx_req_type), rx_req_type,
drm_dp_mst_req_type_str(tx_req_type), tx_req_type);
return false;
}
static int drm_dp_mst_handle_down_rep(struct drm_dp_mst_topology_mgr *mgr)
{
struct drm_dp_sideband_msg_tx *txmsg;
@@ -3888,6 +3923,9 @@ static int drm_dp_mst_handle_down_rep(struct drm_dp_mst_topology_mgr *mgr)
goto out_clear_reply;
}
if (!verify_rx_request_type(mgr, txmsg, msg))
goto out_clear_reply;
drm_dp_sideband_parse_reply(mgr, msg, &txmsg->reply);
if (txmsg->reply.reply_type == DP_SIDEBAND_REPLY_NAK) {
@@ -4063,6 +4101,17 @@ out:
return 0;
}
static void update_msg_rx_state(struct drm_dp_mst_topology_mgr *mgr)
{
mutex_lock(&mgr->lock);
if (mgr->reset_rx_state) {
mgr->reset_rx_state = false;
reset_msg_rx_state(&mgr->down_rep_recv);
reset_msg_rx_state(&mgr->up_req_recv);
}
mutex_unlock(&mgr->lock);
}
/**
* drm_dp_mst_hpd_irq_handle_event() - MST hotplug IRQ handle MST event
* @mgr: manager to notify irq for.
@@ -4097,6 +4146,8 @@ int drm_dp_mst_hpd_irq_handle_event(struct drm_dp_mst_topology_mgr *mgr, const u
*handled = true;
}
update_msg_rx_state(mgr);
if (esi[1] & DP_DOWN_REP_MSG_RDY) {
ret = drm_dp_mst_handle_down_rep(mgr);
*handled = true;

View File

@@ -137,7 +137,7 @@ static void mixer_dbg_crb(struct seq_file *s, int val)
}
}
static void mixer_dbg_mxn(struct seq_file *s, void *addr)
static void mixer_dbg_mxn(struct seq_file *s, void __iomem *addr)
{
int i;

View File

@@ -49,9 +49,9 @@ void v3d_perfmon_start(struct v3d_dev *v3d, struct v3d_perfmon *perfmon)
V3D_CORE_WRITE(0, V3D_V4_PCTR_0_SRC_X(source), channel);
}
V3D_CORE_WRITE(0, V3D_V4_PCTR_0_EN, mask);
V3D_CORE_WRITE(0, V3D_V4_PCTR_0_CLR, mask);
V3D_CORE_WRITE(0, V3D_PCTR_0_OVERFLOW, mask);
V3D_CORE_WRITE(0, V3D_V4_PCTR_0_EN, mask);
v3d->active_perfmon = perfmon;
}

View File

@@ -2234,7 +2234,8 @@ static void wacom_update_name(struct wacom *wacom, const char *suffix)
if (hid_is_usb(wacom->hdev)) {
struct usb_interface *intf = to_usb_interface(wacom->hdev->dev.parent);
struct usb_device *dev = interface_to_usbdev(intf);
product_name = dev->product;
if (dev->product != NULL)
product_name = dev->product;
}
if (wacom->hdev->bus == BUS_I2C) {

View File

@@ -341,10 +341,10 @@ struct bus_type i3c_bus_type = {
};
static enum i3c_addr_slot_status
i3c_bus_get_addr_slot_status(struct i3c_bus *bus, u16 addr)
i3c_bus_get_addr_slot_status_mask(struct i3c_bus *bus, u16 addr, u32 mask)
{
unsigned long status;
int bitpos = addr * 2;
int bitpos = addr * I3C_ADDR_SLOT_STATUS_BITS;
if (addr > I2C_MAX_ADDR)
return I3C_ADDR_SLOT_RSVD;
@@ -352,22 +352,33 @@ i3c_bus_get_addr_slot_status(struct i3c_bus *bus, u16 addr)
status = bus->addrslots[bitpos / BITS_PER_LONG];
status >>= bitpos % BITS_PER_LONG;
return status & I3C_ADDR_SLOT_STATUS_MASK;
return status & mask;
}
static void i3c_bus_set_addr_slot_status(struct i3c_bus *bus, u16 addr,
enum i3c_addr_slot_status status)
static enum i3c_addr_slot_status
i3c_bus_get_addr_slot_status(struct i3c_bus *bus, u16 addr)
{
int bitpos = addr * 2;
return i3c_bus_get_addr_slot_status_mask(bus, addr, I3C_ADDR_SLOT_STATUS_MASK);
}
static void i3c_bus_set_addr_slot_status_mask(struct i3c_bus *bus, u16 addr,
enum i3c_addr_slot_status status, u32 mask)
{
int bitpos = addr * I3C_ADDR_SLOT_STATUS_BITS;
unsigned long *ptr;
if (addr > I2C_MAX_ADDR)
return;
ptr = bus->addrslots + (bitpos / BITS_PER_LONG);
*ptr &= ~((unsigned long)I3C_ADDR_SLOT_STATUS_MASK <<
(bitpos % BITS_PER_LONG));
*ptr |= (unsigned long)status << (bitpos % BITS_PER_LONG);
*ptr &= ~((unsigned long)mask << (bitpos % BITS_PER_LONG));
*ptr |= ((unsigned long)status & mask) << (bitpos % BITS_PER_LONG);
}
static void i3c_bus_set_addr_slot_status(struct i3c_bus *bus, u16 addr,
enum i3c_addr_slot_status status)
{
i3c_bus_set_addr_slot_status_mask(bus, addr, status, I3C_ADDR_SLOT_STATUS_MASK);
}
static bool i3c_bus_dev_addr_is_avail(struct i3c_bus *bus, u8 addr)
@@ -379,13 +390,44 @@ static bool i3c_bus_dev_addr_is_avail(struct i3c_bus *bus, u8 addr)
return status == I3C_ADDR_SLOT_FREE;
}
/*
*
* S/Sr 7'h7E RnW=0 ACK ENTDAA T
*
*
*
* Sr7'h7E RnW=1 ACK48bit UID BCR DCRAssign 7bit AddrPAR ACK/NACK
*
* Some master controllers (such as HCI) need to prepare the entire above transaction before
* sending it out to the I3C bus. This means that a 7-bit dynamic address needs to be allocated
* before knowing the target device's UID information.
*
* However, some I3C targets may request specific addresses (called as "init_dyn_addr"), which is
* typically specified by the DT-'s assigned-address property. Lower addresses having higher IBI
* priority. If it is available, i3c_bus_get_free_addr() preferably return a free address that is
* not in the list of desired addresses (called as "init_dyn_addr"). This allows the device with
* the "init_dyn_addr" to switch to its "init_dyn_addr" when it hot-joins the I3C bus. Otherwise,
* if the "init_dyn_addr" is already in use by another I3C device, the target device will not be
* able to switch to its desired address.
*
* If the previous step fails, fallback returning one of the remaining unassigned address,
* regardless of its state in the desired list.
*/
static int i3c_bus_get_free_addr(struct i3c_bus *bus, u8 start_addr)
{
enum i3c_addr_slot_status status;
u8 addr;
for (addr = start_addr; addr < I3C_MAX_ADDR; addr++) {
status = i3c_bus_get_addr_slot_status(bus, addr);
status = i3c_bus_get_addr_slot_status_mask(bus, addr,
I3C_ADDR_SLOT_EXT_STATUS_MASK);
if (status == I3C_ADDR_SLOT_FREE)
return addr;
}
for (addr = start_addr; addr < I3C_MAX_ADDR; addr++) {
status = i3c_bus_get_addr_slot_status_mask(bus, addr,
I3C_ADDR_SLOT_STATUS_MASK);
if (status == I3C_ADDR_SLOT_FREE)
return addr;
}
@@ -514,6 +556,88 @@ static ssize_t i2c_scl_frequency_show(struct device *dev,
}
static DEVICE_ATTR_RO(i2c_scl_frequency);
static int i3c_set_hotjoin(struct i3c_master_controller *master, bool enable)
{
int ret;
if (!master || !master->ops)
return -EINVAL;
if (!master->ops->enable_hotjoin || !master->ops->disable_hotjoin)
return -EINVAL;
i3c_bus_normaluse_lock(&master->bus);
if (enable)
ret = master->ops->enable_hotjoin(master);
else
ret = master->ops->disable_hotjoin(master);
master->hotjoin = enable;
i3c_bus_normaluse_unlock(&master->bus);
return ret;
}
static ssize_t hotjoin_store(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
{
struct i3c_bus *i3cbus = dev_to_i3cbus(dev);
int ret;
bool res;
if (!i3cbus->cur_master)
return -EINVAL;
if (kstrtobool(buf, &res))
return -EINVAL;
ret = i3c_set_hotjoin(i3cbus->cur_master->common.master, res);
if (ret)
return ret;
return count;
}
/*
* i3c_master_enable_hotjoin - Enable hotjoin
* @master: I3C master object
*
* Return: a 0 in case of success, an negative error code otherwise.
*/
int i3c_master_enable_hotjoin(struct i3c_master_controller *master)
{
return i3c_set_hotjoin(master, true);
}
EXPORT_SYMBOL_GPL(i3c_master_enable_hotjoin);
/*
* i3c_master_disable_hotjoin - Disable hotjoin
* @master: I3C master object
*
* Return: a 0 in case of success, an negative error code otherwise.
*/
int i3c_master_disable_hotjoin(struct i3c_master_controller *master)
{
return i3c_set_hotjoin(master, false);
}
EXPORT_SYMBOL_GPL(i3c_master_disable_hotjoin);
static ssize_t hotjoin_show(struct device *dev, struct device_attribute *da, char *buf)
{
struct i3c_bus *i3cbus = dev_to_i3cbus(dev);
ssize_t ret;
i3c_bus_normaluse_lock(i3cbus);
ret = sysfs_emit(buf, "%d\n", i3cbus->cur_master->common.master->hotjoin);
i3c_bus_normaluse_unlock(i3cbus);
return ret;
}
static DEVICE_ATTR_RW(hotjoin);
static struct attribute *i3c_masterdev_attrs[] = {
&dev_attr_mode.attr,
&dev_attr_current_master.attr,
@@ -524,6 +648,7 @@ static struct attribute *i3c_masterdev_attrs[] = {
&dev_attr_pid.attr,
&dev_attr_dynamic_address.attr,
&dev_attr_hdrcap.attr,
&dev_attr_hotjoin.attr,
NULL,
};
ATTRIBUTE_GROUPS(i3c_masterdev);
@@ -1366,16 +1491,9 @@ static int i3c_master_reattach_i3c_dev(struct i3c_dev_desc *dev,
u8 old_dyn_addr)
{
struct i3c_master_controller *master = i3c_dev_get_master(dev);
enum i3c_addr_slot_status status;
int ret;
if (dev->info.dyn_addr != old_dyn_addr &&
(!dev->boardinfo ||
dev->info.dyn_addr != dev->boardinfo->init_dyn_addr)) {
status = i3c_bus_get_addr_slot_status(&master->bus,
dev->info.dyn_addr);
if (status != I3C_ADDR_SLOT_FREE)
return -EBUSY;
if (dev->info.dyn_addr != old_dyn_addr) {
i3c_bus_set_addr_slot_status(&master->bus,
dev->info.dyn_addr,
I3C_ADDR_SLOT_I3C_DEV);
@@ -1727,6 +1845,12 @@ static int i3c_master_bus_init(struct i3c_master_controller *master)
goto err_bus_cleanup;
}
if (master->ops->set_speed) {
ret = master->ops->set_speed(master, I3C_OPEN_DRAIN_SLOW_SPEED);
if (ret)
goto err_bus_cleanup;
}
/*
* Reset all dynamic address that may have been assigned before
* (assigned by the bootloader for example).
@@ -1735,6 +1859,12 @@ static int i3c_master_bus_init(struct i3c_master_controller *master)
if (ret && ret != I3C_ERROR_M2)
goto err_bus_cleanup;
if (master->ops->set_speed) {
master->ops->set_speed(master, I3C_OPEN_DRAIN_NORMAL_SPEED);
if (ret)
goto err_bus_cleanup;
}
/* Disable all slave events before starting DAA. */
ret = i3c_master_disec_locked(master, I3C_BROADCAST_ADDR,
I3C_CCC_EVENT_SIR | I3C_CCC_EVENT_MR |
@@ -1765,9 +1895,11 @@ static int i3c_master_bus_init(struct i3c_master_controller *master)
goto err_rstdaa;
}
i3c_bus_set_addr_slot_status(&master->bus,
i3cboardinfo->init_dyn_addr,
I3C_ADDR_SLOT_I3C_DEV);
/* Do not mark as occupied until real device exist in bus */
i3c_bus_set_addr_slot_status_mask(&master->bus,
i3cboardinfo->init_dyn_addr,
I3C_ADDR_SLOT_EXT_DESIRED,
I3C_ADDR_SLOT_EXT_STATUS_MASK);
/*
* Only try to create/attach devices that have a static
@@ -1930,7 +2062,8 @@ int i3c_master_add_i3c_dev_locked(struct i3c_master_controller *master,
else
expected_dyn_addr = newdev->info.dyn_addr;
if (newdev->info.dyn_addr != expected_dyn_addr) {
if (newdev->info.dyn_addr != expected_dyn_addr &&
i3c_bus_get_addr_slot_status(&master->bus, expected_dyn_addr) == I3C_ADDR_SLOT_FREE) {
/*
* Try to apply the expected dynamic address. If it fails, keep
* the address assigned by the master.
@@ -2696,17 +2829,13 @@ EXPORT_SYMBOL_GPL(i3c_master_register);
* @master: master used to send frames on the bus
*
* Basically undo everything done in i3c_master_register().
*
* Return: 0 in case of success, a negative error code otherwise.
*/
int i3c_master_unregister(struct i3c_master_controller *master)
void i3c_master_unregister(struct i3c_master_controller *master)
{
i3c_master_i2c_adapter_cleanup(master);
i3c_master_unregister_i3c_devs(master);
i3c_master_bus_cleanup(master);
device_unregister(&master->dev);
return 0;
}
EXPORT_SYMBOL_GPL(i3c_master_unregister);

View File

@@ -1184,11 +1184,8 @@ err_disable_core_clk:
static int dw_i3c_remove(struct platform_device *pdev)
{
struct dw_i3c_master *master = platform_get_drvdata(pdev);
int ret;
ret = i3c_master_unregister(&master->base);
if (ret)
return ret;
i3c_master_unregister(&master->base);
reset_control_assert(master->core_rst);

View File

@@ -1666,11 +1666,8 @@ err_disable_pclk:
static int cdns_i3c_master_remove(struct platform_device *pdev)
{
struct cdns_i3c_master *master = platform_get_drvdata(pdev);
int ret;
ret = i3c_master_unregister(&master->base);
if (ret)
return ret;
i3c_master_unregister(&master->base);
clk_disable_unprepare(master->sysclk);
clk_disable_unprepare(master->pclk);

View File

@@ -769,7 +769,9 @@ static int i3c_hci_remove(struct platform_device *pdev)
{
struct i3c_hci *hci = platform_get_drvdata(pdev);
return i3c_master_unregister(&hci->master);
i3c_master_unregister(&hci->master);
return 0;
}
static const __maybe_unused struct of_device_id i3c_hci_of_match[] = {

View File

@@ -128,6 +128,9 @@
/* This parameter depends on the implementation and may be tuned */
#define SVC_I3C_FIFO_SIZE 16
#define SVC_I3C_EVENT_IBI GENMASK(7, 0)
#define SVC_I3C_EVENT_HOTJOIN BIT(31)
struct svc_i3c_cmd {
u8 addr;
bool rnw;
@@ -171,6 +174,8 @@ struct svc_i3c_xfer {
* @ibi.tbq_slot: To be queued IBI slot
* @ibi.lock: IBI lock
* @lock: Transfer lock, protect between IBI work thread and callbacks from master
* @enabled_events: Bit masks for enable events (IBI, HotJoin).
* @mctrl_config: Configuration value in SVC_I3C_MCTRL for setting speed back.
*/
struct svc_i3c_master {
struct i3c_master_controller base;
@@ -199,6 +204,8 @@ struct svc_i3c_master {
spinlock_t lock;
} ibi;
struct mutex lock;
u32 enabled_events;
u32 mctrl_config;
};
/**
@@ -213,6 +220,11 @@ struct svc_i3c_i2c_dev_data {
struct i3c_generic_ibi_pool *ibi_pool;
};
static inline bool is_events_enabled(struct svc_i3c_master *master, u32 mask)
{
return !!(master->enabled_events & mask);
}
static bool svc_i3c_master_error(struct svc_i3c_master *master)
{
u32 mstatus, merrwarn;
@@ -432,13 +444,16 @@ static void svc_i3c_master_ibi_work(struct work_struct *work)
switch (ibitype) {
case SVC_I3C_MSTATUS_IBITYPE_IBI:
dev = svc_i3c_master_dev_from_addr(master, ibiaddr);
if (!dev)
if (!dev || !is_events_enabled(master, SVC_I3C_EVENT_IBI))
svc_i3c_master_nack_ibi(master);
else
svc_i3c_master_handle_ibi(master, dev);
break;
case SVC_I3C_MSTATUS_IBITYPE_HOT_JOIN:
svc_i3c_master_ack_ibi(master, false);
if (is_events_enabled(master, SVC_I3C_EVENT_HOTJOIN))
svc_i3c_master_ack_ibi(master, false);
else
svc_i3c_master_nack_ibi(master);
break;
case SVC_I3C_MSTATUS_IBITYPE_MASTER_REQUEST:
svc_i3c_master_nack_ibi(master);
@@ -475,7 +490,9 @@ static void svc_i3c_master_ibi_work(struct work_struct *work)
svc_i3c_master_emit_stop(master);
break;
case SVC_I3C_MSTATUS_IBITYPE_HOT_JOIN:
queue_work(master->base.wq, &master->hj_work);
svc_i3c_master_emit_stop(master);
if (is_events_enabled(master, SVC_I3C_EVENT_HOTJOIN))
queue_work(master->base.wq, &master->hj_work);
break;
case SVC_I3C_MSTATUS_IBITYPE_MASTER_REQUEST:
default:
@@ -506,6 +523,54 @@ static irqreturn_t svc_i3c_master_irq_handler(int irq, void *dev_id)
return IRQ_HANDLED;
}
static int svc_i3c_master_set_speed(struct i3c_master_controller *m,
enum i3c_open_drain_speed speed)
{
struct svc_i3c_master *master = to_svc_i3c_master(m);
struct i3c_bus *bus = i3c_master_get_bus(&master->base);
u32 ppbaud, odbaud, odhpp, mconfig;
unsigned long fclk_rate;
int ret;
ret = pm_runtime_resume_and_get(master->dev);
if (ret < 0) {
dev_err(master->dev, "<%s> Cannot get runtime PM.\n", __func__);
return ret;
}
switch (speed) {
case I3C_OPEN_DRAIN_SLOW_SPEED:
fclk_rate = clk_get_rate(master->fclk);
if (!fclk_rate) {
ret = -EINVAL;
goto rpm_out;
}
/*
* Set 50% duty-cycle I2C speed to I3C OPEN-DRAIN mode, so the first
* broadcast address is visible to all I2C/I3C devices on the I3C bus.
* I3C device working as a I2C device will turn off its 50ns Spike
* Filter to change to I3C mode.
*/
mconfig = master->mctrl_config;
ppbaud = FIELD_GET(GENMASK(11, 8), mconfig);
odhpp = 0;
odbaud = DIV_ROUND_UP(fclk_rate, bus->scl_rate.i2c * (2 + 2 * ppbaud)) - 1;
mconfig &= ~GENMASK(24, 16);
mconfig |= SVC_I3C_MCONFIG_ODBAUD(odbaud) | SVC_I3C_MCONFIG_ODHPP(odhpp);
writel(mconfig, master->regs + SVC_I3C_MCONFIG);
break;
case I3C_OPEN_DRAIN_NORMAL_SPEED:
writel(master->mctrl_config, master->regs + SVC_I3C_MCONFIG);
break;
}
rpm_out:
pm_runtime_mark_last_busy(master->dev);
pm_runtime_put_autosuspend(master->dev);
return ret;
}
static int svc_i3c_master_bus_init(struct i3c_master_controller *m)
{
struct svc_i3c_master *master = to_svc_i3c_master(m);
@@ -588,6 +653,7 @@ static int svc_i3c_master_bus_init(struct i3c_master_controller *m)
SVC_I3C_MCONFIG_I2CBAUD(i2cbaud);
writel(reg, master->regs + SVC_I3C_MCONFIG);
master->mctrl_config = reg;
/* Master core's registration */
ret = i3c_master_get_free_addr(m, 0);
if (ret < 0)
@@ -1475,6 +1541,7 @@ static int svc_i3c_master_enable_ibi(struct i3c_dev_desc *dev)
return ret;
}
master->enabled_events++;
svc_i3c_master_enable_interrupts(master, SVC_I3C_MINT_SLVSTART);
return i3c_master_enec_locked(m, dev->info.dyn_addr, I3C_CCC_EVENT_SIR);
@@ -1486,7 +1553,9 @@ static int svc_i3c_master_disable_ibi(struct i3c_dev_desc *dev)
struct svc_i3c_master *master = to_svc_i3c_master(m);
int ret;
svc_i3c_master_disable_interrupts(master);
master->enabled_events--;
if (!master->enabled_events)
svc_i3c_master_disable_interrupts(master);
ret = i3c_master_disec_locked(m, dev->info.dyn_addr, I3C_CCC_EVENT_SIR);
@@ -1496,6 +1565,39 @@ static int svc_i3c_master_disable_ibi(struct i3c_dev_desc *dev)
return ret;
}
static int svc_i3c_master_enable_hotjoin(struct i3c_master_controller *m)
{
struct svc_i3c_master *master = to_svc_i3c_master(m);
int ret;
ret = pm_runtime_resume_and_get(master->dev);
if (ret < 0) {
dev_err(master->dev, "<%s> Cannot get runtime PM.\n", __func__);
return ret;
}
master->enabled_events |= SVC_I3C_EVENT_HOTJOIN;
svc_i3c_master_enable_interrupts(master, SVC_I3C_MINT_SLVSTART);
return 0;
}
static int svc_i3c_master_disable_hotjoin(struct i3c_master_controller *m)
{
struct svc_i3c_master *master = to_svc_i3c_master(m);
master->enabled_events &= ~SVC_I3C_EVENT_HOTJOIN;
if (!master->enabled_events)
svc_i3c_master_disable_interrupts(master);
pm_runtime_mark_last_busy(master->dev);
pm_runtime_put_autosuspend(master->dev);
return 0;
}
static void svc_i3c_master_recycle_ibi_slot(struct i3c_dev_desc *dev,
struct i3c_ibi_slot *slot)
{
@@ -1522,6 +1624,9 @@ static const struct i3c_master_controller_ops svc_i3c_master_ops = {
.recycle_ibi_slot = svc_i3c_master_recycle_ibi_slot,
.enable_ibi = svc_i3c_master_enable_ibi,
.disable_ibi = svc_i3c_master_disable_ibi,
.enable_hotjoin = svc_i3c_master_enable_hotjoin,
.disable_hotjoin = svc_i3c_master_disable_hotjoin,
.set_speed = svc_i3c_master_set_speed,
};
static int svc_i3c_master_prepare_clks(struct svc_i3c_master *master)
@@ -1651,11 +1756,8 @@ err_disable_clks:
static int svc_i3c_master_remove(struct platform_device *pdev)
{
struct svc_i3c_master *master = platform_get_drvdata(pdev);
int ret;
ret = i3c_master_unregister(&master->base);
if (ret)
return ret;
i3c_master_unregister(&master->base);
pm_runtime_dont_use_autosuspend(&pdev->dev);
pm_runtime_disable(&pdev->dev);

View File

@@ -372,6 +372,7 @@ static int yas537_measure(struct yas5xx *yas5xx, u16 *t, u16 *x, u16 *y1, u16 *y
u8 data[8];
u16 xy1y2[3];
s32 h[3], s[3];
int half_range = BIT(13);
int i, ret;
mutex_lock(&yas5xx->lock);
@@ -406,13 +407,13 @@ static int yas537_measure(struct yas5xx *yas5xx, u16 *t, u16 *x, u16 *y1, u16 *y
/* The second version of YAS537 needs to include calibration coefficients */
if (yas5xx->version == YAS537_VERSION_1) {
for (i = 0; i < 3; i++)
s[i] = xy1y2[i] - BIT(13);
h[0] = (c->k * (128 * s[0] + c->a2 * s[1] + c->a3 * s[2])) / BIT(13);
h[1] = (c->k * (c->a4 * s[0] + c->a5 * s[1] + c->a6 * s[2])) / BIT(13);
h[2] = (c->k * (c->a7 * s[0] + c->a8 * s[1] + c->a9 * s[2])) / BIT(13);
s[i] = xy1y2[i] - half_range;
h[0] = (c->k * (128 * s[0] + c->a2 * s[1] + c->a3 * s[2])) / half_range;
h[1] = (c->k * (c->a4 * s[0] + c->a5 * s[1] + c->a6 * s[2])) / half_range;
h[2] = (c->k * (c->a7 * s[0] + c->a8 * s[1] + c->a9 * s[2])) / half_range;
for (i = 0; i < 3; i++) {
clamp_val(h[i], -BIT(13), BIT(13) - 1);
xy1y2[i] = h[i] + BIT(13);
h[i] = clamp(h[i], -half_range, half_range - 1);
xy1y2[i] = h[i] + half_range;
}
}

View File

@@ -1363,6 +1363,17 @@ static struct iommu_device *arm_smmu_probe_device(struct device *dev)
goto out_free;
} else if (fwspec && fwspec->ops == &arm_smmu_ops) {
smmu = arm_smmu_get_by_fwnode(fwspec->iommu_fwnode);
/*
* Defer probe if the relevant SMMU instance hasn't finished
* probing yet. This is a fragile hack and we'd ideally
* avoid this race in the core code. Until that's ironed
* out, however, this is the most pragmatic option on the
* table.
*/
if (!smmu)
return ERR_PTR(dev_err_probe(dev, -EPROBE_DEFER,
"smmu dev has not bound yet\n"));
} else {
return ERR_PTR(-ENODEV);
}

View File

@@ -797,7 +797,6 @@ static void mt6360_v4l2_flash_release(struct mt6360_priv *priv)
static int mt6360_led_probe(struct platform_device *pdev)
{
struct mt6360_priv *priv;
struct fwnode_handle *child;
size_t count;
int i = 0, ret;
@@ -824,7 +823,7 @@ static int mt6360_led_probe(struct platform_device *pdev)
return -ENODEV;
}
device_for_each_child_node(&pdev->dev, child) {
device_for_each_child_node_scoped(&pdev->dev, child) {
struct mt6360_led *led = priv->leds + i;
struct led_init_data init_data = { .fwnode = child, };
u32 reg, led_color;

View File

@@ -1726,7 +1726,7 @@ static void cache_set_flush(struct closure *cl)
if (!IS_ERR_OR_NULL(c->gc_thread))
kthread_stop(c->gc_thread);
if (!IS_ERR(c->root))
if (!IS_ERR_OR_NULL(c->root))
list_add(&c->root->list, &c->btree_cache);
/*

View File

@@ -994,6 +994,8 @@ const unsigned int cx231xx_bcount = ARRAY_SIZE(cx231xx_boards);
/* table of devices that work with this driver */
struct usb_device_id cx231xx_id_table[] = {
{USB_DEVICE(0x1D19, 0x6108),
.driver_info = CX231XX_BOARD_PV_XCAPTURE_USB},
{USB_DEVICE(0x1D19, 0x6109),
.driver_info = CX231XX_BOARD_PV_XCAPTURE_USB},
{USB_DEVICE(0x0572, 0x5A3C),

View File

@@ -2441,6 +2441,8 @@ static const struct uvc_device_info uvc_quirk_force_y8 = {
* The Logitech cameras listed below have their interface class set to
* VENDOR_SPEC because they don't announce themselves as UVC devices, even
* though they are compliant.
*
* Sort these by vendor/product ID.
*/
static const struct usb_device_id uvc_ids[] = {
/* Quanta USB2.0 HD UVC Webcam */
@@ -2983,6 +2985,15 @@ static const struct usb_device_id uvc_ids[] = {
.bInterfaceProtocol = 0,
.driver_info = UVC_INFO_QUIRK(UVC_QUIRK_PROBE_MINMAX
| UVC_QUIRK_IGNORE_SELECTOR_UNIT) },
/* NXP Semiconductors IR VIDEO */
{ .match_flags = USB_DEVICE_ID_MATCH_DEVICE
| USB_DEVICE_ID_MATCH_INT_INFO,
.idVendor = 0x1fc9,
.idProduct = 0x009b,
.bInterfaceClass = USB_CLASS_VIDEO,
.bInterfaceSubClass = 1,
.bInterfaceProtocol = 0,
.driver_info = (kernel_ulong_t)&uvc_quirk_probe_minmax },
/* Oculus VR Positional Tracker DK2 */
{ .match_flags = USB_DEVICE_ID_MATCH_DEVICE
| USB_DEVICE_ID_MATCH_INT_INFO,

View File

@@ -149,6 +149,8 @@ static void mmc_bus_shutdown(struct device *dev)
if (dev->driver && drv->shutdown)
drv->shutdown(card);
__mmc_stop_host(host);
if (host->bus_ops->shutdown) {
ret = host->bus_ops->shutdown(host);
if (ret)

View File

@@ -82,6 +82,7 @@ struct mmc_fixup {
#define CID_MANFID_SANDISK_SD 0x3
#define CID_MANFID_ATP 0x9
#define CID_MANFID_TOSHIBA 0x11
#define CID_MANFID_GIGASTONE 0x12
#define CID_MANFID_MICRON 0x13
#define CID_MANFID_SAMSUNG 0x15
#define CID_MANFID_APACER 0x27
@@ -280,4 +281,14 @@ static inline int mmc_card_broken_sd_cache(const struct mmc_card *c)
return c->quirks & MMC_QUIRK_BROKEN_SD_CACHE;
}
static inline int mmc_card_broken_cache_flush(const struct mmc_card *c)
{
return c->quirks & MMC_QUIRK_BROKEN_CACHE_FLUSH;
}
static inline int mmc_card_broken_sd_poweroff_notify(const struct mmc_card *c)
{
return c->quirks & MMC_QUIRK_BROKEN_SD_POWEROFF_NOTIFY;
}
#endif

View File

@@ -2297,6 +2297,9 @@ void mmc_start_host(struct mmc_host *host)
void __mmc_stop_host(struct mmc_host *host)
{
if (host->rescan_disable)
return;
if (host->slot.cd_irq >= 0) {
mmc_gpio_set_cd_wake(host, false);
disable_irq(host->slot.cd_irq);

View File

@@ -25,6 +25,15 @@ static const struct mmc_fixup __maybe_unused mmc_sd_fixups[] = {
0, -1ull, SDIO_ANY_ID, SDIO_ANY_ID, add_quirk_sd,
MMC_QUIRK_BROKEN_SD_CACHE, EXT_CSD_REV_ANY),
/*
* GIGASTONE Gaming Plus microSD cards manufactured on 02/2022 never
* clear Flush Cache bit and set Poweroff Notification Ready bit.
*/
_FIXUP_EXT("ASTC", CID_MANFID_GIGASTONE, 0x3456, 2022, 2,
0, -1ull, SDIO_ANY_ID, SDIO_ANY_ID, add_quirk_sd,
MMC_QUIRK_BROKEN_SD_CACHE | MMC_QUIRK_BROKEN_SD_POWEROFF_NOTIFY,
EXT_CSD_REV_ANY),
END_FIXUP
};

View File

@@ -1122,7 +1122,7 @@ static int sd_parse_ext_reg_power(struct mmc_card *card, u8 fno, u8 page,
card->ext_power.rev = reg_buf[0] & 0xf;
/* Power Off Notification support at bit 4. */
if (reg_buf[1] & BIT(4))
if ((reg_buf[1] & BIT(4)) && !mmc_card_broken_sd_poweroff_notify(card))
card->ext_power.feature_support |= SD_EXT_POWER_OFF_NOTIFY;
/* Power Sustenance support at bit 5. */

View File

@@ -21,6 +21,7 @@
#include <linux/io.h>
#include <linux/iopoll.h>
#include <linux/gpio.h>
#include <linux/gpio/machine.h>
#include <linux/pm_runtime.h>
#include <linux/pm_qos.h>
#include <linux/debugfs.h>
@@ -1239,6 +1240,29 @@ static const struct sdhci_pci_fixes sdhci_intel_byt_sdio = {
.priv_size = sizeof(struct intel_host),
};
/* DMI quirks for devices with missing or broken CD GPIO info */
static const struct gpiod_lookup_table vexia_edu_atla10_cd_gpios = {
.dev_id = "0000:00:12.0",
.table = {
GPIO_LOOKUP("INT33FC:00", 38, "cd", GPIO_ACTIVE_HIGH),
{ }
},
};
static const struct dmi_system_id sdhci_intel_byt_cd_gpio_override[] = {
{
/* Vexia Edu Atla 10 tablet 9V version */
.matches = {
DMI_MATCH(DMI_BOARD_VENDOR, "AMI Corporation"),
DMI_MATCH(DMI_BOARD_NAME, "Aptio CRB"),
/* Above strings are too generic, also match on BIOS date */
DMI_MATCH(DMI_BIOS_DATE, "08/25/2014"),
},
.driver_data = (void *)&vexia_edu_atla10_cd_gpios,
},
{ }
};
static const struct sdhci_pci_fixes sdhci_intel_byt_sd = {
#ifdef CONFIG_PM_SLEEP
.resume = byt_resume,
@@ -1257,6 +1281,7 @@ static const struct sdhci_pci_fixes sdhci_intel_byt_sd = {
.add_host = byt_add_host,
.remove_slot = byt_remove_slot,
.ops = &sdhci_intel_byt_ops,
.cd_gpio_override = sdhci_intel_byt_cd_gpio_override,
.priv_size = sizeof(struct intel_host),
};
@@ -2036,6 +2061,42 @@ static const struct dev_pm_ops sdhci_pci_pm_ops = {
* *
\*****************************************************************************/
static struct gpiod_lookup_table *sdhci_pci_add_gpio_lookup_table(
struct sdhci_pci_chip *chip)
{
struct gpiod_lookup_table *cd_gpio_lookup_table;
const struct dmi_system_id *dmi_id = NULL;
size_t count;
if (chip->fixes && chip->fixes->cd_gpio_override)
dmi_id = dmi_first_match(chip->fixes->cd_gpio_override);
if (!dmi_id)
return NULL;
cd_gpio_lookup_table = dmi_id->driver_data;
for (count = 0; cd_gpio_lookup_table->table[count].key; count++)
;
cd_gpio_lookup_table = kmemdup(dmi_id->driver_data,
/* count + 1 terminating entry */
struct_size(cd_gpio_lookup_table, table, count + 1),
GFP_KERNEL);
if (!cd_gpio_lookup_table)
return ERR_PTR(-ENOMEM);
gpiod_add_lookup_table(cd_gpio_lookup_table);
return cd_gpio_lookup_table;
}
static void sdhci_pci_remove_gpio_lookup_table(struct gpiod_lookup_table *lookup_table)
{
if (lookup_table) {
gpiod_remove_lookup_table(lookup_table);
kfree(lookup_table);
}
}
static struct sdhci_pci_slot *sdhci_pci_probe_slot(
struct pci_dev *pdev, struct sdhci_pci_chip *chip, int first_bar,
int slotno)
@@ -2111,8 +2172,19 @@ static struct sdhci_pci_slot *sdhci_pci_probe_slot(
device_init_wakeup(&pdev->dev, true);
if (slot->cd_idx >= 0) {
struct gpiod_lookup_table *cd_gpio_lookup_table;
cd_gpio_lookup_table = sdhci_pci_add_gpio_lookup_table(chip);
if (IS_ERR(cd_gpio_lookup_table)) {
ret = PTR_ERR(cd_gpio_lookup_table);
goto remove;
}
ret = mmc_gpiod_request_cd(host->mmc, "cd", slot->cd_idx,
slot->cd_override_level, 0);
sdhci_pci_remove_gpio_lookup_table(cd_gpio_lookup_table);
if (ret && ret != -EPROBE_DEFER)
ret = mmc_gpiod_request_cd(host->mmc, NULL,
slot->cd_idx,

View File

@@ -151,6 +151,7 @@ struct sdhci_pci_fixes {
#endif
const struct sdhci_ops *ops;
const struct dmi_system_id *cd_gpio_override;
size_t priv_size;
};

View File

@@ -452,7 +452,7 @@ static int can_set_termination(struct net_device *ndev, u16 term)
else
set = 0;
gpiod_set_value(priv->termination_gpio, set);
gpiod_set_value_cansleep(priv->termination_gpio, set);
return 0;
}

View File

@@ -21,6 +21,11 @@ static inline bool mcp251xfd_tx_fifo_sta_empty(u32 fifo_sta)
return fifo_sta & MCP251XFD_REG_FIFOSTA_TFERFFIF;
}
static inline bool mcp251xfd_tx_fifo_sta_less_than_half_full(u32 fifo_sta)
{
return fifo_sta & MCP251XFD_REG_FIFOSTA_TFHRFHIF;
}
static inline int
mcp251xfd_tef_tail_get_from_chip(const struct mcp251xfd_priv *priv,
u8 *tef_tail)
@@ -147,7 +152,29 @@ mcp251xfd_get_tef_len(struct mcp251xfd_priv *priv, u8 *len_p)
BUILD_BUG_ON(sizeof(tx_ring->obj_num) != sizeof(len));
len = (chip_tx_tail << shift) - (tail << shift);
*len_p = len >> shift;
len >>= shift;
/* According to mcp2518fd erratum DS80000789E 6. the FIFOCI
* bits of a FIFOSTA register, here the TX-FIFO tail index
* might be corrupted.
*
* However here it seems the bit indicating that the TX-FIFO
* is empty (MCP251XFD_REG_FIFOSTA_TFERFFIF) is not correct
* while the TX-FIFO tail index is.
*
* We assume the TX-FIFO is empty, i.e. all pending CAN frames
* haven been send, if:
* - Chip's head and tail index are equal (len == 0).
* - The TX-FIFO is less than half full.
* (The TX-FIFO empty case has already been checked at the
* beginning of this function.)
* - No free buffers in the TX ring.
*/
if (len == 0 && mcp251xfd_tx_fifo_sta_less_than_half_full(fifo_sta) &&
mcp251xfd_get_tx_free(tx_ring) == 0)
len = tx_ring->obj_num;
*len_p = len;
return 0;
}

View File

@@ -613,7 +613,7 @@ int pci_epc_add_epf(struct pci_epc *epc, struct pci_epf *epf,
if (type == SECONDARY_INTERFACE && epf->sec_epc)
return -EBUSY;
mutex_lock(&epc->lock);
mutex_lock(&epc->list_lock);
func_no = find_first_zero_bit(&epc->function_num_map,
BITS_PER_LONG);
if (func_no >= BITS_PER_LONG) {
@@ -640,7 +640,7 @@ int pci_epc_add_epf(struct pci_epc *epc, struct pci_epf *epf,
list_add_tail(list, &epc->pci_epf);
ret:
mutex_unlock(&epc->lock);
mutex_unlock(&epc->list_lock);
return ret;
}
@@ -664,19 +664,19 @@ void pci_epc_remove_epf(struct pci_epc *epc, struct pci_epf *epf,
if (!epc || IS_ERR(epc) || !epf)
return;
mutex_lock(&epc->list_lock);
if (type == PRIMARY_INTERFACE) {
func_no = epf->func_no;
list = &epf->list;
epf->epc = NULL;
} else {
func_no = epf->sec_epc_func_no;
list = &epf->sec_epc_list;
epf->sec_epc = NULL;
}
mutex_lock(&epc->lock);
clear_bit(func_no, &epc->function_num_map);
list_del(list);
epf->epc = NULL;
mutex_unlock(&epc->lock);
mutex_unlock(&epc->list_lock);
}
EXPORT_SYMBOL_GPL(pci_epc_remove_epf);
@@ -773,6 +773,7 @@ __pci_epc_create(struct device *dev, const struct pci_epc_ops *ops,
}
mutex_init(&epc->lock);
mutex_init(&epc->list_lock);
INIT_LIST_HEAD(&epc->pci_epf);
ATOMIC_INIT_NOTIFIER_HEAD(&epc->notifier);

View File

@@ -3312,6 +3312,7 @@ struct fc_function_template qla2xxx_transport_vport_functions = {
.show_host_node_name = 1,
.show_host_port_name = 1,
.show_host_supported_classes = 1,
.show_host_supported_speeds = 1,
.get_host_port_id = qla2x00_get_host_port_id,
.show_host_port_id = 1,

View File

@@ -24,6 +24,7 @@ void qla2x00_bsg_job_done(srb_t *sp, int res)
{
struct bsg_job *bsg_job = sp->u.bsg_job;
struct fc_bsg_reply *bsg_reply = bsg_job->reply;
struct completion *comp = sp->comp;
ql_dbg(ql_dbg_user, sp->vha, 0x7009,
"%s: sp hdl %x, result=%x bsg ptr %p\n",
@@ -35,6 +36,9 @@ void qla2x00_bsg_job_done(srb_t *sp, int res)
bsg_reply->result = res;
bsg_job_done(bsg_job, bsg_reply->result,
bsg_reply->reply_payload_rcv_len);
if (comp)
complete(comp);
}
void qla2x00_bsg_sp_free(srb_t *sp)
@@ -490,16 +494,6 @@ qla2x00_process_ct(struct bsg_job *bsg_job)
goto done;
}
if ((req_sg_cnt != bsg_job->request_payload.sg_cnt) ||
(rsp_sg_cnt != bsg_job->reply_payload.sg_cnt)) {
ql_log(ql_log_warn, vha, 0x7011,
"request_sg_cnt: %x dma_request_sg_cnt: %x reply_sg_cnt:%x "
"dma_reply_sg_cnt: %x\n", bsg_job->request_payload.sg_cnt,
req_sg_cnt, bsg_job->reply_payload.sg_cnt, rsp_sg_cnt);
rval = -EAGAIN;
goto done_unmap_sg;
}
if (!vha->flags.online) {
ql_log(ql_log_warn, vha, 0x7012,
"Host is not online.\n");
@@ -3061,7 +3055,7 @@ skip_chip_chk:
static bool qla_bsg_found(struct qla_qpair *qpair, struct bsg_job *bsg_job)
{
bool found = false;
bool found, do_bsg_done;
struct fc_bsg_reply *bsg_reply = bsg_job->reply;
scsi_qla_host_t *vha = shost_priv(fc_bsg_to_shost(bsg_job));
struct qla_hw_data *ha = vha->hw;
@@ -3069,6 +3063,11 @@ static bool qla_bsg_found(struct qla_qpair *qpair, struct bsg_job *bsg_job)
int cnt;
unsigned long flags;
struct req_que *req;
int rval;
DECLARE_COMPLETION_ONSTACK(comp);
uint32_t ratov_j;
found = do_bsg_done = false;
spin_lock_irqsave(qpair->qp_lock_ptr, flags);
req = qpair->req;
@@ -3080,42 +3079,104 @@ static bool qla_bsg_found(struct qla_qpair *qpair, struct bsg_job *bsg_job)
sp->type == SRB_ELS_CMD_HST ||
sp->type == SRB_ELS_CMD_HST_NOLOGIN) &&
sp->u.bsg_job == bsg_job) {
req->outstanding_cmds[cnt] = NULL;
spin_unlock_irqrestore(qpair->qp_lock_ptr, flags);
if (!ha->flags.eeh_busy && ha->isp_ops->abort_command(sp)) {
ql_log(ql_log_warn, vha, 0x7089,
"mbx abort_command failed.\n");
bsg_reply->result = -EIO;
} else {
ql_dbg(ql_dbg_user, vha, 0x708a,
"mbx abort_command success.\n");
bsg_reply->result = 0;
}
/* ref: INIT */
kref_put(&sp->cmd_kref, qla2x00_sp_release);
found = true;
goto done;
sp->comp = &comp;
break;
}
}
spin_unlock_irqrestore(qpair->qp_lock_ptr, flags);
done:
return found;
if (!found)
return false;
if (ha->flags.eeh_busy) {
/* skip over abort. EEH handling will return the bsg. Wait for it */
rval = QLA_SUCCESS;
ql_dbg(ql_dbg_user, vha, 0x802c,
"eeh encounter. bsg %p sp=%p handle=%x \n",
bsg_job, sp, sp->handle);
} else {
rval = ha->isp_ops->abort_command(sp);
ql_dbg(ql_dbg_user, vha, 0x802c,
"Aborting bsg %p sp=%p handle=%x rval=%x\n",
bsg_job, sp, sp->handle, rval);
}
switch (rval) {
case QLA_SUCCESS:
/* Wait for the command completion. */
ratov_j = ha->r_a_tov / 10 * 4 * 1000;
ratov_j = msecs_to_jiffies(ratov_j);
if (!wait_for_completion_timeout(&comp, ratov_j)) {
ql_log(ql_log_info, vha, 0x7089,
"bsg abort timeout. bsg=%p sp=%p handle %#x .\n",
bsg_job, sp, sp->handle);
do_bsg_done = true;
} else {
/* fw had returned the bsg */
ql_dbg(ql_dbg_user, vha, 0x708a,
"bsg abort success. bsg %p sp=%p handle=%#x\n",
bsg_job, sp, sp->handle);
do_bsg_done = false;
}
break;
default:
ql_log(ql_log_info, vha, 0x704f,
"bsg abort fail. bsg=%p sp=%p rval=%x.\n",
bsg_job, sp, rval);
do_bsg_done = true;
break;
}
if (!do_bsg_done)
return true;
spin_lock_irqsave(qpair->qp_lock_ptr, flags);
/*
* recheck to make sure it's still the same bsg_job due to
* qp_lock_ptr was released earlier.
*/
if (req->outstanding_cmds[cnt] &&
req->outstanding_cmds[cnt]->u.bsg_job != bsg_job) {
/* fw had returned the bsg */
spin_unlock_irqrestore(qpair->qp_lock_ptr, flags);
return true;
}
req->outstanding_cmds[cnt] = NULL;
spin_unlock_irqrestore(qpair->qp_lock_ptr, flags);
/* ref: INIT */
sp->comp = NULL;
kref_put(&sp->cmd_kref, qla2x00_sp_release);
bsg_reply->result = -ENXIO;
bsg_reply->reply_payload_rcv_len = 0;
ql_dbg(ql_dbg_user, vha, 0x7051,
"%s bsg_job_done : bsg %p result %#x sp %p.\n",
__func__, bsg_job, bsg_reply->result, sp);
bsg_job_done(bsg_job, bsg_reply->result, bsg_reply->reply_payload_rcv_len);
return true;
}
int
qla24xx_bsg_timeout(struct bsg_job *bsg_job)
{
struct fc_bsg_reply *bsg_reply = bsg_job->reply;
struct fc_bsg_request *bsg_request = bsg_job->request;
scsi_qla_host_t *vha = shost_priv(fc_bsg_to_shost(bsg_job));
struct qla_hw_data *ha = vha->hw;
int i;
struct qla_qpair *qpair;
ql_log(ql_log_info, vha, 0x708b, "%s CMD timeout. bsg ptr %p.\n",
__func__, bsg_job);
ql_log(ql_log_info, vha, 0x708b,
"%s CMD timeout. bsg ptr %p msgcode %x vendor cmd %x\n",
__func__, bsg_job, bsg_request->msgcode,
bsg_request->rqst_data.h_vendor.vendor_cmd[0]);
if (qla2x00_isp_reg_stat(ha)) {
ql_log(ql_log_info, vha, 0x9007,
@@ -3136,7 +3197,6 @@ qla24xx_bsg_timeout(struct bsg_job *bsg_job)
}
ql_log(ql_log_info, vha, 0x708b, "SRB not found to abort.\n");
bsg_reply->result = -ENXIO;
done:
return 0;

View File

@@ -515,6 +515,7 @@ qla24xx_create_vhost(struct fc_vport *fc_vport)
return(NULL);
}
vha->irq_offset = QLA_BASE_VECTORS;
host = vha->host;
fc_vport->dd_data = vha;
/* New host info */

View File

@@ -6883,12 +6883,15 @@ qla2x00_do_dpc(void *data)
set_user_nice(current, MIN_NICE);
set_current_state(TASK_INTERRUPTIBLE);
while (!kthread_should_stop()) {
while (1) {
ql_dbg(ql_dbg_dpc, base_vha, 0x4000,
"DPC handler sleeping.\n");
schedule();
if (kthread_should_stop())
break;
if (test_and_clear_bit(DO_EEH_RECOVERY, &base_vha->dpc_flags))
qla_pci_set_eeh_busy(base_vha);
@@ -6901,15 +6904,16 @@ qla2x00_do_dpc(void *data)
goto end_loop;
}
if (test_bit(UNLOADING, &base_vha->dpc_flags))
/* don't do any work. Wait to be terminated by kthread_stop */
goto end_loop;
ha->dpc_active = 1;
ql_dbg(ql_dbg_dpc + ql_dbg_verbose, base_vha, 0x4001,
"DPC handler waking up, dpc_flags=0x%lx.\n",
base_vha->dpc_flags);
if (test_bit(UNLOADING, &base_vha->dpc_flags))
break;
if (IS_P3P_TYPE(ha)) {
if (IS_QLA8044(ha)) {
if (test_and_clear_bit(ISP_UNRECOVERABLE,
@@ -7227,9 +7231,6 @@ end_loop:
*/
ha->dpc_active = 0;
/* Cleanup any residual CTX SRBs. */
qla2x00_abort_all_cmds(base_vha, DID_NO_CONNECT << 16);
return 0;
}

View File

@@ -5673,7 +5673,7 @@ static int schedule_resp(struct scsi_cmnd *cmnd, struct sdebug_dev_info *devip,
if (sdebug_host_max_queue)
sd_dp->hc_idx = get_tag(cmnd);
if (polled)
if (polled || (ndelay > 0 && ndelay < INCLUSIVE_TIMING_MAX_NS))
ns_from_boot = ktime_get_boottime_ns();
/* one of the resp_*() response functions is called here */

View File

@@ -519,6 +519,7 @@ static int mpc52xx_spi_remove(struct platform_device *op)
struct mpc52xx_spi *ms = spi_master_get_devdata(master);
int i;
cancel_work_sync(&ms->work);
free_irq(ms->irq0, ms);
free_irq(ms->irq1, ms);

View File

@@ -454,6 +454,9 @@ static ssize_t read_req_latency_avg_show(struct device *dev,
struct ufs_hba *hba = dev_get_drvdata(dev);
struct ufs_hba_monitor *m = &hba->monitor;
if (!m->nr_req[READ])
return sysfs_emit(buf, "0\n");
return sysfs_emit(buf, "%llu\n", div_u64(ktime_to_us(m->lat_sum[READ]),
m->nr_req[READ]));
}
@@ -521,6 +524,9 @@ static ssize_t write_req_latency_avg_show(struct device *dev,
struct ufs_hba *hba = dev_get_drvdata(dev);
struct ufs_hba_monitor *m = &hba->monitor;
if (!m->nr_req[WRITE])
return sysfs_emit(buf, "0\n");
return sysfs_emit(buf, "%llu\n", div_u64(ktime_to_us(m->lat_sum[WRITE]),
m->nr_req[WRITE]));
}

View File

@@ -4633,9 +4633,6 @@ static int ufshcd_change_power_mode(struct ufs_hba *hba,
dev_err(hba->dev,
"%s: power mode change failed %d\n", __func__, ret);
} else {
ufshcd_vops_pwr_change_notify(hba, POST_CHANGE, NULL,
pwr_mode);
memcpy(&hba->pwr_info, pwr_mode,
sizeof(struct ufs_pa_layer_attr));
}
@@ -4662,6 +4659,10 @@ int ufshcd_config_pwr_mode(struct ufs_hba *hba,
ret = ufshcd_change_power_mode(hba, &final_params);
if (!ret)
ufshcd_vops_pwr_change_notify(hba, POST_CHANGE, NULL,
&final_params);
return ret;
}
EXPORT_SYMBOL_GPL(ufshcd_config_pwr_mode);

View File

@@ -54,7 +54,7 @@
#define MAX_HW_ERROR 250
static int heartbeat = DEFAULT_HEARTBEAT;
static int heartbeat;
/*
* struct to hold data for each WDT device
@@ -240,6 +240,7 @@ static int rti_wdt_probe(struct platform_device *pdev)
wdd->min_timeout = 1;
wdd->max_hw_heartbeat_ms = (WDT_PRELOAD_MAX << WDT_PRELOAD_SHIFT) /
wdt->freq * 1000;
wdd->timeout = DEFAULT_HEARTBEAT;
wdd->parent = dev;
watchdog_set_drvdata(wdd, wdt);

View File

@@ -671,6 +671,42 @@ u8 *btrfs_sb_fsid_ptr(struct btrfs_super_block *sb)
return has_metadata_uuid ? sb->metadata_uuid : sb->fsid;
}
static bool is_same_device(struct btrfs_device *device, const char *new_path)
{
struct path old = { .mnt = NULL, .dentry = NULL };
struct path new = { .mnt = NULL, .dentry = NULL };
char *old_path = NULL;
bool is_same = false;
int ret;
if (!device->name)
goto out;
old_path = kzalloc(PATH_MAX, GFP_NOFS);
if (!old_path)
goto out;
rcu_read_lock();
ret = strscpy(old_path, rcu_str_deref(device->name), PATH_MAX);
rcu_read_unlock();
if (ret < 0)
goto out;
ret = kern_path(old_path, LOOKUP_FOLLOW, &old);
if (ret)
goto out;
ret = kern_path(new_path, LOOKUP_FOLLOW, &new);
if (ret)
goto out;
if (path_equal(&old, &new))
is_same = true;
out:
kfree(old_path);
path_put(&old);
path_put(&new);
return is_same;
}
/*
* Handle scanned device having its CHANGING_FSID_V2 flag set and the fs_devices
* being created with a disk that has already completed its fsid change. Such
@@ -889,7 +925,7 @@ static noinline struct btrfs_device *device_list_add(const char *path,
disk_super->fsid, devid, found_transid, path,
current->comm, task_pid_nr(current));
} else if (!device->name || strcmp(device->name->str, path)) {
} else if (!device->name || !is_same_device(device, path)) {
/*
* When FS is already mounted.
* 1. If you are here and if the device->name is NULL that
@@ -2731,8 +2767,6 @@ int btrfs_init_new_device(struct btrfs_fs_info *fs_info, const char *device_path
set_blocksize(device->bdev, BTRFS_BDEV_BLOCKSIZE);
if (seeding_dev) {
btrfs_clear_sb_rdonly(sb);
/* GFP_KERNEL allocation must not be under device_list_mutex */
seed_devices = btrfs_init_sprout(fs_info);
if (IS_ERR(seed_devices)) {
@@ -2875,8 +2909,6 @@ error_sysfs:
mutex_unlock(&fs_info->chunk_mutex);
mutex_unlock(&fs_info->fs_devices->device_list_mutex);
error_trans:
if (seeding_dev)
btrfs_set_sb_rdonly(sb);
if (trans)
btrfs_end_transaction(trans);
error_free_zone:

View File

@@ -743,7 +743,8 @@ static bool __ep_remove(struct eventpoll *ep, struct epitem *epi, bool force)
to_free = NULL;
head = file->f_ep;
if (head->first == &epi->fllink && !epi->fllink.next) {
file->f_ep = NULL;
/* See eventpoll_release() for details. */
WRITE_ONCE(file->f_ep, NULL);
if (!is_file_epoll(file)) {
struct epitems_head *v;
v = container_of(head, struct epitems_head, epitems);
@@ -1513,7 +1514,8 @@ allocate:
spin_unlock(&file->f_lock);
goto allocate;
}
file->f_ep = head;
/* See eventpoll_release() for details. */
WRITE_ONCE(file->f_ep, head);
to_free = NULL;
}
hlist_add_head_rcu(&epi->fllink, file->f_ep);

View File

@@ -76,7 +76,7 @@ static inline void nilfs_put_page(struct page *page)
*/
static unsigned int nilfs_last_byte(struct inode *inode, unsigned long page_nr)
{
unsigned int last_byte = inode->i_size;
u64 last_byte = inode->i_size;
last_byte -= page_nr << PAGE_SHIFT;
if (last_byte > PAGE_SIZE)

View File

@@ -3108,6 +3108,7 @@ static void *ocfs2_dlm_seq_next(struct seq_file *m, void *v, loff_t *pos)
struct ocfs2_lock_res *iter = v;
struct ocfs2_lock_res *dummy = &priv->p_iter_res;
(*pos)++;
spin_lock(&ocfs2_dlm_tracking_lock);
iter = ocfs2_dlm_next_res(iter, priv);
list_del_init(&dummy->l_debug_list);

View File

@@ -200,8 +200,10 @@ static struct inode *ocfs2_get_init_inode(struct inode *dir, umode_t mode)
mode = mode_strip_sgid(&init_user_ns, dir, mode);
inode_init_owner(&init_user_ns, inode, dir, mode);
status = dquot_initialize(inode);
if (status)
if (status) {
iput(inode);
return ERR_PTR(status);
}
return inode;
}

View File

@@ -6370,6 +6370,10 @@ int smb2_read(struct ksmbd_work *work)
}
offset = le64_to_cpu(req->Offset);
if (offset < 0) {
err = -EINVAL;
goto out;
}
length = le32_to_cpu(req->Length);
mincount = le32_to_cpu(req->MinimumCount);
@@ -6583,6 +6587,8 @@ int smb2_write(struct ksmbd_work *work)
}
offset = le64_to_cpu(req->Offset);
if (offset < 0)
return -EINVAL;
length = le32_to_cpu(req->Length);
if (req->Channel == SMB2_CHANNEL_RDMA_V1 ||

View File

@@ -694,6 +694,13 @@ struct drm_dp_mst_topology_mgr {
*/
bool payload_id_table_cleared : 1;
/**
* @reset_rx_state: The down request's reply and up request message
* receiver state must be reset, after the topology manager got
* removed. Protected by @lock.
*/
bool reset_rx_state : 1;
/**
* @payload_count: The number of currently active payloads in hardware. This value is only
* intended to be used internally by MST helpers for payload tracking, and is only safe to

View File

@@ -42,7 +42,7 @@ static inline void eventpoll_release(struct file *file)
* because the file in on the way to be removed and nobody ( but
* eventpoll ) has still a reference to this file.
*/
if (likely(!file->f_ep))
if (likely(!READ_ONCE(file->f_ep)))
return;
/*

View File

@@ -53,8 +53,10 @@ struct fwnode_handle {
* fwnode link flags
*
* CYCLE: The fwnode link is part of a cycle. Don't defer probe.
* IGNORE: Completely ignore this link, even during cycle detection.
*/
#define FWLINK_FLAG_CYCLE BIT(0)
#define FWLINK_FLAG_IGNORE BIT(1)
struct fwnode_link {
struct fwnode_handle *supplier;

View File

@@ -268,6 +268,20 @@ enum i3c_bus_mode {
I3C_BUS_MODE_MIXED_SLOW,
};
/**
* enum i3c_open_drain_speed - I3C open-drain speed
* @I3C_OPEN_DRAIN_SLOW_SPEED: Slow open-drain speed for sending the first
* broadcast address. The first broadcast address at this speed
* will be visible to all devices on the I3C bus. I3C devices
* working in I2C mode will turn off their spike filter when
* switching into I3C mode.
* @I3C_OPEN_DRAIN_NORMAL_SPEED: Normal open-drain speed in I3C bus mode.
*/
enum i3c_open_drain_speed {
I3C_OPEN_DRAIN_SLOW_SPEED,
I3C_OPEN_DRAIN_NORMAL_SPEED,
};
/**
* enum i3c_addr_slot_status - I3C address slot status
* @I3C_ADDR_SLOT_FREE: address is free
@@ -275,7 +289,8 @@ enum i3c_bus_mode {
* @I3C_ADDR_SLOT_I2C_DEV: address is assigned to an I2C device
* @I3C_ADDR_SLOT_I3C_DEV: address is assigned to an I3C device
* @I3C_ADDR_SLOT_STATUS_MASK: address slot mask
*
* @I3C_ADDR_SLOT_EXT_DESIRED: the bitmask represents addresses that are preferred by some devices,
* such as the "assigned-address" property in a device tree source.
* On an I3C bus, addresses are assigned dynamically, and we need to know which
* addresses are free to use and which ones are already assigned.
*
@@ -288,8 +303,12 @@ enum i3c_addr_slot_status {
I3C_ADDR_SLOT_I2C_DEV,
I3C_ADDR_SLOT_I3C_DEV,
I3C_ADDR_SLOT_STATUS_MASK = 3,
I3C_ADDR_SLOT_EXT_STATUS_MASK = 7,
I3C_ADDR_SLOT_EXT_DESIRED = BIT(2),
};
#define I3C_ADDR_SLOT_STATUS_BITS 4
/**
* struct i3c_bus - I3C bus object
* @cur_master: I3C master currently driving the bus. Since I3C is multi-master
@@ -331,7 +350,7 @@ enum i3c_addr_slot_status {
struct i3c_bus {
struct i3c_dev_desc *cur_master;
int id;
unsigned long addrslots[((I2C_MAX_ADDR + 1) * 2) / BITS_PER_LONG];
unsigned long addrslots[((I2C_MAX_ADDR + 1) * I3C_ADDR_SLOT_STATUS_BITS) / BITS_PER_LONG];
enum i3c_bus_mode mode;
struct {
unsigned long i3c;
@@ -425,6 +444,9 @@ struct i3c_bus {
* for a future IBI
* This method is mandatory only if ->request_ibi is not
* NULL.
* @enable_hotjoin: enable hot join event detect.
* @disable_hotjoin: disable hot join event detect.
* @set_speed: adjust I3C open drain mode timing.
*/
struct i3c_master_controller_ops {
int (*bus_init)(struct i3c_master_controller *master);
@@ -451,6 +473,9 @@ struct i3c_master_controller_ops {
int (*disable_ibi)(struct i3c_dev_desc *dev);
void (*recycle_ibi_slot)(struct i3c_dev_desc *dev,
struct i3c_ibi_slot *slot);
int (*enable_hotjoin)(struct i3c_master_controller *master);
int (*disable_hotjoin)(struct i3c_master_controller *master);
int (*set_speed)(struct i3c_master_controller *master, enum i3c_open_drain_speed speed);
};
/**
@@ -464,6 +489,7 @@ struct i3c_master_controller_ops {
* @ops: master operations. See &struct i3c_master_controller_ops
* @secondary: true if the master is a secondary master
* @init_done: true when the bus initialization is done
* @hotjoin: true if the master support hotjoin
* @boardinfo.i3c: list of I3C boardinfo objects
* @boardinfo.i2c: list of I2C boardinfo objects
* @boardinfo: board-level information attached to devices connected on the bus
@@ -486,6 +512,7 @@ struct i3c_master_controller {
const struct i3c_master_controller_ops *ops;
unsigned int secondary : 1;
unsigned int init_done : 1;
unsigned int hotjoin: 1;
struct {
struct list_head i3c;
struct list_head i2c;
@@ -541,7 +568,9 @@ int i3c_master_register(struct i3c_master_controller *master,
struct device *parent,
const struct i3c_master_controller_ops *ops,
bool secondary);
int i3c_master_unregister(struct i3c_master_controller *master);
void i3c_master_unregister(struct i3c_master_controller *master);
int i3c_master_enable_hotjoin(struct i3c_master_controller *master);
int i3c_master_disable_hotjoin(struct i3c_master_controller *master);
/**
* i3c_dev_get_master_data() - get master private data attached to an I3C

View File

@@ -298,6 +298,8 @@ struct mmc_card {
#define MMC_QUIRK_BROKEN_HPI (1<<13) /* Disable broken HPI support */
#define MMC_QUIRK_BROKEN_SD_DISCARD (1<<14) /* Disable broken SD discard support */
#define MMC_QUIRK_BROKEN_SD_CACHE (1<<15) /* Disable broken SD cache support */
#define MMC_QUIRK_BROKEN_CACHE_FLUSH (1<<16) /* Don't flush cache until the write has occurred */
#define MMC_QUIRK_BROKEN_SD_POWEROFF_NOTIFY (1<<17) /* Disable broken SD poweroff notify support */
bool reenable_cmdq; /* Re-enable Command Queue */

View File

@@ -122,6 +122,7 @@ struct pci_epc_mem {
* struct pci_epc - represents the PCI EPC device
* @dev: PCI EPC device
* @pci_epf: list of endpoint functions present in this EPC device
* list_lock: Mutex for protecting pci_epf list
* @ops: function pointers for performing endpoint operations
* @windows: array of address space of the endpoint controller
* @mem: first window of the endpoint controller, which corresponds to
@@ -139,6 +140,7 @@ struct pci_epc_mem {
struct pci_epc {
struct device dev;
struct list_head pci_epf;
struct mutex list_lock;
const struct pci_epc_ops *ops;
struct pci_epc_mem **windows;
struct pci_epc_mem *mem;

View File

@@ -11,6 +11,7 @@
#define _LINUX_PROPERTY_H_
#include <linux/bits.h>
#include <linux/cleanup.h>
#include <linux/fwnode.h>
#include <linux/types.h>
@@ -109,25 +110,32 @@ struct fwnode_handle *fwnode_get_next_available_child_node(
for (child = fwnode_get_next_available_child_node(fwnode, NULL); child;\
child = fwnode_get_next_available_child_node(fwnode, child))
struct fwnode_handle *device_get_next_child_node(
struct device *dev, struct fwnode_handle *child);
struct fwnode_handle *device_get_next_child_node(const struct device *dev,
struct fwnode_handle *child);
#define device_for_each_child_node(dev, child) \
for (child = device_get_next_child_node(dev, NULL); child; \
child = device_get_next_child_node(dev, child))
struct fwnode_handle *fwnode_get_named_child_node(
const struct fwnode_handle *fwnode, const char *childname);
struct fwnode_handle *device_get_named_child_node(struct device *dev,
#define device_for_each_child_node_scoped(dev, child) \
for (struct fwnode_handle *child __free(fwnode_handle) = \
device_get_next_child_node(dev, NULL); \
child; child = device_get_next_child_node(dev, child))
struct fwnode_handle *fwnode_get_named_child_node(const struct fwnode_handle *fwnode,
const char *childname);
struct fwnode_handle *device_get_named_child_node(const struct device *dev,
const char *childname);
struct fwnode_handle *fwnode_handle_get(struct fwnode_handle *fwnode);
void fwnode_handle_put(struct fwnode_handle *fwnode);
DEFINE_FREE(fwnode_handle, struct fwnode_handle *, fwnode_handle_put(_T))
int fwnode_irq_get(const struct fwnode_handle *fwnode, unsigned int index);
int fwnode_irq_get_byname(const struct fwnode_handle *fwnode, const char *name);
unsigned int device_get_child_node_count(struct device *dev);
unsigned int device_get_child_node_count(const struct device *dev);
static inline bool device_property_read_bool(struct device *dev,
const char *propname)

View File

@@ -288,7 +288,7 @@ static inline void sg_dma_mark_bus_address(struct scatterlist *sg)
}
/**
* sg_unmark_bus_address - Unmark the scatterlist entry as a bus address
* sg_dma_unmark_bus_address - Unmark the scatterlist entry as a bus address
* @sg: SG entry
*
* Description:

View File

@@ -287,7 +287,9 @@ struct ufs_pwr_mode_info {
* to allow variant specific Uni-Pro initialization.
* @pwr_change_notify: called before and after a power mode change
* is carried out to allow vendor spesific capabilities
* to be set.
* to be set. PRE_CHANGE can modify final_params based
* on desired_pwr_mode, but POST_CHANGE must not alter
* the final_params parameter
* @setup_xfer_req: called before any transfer request is issued
* to set some things
* @setup_task_mgmt: called before any task management request is issued
@@ -324,9 +326,9 @@ struct ufs_hba_variant_ops {
int (*link_startup_notify)(struct ufs_hba *,
enum ufs_notify_change_status);
int (*pwr_change_notify)(struct ufs_hba *,
enum ufs_notify_change_status status,
struct ufs_pa_layer_attr *,
struct ufs_pa_layer_attr *);
enum ufs_notify_change_status status,
struct ufs_pa_layer_attr *desired_pwr_mode,
struct ufs_pa_layer_attr *final_params);
void (*setup_xfer_req)(struct ufs_hba *hba, int tag,
bool is_scsi_cmd);
void (*setup_task_mgmt)(struct ufs_hba *, int, u8);

View File

@@ -184,7 +184,7 @@ static struct bpf_map *dev_map_alloc(union bpf_attr *attr)
static void dev_map_free(struct bpf_map *map)
{
struct bpf_dtab *dtab = container_of(map, struct bpf_dtab, map);
int i;
u32 i;
/* At this point bpf_prog->aux->refcnt == 0 and this map->refcnt == 0,
* so the programs (can be more than one that used this map) were
@@ -807,7 +807,7 @@ static int dev_map_delete_elem(struct bpf_map *map, void *key)
{
struct bpf_dtab *dtab = container_of(map, struct bpf_dtab, map);
struct bpf_dtab_netdev *old_dev;
int k = *(u32 *)key;
u32 k = *(u32 *)key;
if (k >= map->max_entries)
return -EINVAL;
@@ -822,7 +822,7 @@ static int dev_map_hash_delete_elem(struct bpf_map *map, void *key)
{
struct bpf_dtab *dtab = container_of(map, struct bpf_dtab, map);
struct bpf_dtab_netdev *old_dev;
int k = *(u32 *)key;
u32 k = *(u32 *)key;
unsigned long flags;
int ret = -ENOENT;

View File

@@ -302,12 +302,22 @@ static struct lpm_trie_node *lpm_trie_node_alloc(const struct lpm_trie *trie,
return node;
}
static int trie_check_add_elem(struct lpm_trie *trie, u64 flags)
{
if (flags == BPF_EXIST)
return -ENOENT;
if (trie->n_entries == trie->map.max_entries)
return -ENOSPC;
trie->n_entries++;
return 0;
}
/* Called from syscall or from eBPF program */
static int trie_update_elem(struct bpf_map *map,
void *_key, void *value, u64 flags)
{
struct lpm_trie *trie = container_of(map, struct lpm_trie, map);
struct lpm_trie_node *node, *im_node = NULL, *new_node = NULL;
struct lpm_trie_node *node, *im_node, *new_node = NULL;
struct lpm_trie_node *free_node = NULL;
struct lpm_trie_node __rcu **slot;
struct bpf_lpm_trie_key_u8 *key = _key;
@@ -325,20 +335,12 @@ static int trie_update_elem(struct bpf_map *map,
spin_lock_irqsave(&trie->lock, irq_flags);
/* Allocate and fill a new node */
if (trie->n_entries == trie->map.max_entries) {
ret = -ENOSPC;
goto out;
}
new_node = lpm_trie_node_alloc(trie, value);
if (!new_node) {
ret = -ENOMEM;
goto out;
}
trie->n_entries++;
new_node->prefixlen = key->prefixlen;
RCU_INIT_POINTER(new_node->child[0], NULL);
RCU_INIT_POINTER(new_node->child[1], NULL);
@@ -368,6 +370,10 @@ static int trie_update_elem(struct bpf_map *map,
* simply assign the @new_node to that slot and be done.
*/
if (!node) {
ret = trie_check_add_elem(trie, flags);
if (ret)
goto out;
rcu_assign_pointer(*slot, new_node);
goto out;
}
@@ -376,18 +382,30 @@ static int trie_update_elem(struct bpf_map *map,
* which already has the correct data array set.
*/
if (node->prefixlen == matchlen) {
if (!(node->flags & LPM_TREE_NODE_FLAG_IM)) {
if (flags == BPF_NOEXIST) {
ret = -EEXIST;
goto out;
}
} else {
ret = trie_check_add_elem(trie, flags);
if (ret)
goto out;
}
new_node->child[0] = node->child[0];
new_node->child[1] = node->child[1];
if (!(node->flags & LPM_TREE_NODE_FLAG_IM))
trie->n_entries--;
rcu_assign_pointer(*slot, new_node);
free_node = node;
goto out;
}
ret = trie_check_add_elem(trie, flags);
if (ret)
goto out;
/* If the new node matches the prefix completely, it must be inserted
* as an ancestor. Simply insert it between @node and *@slot.
*/
@@ -400,6 +418,7 @@ static int trie_update_elem(struct bpf_map *map,
im_node = lpm_trie_node_alloc(trie, NULL);
if (!im_node) {
trie->n_entries--;
ret = -ENOMEM;
goto out;
}
@@ -421,14 +440,8 @@ static int trie_update_elem(struct bpf_map *map,
rcu_assign_pointer(*slot, im_node);
out:
if (ret) {
if (new_node)
trie->n_entries--;
if (ret)
kfree(new_node);
kfree(im_node);
}
spin_unlock_irqrestore(&trie->lock, irq_flags);
kfree_rcu(free_node, rcu);
@@ -628,7 +641,7 @@ static int trie_get_next_key(struct bpf_map *map, void *_key, void *_next_key)
struct lpm_trie_node **node_stack = NULL;
int err = 0, stack_ptr = -1;
unsigned int next_bit;
size_t matchlen;
size_t matchlen = 0;
/* The get_next_key follows postorder. For the 4 node example in
* the top of this file, the trie_get_next_key() returns the following
@@ -667,7 +680,7 @@ static int trie_get_next_key(struct bpf_map *map, void *_key, void *_next_key)
next_bit = extract_bit(key->data, node->prefixlen);
node = rcu_dereference(node->child[next_bit]);
}
if (!node || node->prefixlen != key->prefixlen ||
if (!node || node->prefixlen != matchlen ||
(node->flags & LPM_TREE_NODE_FLAG_IM))
goto find_leftmost;

View File

@@ -46,14 +46,8 @@ static struct {
int used; /* number of elements used */
bool sorted; /* if elements are sorted */
bool whitelist; /* if list is a blacklist or whitelist */
} report_filterlist = {
.addrs = NULL,
.size = 8, /* small initial size */
.used = 0,
.sorted = false,
.whitelist = false, /* default is blacklist */
};
static DEFINE_SPINLOCK(report_filterlist_lock);
} report_filterlist;
static DEFINE_RAW_SPINLOCK(report_filterlist_lock);
/*
* The microbenchmark allows benchmarking KCSAN core runtime only. To run
@@ -110,7 +104,7 @@ bool kcsan_skip_report_debugfs(unsigned long func_addr)
return false;
func_addr -= offset; /* Get function start */
spin_lock_irqsave(&report_filterlist_lock, flags);
raw_spin_lock_irqsave(&report_filterlist_lock, flags);
if (report_filterlist.used == 0)
goto out;
@@ -127,7 +121,7 @@ bool kcsan_skip_report_debugfs(unsigned long func_addr)
ret = !ret;
out:
spin_unlock_irqrestore(&report_filterlist_lock, flags);
raw_spin_unlock_irqrestore(&report_filterlist_lock, flags);
return ret;
}
@@ -135,9 +129,9 @@ static void set_report_filterlist_whitelist(bool whitelist)
{
unsigned long flags;
spin_lock_irqsave(&report_filterlist_lock, flags);
raw_spin_lock_irqsave(&report_filterlist_lock, flags);
report_filterlist.whitelist = whitelist;
spin_unlock_irqrestore(&report_filterlist_lock, flags);
raw_spin_unlock_irqrestore(&report_filterlist_lock, flags);
}
/* Returns 0 on success, error-code otherwise. */
@@ -145,6 +139,9 @@ static ssize_t insert_report_filterlist(const char *func)
{
unsigned long flags;
unsigned long addr = kallsyms_lookup_name(func);
unsigned long *delay_free = NULL;
unsigned long *new_addrs = NULL;
size_t new_size = 0;
ssize_t ret = 0;
if (!addr) {
@@ -152,32 +149,33 @@ static ssize_t insert_report_filterlist(const char *func)
return -ENOENT;
}
spin_lock_irqsave(&report_filterlist_lock, flags);
retry_alloc:
/*
* Check if we need an allocation, and re-validate under the lock. Since
* the report_filterlist_lock is a raw, cannot allocate under the lock.
*/
if (data_race(report_filterlist.used == report_filterlist.size)) {
new_size = (report_filterlist.size ?: 4) * 2;
delay_free = new_addrs = kmalloc_array(new_size, sizeof(unsigned long), GFP_KERNEL);
if (!new_addrs)
return -ENOMEM;
}
if (report_filterlist.addrs == NULL) {
/* initial allocation */
report_filterlist.addrs =
kmalloc_array(report_filterlist.size,
sizeof(unsigned long), GFP_ATOMIC);
if (report_filterlist.addrs == NULL) {
ret = -ENOMEM;
goto out;
}
} else if (report_filterlist.used == report_filterlist.size) {
/* resize filterlist */
size_t new_size = report_filterlist.size * 2;
unsigned long *new_addrs =
krealloc(report_filterlist.addrs,
new_size * sizeof(unsigned long), GFP_ATOMIC);
if (new_addrs == NULL) {
/* leave filterlist itself untouched */
ret = -ENOMEM;
goto out;
raw_spin_lock_irqsave(&report_filterlist_lock, flags);
if (report_filterlist.used == report_filterlist.size) {
/* Check we pre-allocated enough, and retry if not. */
if (report_filterlist.used >= new_size) {
raw_spin_unlock_irqrestore(&report_filterlist_lock, flags);
kfree(new_addrs); /* kfree(NULL) is safe */
delay_free = new_addrs = NULL;
goto retry_alloc;
}
if (report_filterlist.used)
memcpy(new_addrs, report_filterlist.addrs, report_filterlist.used * sizeof(unsigned long));
delay_free = report_filterlist.addrs; /* free the old list */
report_filterlist.addrs = new_addrs; /* switch to the new list */
report_filterlist.size = new_size;
report_filterlist.addrs = new_addrs;
}
/* Note: deduplicating should be done in userspace. */
@@ -185,9 +183,9 @@ static ssize_t insert_report_filterlist(const char *func)
kallsyms_lookup_name(func);
report_filterlist.sorted = false;
out:
spin_unlock_irqrestore(&report_filterlist_lock, flags);
raw_spin_unlock_irqrestore(&report_filterlist_lock, flags);
kfree(delay_free);
return ret;
}
@@ -204,13 +202,13 @@ static int show_info(struct seq_file *file, void *v)
}
/* show filter functions, and filter type */
spin_lock_irqsave(&report_filterlist_lock, flags);
raw_spin_lock_irqsave(&report_filterlist_lock, flags);
seq_printf(file, "\n%s functions: %s\n",
report_filterlist.whitelist ? "whitelisted" : "blacklisted",
report_filterlist.used == 0 ? "none" : "");
for (i = 0; i < report_filterlist.used; ++i)
seq_printf(file, " %ps\n", (void *)report_filterlist.addrs[i]);
spin_unlock_irqrestore(&report_filterlist_lock, flags);
raw_spin_unlock_irqrestore(&report_filterlist_lock, flags);
return 0;
}

View File

@@ -796,7 +796,7 @@ int __do_adjtimex(struct __kernel_timex *txc, const struct timespec64 *ts,
txc->offset = shift_right(time_offset * NTP_INTERVAL_FREQ,
NTP_SCALE_SHIFT);
if (!(time_status & STA_NANO))
txc->offset = (u32)txc->offset / NSEC_PER_USEC;
txc->offset = div_s64(txc->offset, NSEC_PER_USEC);
}
result = time_state; /* mostly `TIME_OK' */

View File

@@ -845,15 +845,11 @@ int tracing_map_init(struct tracing_map *map)
static int cmp_entries_dup(const void *A, const void *B)
{
const struct tracing_map_sort_entry *a, *b;
int ret = 0;
a = *(const struct tracing_map_sort_entry **)A;
b = *(const struct tracing_map_sort_entry **)B;
if (memcmp(a->key, b->key, a->elt->map->key_size))
ret = 1;
return ret;
return memcmp(a->key, b->key, a->elt->map->key_size);
}
static int cmp_entries_sum(const void *A, const void *B)

View File

@@ -199,6 +199,7 @@ static noinline void test_ ## name (struct kunit *test) \
static noinline DO_NOTHING_TYPE_ ## which(var_type) \
do_nothing_ ## name(var_type *ptr) \
{ \
OPTIMIZER_HIDE_VAR(ptr); \
/* Will always be true, but compiler doesn't know. */ \
if ((unsigned long)ptr > 0x2) \
return DO_NOTHING_RETURN_ ## which(ptr); \

View File

@@ -1441,12 +1441,27 @@ static __always_inline bool free_pages_prepare(struct page *page,
int bad = 0;
bool skip_kasan_poison = should_skip_kasan_poison(page, fpi_flags);
bool init = want_init_on_free();
struct folio *folio = page_folio(page);
VM_BUG_ON_PAGE(PageTail(page), page);
trace_mm_page_free(page, order);
kmsan_free_page(page, order);
/*
* In rare cases, when truncation or holepunching raced with
* munlock after VM_LOCKED was cleared, Mlocked may still be
* found set here. This does not indicate a problem, unless
* "unevictable_pgs_cleared" appears worryingly large.
*/
if (unlikely(folio_test_mlocked(folio))) {
long nr_pages = folio_nr_pages(folio);
__folio_clear_mlocked(folio);
zone_stat_mod_folio(folio, NR_MLOCK, -nr_pages);
count_vm_events(UNEVICTABLE_PGCLEARED, nr_pages);
}
if (unlikely(PageHWPoison(page)) && !order) {
/*
* Do not let hwpoison pages hit pcplists/buddy

View File

@@ -88,14 +88,6 @@ static void __page_cache_release(struct folio *folio)
__folio_clear_lru_flags(folio);
unlock_page_lruvec_irqrestore(lruvec, flags);
}
/* See comment on folio_test_mlocked in release_pages() */
if (unlikely(folio_test_mlocked(folio))) {
long nr_pages = folio_nr_pages(folio);
__folio_clear_mlocked(folio);
zone_stat_mod_folio(folio, NR_MLOCK, -nr_pages);
count_vm_events(UNEVICTABLE_PGCLEARED, nr_pages);
}
}
static void __folio_put_small(struct folio *folio)
@@ -1042,18 +1034,6 @@ void release_pages(struct page **pages, int nr)
__folio_clear_lru_flags(folio);
}
/*
* In rare cases, when truncation or holepunching raced with
* munlock after VM_LOCKED was cleared, Mlocked may still be
* found set here. This does not indicate a problem, unless
* "unevictable_pgs_cleared" appears worryingly large.
*/
if (unlikely(folio_test_mlocked(folio))) {
__folio_clear_mlocked(folio);
zone_stat_sub_folio(folio, NR_MLOCK);
count_vm_event(UNEVICTABLE_PGCLEARED);
}
list_add(&folio->lru, &pages_to_free);
}
if (lruvec)

View File

@@ -424,7 +424,6 @@ more_data:
cork = true;
psock->cork = NULL;
}
sk_msg_return(sk, msg, tosend);
release_sock(sk);
origsize = msg->sg.size;
@@ -436,8 +435,9 @@ more_data:
sock_put(sk_redir);
lock_sock(sk);
sk_mem_uncharge(sk, sent);
if (unlikely(ret < 0)) {
int free = sk_msg_free_nocharge(sk, msg);
int free = sk_msg_free(sk, msg);
if (!cork)
*copied -= free;
@@ -451,7 +451,7 @@ more_data:
break;
case __SK_DROP:
default:
sk_msg_free_partial(sk, msg, tosend);
sk_msg_free(sk, msg);
sk_msg_apply_bytes(psock, tosend);
*copied -= (tosend + delta);
return -EACCES;
@@ -467,11 +467,8 @@ more_data:
}
if (msg &&
msg->sg.data[msg->sg.start].page_link &&
msg->sg.data[msg->sg.start].length) {
if (eval == __SK_REDIRECT)
sk_mem_charge(sk, tosend - sent);
msg->sg.data[msg->sg.start].length)
goto more_data;
}
}
return ret;
}

View File

@@ -356,10 +356,9 @@ void xp_dma_unmap(struct xsk_buff_pool *pool, unsigned long attrs)
return;
}
if (!refcount_dec_and_test(&dma_map->users))
return;
if (refcount_dec_and_test(&dma_map->users))
__xp_dma_unmap(dma_map, attrs);
__xp_dma_unmap(dma_map, attrs);
kvfree(pool->dma_pages);
pool->dma_pages_cnt = 0;
pool->dev = NULL;

View File

@@ -216,7 +216,7 @@ static int xsk_map_delete_elem(struct bpf_map *map, void *key)
struct xsk_map *m = container_of(map, struct xsk_map, map);
struct xdp_sock __rcu **map_entry;
struct xdp_sock *old_xs;
int k = *(u32 *)key;
u32 k = *(u32 *)key;
if (k >= map->max_entries)
return -EINVAL;

View File

@@ -832,7 +832,7 @@ static void check_section(const char *modname, struct elf_info *elf,
".ltext", ".ltext.*"
#define OTHER_TEXT_SECTIONS ".ref.text", ".head.text", ".spinlock.text", \
".fixup", ".entry.text", ".exception.text", \
".coldtext", ".softirqentry.text"
".coldtext", ".softirqentry.text", ".irqentry.text"
#define INIT_SECTIONS ".init.*"
#define MEM_INIT_SECTIONS ".meminit.*"
@@ -892,7 +892,7 @@ enum mismatch {
struct sectioncheck {
const char *fromsec[20];
const char *bad_tosec[20];
const char *good_tosec[20];
const char *good_tosec[21];
enum mismatch mismatch;
void (*handler)(const char *modname, struct elf_info *elf,
const struct sectioncheck* const mismatch,

View File

@@ -9766,6 +9766,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
SND_PCI_QUIRK(0x103c, 0x87b7, "HP Laptop 14-fq0xxx", ALC236_FIXUP_HP_MUTE_LED_COEFBIT2),
SND_PCI_QUIRK(0x103c, 0x87c8, "HP", ALC287_FIXUP_HP_GPIO_LED),
SND_PCI_QUIRK(0x103c, 0x87d3, "HP Laptop 15-gw0xxx", ALC236_FIXUP_HP_MUTE_LED_COEFBIT2),
SND_PCI_QUIRK(0x103c, 0x87df, "HP ProBook 430 G8 Notebook PC", ALC236_FIXUP_HP_GPIO_LED),
SND_PCI_QUIRK(0x103c, 0x87e5, "HP ProBook 440 G8 Notebook PC", ALC236_FIXUP_HP_GPIO_LED),
SND_PCI_QUIRK(0x103c, 0x87e7, "HP ProBook 450 G8 Notebook PC", ALC236_FIXUP_HP_GPIO_LED),
SND_PCI_QUIRK(0x103c, 0x87f1, "HP ProBook 630 G8 Notebook PC", ALC236_FIXUP_HP_GPIO_LED),
@@ -10015,6 +10016,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
SND_PCI_QUIRK(0x144d, 0xc830, "Samsung Galaxy Book Ion (NT950XCJ-X716A)", ALC298_FIXUP_SAMSUNG_AMP),
SND_PCI_QUIRK(0x144d, 0xc832, "Samsung Galaxy Book Flex Alpha (NP730QCJ)", ALC256_FIXUP_SAMSUNG_HEADPHONE_VERY_QUIET),
SND_PCI_QUIRK(0x144d, 0xca03, "Samsung Galaxy Book2 Pro 360 (NP930QED)", ALC298_FIXUP_SAMSUNG_AMP),
SND_PCI_QUIRK(0x144d, 0xca06, "Samsung Galaxy Book3 360 (NP730QFG)", ALC298_FIXUP_SAMSUNG_HEADPHONE_VERY_QUIET),
SND_PCI_QUIRK(0x144d, 0xc868, "Samsung Galaxy Book2 Pro (NP930XED)", ALC298_FIXUP_SAMSUNG_AMP),
SND_PCI_QUIRK(0x1458, 0xfa53, "Gigabyte BXBT-2807", ALC283_FIXUP_HEADSET_MIC),
SND_PCI_QUIRK(0x1462, 0xb120, "MSI Cubi MS-B120", ALC283_FIXUP_HEADSET_MIC),

View File

@@ -403,10 +403,15 @@ static int prepare_inbound_urb(struct snd_usb_endpoint *ep,
static void notify_xrun(struct snd_usb_endpoint *ep)
{
struct snd_usb_substream *data_subs;
struct snd_pcm_substream *psubs;
data_subs = READ_ONCE(ep->data_subs);
if (data_subs && data_subs->pcm_substream)
snd_pcm_stop_xrun(data_subs->pcm_substream);
if (!data_subs)
return;
psubs = data_subs->pcm_substream;
if (psubs && psubs->runtime &&
psubs->runtime->state == SNDRV_PCM_STATE_RUNNING)
snd_pcm_stop_xrun(psubs);
}
static struct snd_usb_packet_info *
@@ -557,7 +562,10 @@ static void snd_complete_urb(struct urb *urb)
push_back_to_ready_list(ep, ctx);
clear_bit(ctx->index, &ep->active_mask);
snd_usb_queue_pending_output_urbs(ep, false);
atomic_dec(&ep->submitted_urbs); /* decrement at last */
/* decrement at last, and check xrun */
if (atomic_dec_and_test(&ep->submitted_urbs) &&
!snd_usb_endpoint_implicit_feedback_sink(ep))
notify_xrun(ep);
return;
}

View File

@@ -621,6 +621,16 @@ static const struct usbmix_ctl_map usbmix_ctl_maps[] = {
.id = USB_ID(0x1b1c, 0x0a42),
.map = corsair_virtuoso_map,
},
{
/* Corsair HS80 RGB Wireless (wired mode) */
.id = USB_ID(0x1b1c, 0x0a6a),
.map = corsair_virtuoso_map,
},
{
/* Corsair HS80 RGB Wireless (wireless mode) */
.id = USB_ID(0x1b1c, 0x0a6b),
.map = corsair_virtuoso_map,
},
{ /* Gigabyte TRX40 Aorus Master (rear panel + front mic) */
.id = USB_ID(0x0414, 0xa001),
.map = aorus_master_alc1220vb_map,

View File

@@ -16,7 +16,6 @@
#include <stdarg.h>
#include <stdint.h>
#include <stdlib.h>
#include <assert.h>
#include <unistd.h>
#include <string.h>
#include <bfd.h>
@@ -29,14 +28,18 @@
#include "json_writer.h"
#include "main.h"
static void get_exec_path(char *tpath, size_t size)
static int get_exec_path(char *tpath, size_t size)
{
const char *path = "/proc/self/exe";
ssize_t len;
len = readlink(path, tpath, size - 1);
assert(len > 0);
if (len <= 0)
return -1;
tpath[len] = 0;
return 0;
}
static int oper_count;
@@ -97,30 +100,39 @@ static int fprintf_json_styled(void *out,
return r;
}
void disasm_print_insn(unsigned char *image, ssize_t len, int opcodes,
const char *arch, const char *disassembler_options,
const struct btf *btf,
const struct bpf_prog_linfo *prog_linfo,
__u64 func_ksym, unsigned int func_idx,
bool linum)
int disasm_print_insn(unsigned char *image, ssize_t len, int opcodes,
const char *arch, const char *disassembler_options,
const struct btf *btf,
const struct bpf_prog_linfo *prog_linfo,
__u64 func_ksym, unsigned int func_idx,
bool linum)
{
const struct bpf_line_info *linfo = NULL;
disassembler_ftype disassemble;
int count, i, pc = 0, err = -1;
struct disassemble_info info;
unsigned int nr_skip = 0;
int count, i, pc = 0;
char tpath[PATH_MAX];
bfd *bfdf;
if (!len)
return;
return -1;
memset(tpath, 0, sizeof(tpath));
get_exec_path(tpath, sizeof(tpath));
if (get_exec_path(tpath, sizeof(tpath))) {
p_err("failed to create disasembler (get_exec_path)");
return -1;
}
bfdf = bfd_openr(tpath, NULL);
assert(bfdf);
assert(bfd_check_format(bfdf, bfd_object));
if (!bfdf) {
p_err("failed to create disassembler (bfd_openr)");
return -1;
}
if (!bfd_check_format(bfdf, bfd_object)) {
p_err("failed to create disassembler (bfd_check_format)");
goto exit_close;
}
if (json_output)
init_disassemble_info_compat(&info, stdout,
@@ -139,7 +151,7 @@ void disasm_print_insn(unsigned char *image, ssize_t len, int opcodes,
bfdf->arch_info = inf;
} else {
p_err("No libbfd support for %s", arch);
return;
goto exit_close;
}
}
@@ -160,7 +172,10 @@ void disasm_print_insn(unsigned char *image, ssize_t len, int opcodes,
#else
disassemble = disassembler(bfdf);
#endif
assert(disassemble);
if (!disassemble) {
p_err("failed to create disassembler");
goto exit_close;
}
if (json_output)
jsonw_start_array(json_wtr);
@@ -224,7 +239,11 @@ void disasm_print_insn(unsigned char *image, ssize_t len, int opcodes,
if (json_output)
jsonw_end_array(json_wtr);
err = 0;
exit_close:
bfd_close(bfdf);
return err;
}
int disasm_init(void)

View File

@@ -173,22 +173,23 @@ int map_parse_fd_and_info(int *argc, char ***argv, void *info, __u32 *info_len);
struct bpf_prog_linfo;
#ifdef HAVE_LIBBFD_SUPPORT
void disasm_print_insn(unsigned char *image, ssize_t len, int opcodes,
const char *arch, const char *disassembler_options,
const struct btf *btf,
const struct bpf_prog_linfo *prog_linfo,
__u64 func_ksym, unsigned int func_idx,
bool linum);
int disasm_print_insn(unsigned char *image, ssize_t len, int opcodes,
const char *arch, const char *disassembler_options,
const struct btf *btf,
const struct bpf_prog_linfo *prog_linfo,
__u64 func_ksym, unsigned int func_idx,
bool linum);
int disasm_init(void);
#else
static inline
void disasm_print_insn(unsigned char *image, ssize_t len, int opcodes,
const char *arch, const char *disassembler_options,
const struct btf *btf,
const struct bpf_prog_linfo *prog_linfo,
__u64 func_ksym, unsigned int func_idx,
bool linum)
int disasm_print_insn(unsigned char *image, ssize_t len, int opcodes,
const char *arch, const char *disassembler_options,
const struct btf *btf,
const struct bpf_prog_linfo *prog_linfo,
__u64 func_ksym, unsigned int func_idx,
bool linum)
{
return 0;
}
static inline int disasm_init(void)
{

View File

@@ -1,7 +1,6 @@
// SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
/* Copyright (C) 2017-2018 Netronome Systems, Inc. */
#include <assert.h>
#include <errno.h>
#include <fcntl.h>
#include <linux/err.h>

View File

@@ -820,10 +820,18 @@ prog_dump(struct bpf_prog_info *info, enum dump_mode mode,
printf("%s:\n", sym_name);
}
disasm_print_insn(img, lens[i], opcodes,
name, disasm_opt, btf,
prog_linfo, ksyms[i], i,
linum);
if (ksyms) {
if (disasm_print_insn(img, lens[i], opcodes,
name, disasm_opt, btf,
prog_linfo, ksyms[i], i,
linum))
goto exit_free;
} else {
if (disasm_print_insn(img, lens[i], opcodes,
name, disasm_opt, btf,
NULL, 0, 0, false))
goto exit_free;
}
img += lens[i];
@@ -836,8 +844,10 @@ prog_dump(struct bpf_prog_info *info, enum dump_mode mode,
if (json_output)
jsonw_end_array(json_wtr);
} else {
disasm_print_insn(buf, member_len, opcodes, name,
disasm_opt, btf, NULL, 0, 0, false);
if (disasm_print_insn(buf, member_len, opcodes, name,
disasm_opt, btf, NULL, 0, 0,
false))
goto exit_free;
}
} else if (visual) {
if (json_output)

View File

@@ -7,8 +7,8 @@ HOSTARCH := $(shell uname -m | sed -e s/i.86/x86/ -e s/x86_64/x86/ \
-e s/sh[234].*/sh/ -e s/aarch64.*/arm64/ \
-e s/riscv.*/riscv/)
ifndef ARCH
ARCH := $(HOSTARCH)
ifeq ($(strip $(ARCH)),)
override ARCH := $(HOSTARCH)
endif
SRCARCH := $(ARCH)

View File

@@ -182,6 +182,9 @@ int exec_sign_all(struct signatures *signed_vals, size_t val)
return -1;
}
close(new_stdin[1]);
close(new_stdout[0]);
return 0;
}