mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-06 10:58:48 +09:00
Merge tag 'v6.6.60' of git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable into odroid-6.6.y
This is the 6.6.60 stable release Change-Id: I469b0866ad244ccf932686ca8eba494ae5729a74
This commit is contained in:
2
Makefile
2
Makefile
@@ -1,7 +1,7 @@
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
VERSION = 6
|
||||
PATCHLEVEL = 6
|
||||
SUBLEVEL = 59
|
||||
SUBLEVEL = 60
|
||||
EXTRAVERSION =
|
||||
NAME = Pinguïn Aangedreven
|
||||
|
||||
|
||||
@@ -352,7 +352,7 @@
|
||||
};
|
||||
|
||||
flexspi2: spi@29810000 {
|
||||
compatible = "nxp,imx8mm-fspi";
|
||||
compatible = "nxp,imx8ulp-fspi";
|
||||
reg = <0x29810000 0x10000>, <0x60000000 0x10000000>;
|
||||
reg-names = "fspi_base", "fspi_mmap";
|
||||
#address-cells = <1>;
|
||||
|
||||
@@ -204,7 +204,7 @@ void __init __iomem *__acpi_map_table(unsigned long phys, unsigned long size)
|
||||
if (!size)
|
||||
return NULL;
|
||||
|
||||
return early_ioremap(phys, size);
|
||||
return early_memremap(phys, size);
|
||||
}
|
||||
|
||||
void __init __acpi_unmap_table(void __iomem *map, unsigned long size)
|
||||
@@ -212,7 +212,7 @@ void __init __acpi_unmap_table(void __iomem *map, unsigned long size)
|
||||
if (!map || !size)
|
||||
return;
|
||||
|
||||
early_iounmap(map, size);
|
||||
early_memunmap(map, size);
|
||||
}
|
||||
|
||||
void __iomem *acpi_os_ioremap(acpi_physical_address phys, acpi_size size)
|
||||
|
||||
@@ -4,8 +4,6 @@
|
||||
* Copyright (C) 2017 SiFive
|
||||
*/
|
||||
|
||||
#define GENERATING_ASM_OFFSETS
|
||||
|
||||
#include <linux/kbuild.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/sched.h>
|
||||
|
||||
@@ -65,7 +65,7 @@ void arch_cpuhp_cleanup_dead_cpu(unsigned int cpu)
|
||||
if (cpu_ops[cpu]->cpu_is_stopped)
|
||||
ret = cpu_ops[cpu]->cpu_is_stopped(cpu);
|
||||
if (ret)
|
||||
pr_warn("CPU%d may not have stopped: %d\n", cpu, ret);
|
||||
pr_warn("CPU%u may not have stopped: %d\n", cpu, ret);
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -64,7 +64,7 @@ extra_header_fields:
|
||||
.long efi_header_end - _start // SizeOfHeaders
|
||||
.long 0 // CheckSum
|
||||
.short IMAGE_SUBSYSTEM_EFI_APPLICATION // Subsystem
|
||||
.short 0 // DllCharacteristics
|
||||
.short IMAGE_DLL_CHARACTERISTICS_NX_COMPAT // DllCharacteristics
|
||||
.quad 0 // SizeOfStackReserve
|
||||
.quad 0 // SizeOfStackCommit
|
||||
.quad 0 // SizeOfHeapReserve
|
||||
|
||||
@@ -132,8 +132,6 @@
|
||||
#define REG_PTR(insn, pos, regs) \
|
||||
(ulong *)((ulong)(regs) + REG_OFFSET(insn, pos))
|
||||
|
||||
#define GET_RM(insn) (((insn) >> 12) & 7)
|
||||
|
||||
#define GET_RS1(insn, regs) (*REG_PTR(insn, SH_RS1, regs))
|
||||
#define GET_RS2(insn, regs) (*REG_PTR(insn, SH_RS2, regs))
|
||||
#define GET_RS1S(insn, regs) (*REG_PTR(RVC_RS1S(insn), 0, regs))
|
||||
|
||||
@@ -18,6 +18,7 @@ obj-vdso = $(patsubst %, %.o, $(vdso-syms)) note.o
|
||||
|
||||
ccflags-y := -fno-stack-protector
|
||||
ccflags-y += -DDISABLE_BRANCH_PROFILING
|
||||
ccflags-y += -fno-builtin
|
||||
|
||||
ifneq ($(c-gettimeofday-y),)
|
||||
CFLAGS_vgettimeofday.o += -fPIC -include $(c-gettimeofday-y)
|
||||
|
||||
@@ -13,6 +13,18 @@
|
||||
#define INSN_UD2 0x0b0f
|
||||
#define LEN_UD2 2
|
||||
|
||||
/*
|
||||
* In clang we have UD1s reporting UBSAN failures on X86, 64 and 32bit.
|
||||
*/
|
||||
#define INSN_ASOP 0x67
|
||||
#define OPCODE_ESCAPE 0x0f
|
||||
#define SECOND_BYTE_OPCODE_UD1 0xb9
|
||||
#define SECOND_BYTE_OPCODE_UD2 0x0b
|
||||
|
||||
#define BUG_NONE 0xffff
|
||||
#define BUG_UD1 0xfffe
|
||||
#define BUG_UD2 0xfffd
|
||||
|
||||
#ifdef CONFIG_GENERIC_BUG
|
||||
|
||||
#ifdef CONFIG_X86_32
|
||||
|
||||
@@ -41,6 +41,7 @@
|
||||
#include <linux/hardirq.h>
|
||||
#include <linux/atomic.h>
|
||||
#include <linux/iommu.h>
|
||||
#include <linux/ubsan.h>
|
||||
|
||||
#include <asm/stacktrace.h>
|
||||
#include <asm/processor.h>
|
||||
@@ -89,6 +90,47 @@ __always_inline int is_valid_bugaddr(unsigned long addr)
|
||||
return *(unsigned short *)addr == INSN_UD2;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check for UD1 or UD2, accounting for Address Size Override Prefixes.
|
||||
* If it's a UD1, get the ModRM byte to pass along to UBSan.
|
||||
*/
|
||||
__always_inline int decode_bug(unsigned long addr, u32 *imm)
|
||||
{
|
||||
u8 v;
|
||||
|
||||
if (addr < TASK_SIZE_MAX)
|
||||
return BUG_NONE;
|
||||
|
||||
v = *(u8 *)(addr++);
|
||||
if (v == INSN_ASOP)
|
||||
v = *(u8 *)(addr++);
|
||||
if (v != OPCODE_ESCAPE)
|
||||
return BUG_NONE;
|
||||
|
||||
v = *(u8 *)(addr++);
|
||||
if (v == SECOND_BYTE_OPCODE_UD2)
|
||||
return BUG_UD2;
|
||||
|
||||
if (!IS_ENABLED(CONFIG_UBSAN_TRAP) || v != SECOND_BYTE_OPCODE_UD1)
|
||||
return BUG_NONE;
|
||||
|
||||
/* Retrieve the immediate (type value) for the UBSAN UD1 */
|
||||
v = *(u8 *)(addr++);
|
||||
if (X86_MODRM_RM(v) == 4)
|
||||
addr++;
|
||||
|
||||
*imm = 0;
|
||||
if (X86_MODRM_MOD(v) == 1)
|
||||
*imm = *(u8 *)addr;
|
||||
else if (X86_MODRM_MOD(v) == 2)
|
||||
*imm = *(u32 *)addr;
|
||||
else
|
||||
WARN_ONCE(1, "Unexpected MODRM_MOD: %u\n", X86_MODRM_MOD(v));
|
||||
|
||||
return BUG_UD1;
|
||||
}
|
||||
|
||||
|
||||
static nokprobe_inline int
|
||||
do_trap_no_signal(struct task_struct *tsk, int trapnr, const char *str,
|
||||
struct pt_regs *regs, long error_code)
|
||||
@@ -214,30 +256,37 @@ static inline void handle_invalid_op(struct pt_regs *regs)
|
||||
static noinstr bool handle_bug(struct pt_regs *regs)
|
||||
{
|
||||
bool handled = false;
|
||||
int ud_type;
|
||||
u32 imm;
|
||||
|
||||
/*
|
||||
* Normally @regs are unpoisoned by irqentry_enter(), but handle_bug()
|
||||
* is a rare case that uses @regs without passing them to
|
||||
* irqentry_enter().
|
||||
*/
|
||||
kmsan_unpoison_entry_regs(regs);
|
||||
if (!is_valid_bugaddr(regs->ip))
|
||||
ud_type = decode_bug(regs->ip, &imm);
|
||||
if (ud_type == BUG_NONE)
|
||||
return handled;
|
||||
|
||||
/*
|
||||
* All lies, just get the WARN/BUG out.
|
||||
*/
|
||||
instrumentation_begin();
|
||||
/*
|
||||
* Normally @regs are unpoisoned by irqentry_enter(), but handle_bug()
|
||||
* is a rare case that uses @regs without passing them to
|
||||
* irqentry_enter().
|
||||
*/
|
||||
kmsan_unpoison_entry_regs(regs);
|
||||
/*
|
||||
* Since we're emulating a CALL with exceptions, restore the interrupt
|
||||
* state to what it was at the exception site.
|
||||
*/
|
||||
if (regs->flags & X86_EFLAGS_IF)
|
||||
raw_local_irq_enable();
|
||||
if (report_bug(regs->ip, regs) == BUG_TRAP_TYPE_WARN ||
|
||||
handle_cfi_failure(regs) == BUG_TRAP_TYPE_WARN) {
|
||||
regs->ip += LEN_UD2;
|
||||
handled = true;
|
||||
if (ud_type == BUG_UD2) {
|
||||
if (report_bug(regs->ip, regs) == BUG_TRAP_TYPE_WARN ||
|
||||
handle_cfi_failure(regs) == BUG_TRAP_TYPE_WARN) {
|
||||
regs->ip += LEN_UD2;
|
||||
handled = true;
|
||||
}
|
||||
} else if (IS_ENABLED(CONFIG_UBSAN_TRAP)) {
|
||||
pr_crit("%s at %pS\n", report_ubsan_failure(regs, imm), (void *)regs->ip);
|
||||
}
|
||||
if (regs->flags & X86_EFLAGS_IF)
|
||||
raw_local_irq_disable();
|
||||
|
||||
@@ -600,9 +600,7 @@ static int blk_rq_map_user_bvec(struct request *rq, const struct iov_iter *iter)
|
||||
if (nsegs >= nr_segs || bytes > UINT_MAX - bv->bv_len)
|
||||
goto put_bio;
|
||||
if (bytes + bv->bv_len > nr_iter)
|
||||
goto put_bio;
|
||||
if (bv->bv_offset + bv->bv_len > PAGE_SIZE)
|
||||
goto put_bio;
|
||||
break;
|
||||
|
||||
nsegs++;
|
||||
bytes += bv->bv_len;
|
||||
|
||||
@@ -863,7 +863,7 @@ int acpi_cppc_processor_probe(struct acpi_processor *pr)
|
||||
|
||||
/* Store CPU Logical ID */
|
||||
cpc_ptr->cpu_id = pr->id;
|
||||
spin_lock_init(&cpc_ptr->rmw_lock);
|
||||
raw_spin_lock_init(&cpc_ptr->rmw_lock);
|
||||
|
||||
/* Parse PSD data for this CPU */
|
||||
ret = acpi_get_psd(cpc_ptr, handle);
|
||||
@@ -1083,6 +1083,7 @@ static int cpc_write(int cpu, struct cpc_register_resource *reg_res, u64 val)
|
||||
int pcc_ss_id = per_cpu(cpu_pcc_subspace_idx, cpu);
|
||||
struct cpc_reg *reg = ®_res->cpc_entry.reg;
|
||||
struct cpc_desc *cpc_desc;
|
||||
unsigned long flags;
|
||||
|
||||
size = GET_BIT_WIDTH(reg);
|
||||
|
||||
@@ -1122,7 +1123,7 @@ static int cpc_write(int cpu, struct cpc_register_resource *reg_res, u64 val)
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
spin_lock(&cpc_desc->rmw_lock);
|
||||
raw_spin_lock_irqsave(&cpc_desc->rmw_lock, flags);
|
||||
switch (size) {
|
||||
case 8:
|
||||
prev_val = readb_relaxed(vaddr);
|
||||
@@ -1137,7 +1138,7 @@ static int cpc_write(int cpu, struct cpc_register_resource *reg_res, u64 val)
|
||||
prev_val = readq_relaxed(vaddr);
|
||||
break;
|
||||
default:
|
||||
spin_unlock(&cpc_desc->rmw_lock);
|
||||
raw_spin_unlock_irqrestore(&cpc_desc->rmw_lock, flags);
|
||||
return -EFAULT;
|
||||
}
|
||||
val = MASK_VAL_WRITE(reg, prev_val, val);
|
||||
@@ -1170,7 +1171,7 @@ static int cpc_write(int cpu, struct cpc_register_resource *reg_res, u64 val)
|
||||
}
|
||||
|
||||
if (reg->space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY)
|
||||
spin_unlock(&cpc_desc->rmw_lock);
|
||||
raw_spin_unlock_irqrestore(&cpc_desc->rmw_lock, flags);
|
||||
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
@@ -25,7 +25,6 @@
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
#include <linux/netdevice.h>
|
||||
#include <linux/rcupdate.h>
|
||||
#include <linux/sched/signal.h>
|
||||
#include <linux/sched/mm.h>
|
||||
#include <linux/string_helpers.h>
|
||||
@@ -2566,7 +2565,6 @@ static const char *dev_uevent_name(const struct kobject *kobj)
|
||||
static int dev_uevent(const struct kobject *kobj, struct kobj_uevent_env *env)
|
||||
{
|
||||
const struct device *dev = kobj_to_dev(kobj);
|
||||
struct device_driver *driver;
|
||||
int retval = 0;
|
||||
|
||||
/* add device node properties if present */
|
||||
@@ -2595,12 +2593,8 @@ static int dev_uevent(const struct kobject *kobj, struct kobj_uevent_env *env)
|
||||
if (dev->type && dev->type->name)
|
||||
add_uevent_var(env, "DEVTYPE=%s", dev->type->name);
|
||||
|
||||
/* Synchronize with module_remove_driver() */
|
||||
rcu_read_lock();
|
||||
driver = READ_ONCE(dev->driver);
|
||||
if (driver)
|
||||
add_uevent_var(env, "DRIVER=%s", driver->name);
|
||||
rcu_read_unlock();
|
||||
if (dev->driver)
|
||||
add_uevent_var(env, "DRIVER=%s", dev->driver->name);
|
||||
|
||||
/* Add common DT information about the device */
|
||||
of_device_uevent(dev, env);
|
||||
@@ -2670,8 +2664,11 @@ static ssize_t uevent_show(struct device *dev, struct device_attribute *attr,
|
||||
if (!env)
|
||||
return -ENOMEM;
|
||||
|
||||
/* Synchronize with really_probe() */
|
||||
device_lock(dev);
|
||||
/* let the kset specific function add its keys */
|
||||
retval = kset->uevent_ops->uevent(&dev->kobj, env);
|
||||
device_unlock(dev);
|
||||
if (retval)
|
||||
goto out;
|
||||
|
||||
@@ -4014,6 +4011,41 @@ int device_for_each_child_reverse(struct device *parent, void *data,
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(device_for_each_child_reverse);
|
||||
|
||||
/**
|
||||
* device_for_each_child_reverse_from - device child iterator in reversed order.
|
||||
* @parent: parent struct device.
|
||||
* @from: optional starting point in child list
|
||||
* @fn: function to be called for each device.
|
||||
* @data: data for the callback.
|
||||
*
|
||||
* Iterate over @parent's child devices, starting at @from, and call @fn
|
||||
* for each, passing it @data. This helper is identical to
|
||||
* device_for_each_child_reverse() when @from is NULL.
|
||||
*
|
||||
* @fn is checked each iteration. If it returns anything other than 0,
|
||||
* iteration stop and that value is returned to the caller of
|
||||
* device_for_each_child_reverse_from();
|
||||
*/
|
||||
int device_for_each_child_reverse_from(struct device *parent,
|
||||
struct device *from, const void *data,
|
||||
int (*fn)(struct device *, const void *))
|
||||
{
|
||||
struct klist_iter i;
|
||||
struct device *child;
|
||||
int error = 0;
|
||||
|
||||
if (!parent->p)
|
||||
return 0;
|
||||
|
||||
klist_iter_init_node(&parent->p->klist_children, &i,
|
||||
(from ? &from->p->knode_parent : NULL));
|
||||
while ((child = prev_device(&i)) && !error)
|
||||
error = fn(child, data);
|
||||
klist_iter_exit(&i);
|
||||
return error;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(device_for_each_child_reverse_from);
|
||||
|
||||
/**
|
||||
* device_find_child - device iterator for locating a particular device.
|
||||
* @parent: parent struct device
|
||||
|
||||
@@ -7,7 +7,6 @@
|
||||
#include <linux/errno.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/rcupdate.h>
|
||||
#include "base.h"
|
||||
|
||||
static char *make_driver_name(struct device_driver *drv)
|
||||
@@ -102,9 +101,6 @@ void module_remove_driver(struct device_driver *drv)
|
||||
if (!drv)
|
||||
return;
|
||||
|
||||
/* Synchronize with dev_uevent() */
|
||||
synchronize_rcu();
|
||||
|
||||
sysfs_remove_link(&drv->p->kobj, "module");
|
||||
|
||||
if (drv->owner)
|
||||
|
||||
@@ -768,6 +768,13 @@ static void __exit cxl_acpi_exit(void)
|
||||
|
||||
/* load before dax_hmem sees 'Soft Reserved' CXL ranges */
|
||||
subsys_initcall(cxl_acpi_init);
|
||||
|
||||
/*
|
||||
* Arrange for host-bridge ports to be active synchronous with
|
||||
* cxl_acpi_probe() exit.
|
||||
*/
|
||||
MODULE_SOFTDEP("pre: cxl_port");
|
||||
|
||||
module_exit(cxl_acpi_exit);
|
||||
MODULE_LICENSE("GPL v2");
|
||||
MODULE_IMPORT_NS(CXL);
|
||||
|
||||
@@ -723,7 +723,44 @@ static int cxl_decoder_commit(struct cxl_decoder *cxld)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cxl_decoder_reset(struct cxl_decoder *cxld)
|
||||
static int commit_reap(struct device *dev, const void *data)
|
||||
{
|
||||
struct cxl_port *port = to_cxl_port(dev->parent);
|
||||
struct cxl_decoder *cxld;
|
||||
|
||||
if (!is_switch_decoder(dev) && !is_endpoint_decoder(dev))
|
||||
return 0;
|
||||
|
||||
cxld = to_cxl_decoder(dev);
|
||||
if (port->commit_end == cxld->id &&
|
||||
((cxld->flags & CXL_DECODER_F_ENABLE) == 0)) {
|
||||
port->commit_end--;
|
||||
dev_dbg(&port->dev, "reap: %s commit_end: %d\n",
|
||||
dev_name(&cxld->dev), port->commit_end);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void cxl_port_commit_reap(struct cxl_decoder *cxld)
|
||||
{
|
||||
struct cxl_port *port = to_cxl_port(cxld->dev.parent);
|
||||
|
||||
lockdep_assert_held_write(&cxl_region_rwsem);
|
||||
|
||||
/*
|
||||
* Once the highest committed decoder is disabled, free any other
|
||||
* decoders that were pinned allocated by out-of-order release.
|
||||
*/
|
||||
port->commit_end--;
|
||||
dev_dbg(&port->dev, "reap: %s commit_end: %d\n", dev_name(&cxld->dev),
|
||||
port->commit_end);
|
||||
device_for_each_child_reverse_from(&port->dev, &cxld->dev, NULL,
|
||||
commit_reap);
|
||||
}
|
||||
EXPORT_SYMBOL_NS_GPL(cxl_port_commit_reap, CXL);
|
||||
|
||||
static void cxl_decoder_reset(struct cxl_decoder *cxld)
|
||||
{
|
||||
struct cxl_port *port = to_cxl_port(cxld->dev.parent);
|
||||
struct cxl_hdm *cxlhdm = dev_get_drvdata(&port->dev);
|
||||
@@ -732,14 +769,14 @@ static int cxl_decoder_reset(struct cxl_decoder *cxld)
|
||||
u32 ctrl;
|
||||
|
||||
if ((cxld->flags & CXL_DECODER_F_ENABLE) == 0)
|
||||
return 0;
|
||||
return;
|
||||
|
||||
if (port->commit_end != id) {
|
||||
if (port->commit_end == id)
|
||||
cxl_port_commit_reap(cxld);
|
||||
else
|
||||
dev_dbg(&port->dev,
|
||||
"%s: out of order reset, expected decoder%d.%d\n",
|
||||
dev_name(&cxld->dev), port->id, port->commit_end);
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
down_read(&cxl_dpa_rwsem);
|
||||
ctrl = readl(hdm + CXL_HDM_DECODER0_CTRL_OFFSET(id));
|
||||
@@ -752,7 +789,6 @@ static int cxl_decoder_reset(struct cxl_decoder *cxld)
|
||||
writel(0, hdm + CXL_HDM_DECODER0_BASE_LOW_OFFSET(id));
|
||||
up_read(&cxl_dpa_rwsem);
|
||||
|
||||
port->commit_end--;
|
||||
cxld->flags &= ~CXL_DECODER_F_ENABLE;
|
||||
|
||||
/* Userspace is now responsible for reconfiguring this decoder */
|
||||
@@ -762,8 +798,6 @@ static int cxl_decoder_reset(struct cxl_decoder *cxld)
|
||||
cxled = to_cxl_endpoint_decoder(&cxld->dev);
|
||||
cxled->state = CXL_DECODER_STATE_MANUAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cxl_setup_hdm_decoder_from_dvsec(
|
||||
|
||||
@@ -1969,11 +1969,18 @@ static void cxl_bus_remove(struct device *dev)
|
||||
|
||||
static struct workqueue_struct *cxl_bus_wq;
|
||||
|
||||
static int cxl_rescan_attach(struct device *dev, void *data)
|
||||
{
|
||||
int rc = device_attach(dev);
|
||||
|
||||
dev_vdbg(dev, "rescan: %s\n", rc ? "attach" : "detached");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void cxl_bus_rescan_queue(struct work_struct *w)
|
||||
{
|
||||
int rc = bus_rescan_devices(&cxl_bus_type);
|
||||
|
||||
pr_debug("CXL bus rescan result: %d\n", rc);
|
||||
bus_for_each_dev(&cxl_bus_type, NULL, NULL, cxl_rescan_attach);
|
||||
}
|
||||
|
||||
void cxl_bus_rescan(void)
|
||||
|
||||
@@ -128,8 +128,8 @@ static int cxl_region_invalidate_memregion(struct cxl_region *cxlr)
|
||||
"Bypassing cpu_cache_invalidate_memregion() for testing!\n");
|
||||
return 0;
|
||||
} else {
|
||||
dev_err(&cxlr->dev,
|
||||
"Failed to synchronize CPU cache state\n");
|
||||
dev_WARN(&cxlr->dev,
|
||||
"Failed to synchronize CPU cache state\n");
|
||||
return -ENXIO;
|
||||
}
|
||||
}
|
||||
@@ -138,19 +138,17 @@ static int cxl_region_invalidate_memregion(struct cxl_region *cxlr)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cxl_region_decode_reset(struct cxl_region *cxlr, int count)
|
||||
static void cxl_region_decode_reset(struct cxl_region *cxlr, int count)
|
||||
{
|
||||
struct cxl_region_params *p = &cxlr->params;
|
||||
int i, rc = 0;
|
||||
int i;
|
||||
|
||||
/*
|
||||
* Before region teardown attempt to flush, and if the flush
|
||||
* fails cancel the region teardown for data consistency
|
||||
* concerns
|
||||
* Before region teardown attempt to flush, evict any data cached for
|
||||
* this region, or scream loudly about missing arch / platform support
|
||||
* for CXL teardown.
|
||||
*/
|
||||
rc = cxl_region_invalidate_memregion(cxlr);
|
||||
if (rc)
|
||||
return rc;
|
||||
cxl_region_invalidate_memregion(cxlr);
|
||||
|
||||
for (i = count - 1; i >= 0; i--) {
|
||||
struct cxl_endpoint_decoder *cxled = p->targets[i];
|
||||
@@ -173,23 +171,17 @@ static int cxl_region_decode_reset(struct cxl_region *cxlr, int count)
|
||||
cxl_rr = cxl_rr_load(iter, cxlr);
|
||||
cxld = cxl_rr->decoder;
|
||||
if (cxld->reset)
|
||||
rc = cxld->reset(cxld);
|
||||
if (rc)
|
||||
return rc;
|
||||
cxld->reset(cxld);
|
||||
set_bit(CXL_REGION_F_NEEDS_RESET, &cxlr->flags);
|
||||
}
|
||||
|
||||
endpoint_reset:
|
||||
rc = cxled->cxld.reset(&cxled->cxld);
|
||||
if (rc)
|
||||
return rc;
|
||||
cxled->cxld.reset(&cxled->cxld);
|
||||
set_bit(CXL_REGION_F_NEEDS_RESET, &cxlr->flags);
|
||||
}
|
||||
|
||||
/* all decoders associated with this region have been torn down */
|
||||
clear_bit(CXL_REGION_F_NEEDS_RESET, &cxlr->flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int commit_decoder(struct cxl_decoder *cxld)
|
||||
@@ -305,16 +297,8 @@ static ssize_t commit_store(struct device *dev, struct device_attribute *attr,
|
||||
* still pending.
|
||||
*/
|
||||
if (p->state == CXL_CONFIG_RESET_PENDING) {
|
||||
rc = cxl_region_decode_reset(cxlr, p->interleave_ways);
|
||||
/*
|
||||
* Revert to committed since there may still be active
|
||||
* decoders associated with this region, or move forward
|
||||
* to active to mark the reset successful
|
||||
*/
|
||||
if (rc)
|
||||
p->state = CXL_CONFIG_COMMIT;
|
||||
else
|
||||
p->state = CXL_CONFIG_ACTIVE;
|
||||
cxl_region_decode_reset(cxlr, p->interleave_ways);
|
||||
p->state = CXL_CONFIG_ACTIVE;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1945,13 +1929,7 @@ static int cxl_region_detach(struct cxl_endpoint_decoder *cxled)
|
||||
get_device(&cxlr->dev);
|
||||
|
||||
if (p->state > CXL_CONFIG_ACTIVE) {
|
||||
/*
|
||||
* TODO: tear down all impacted regions if a device is
|
||||
* removed out of order
|
||||
*/
|
||||
rc = cxl_region_decode_reset(cxlr, p->interleave_ways);
|
||||
if (rc)
|
||||
goto out;
|
||||
cxl_region_decode_reset(cxlr, p->interleave_ways);
|
||||
p->state = CXL_CONFIG_ACTIVE;
|
||||
}
|
||||
|
||||
|
||||
@@ -278,7 +278,7 @@ TRACE_EVENT(cxl_generic_event,
|
||||
#define CXL_GMER_MEM_EVT_TYPE_ECC_ERROR 0x00
|
||||
#define CXL_GMER_MEM_EVT_TYPE_INV_ADDR 0x01
|
||||
#define CXL_GMER_MEM_EVT_TYPE_DATA_PATH_ERROR 0x02
|
||||
#define show_mem_event_type(type) __print_symbolic(type, \
|
||||
#define show_gmer_mem_event_type(type) __print_symbolic(type, \
|
||||
{ CXL_GMER_MEM_EVT_TYPE_ECC_ERROR, "ECC Error" }, \
|
||||
{ CXL_GMER_MEM_EVT_TYPE_INV_ADDR, "Invalid Address" }, \
|
||||
{ CXL_GMER_MEM_EVT_TYPE_DATA_PATH_ERROR, "Data Path Error" } \
|
||||
@@ -359,7 +359,7 @@ TRACE_EVENT(cxl_general_media,
|
||||
"device=%x comp_id=%s validity_flags='%s'",
|
||||
__entry->dpa, show_dpa_flags(__entry->dpa_flags),
|
||||
show_event_desc_flags(__entry->descriptor),
|
||||
show_mem_event_type(__entry->type),
|
||||
show_gmer_mem_event_type(__entry->type),
|
||||
show_trans_type(__entry->transaction_type),
|
||||
__entry->channel, __entry->rank, __entry->device,
|
||||
__print_hex(__entry->comp_id, CXL_EVENT_GEN_MED_COMP_ID_SIZE),
|
||||
@@ -376,6 +376,17 @@ TRACE_EVENT(cxl_general_media,
|
||||
* DRAM Event Record defines many fields the same as the General Media Event
|
||||
* Record. Reuse those definitions as appropriate.
|
||||
*/
|
||||
#define CXL_DER_MEM_EVT_TYPE_ECC_ERROR 0x00
|
||||
#define CXL_DER_MEM_EVT_TYPE_SCRUB_MEDIA_ECC_ERROR 0x01
|
||||
#define CXL_DER_MEM_EVT_TYPE_INV_ADDR 0x02
|
||||
#define CXL_DER_MEM_EVT_TYPE_DATA_PATH_ERROR 0x03
|
||||
#define show_dram_mem_event_type(type) __print_symbolic(type, \
|
||||
{ CXL_DER_MEM_EVT_TYPE_ECC_ERROR, "ECC Error" }, \
|
||||
{ CXL_DER_MEM_EVT_TYPE_SCRUB_MEDIA_ECC_ERROR, "Scrub Media ECC Error" }, \
|
||||
{ CXL_DER_MEM_EVT_TYPE_INV_ADDR, "Invalid Address" }, \
|
||||
{ CXL_DER_MEM_EVT_TYPE_DATA_PATH_ERROR, "Data Path Error" } \
|
||||
)
|
||||
|
||||
#define CXL_DER_VALID_CHANNEL BIT(0)
|
||||
#define CXL_DER_VALID_RANK BIT(1)
|
||||
#define CXL_DER_VALID_NIBBLE BIT(2)
|
||||
@@ -449,7 +460,7 @@ TRACE_EVENT(cxl_dram,
|
||||
"validity_flags='%s'",
|
||||
__entry->dpa, show_dpa_flags(__entry->dpa_flags),
|
||||
show_event_desc_flags(__entry->descriptor),
|
||||
show_mem_event_type(__entry->type),
|
||||
show_dram_mem_event_type(__entry->type),
|
||||
show_trans_type(__entry->transaction_type),
|
||||
__entry->channel, __entry->rank, __entry->nibble_mask,
|
||||
__entry->bank_group, __entry->bank,
|
||||
|
||||
@@ -347,7 +347,7 @@ struct cxl_decoder {
|
||||
struct cxl_region *region;
|
||||
unsigned long flags;
|
||||
int (*commit)(struct cxl_decoder *cxld);
|
||||
int (*reset)(struct cxl_decoder *cxld);
|
||||
void (*reset)(struct cxl_decoder *cxld);
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -682,6 +682,7 @@ static inline bool is_cxl_root(struct cxl_port *port)
|
||||
int cxl_num_decoders_committed(struct cxl_port *port);
|
||||
bool is_cxl_port(const struct device *dev);
|
||||
struct cxl_port *to_cxl_port(const struct device *dev);
|
||||
void cxl_port_commit_reap(struct cxl_decoder *cxld);
|
||||
struct pci_bus;
|
||||
int devm_cxl_register_pci_bus(struct device *host, struct device *uport_dev,
|
||||
struct pci_bus *bus);
|
||||
|
||||
@@ -763,7 +763,7 @@ static int sdei_device_freeze(struct device *dev)
|
||||
int err;
|
||||
|
||||
/* unregister private events */
|
||||
cpuhp_remove_state(sdei_entry_point);
|
||||
cpuhp_remove_state(sdei_hp_state);
|
||||
|
||||
err = sdei_unregister_shared();
|
||||
if (err)
|
||||
|
||||
@@ -735,6 +735,9 @@ bool dcn30_apply_idle_power_optimizations(struct dc *dc, bool enable)
|
||||
stream = dc->current_state->streams[0];
|
||||
plane = (stream ? dc->current_state->stream_status[0].plane_states[0] : NULL);
|
||||
|
||||
if (!stream || !plane)
|
||||
return false;
|
||||
|
||||
if (stream && plane) {
|
||||
cursor_cache_enable = stream->cursor_position.enable &&
|
||||
plane->address.grph.cursor_cache_addr.quad_part;
|
||||
|
||||
@@ -643,7 +643,7 @@ static int ad7124_write_raw(struct iio_dev *indio_dev,
|
||||
|
||||
switch (info) {
|
||||
case IIO_CHAN_INFO_SAMP_FREQ:
|
||||
if (val2 != 0) {
|
||||
if (val2 != 0 || val == 0) {
|
||||
ret = -EINVAL;
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -307,13 +307,15 @@ static int iio_gts_build_avail_scale_table(struct iio_gts *gts)
|
||||
if (ret)
|
||||
goto err_free_out;
|
||||
|
||||
for (i = 0; i < gts->num_itime; i++)
|
||||
kfree(per_time_gains[i]);
|
||||
kfree(per_time_gains);
|
||||
gts->per_time_avail_scale_tables = per_time_scales;
|
||||
|
||||
return 0;
|
||||
|
||||
err_free_out:
|
||||
for (i--; i; i--) {
|
||||
for (i--; i >= 0; i--) {
|
||||
kfree(per_time_scales[i]);
|
||||
kfree(per_time_gains[i]);
|
||||
}
|
||||
|
||||
@@ -522,7 +522,7 @@ static int veml6030_read_raw(struct iio_dev *indio_dev,
|
||||
}
|
||||
if (mask == IIO_CHAN_INFO_PROCESSED) {
|
||||
*val = (reg * data->cur_resolution) / 10000;
|
||||
*val2 = (reg * data->cur_resolution) % 10000;
|
||||
*val2 = (reg * data->cur_resolution) % 10000 * 100;
|
||||
return IIO_VAL_INT_PLUS_MICRO;
|
||||
}
|
||||
*val = reg;
|
||||
|
||||
@@ -1513,9 +1513,11 @@ int bnxt_qplib_destroy_qp(struct bnxt_qplib_res *res,
|
||||
u32 tbl_indx;
|
||||
int rc;
|
||||
|
||||
spin_lock_bh(&rcfw->tbl_lock);
|
||||
tbl_indx = map_qp_id_to_tbl_indx(qp->id, rcfw);
|
||||
rcfw->qp_tbl[tbl_indx].qp_id = BNXT_QPLIB_QP_ID_INVALID;
|
||||
rcfw->qp_tbl[tbl_indx].qp_handle = NULL;
|
||||
spin_unlock_bh(&rcfw->tbl_lock);
|
||||
|
||||
bnxt_qplib_rcfw_cmd_prep((struct cmdq_base *)&req,
|
||||
CMDQ_BASE_OPCODE_DESTROY_QP,
|
||||
@@ -1526,8 +1528,10 @@ int bnxt_qplib_destroy_qp(struct bnxt_qplib_res *res,
|
||||
sizeof(resp), 0);
|
||||
rc = bnxt_qplib_rcfw_send_message(rcfw, &msg);
|
||||
if (rc) {
|
||||
spin_lock_bh(&rcfw->tbl_lock);
|
||||
rcfw->qp_tbl[tbl_indx].qp_id = qp->id;
|
||||
rcfw->qp_tbl[tbl_indx].qp_handle = qp;
|
||||
spin_unlock_bh(&rcfw->tbl_lock);
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
@@ -290,7 +290,6 @@ static int __send_message(struct bnxt_qplib_rcfw *rcfw,
|
||||
struct bnxt_qplib_hwq *hwq;
|
||||
u32 sw_prod, cmdq_prod;
|
||||
struct pci_dev *pdev;
|
||||
unsigned long flags;
|
||||
u16 cookie;
|
||||
u8 *preq;
|
||||
|
||||
@@ -301,7 +300,7 @@ static int __send_message(struct bnxt_qplib_rcfw *rcfw,
|
||||
/* Cmdq are in 16-byte units, each request can consume 1 or more
|
||||
* cmdqe
|
||||
*/
|
||||
spin_lock_irqsave(&hwq->lock, flags);
|
||||
spin_lock_bh(&hwq->lock);
|
||||
required_slots = bnxt_qplib_get_cmd_slots(msg->req);
|
||||
free_slots = HWQ_FREE_SLOTS(hwq);
|
||||
cookie = cmdq->seq_num & RCFW_MAX_COOKIE_VALUE;
|
||||
@@ -311,7 +310,7 @@ static int __send_message(struct bnxt_qplib_rcfw *rcfw,
|
||||
dev_info_ratelimited(&pdev->dev,
|
||||
"CMDQ is full req/free %d/%d!",
|
||||
required_slots, free_slots);
|
||||
spin_unlock_irqrestore(&hwq->lock, flags);
|
||||
spin_unlock_bh(&hwq->lock);
|
||||
return -EAGAIN;
|
||||
}
|
||||
if (msg->block)
|
||||
@@ -367,7 +366,7 @@ static int __send_message(struct bnxt_qplib_rcfw *rcfw,
|
||||
wmb();
|
||||
writel(cmdq_prod, cmdq->cmdq_mbox.prod);
|
||||
writel(RCFW_CMDQ_TRIG_VAL, cmdq->cmdq_mbox.db);
|
||||
spin_unlock_irqrestore(&hwq->lock, flags);
|
||||
spin_unlock_bh(&hwq->lock);
|
||||
/* Return the CREQ response pointer */
|
||||
return 0;
|
||||
}
|
||||
@@ -486,7 +485,6 @@ static int __bnxt_qplib_rcfw_send_message(struct bnxt_qplib_rcfw *rcfw,
|
||||
{
|
||||
struct creq_qp_event *evnt = (struct creq_qp_event *)msg->resp;
|
||||
struct bnxt_qplib_crsqe *crsqe;
|
||||
unsigned long flags;
|
||||
u16 cookie;
|
||||
int rc;
|
||||
u8 opcode;
|
||||
@@ -512,12 +510,12 @@ static int __bnxt_qplib_rcfw_send_message(struct bnxt_qplib_rcfw *rcfw,
|
||||
rc = __poll_for_resp(rcfw, cookie);
|
||||
|
||||
if (rc) {
|
||||
spin_lock_irqsave(&rcfw->cmdq.hwq.lock, flags);
|
||||
spin_lock_bh(&rcfw->cmdq.hwq.lock);
|
||||
crsqe = &rcfw->crsqe_tbl[cookie];
|
||||
crsqe->is_waiter_alive = false;
|
||||
if (rc == -ENODEV)
|
||||
set_bit(FIRMWARE_STALL_DETECTED, &rcfw->cmdq.flags);
|
||||
spin_unlock_irqrestore(&rcfw->cmdq.hwq.lock, flags);
|
||||
spin_unlock_bh(&rcfw->cmdq.hwq.lock);
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
|
||||
@@ -628,7 +626,6 @@ static int bnxt_qplib_process_qp_event(struct bnxt_qplib_rcfw *rcfw,
|
||||
u16 cookie, blocked = 0;
|
||||
bool is_waiter_alive;
|
||||
struct pci_dev *pdev;
|
||||
unsigned long flags;
|
||||
u32 wait_cmds = 0;
|
||||
int rc = 0;
|
||||
|
||||
@@ -637,17 +634,21 @@ static int bnxt_qplib_process_qp_event(struct bnxt_qplib_rcfw *rcfw,
|
||||
case CREQ_QP_EVENT_EVENT_QP_ERROR_NOTIFICATION:
|
||||
err_event = (struct creq_qp_error_notification *)qp_event;
|
||||
qp_id = le32_to_cpu(err_event->xid);
|
||||
spin_lock(&rcfw->tbl_lock);
|
||||
tbl_indx = map_qp_id_to_tbl_indx(qp_id, rcfw);
|
||||
qp = rcfw->qp_tbl[tbl_indx].qp_handle;
|
||||
if (!qp) {
|
||||
spin_unlock(&rcfw->tbl_lock);
|
||||
break;
|
||||
}
|
||||
bnxt_qplib_mark_qp_error(qp);
|
||||
rc = rcfw->creq.aeq_handler(rcfw, qp_event, qp);
|
||||
spin_unlock(&rcfw->tbl_lock);
|
||||
dev_dbg(&pdev->dev, "Received QP error notification\n");
|
||||
dev_dbg(&pdev->dev,
|
||||
"qpid 0x%x, req_err=0x%x, resp_err=0x%x\n",
|
||||
qp_id, err_event->req_err_state_reason,
|
||||
err_event->res_err_state_reason);
|
||||
if (!qp)
|
||||
break;
|
||||
bnxt_qplib_mark_qp_error(qp);
|
||||
rc = rcfw->creq.aeq_handler(rcfw, qp_event, qp);
|
||||
break;
|
||||
default:
|
||||
/*
|
||||
@@ -659,8 +660,7 @@ static int bnxt_qplib_process_qp_event(struct bnxt_qplib_rcfw *rcfw,
|
||||
*
|
||||
*/
|
||||
|
||||
spin_lock_irqsave_nested(&hwq->lock, flags,
|
||||
SINGLE_DEPTH_NESTING);
|
||||
spin_lock_nested(&hwq->lock, SINGLE_DEPTH_NESTING);
|
||||
cookie = le16_to_cpu(qp_event->cookie);
|
||||
blocked = cookie & RCFW_CMD_IS_BLOCKING;
|
||||
cookie &= RCFW_MAX_COOKIE_VALUE;
|
||||
@@ -672,7 +672,7 @@ static int bnxt_qplib_process_qp_event(struct bnxt_qplib_rcfw *rcfw,
|
||||
dev_info(&pdev->dev,
|
||||
"rcfw timedout: cookie = %#x, free_slots = %d",
|
||||
cookie, crsqe->free_slots);
|
||||
spin_unlock_irqrestore(&hwq->lock, flags);
|
||||
spin_unlock(&hwq->lock);
|
||||
return rc;
|
||||
}
|
||||
|
||||
@@ -720,7 +720,7 @@ static int bnxt_qplib_process_qp_event(struct bnxt_qplib_rcfw *rcfw,
|
||||
__destroy_timedout_ah(rcfw,
|
||||
(struct creq_create_ah_resp *)
|
||||
qp_event);
|
||||
spin_unlock_irqrestore(&hwq->lock, flags);
|
||||
spin_unlock(&hwq->lock);
|
||||
}
|
||||
*num_wait += wait_cmds;
|
||||
return rc;
|
||||
@@ -734,12 +734,11 @@ static void bnxt_qplib_service_creq(struct tasklet_struct *t)
|
||||
u32 type, budget = CREQ_ENTRY_POLL_BUDGET;
|
||||
struct bnxt_qplib_hwq *hwq = &creq->hwq;
|
||||
struct creq_base *creqe;
|
||||
unsigned long flags;
|
||||
u32 num_wakeup = 0;
|
||||
u32 hw_polled = 0;
|
||||
|
||||
/* Service the CREQ until budget is over */
|
||||
spin_lock_irqsave(&hwq->lock, flags);
|
||||
spin_lock_bh(&hwq->lock);
|
||||
while (budget > 0) {
|
||||
creqe = bnxt_qplib_get_qe(hwq, hwq->cons, NULL);
|
||||
if (!CREQ_CMP_VALID(creqe, creq->creq_db.dbinfo.flags))
|
||||
@@ -782,7 +781,7 @@ static void bnxt_qplib_service_creq(struct tasklet_struct *t)
|
||||
if (hw_polled)
|
||||
bnxt_qplib_ring_nq_db(&creq->creq_db.dbinfo,
|
||||
rcfw->res->cctx, true);
|
||||
spin_unlock_irqrestore(&hwq->lock, flags);
|
||||
spin_unlock_bh(&hwq->lock);
|
||||
if (num_wakeup)
|
||||
wake_up_nr(&rcfw->cmdq.waitq, num_wakeup);
|
||||
}
|
||||
@@ -978,6 +977,7 @@ int bnxt_qplib_alloc_rcfw_channel(struct bnxt_qplib_res *res,
|
||||
GFP_KERNEL);
|
||||
if (!rcfw->qp_tbl)
|
||||
goto fail;
|
||||
spin_lock_init(&rcfw->tbl_lock);
|
||||
|
||||
rcfw->max_timeout = res->cctx->hwrm_cmd_max_timeout;
|
||||
|
||||
|
||||
@@ -224,6 +224,8 @@ struct bnxt_qplib_rcfw {
|
||||
struct bnxt_qplib_crsqe *crsqe_tbl;
|
||||
int qp_tbl_size;
|
||||
struct bnxt_qplib_qp_node *qp_tbl;
|
||||
/* To synchronize the qp-handle hash table */
|
||||
spinlock_t tbl_lock;
|
||||
u64 oos_prev;
|
||||
u32 init_oos_stats;
|
||||
u32 cmdq_depth;
|
||||
|
||||
@@ -474,6 +474,7 @@ static const struct ib_device_ops c4iw_dev_ops = {
|
||||
.fill_res_cq_entry = c4iw_fill_res_cq_entry,
|
||||
.fill_res_cm_id_entry = c4iw_fill_res_cm_id_entry,
|
||||
.fill_res_mr_entry = c4iw_fill_res_mr_entry,
|
||||
.fill_res_qp_entry = c4iw_fill_res_qp_entry,
|
||||
.get_dev_fw_str = get_dev_fw_str,
|
||||
.get_dma_mr = c4iw_get_dma_mr,
|
||||
.get_hw_stats = c4iw_get_mib,
|
||||
|
||||
@@ -4272,14 +4272,14 @@ static int __mlx5_ib_modify_qp(struct ib_qp *ibqp,
|
||||
MLX5_SET(qpc, qpc, retry_count, attr->retry_cnt);
|
||||
|
||||
if (attr_mask & IB_QP_MAX_QP_RD_ATOMIC && attr->max_rd_atomic)
|
||||
MLX5_SET(qpc, qpc, log_sra_max, ilog2(attr->max_rd_atomic));
|
||||
MLX5_SET(qpc, qpc, log_sra_max, fls(attr->max_rd_atomic - 1));
|
||||
|
||||
if (attr_mask & IB_QP_SQ_PSN)
|
||||
MLX5_SET(qpc, qpc, next_send_psn, attr->sq_psn);
|
||||
|
||||
if (attr_mask & IB_QP_MAX_DEST_RD_ATOMIC && attr->max_dest_rd_atomic)
|
||||
MLX5_SET(qpc, qpc, log_rra_max,
|
||||
ilog2(attr->max_dest_rd_atomic));
|
||||
fls(attr->max_dest_rd_atomic - 1));
|
||||
|
||||
if (attr_mask & (IB_QP_ACCESS_FLAGS | IB_QP_MAX_DEST_RD_ATOMIC)) {
|
||||
err = set_qpc_atomic_flags(qp, attr, attr_mask, qpc);
|
||||
|
||||
@@ -127,6 +127,7 @@ static const struct xpad_device {
|
||||
u8 mapping;
|
||||
u8 xtype;
|
||||
} xpad_device[] = {
|
||||
/* Please keep this list sorted by vendor and product ID. */
|
||||
{ 0x0079, 0x18d4, "GPD Win 2 X-Box Controller", 0, XTYPE_XBOX360 },
|
||||
{ 0x03eb, 0xff01, "Wooting One (Legacy)", 0, XTYPE_XBOX360 },
|
||||
{ 0x03eb, 0xff02, "Wooting Two (Legacy)", 0, XTYPE_XBOX360 },
|
||||
@@ -152,9 +153,9 @@ static const struct xpad_device {
|
||||
{ 0x045e, 0x02d1, "Microsoft X-Box One pad", 0, XTYPE_XBOXONE },
|
||||
{ 0x045e, 0x02dd, "Microsoft X-Box One pad (Firmware 2015)", 0, XTYPE_XBOXONE },
|
||||
{ 0x045e, 0x02e3, "Microsoft X-Box One Elite pad", MAP_PADDLES, XTYPE_XBOXONE },
|
||||
{ 0x045e, 0x0b00, "Microsoft X-Box One Elite 2 pad", MAP_PADDLES, XTYPE_XBOXONE },
|
||||
{ 0x045e, 0x02ea, "Microsoft X-Box One S pad", 0, XTYPE_XBOXONE },
|
||||
{ 0x045e, 0x0719, "Xbox 360 Wireless Receiver", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX360W },
|
||||
{ 0x045e, 0x0b00, "Microsoft X-Box One Elite 2 pad", MAP_PADDLES, XTYPE_XBOXONE },
|
||||
{ 0x045e, 0x0b0a, "Microsoft X-Box Adaptive Controller", MAP_PROFILE_BUTTON, XTYPE_XBOXONE },
|
||||
{ 0x045e, 0x0b12, "Microsoft Xbox Series S|X Controller", MAP_SELECT_BUTTON, XTYPE_XBOXONE },
|
||||
{ 0x046d, 0xc21d, "Logitech Gamepad F310", 0, XTYPE_XBOX360 },
|
||||
@@ -343,7 +344,6 @@ static const struct xpad_device {
|
||||
{ 0x20d6, 0x2001, "BDA Xbox Series X Wired Controller", 0, XTYPE_XBOXONE },
|
||||
{ 0x20d6, 0x2009, "PowerA Enhanced Wired Controller for Xbox Series X|S", 0, XTYPE_XBOXONE },
|
||||
{ 0x20d6, 0x281f, "PowerA Wired Controller For Xbox 360", 0, XTYPE_XBOX360 },
|
||||
{ 0x2e24, 0x0652, "Hyperkin Duke X-Box One pad", 0, XTYPE_XBOXONE },
|
||||
{ 0x24c6, 0x5000, "Razer Atrox Arcade Stick", MAP_TRIGGERS_TO_BUTTONS, XTYPE_XBOX360 },
|
||||
{ 0x24c6, 0x5300, "PowerA MINI PROEX Controller", 0, XTYPE_XBOX360 },
|
||||
{ 0x24c6, 0x5303, "Xbox Airflo wired controller", 0, XTYPE_XBOX360 },
|
||||
@@ -358,9 +358,9 @@ static const struct xpad_device {
|
||||
{ 0x24c6, 0x5502, "Hori Fighting Stick VX Alt", MAP_TRIGGERS_TO_BUTTONS, XTYPE_XBOX360 },
|
||||
{ 0x24c6, 0x5503, "Hori Fighting Edge", MAP_TRIGGERS_TO_BUTTONS, XTYPE_XBOX360 },
|
||||
{ 0x24c6, 0x5506, "Hori SOULCALIBUR V Stick", 0, XTYPE_XBOX360 },
|
||||
{ 0x24c6, 0x5510, "Hori Fighting Commander ONE (Xbox 360/PC Mode)", MAP_TRIGGERS_TO_BUTTONS, XTYPE_XBOX360 },
|
||||
{ 0x24c6, 0x550d, "Hori GEM Xbox controller", 0, XTYPE_XBOX360 },
|
||||
{ 0x24c6, 0x550e, "Hori Real Arcade Pro V Kai 360", MAP_TRIGGERS_TO_BUTTONS, XTYPE_XBOX360 },
|
||||
{ 0x24c6, 0x5510, "Hori Fighting Commander ONE (Xbox 360/PC Mode)", MAP_TRIGGERS_TO_BUTTONS, XTYPE_XBOX360 },
|
||||
{ 0x24c6, 0x551a, "PowerA FUSION Pro Controller", 0, XTYPE_XBOXONE },
|
||||
{ 0x24c6, 0x561a, "PowerA FUSION Controller", 0, XTYPE_XBOXONE },
|
||||
{ 0x24c6, 0x5b00, "ThrustMaster Ferrari 458 Racing Wheel", 0, XTYPE_XBOX360 },
|
||||
@@ -373,6 +373,8 @@ static const struct xpad_device {
|
||||
{ 0x294b, 0x3404, "Snakebyte GAMEPAD RGB X", 0, XTYPE_XBOXONE },
|
||||
{ 0x2dc8, 0x2000, "8BitDo Pro 2 Wired Controller fox Xbox", 0, XTYPE_XBOXONE },
|
||||
{ 0x2dc8, 0x3106, "8BitDo Pro 2 Wired Controller", 0, XTYPE_XBOX360 },
|
||||
{ 0x2dc8, 0x310a, "8BitDo Ultimate 2C Wireless Controller", 0, XTYPE_XBOX360 },
|
||||
{ 0x2e24, 0x0652, "Hyperkin Duke X-Box One pad", 0, XTYPE_XBOXONE },
|
||||
{ 0x31e3, 0x1100, "Wooting One", 0, XTYPE_XBOX360 },
|
||||
{ 0x31e3, 0x1200, "Wooting Two", 0, XTYPE_XBOX360 },
|
||||
{ 0x31e3, 0x1210, "Wooting Lekker", 0, XTYPE_XBOX360 },
|
||||
@@ -470,6 +472,10 @@ static const signed short xpad_btn_paddles[] = {
|
||||
{ XPAD_XBOXONE_VENDOR_PROTOCOL((vend), 208) }
|
||||
|
||||
static const struct usb_device_id xpad_table[] = {
|
||||
/*
|
||||
* Please keep this list sorted by vendor ID. Note that there are 2
|
||||
* macros - XPAD_XBOX360_VENDOR and XPAD_XBOXONE_VENDOR.
|
||||
*/
|
||||
{ USB_INTERFACE_INFO('X', 'B', 0) }, /* Xbox USB-IF not-approved class */
|
||||
XPAD_XBOX360_VENDOR(0x0079), /* GPD Win 2 controller */
|
||||
XPAD_XBOX360_VENDOR(0x03eb), /* Wooting Keyboards (Legacy) */
|
||||
|
||||
@@ -1124,6 +1124,14 @@ static void edt_ft5x06_ts_set_regs(struct edt_ft5x06_ts_data *tsdata)
|
||||
}
|
||||
}
|
||||
|
||||
static void edt_ft5x06_exit_regmap(void *arg)
|
||||
{
|
||||
struct edt_ft5x06_ts_data *data = arg;
|
||||
|
||||
if (!IS_ERR_OR_NULL(data->regmap))
|
||||
regmap_exit(data->regmap);
|
||||
}
|
||||
|
||||
static void edt_ft5x06_disable_regulators(void *arg)
|
||||
{
|
||||
struct edt_ft5x06_ts_data *data = arg;
|
||||
@@ -1157,6 +1165,16 @@ static int edt_ft5x06_ts_probe(struct i2c_client *client)
|
||||
return PTR_ERR(tsdata->regmap);
|
||||
}
|
||||
|
||||
/*
|
||||
* We are not using devm_regmap_init_i2c() and instead install a
|
||||
* custom action because we may replace regmap with M06-specific one
|
||||
* and we need to make sure that it will not be released too early.
|
||||
*/
|
||||
error = devm_add_action_or_reset(&client->dev, edt_ft5x06_exit_regmap,
|
||||
tsdata);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
chip_data = device_get_match_data(&client->dev);
|
||||
if (!chip_data)
|
||||
chip_data = (const struct edt_i2c_chip_data *)id->driver_data;
|
||||
@@ -1354,7 +1372,6 @@ static void edt_ft5x06_ts_remove(struct i2c_client *client)
|
||||
struct edt_ft5x06_ts_data *tsdata = i2c_get_clientdata(client);
|
||||
|
||||
edt_ft5x06_ts_teardown_debugfs(tsdata);
|
||||
regmap_exit(tsdata->regmap);
|
||||
}
|
||||
|
||||
static int edt_ft5x06_ts_suspend(struct device *dev)
|
||||
|
||||
@@ -321,7 +321,7 @@ void mei_io_cb_free(struct mei_cl_cb *cb)
|
||||
return;
|
||||
|
||||
list_del(&cb->list);
|
||||
kfree(cb->buf.data);
|
||||
kvfree(cb->buf.data);
|
||||
kfree(cb->ext_hdr);
|
||||
kfree(cb);
|
||||
}
|
||||
@@ -497,7 +497,7 @@ struct mei_cl_cb *mei_cl_alloc_cb(struct mei_cl *cl, size_t length,
|
||||
if (length == 0)
|
||||
return cb;
|
||||
|
||||
cb->buf.data = kmalloc(roundup(length, MEI_SLOT_SIZE), GFP_KERNEL);
|
||||
cb->buf.data = kvmalloc(roundup(length, MEI_SLOT_SIZE), GFP_KERNEL);
|
||||
if (!cb->buf.data) {
|
||||
mei_io_cb_free(cb);
|
||||
return NULL;
|
||||
|
||||
@@ -258,7 +258,6 @@ static int gru_get_cpu_resources(int dsr_bytes, void **cb, void **dsr)
|
||||
int lcpu;
|
||||
|
||||
BUG_ON(dsr_bytes > GRU_NUM_KERNEL_DSR_BYTES);
|
||||
preempt_disable();
|
||||
bs = gru_lock_kernel_context(-1);
|
||||
lcpu = uv_blade_processor_id();
|
||||
*cb = bs->kernel_cb + lcpu * GRU_HANDLE_STRIDE;
|
||||
@@ -272,7 +271,6 @@ static int gru_get_cpu_resources(int dsr_bytes, void **cb, void **dsr)
|
||||
static void gru_free_cpu_resources(void *cb, void *dsr)
|
||||
{
|
||||
gru_unlock_kernel_context(uv_numa_blade_id());
|
||||
preempt_enable();
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -941,10 +941,8 @@ vm_fault_t gru_fault(struct vm_fault *vmf)
|
||||
|
||||
again:
|
||||
mutex_lock(>s->ts_ctxlock);
|
||||
preempt_disable();
|
||||
|
||||
if (gru_check_context_placement(gts)) {
|
||||
preempt_enable();
|
||||
mutex_unlock(>s->ts_ctxlock);
|
||||
gru_unload_context(gts, 1);
|
||||
return VM_FAULT_NOPAGE;
|
||||
@@ -953,7 +951,6 @@ again:
|
||||
if (!gts->ts_gru) {
|
||||
STAT(load_user_context);
|
||||
if (!gru_assign_gru_context(gts)) {
|
||||
preempt_enable();
|
||||
mutex_unlock(>s->ts_ctxlock);
|
||||
set_current_state(TASK_INTERRUPTIBLE);
|
||||
schedule_timeout(GRU_ASSIGN_DELAY); /* true hack ZZZ */
|
||||
@@ -969,7 +966,6 @@ again:
|
||||
vma->vm_page_prot);
|
||||
}
|
||||
|
||||
preempt_enable();
|
||||
mutex_unlock(>s->ts_ctxlock);
|
||||
|
||||
return VM_FAULT_NOPAGE;
|
||||
|
||||
@@ -65,7 +65,6 @@ static struct gru_tlb_global_handle *get_lock_tgh_handle(struct gru_state
|
||||
struct gru_tlb_global_handle *tgh;
|
||||
int n;
|
||||
|
||||
preempt_disable();
|
||||
if (uv_numa_blade_id() == gru->gs_blade_id)
|
||||
n = get_on_blade_tgh(gru);
|
||||
else
|
||||
@@ -79,7 +78,6 @@ static struct gru_tlb_global_handle *get_lock_tgh_handle(struct gru_state
|
||||
static void get_unlock_tgh_handle(struct gru_tlb_global_handle *tgh)
|
||||
{
|
||||
unlock_tgh_handle(tgh);
|
||||
preempt_enable();
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -902,28 +902,40 @@ static void gl9767_disable_ssc_pll(struct pci_dev *pdev)
|
||||
gl9767_vhs_read(pdev);
|
||||
}
|
||||
|
||||
static void gl9767_set_low_power_negotiation(struct pci_dev *pdev, bool enable)
|
||||
{
|
||||
u32 value;
|
||||
|
||||
gl9767_vhs_write(pdev);
|
||||
|
||||
pci_read_config_dword(pdev, PCIE_GLI_9767_CFG, &value);
|
||||
if (enable)
|
||||
value &= ~PCIE_GLI_9767_CFG_LOW_PWR_OFF;
|
||||
else
|
||||
value |= PCIE_GLI_9767_CFG_LOW_PWR_OFF;
|
||||
pci_write_config_dword(pdev, PCIE_GLI_9767_CFG, value);
|
||||
|
||||
gl9767_vhs_read(pdev);
|
||||
}
|
||||
|
||||
static void sdhci_gl9767_set_clock(struct sdhci_host *host, unsigned int clock)
|
||||
{
|
||||
struct sdhci_pci_slot *slot = sdhci_priv(host);
|
||||
struct mmc_ios *ios = &host->mmc->ios;
|
||||
struct pci_dev *pdev;
|
||||
u32 value;
|
||||
u16 clk;
|
||||
|
||||
pdev = slot->chip->pdev;
|
||||
host->mmc->actual_clock = 0;
|
||||
|
||||
gl9767_vhs_write(pdev);
|
||||
|
||||
pci_read_config_dword(pdev, PCIE_GLI_9767_CFG, &value);
|
||||
value |= PCIE_GLI_9767_CFG_LOW_PWR_OFF;
|
||||
pci_write_config_dword(pdev, PCIE_GLI_9767_CFG, value);
|
||||
|
||||
gl9767_set_low_power_negotiation(pdev, false);
|
||||
gl9767_disable_ssc_pll(pdev);
|
||||
sdhci_writew(host, 0, SDHCI_CLOCK_CONTROL);
|
||||
|
||||
if (clock == 0)
|
||||
if (clock == 0) {
|
||||
gl9767_set_low_power_negotiation(pdev, true);
|
||||
return;
|
||||
}
|
||||
|
||||
clk = sdhci_calc_clk(host, clock, &host->mmc->actual_clock);
|
||||
if (clock == 200000000 && ios->timing == MMC_TIMING_UHS_SDR104) {
|
||||
@@ -932,12 +944,7 @@ static void sdhci_gl9767_set_clock(struct sdhci_host *host, unsigned int clock)
|
||||
}
|
||||
|
||||
sdhci_enable_clk(host, clk);
|
||||
|
||||
pci_read_config_dword(pdev, PCIE_GLI_9767_CFG, &value);
|
||||
value &= ~PCIE_GLI_9767_CFG_LOW_PWR_OFF;
|
||||
pci_write_config_dword(pdev, PCIE_GLI_9767_CFG, value);
|
||||
|
||||
gl9767_vhs_read(pdev);
|
||||
gl9767_set_low_power_negotiation(pdev, true);
|
||||
}
|
||||
|
||||
static void gli_set_9767(struct sdhci_host *host)
|
||||
@@ -1071,6 +1078,9 @@ static int gl9767_init_sd_express(struct mmc_host *mmc, struct mmc_ios *ios)
|
||||
sdhci_writew(host, value, SDHCI_CLOCK_CONTROL);
|
||||
}
|
||||
|
||||
pci_read_config_dword(pdev, PCIE_GLI_9767_CFG, &value);
|
||||
value &= ~PCIE_GLI_9767_CFG_LOW_PWR_OFF;
|
||||
pci_write_config_dword(pdev, PCIE_GLI_9767_CFG, value);
|
||||
gl9767_vhs_read(pdev);
|
||||
|
||||
return 0;
|
||||
|
||||
@@ -120,9 +120,10 @@ static const struct flash_info winbond_nor_parts[] = {
|
||||
NO_SFDP_FLAGS(SECT_4K) },
|
||||
{ "w25q80bl", INFO(0xef4014, 0, 64 * 1024, 16)
|
||||
NO_SFDP_FLAGS(SECT_4K) },
|
||||
{ "w25q128", INFO(0xef4018, 0, 0, 0)
|
||||
PARSE_SFDP
|
||||
FLAGS(SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB) },
|
||||
{ "w25q128", INFO(0xef4018, 0, 64 * 1024, 256)
|
||||
FLAGS(SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB)
|
||||
NO_SFDP_FLAGS(SECT_4K | SPI_NOR_DUAL_READ |
|
||||
SPI_NOR_QUAD_READ) },
|
||||
{ "w25q256", INFO(0xef4019, 0, 64 * 1024, 512)
|
||||
NO_SFDP_FLAGS(SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ)
|
||||
.fixups = &w25q256_fixups },
|
||||
|
||||
@@ -105,10 +105,6 @@ static struct net_device * __init mvme147lance_probe(void)
|
||||
macaddr[3] = address&0xff;
|
||||
eth_hw_addr_set(dev, macaddr);
|
||||
|
||||
printk("%s: MVME147 at 0x%08lx, irq %d, Hardware Address %pM\n",
|
||||
dev->name, dev->base_addr, MVME147_LANCE_IRQ,
|
||||
dev->dev_addr);
|
||||
|
||||
lp = netdev_priv(dev);
|
||||
lp->ram = __get_dma_pages(GFP_ATOMIC, 3); /* 32K */
|
||||
if (!lp->ram) {
|
||||
@@ -138,6 +134,9 @@ static struct net_device * __init mvme147lance_probe(void)
|
||||
return ERR_PTR(err);
|
||||
}
|
||||
|
||||
netdev_info(dev, "MVME147 at 0x%08lx, irq %d, Hardware Address %pM\n",
|
||||
dev->base_addr, MVME147_LANCE_IRQ, dev->dev_addr);
|
||||
|
||||
return dev;
|
||||
}
|
||||
|
||||
|
||||
@@ -471,11 +471,33 @@ mlxsw_sp_ipip_ol_netdev_change_gre6(struct mlxsw_sp *mlxsw_sp,
|
||||
struct mlxsw_sp_ipip_entry *ipip_entry,
|
||||
struct netlink_ext_ack *extack)
|
||||
{
|
||||
u32 new_kvdl_index, old_kvdl_index = ipip_entry->dip_kvdl_index;
|
||||
struct in6_addr old_addr6 = ipip_entry->parms.daddr.addr6;
|
||||
struct mlxsw_sp_ipip_parms new_parms;
|
||||
int err;
|
||||
|
||||
new_parms = mlxsw_sp_ipip_netdev_parms_init_gre6(ipip_entry->ol_dev);
|
||||
return mlxsw_sp_ipip_ol_netdev_change_gre(mlxsw_sp, ipip_entry,
|
||||
&new_parms, extack);
|
||||
|
||||
err = mlxsw_sp_ipv6_addr_kvdl_index_get(mlxsw_sp,
|
||||
&new_parms.daddr.addr6,
|
||||
&new_kvdl_index);
|
||||
if (err)
|
||||
return err;
|
||||
ipip_entry->dip_kvdl_index = new_kvdl_index;
|
||||
|
||||
err = mlxsw_sp_ipip_ol_netdev_change_gre(mlxsw_sp, ipip_entry,
|
||||
&new_parms, extack);
|
||||
if (err)
|
||||
goto err_change_gre;
|
||||
|
||||
mlxsw_sp_ipv6_addr_put(mlxsw_sp, &old_addr6);
|
||||
|
||||
return 0;
|
||||
|
||||
err_change_gre:
|
||||
ipip_entry->dip_kvdl_index = old_kvdl_index;
|
||||
mlxsw_sp_ipv6_addr_put(mlxsw_sp, &new_parms.daddr.addr6);
|
||||
return err;
|
||||
}
|
||||
|
||||
static int
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
#include "spectrum.h"
|
||||
#include "spectrum_ptp.h"
|
||||
#include "core.h"
|
||||
#include "txheader.h"
|
||||
|
||||
#define MLXSW_SP1_PTP_CLOCK_CYCLES_SHIFT 29
|
||||
#define MLXSW_SP1_PTP_CLOCK_FREQ_KHZ 156257 /* 6.4nSec */
|
||||
@@ -1684,6 +1685,12 @@ int mlxsw_sp_ptp_txhdr_construct(struct mlxsw_core *mlxsw_core,
|
||||
struct sk_buff *skb,
|
||||
const struct mlxsw_tx_info *tx_info)
|
||||
{
|
||||
if (skb_cow_head(skb, MLXSW_TXHDR_LEN)) {
|
||||
this_cpu_inc(mlxsw_sp_port->pcpu_stats->tx_dropped);
|
||||
dev_kfree_skb_any(skb);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
mlxsw_sp_txhdr_construct(skb, tx_info);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -203,8 +203,12 @@ static void _dwmac4_dump_dma_regs(struct stmmac_priv *priv,
|
||||
readl(ioaddr + DMA_CHAN_TX_CONTROL(dwmac4_addrs, channel));
|
||||
reg_space[DMA_CHAN_RX_CONTROL(default_addrs, channel) / 4] =
|
||||
readl(ioaddr + DMA_CHAN_RX_CONTROL(dwmac4_addrs, channel));
|
||||
reg_space[DMA_CHAN_TX_BASE_ADDR_HI(default_addrs, channel) / 4] =
|
||||
readl(ioaddr + DMA_CHAN_TX_BASE_ADDR_HI(dwmac4_addrs, channel));
|
||||
reg_space[DMA_CHAN_TX_BASE_ADDR(default_addrs, channel) / 4] =
|
||||
readl(ioaddr + DMA_CHAN_TX_BASE_ADDR(dwmac4_addrs, channel));
|
||||
reg_space[DMA_CHAN_RX_BASE_ADDR_HI(default_addrs, channel) / 4] =
|
||||
readl(ioaddr + DMA_CHAN_RX_BASE_ADDR_HI(dwmac4_addrs, channel));
|
||||
reg_space[DMA_CHAN_RX_BASE_ADDR(default_addrs, channel) / 4] =
|
||||
readl(ioaddr + DMA_CHAN_RX_BASE_ADDR(dwmac4_addrs, channel));
|
||||
reg_space[DMA_CHAN_TX_END_ADDR(default_addrs, channel) / 4] =
|
||||
@@ -225,8 +229,12 @@ static void _dwmac4_dump_dma_regs(struct stmmac_priv *priv,
|
||||
readl(ioaddr + DMA_CHAN_CUR_TX_DESC(dwmac4_addrs, channel));
|
||||
reg_space[DMA_CHAN_CUR_RX_DESC(default_addrs, channel) / 4] =
|
||||
readl(ioaddr + DMA_CHAN_CUR_RX_DESC(dwmac4_addrs, channel));
|
||||
reg_space[DMA_CHAN_CUR_TX_BUF_ADDR_HI(default_addrs, channel) / 4] =
|
||||
readl(ioaddr + DMA_CHAN_CUR_TX_BUF_ADDR_HI(dwmac4_addrs, channel));
|
||||
reg_space[DMA_CHAN_CUR_TX_BUF_ADDR(default_addrs, channel) / 4] =
|
||||
readl(ioaddr + DMA_CHAN_CUR_TX_BUF_ADDR(dwmac4_addrs, channel));
|
||||
reg_space[DMA_CHAN_CUR_RX_BUF_ADDR_HI(default_addrs, channel) / 4] =
|
||||
readl(ioaddr + DMA_CHAN_CUR_RX_BUF_ADDR_HI(dwmac4_addrs, channel));
|
||||
reg_space[DMA_CHAN_CUR_RX_BUF_ADDR(default_addrs, channel) / 4] =
|
||||
readl(ioaddr + DMA_CHAN_CUR_RX_BUF_ADDR(dwmac4_addrs, channel));
|
||||
reg_space[DMA_CHAN_STATUS(default_addrs, channel) / 4] =
|
||||
|
||||
@@ -127,7 +127,9 @@ static inline u32 dma_chanx_base_addr(const struct dwmac4_addrs *addrs,
|
||||
#define DMA_CHAN_SLOT_CTRL_STATUS(addrs, x) (dma_chanx_base_addr(addrs, x) + 0x3c)
|
||||
#define DMA_CHAN_CUR_TX_DESC(addrs, x) (dma_chanx_base_addr(addrs, x) + 0x44)
|
||||
#define DMA_CHAN_CUR_RX_DESC(addrs, x) (dma_chanx_base_addr(addrs, x) + 0x4c)
|
||||
#define DMA_CHAN_CUR_TX_BUF_ADDR_HI(addrs, x) (dma_chanx_base_addr(addrs, x) + 0x50)
|
||||
#define DMA_CHAN_CUR_TX_BUF_ADDR(addrs, x) (dma_chanx_base_addr(addrs, x) + 0x54)
|
||||
#define DMA_CHAN_CUR_RX_BUF_ADDR_HI(addrs, x) (dma_chanx_base_addr(addrs, x) + 0x58)
|
||||
#define DMA_CHAN_CUR_RX_BUF_ADDR(addrs, x) (dma_chanx_base_addr(addrs, x) + 0x5c)
|
||||
#define DMA_CHAN_STATUS(addrs, x) (dma_chanx_base_addr(addrs, x) + 0x60)
|
||||
|
||||
|
||||
@@ -4196,11 +4196,6 @@ static netdev_tx_t stmmac_tso_xmit(struct sk_buff *skb, struct net_device *dev)
|
||||
if (dma_mapping_error(priv->device, des))
|
||||
goto dma_map_err;
|
||||
|
||||
tx_q->tx_skbuff_dma[first_entry].buf = des;
|
||||
tx_q->tx_skbuff_dma[first_entry].len = skb_headlen(skb);
|
||||
tx_q->tx_skbuff_dma[first_entry].map_as_page = false;
|
||||
tx_q->tx_skbuff_dma[first_entry].buf_type = STMMAC_TXBUF_T_SKB;
|
||||
|
||||
if (priv->dma_cap.addr64 <= 32) {
|
||||
first->des0 = cpu_to_le32(des);
|
||||
|
||||
@@ -4219,6 +4214,23 @@ static netdev_tx_t stmmac_tso_xmit(struct sk_buff *skb, struct net_device *dev)
|
||||
|
||||
stmmac_tso_allocator(priv, des, tmp_pay_len, (nfrags == 0), queue);
|
||||
|
||||
/* In case two or more DMA transmit descriptors are allocated for this
|
||||
* non-paged SKB data, the DMA buffer address should be saved to
|
||||
* tx_q->tx_skbuff_dma[].buf corresponding to the last descriptor,
|
||||
* and leave the other tx_q->tx_skbuff_dma[].buf as NULL to guarantee
|
||||
* that stmmac_tx_clean() does not unmap the entire DMA buffer too early
|
||||
* since the tail areas of the DMA buffer can be accessed by DMA engine
|
||||
* sooner or later.
|
||||
* By saving the DMA buffer address to tx_q->tx_skbuff_dma[].buf
|
||||
* corresponding to the last descriptor, stmmac_tx_clean() will unmap
|
||||
* this DMA buffer right after the DMA engine completely finishes the
|
||||
* full buffer transmission.
|
||||
*/
|
||||
tx_q->tx_skbuff_dma[tx_q->cur_tx].buf = des;
|
||||
tx_q->tx_skbuff_dma[tx_q->cur_tx].len = skb_headlen(skb);
|
||||
tx_q->tx_skbuff_dma[tx_q->cur_tx].map_as_page = false;
|
||||
tx_q->tx_skbuff_dma[tx_q->cur_tx].buf_type = STMMAC_TXBUF_T_SKB;
|
||||
|
||||
/* Prepare fragments */
|
||||
for (i = 0; i < nfrags; i++) {
|
||||
const skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
|
||||
|
||||
@@ -1263,20 +1263,24 @@ static int gtp_encap_enable(struct gtp_dev *gtp, struct nlattr *data[])
|
||||
return -EINVAL;
|
||||
|
||||
if (data[IFLA_GTP_FD0]) {
|
||||
u32 fd0 = nla_get_u32(data[IFLA_GTP_FD0]);
|
||||
int fd0 = nla_get_u32(data[IFLA_GTP_FD0]);
|
||||
|
||||
sk0 = gtp_encap_enable_socket(fd0, UDP_ENCAP_GTP0, gtp);
|
||||
if (IS_ERR(sk0))
|
||||
return PTR_ERR(sk0);
|
||||
if (fd0 >= 0) {
|
||||
sk0 = gtp_encap_enable_socket(fd0, UDP_ENCAP_GTP0, gtp);
|
||||
if (IS_ERR(sk0))
|
||||
return PTR_ERR(sk0);
|
||||
}
|
||||
}
|
||||
|
||||
if (data[IFLA_GTP_FD1]) {
|
||||
u32 fd1 = nla_get_u32(data[IFLA_GTP_FD1]);
|
||||
int fd1 = nla_get_u32(data[IFLA_GTP_FD1]);
|
||||
|
||||
sk1u = gtp_encap_enable_socket(fd1, UDP_ENCAP_GTP1U, gtp);
|
||||
if (IS_ERR(sk1u)) {
|
||||
gtp_encap_disable_sock(sk0);
|
||||
return PTR_ERR(sk1u);
|
||||
if (fd1 >= 0) {
|
||||
sk1u = gtp_encap_enable_socket(fd1, UDP_ENCAP_GTP1U, gtp);
|
||||
if (IS_ERR(sk1u)) {
|
||||
gtp_encap_disable_sock(sk0);
|
||||
return PTR_ERR(sk1u);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -3715,8 +3715,7 @@ static void macsec_free_netdev(struct net_device *dev)
|
||||
{
|
||||
struct macsec_dev *macsec = macsec_priv(dev);
|
||||
|
||||
if (macsec->secy.tx_sc.md_dst)
|
||||
metadata_dst_free(macsec->secy.tx_sc.md_dst);
|
||||
dst_release(&macsec->secy.tx_sc.md_dst->dst);
|
||||
free_percpu(macsec->stats);
|
||||
free_percpu(macsec->secy.tx_sc.stats);
|
||||
|
||||
|
||||
@@ -547,6 +547,9 @@ static int mctp_i2c_header_create(struct sk_buff *skb, struct net_device *dev,
|
||||
if (len > MCTP_I2C_MAXMTU)
|
||||
return -EMSGSIZE;
|
||||
|
||||
if (!daddr || !saddr)
|
||||
return -EINVAL;
|
||||
|
||||
lldst = *((u8 *)daddr);
|
||||
llsrc = *((u8 *)saddr);
|
||||
|
||||
|
||||
@@ -1377,10 +1377,12 @@ static ssize_t nsim_nexthop_bucket_activity_write(struct file *file,
|
||||
|
||||
if (pos != 0)
|
||||
return -EINVAL;
|
||||
if (size > sizeof(buf))
|
||||
if (size > sizeof(buf) - 1)
|
||||
return -EINVAL;
|
||||
if (copy_from_user(buf, user_buf, size))
|
||||
return -EFAULT;
|
||||
buf[size] = 0;
|
||||
|
||||
if (sscanf(buf, "%u %hu", &nhid, &bucket_index) != 2)
|
||||
return -EINVAL;
|
||||
|
||||
|
||||
@@ -3042,9 +3042,14 @@ ath10k_wmi_tlv_op_cleanup_mgmt_tx_send(struct ath10k *ar,
|
||||
struct sk_buff *msdu)
|
||||
{
|
||||
struct ath10k_skb_cb *cb = ATH10K_SKB_CB(msdu);
|
||||
struct ath10k_mgmt_tx_pkt_addr *pkt_addr;
|
||||
struct ath10k_wmi *wmi = &ar->wmi;
|
||||
|
||||
idr_remove(&wmi->mgmt_pending_tx, cb->msdu_id);
|
||||
spin_lock_bh(&ar->data_lock);
|
||||
pkt_addr = idr_remove(&wmi->mgmt_pending_tx, cb->msdu_id);
|
||||
spin_unlock_bh(&ar->data_lock);
|
||||
|
||||
kfree(pkt_addr);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -2440,6 +2440,7 @@ wmi_process_mgmt_tx_comp(struct ath10k *ar, struct mgmt_tx_compl_params *param)
|
||||
dma_unmap_single(ar->dev, pkt_addr->paddr,
|
||||
msdu->len, DMA_TO_DEVICE);
|
||||
info = IEEE80211_SKB_CB(msdu);
|
||||
kfree(pkt_addr);
|
||||
|
||||
if (param->status) {
|
||||
info->flags &= ~IEEE80211_TX_STAT_ACK;
|
||||
@@ -9559,6 +9560,7 @@ static int ath10k_wmi_mgmt_tx_clean_up_pending(int msdu_id, void *ptr,
|
||||
dma_unmap_single(ar->dev, pkt_addr->paddr,
|
||||
msdu->len, DMA_TO_DEVICE);
|
||||
ieee80211_free_txskb(ar->hw, msdu);
|
||||
kfree(pkt_addr);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -5240,8 +5240,11 @@ int ath11k_dp_rx_process_mon_status(struct ath11k_base *ab, int mac_id,
|
||||
hal_status == HAL_TLV_STATUS_PPDU_DONE) {
|
||||
rx_mon_stats->status_ppdu_done++;
|
||||
pmon->mon_ppdu_status = DP_PPDU_STATUS_DONE;
|
||||
ath11k_dp_rx_mon_dest_process(ar, mac_id, budget, napi);
|
||||
pmon->mon_ppdu_status = DP_PPDU_STATUS_START;
|
||||
if (!ab->hw_params.full_monitor_mode) {
|
||||
ath11k_dp_rx_mon_dest_process(ar, mac_id,
|
||||
budget, napi);
|
||||
pmon->mon_ppdu_status = DP_PPDU_STATUS_START;
|
||||
}
|
||||
}
|
||||
|
||||
if (ppdu_info->peer_id == HAL_INVALID_PEERID ||
|
||||
|
||||
@@ -27,6 +27,7 @@ source "drivers/net/wireless/broadcom/brcm80211/brcmfmac/Kconfig"
|
||||
config BRCM_TRACING
|
||||
bool "Broadcom device tracing"
|
||||
depends on BRCMSMAC || BRCMFMAC
|
||||
depends on TRACING
|
||||
help
|
||||
If you say Y here, the Broadcom wireless drivers will register
|
||||
with ftrace to dump event information into the trace ringbuffer.
|
||||
|
||||
@@ -3119,6 +3119,7 @@ il_enqueue_hcmd(struct il_priv *il, struct il_host_cmd *cmd)
|
||||
struct il_cmd_meta *out_meta;
|
||||
dma_addr_t phys_addr;
|
||||
unsigned long flags;
|
||||
u8 *out_payload;
|
||||
u32 idx;
|
||||
u16 fix_size;
|
||||
|
||||
@@ -3154,6 +3155,16 @@ il_enqueue_hcmd(struct il_priv *il, struct il_host_cmd *cmd)
|
||||
out_cmd = txq->cmd[idx];
|
||||
out_meta = &txq->meta[idx];
|
||||
|
||||
/* The payload is in the same place in regular and huge
|
||||
* command buffers, but we need to let the compiler know when
|
||||
* we're using a larger payload buffer to avoid "field-
|
||||
* spanning write" warnings at run-time for huge commands.
|
||||
*/
|
||||
if (cmd->flags & CMD_SIZE_HUGE)
|
||||
out_payload = ((struct il_device_cmd_huge *)out_cmd)->cmd.payload;
|
||||
else
|
||||
out_payload = out_cmd->cmd.payload;
|
||||
|
||||
if (WARN_ON(out_meta->flags & CMD_MAPPED)) {
|
||||
spin_unlock_irqrestore(&il->hcmd_lock, flags);
|
||||
return -ENOSPC;
|
||||
@@ -3167,7 +3178,7 @@ il_enqueue_hcmd(struct il_priv *il, struct il_host_cmd *cmd)
|
||||
out_meta->callback = cmd->callback;
|
||||
|
||||
out_cmd->hdr.cmd = cmd->id;
|
||||
memcpy(&out_cmd->cmd.payload, cmd->data, cmd->len);
|
||||
memcpy(out_payload, cmd->data, cmd->len);
|
||||
|
||||
/* At this point, the out_cmd now has all of the incoming cmd
|
||||
* information */
|
||||
@@ -4961,6 +4972,8 @@ il_pci_resume(struct device *device)
|
||||
*/
|
||||
pci_write_config_byte(pdev, PCI_CFG_RETRY_TIMEOUT, 0x00);
|
||||
|
||||
_il_wr(il, CSR_INT, 0xffffffff);
|
||||
_il_wr(il, CSR_FH_INT_STATUS, 0xffffffff);
|
||||
il_enable_interrupts(il);
|
||||
|
||||
if (!(_il_rd(il, CSR_GP_CNTRL) & CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW))
|
||||
|
||||
@@ -560,6 +560,18 @@ struct il_device_cmd {
|
||||
|
||||
#define TFD_MAX_PAYLOAD_SIZE (sizeof(struct il_device_cmd))
|
||||
|
||||
/**
|
||||
* struct il_device_cmd_huge
|
||||
*
|
||||
* For use when sending huge commands.
|
||||
*/
|
||||
struct il_device_cmd_huge {
|
||||
struct il_cmd_header hdr; /* uCode API */
|
||||
union {
|
||||
u8 payload[IL_MAX_CMD_SIZE - sizeof(struct il_cmd_header)];
|
||||
} __packed cmd;
|
||||
} __packed;
|
||||
|
||||
struct il_host_cmd {
|
||||
const void *data;
|
||||
unsigned long reply_page;
|
||||
|
||||
@@ -1394,11 +1394,18 @@ void iwl_mvm_get_acpi_tables(struct iwl_mvm *mvm)
|
||||
|
||||
#endif /* CONFIG_ACPI */
|
||||
|
||||
static void iwl_mvm_disconnect_iterator(void *data, u8 *mac,
|
||||
struct ieee80211_vif *vif)
|
||||
{
|
||||
if (vif->type == NL80211_IFTYPE_STATION)
|
||||
ieee80211_hw_restart_disconnect(vif);
|
||||
}
|
||||
|
||||
void iwl_mvm_send_recovery_cmd(struct iwl_mvm *mvm, u32 flags)
|
||||
{
|
||||
u32 error_log_size = mvm->fw->ucode_capa.error_log_size;
|
||||
u32 status = 0;
|
||||
int ret;
|
||||
u32 resp;
|
||||
|
||||
struct iwl_fw_error_recovery_cmd recovery_cmd = {
|
||||
.flags = cpu_to_le32(flags),
|
||||
@@ -1406,7 +1413,6 @@ void iwl_mvm_send_recovery_cmd(struct iwl_mvm *mvm, u32 flags)
|
||||
};
|
||||
struct iwl_host_cmd host_cmd = {
|
||||
.id = WIDE_ID(SYSTEM_GROUP, FW_ERROR_RECOVERY_CMD),
|
||||
.flags = CMD_WANT_SKB,
|
||||
.data = {&recovery_cmd, },
|
||||
.len = {sizeof(recovery_cmd), },
|
||||
};
|
||||
@@ -1426,7 +1432,7 @@ void iwl_mvm_send_recovery_cmd(struct iwl_mvm *mvm, u32 flags)
|
||||
recovery_cmd.buf_size = cpu_to_le32(error_log_size);
|
||||
}
|
||||
|
||||
ret = iwl_mvm_send_cmd(mvm, &host_cmd);
|
||||
ret = iwl_mvm_send_cmd_status(mvm, &host_cmd, &status);
|
||||
kfree(mvm->error_recovery_buf);
|
||||
mvm->error_recovery_buf = NULL;
|
||||
|
||||
@@ -1437,11 +1443,15 @@ void iwl_mvm_send_recovery_cmd(struct iwl_mvm *mvm, u32 flags)
|
||||
|
||||
/* skb respond is only relevant in ERROR_RECOVERY_UPDATE_DB */
|
||||
if (flags & ERROR_RECOVERY_UPDATE_DB) {
|
||||
resp = le32_to_cpu(*(__le32 *)host_cmd.resp_pkt->data);
|
||||
if (resp)
|
||||
if (status) {
|
||||
IWL_ERR(mvm,
|
||||
"Failed to send recovery cmd blob was invalid %d\n",
|
||||
resp);
|
||||
status);
|
||||
|
||||
ieee80211_iterate_interfaces(mvm->hw, 0,
|
||||
iwl_mvm_disconnect_iterator,
|
||||
mvm);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -39,8 +39,6 @@ static int iwl_mvm_mld_mac_add_interface(struct ieee80211_hw *hw,
|
||||
/* reset deflink MLO parameters */
|
||||
mvmvif->deflink.fw_link_id = IWL_MVM_FW_LINK_ID_INVALID;
|
||||
mvmvif->deflink.active = 0;
|
||||
/* the first link always points to the default one */
|
||||
mvmvif->link[0] = &mvmvif->deflink;
|
||||
|
||||
ret = iwl_mvm_mld_mac_ctxt_add(mvm, vif);
|
||||
if (ret)
|
||||
@@ -58,9 +56,19 @@ static int iwl_mvm_mld_mac_add_interface(struct ieee80211_hw *hw,
|
||||
IEEE80211_VIF_SUPPORTS_CQM_RSSI;
|
||||
}
|
||||
|
||||
ret = iwl_mvm_add_link(mvm, vif, &vif->bss_conf);
|
||||
if (ret)
|
||||
goto out_free_bf;
|
||||
/* We want link[0] to point to the default link, unless we have MLO and
|
||||
* in this case this will be modified later by .change_vif_links()
|
||||
* If we are in the restart flow with an MLD connection, we will wait
|
||||
* to .change_vif_links() to setup the links.
|
||||
*/
|
||||
if (!test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status) ||
|
||||
!ieee80211_vif_is_mld(vif)) {
|
||||
mvmvif->link[0] = &mvmvif->deflink;
|
||||
|
||||
ret = iwl_mvm_add_link(mvm, vif, &vif->bss_conf);
|
||||
if (ret)
|
||||
goto out_free_bf;
|
||||
}
|
||||
|
||||
/* Save a pointer to p2p device vif, so it can later be used to
|
||||
* update the p2p device MAC when a GO is started/stopped
|
||||
@@ -1015,7 +1023,11 @@ iwl_mvm_mld_change_vif_links(struct ieee80211_hw *hw,
|
||||
|
||||
mutex_lock(&mvm->mutex);
|
||||
|
||||
if (old_links == 0) {
|
||||
/* If we're in RESTART flow, the default link wasn't added in
|
||||
* drv_add_interface(), and link[0] doesn't point to it.
|
||||
*/
|
||||
if (old_links == 0 && !test_bit(IWL_MVM_STATUS_IN_HW_RESTART,
|
||||
&mvm->status)) {
|
||||
err = iwl_mvm_disable_link(mvm, vif, &vif->bss_conf);
|
||||
if (err)
|
||||
goto out_err;
|
||||
|
||||
@@ -1751,7 +1751,8 @@ iwl_mvm_umac_scan_cfg_channels_v7_6g(struct iwl_mvm *mvm,
|
||||
&cp->channel_config[ch_cnt];
|
||||
|
||||
u32 s_ssid_bitmap = 0, bssid_bitmap = 0, flags = 0;
|
||||
u8 j, k, s_max = 0, b_max = 0, n_used_bssid_entries;
|
||||
u8 k, s_max = 0, b_max = 0, n_used_bssid_entries;
|
||||
u32 j;
|
||||
bool force_passive, found = false, allow_passive = true,
|
||||
unsolicited_probe_on_chan = false, psc_no_listen = false;
|
||||
s8 psd_20 = IEEE80211_RNR_TBTT_PARAMS_PSD_RESERVED;
|
||||
|
||||
@@ -101,6 +101,7 @@ int nvmet_setup_dhgroup(struct nvmet_ctrl *ctrl, u8 dhgroup_id)
|
||||
pr_debug("%s: ctrl %d failed to generate private key, err %d\n",
|
||||
__func__, ctrl->cntlid, ret);
|
||||
kfree_sensitive(ctrl->dh_key);
|
||||
ctrl->dh_key = NULL;
|
||||
return ret;
|
||||
}
|
||||
ctrl->dh_keysize = crypto_kpp_maxsize(ctrl->dh_tfm);
|
||||
|
||||
@@ -141,11 +141,6 @@ static int imx8_pcie_phy_power_on(struct phy *phy)
|
||||
IMX8MM_GPR_PCIE_REF_CLK_PLL);
|
||||
usleep_range(100, 200);
|
||||
|
||||
/* Do the PHY common block reset */
|
||||
regmap_update_bits(imx8_phy->iomuxc_gpr, IOMUXC_GPR14,
|
||||
IMX8MM_GPR_PCIE_CMN_RST,
|
||||
IMX8MM_GPR_PCIE_CMN_RST);
|
||||
|
||||
switch (imx8_phy->drvdata->variant) {
|
||||
case IMX8MP:
|
||||
reset_control_deassert(imx8_phy->perst);
|
||||
@@ -156,6 +151,11 @@ static int imx8_pcie_phy_power_on(struct phy *phy)
|
||||
break;
|
||||
}
|
||||
|
||||
/* Do the PHY common block reset */
|
||||
regmap_update_bits(imx8_phy->iomuxc_gpr, IOMUXC_GPR14,
|
||||
IMX8MM_GPR_PCIE_CMN_RST,
|
||||
IMX8MM_GPR_PCIE_CMN_RST);
|
||||
|
||||
/* Polling to check the phy is ready or not. */
|
||||
ret = readl_poll_timeout(imx8_phy->base + IMX8MM_PCIE_PHY_CMN_REG075,
|
||||
val, val == ANA_PLL_DONE, 10, 20000);
|
||||
|
||||
@@ -1302,6 +1302,7 @@ static int qmp_usb_legacy_probe(struct platform_device *pdev)
|
||||
return -ENOMEM;
|
||||
|
||||
qmp->dev = dev;
|
||||
dev_set_drvdata(dev, qmp);
|
||||
|
||||
qmp->cfg = of_device_get_match_data(dev);
|
||||
if (!qmp->cfg)
|
||||
|
||||
@@ -2173,6 +2173,7 @@ static int qmp_usb_probe(struct platform_device *pdev)
|
||||
return -ENOMEM;
|
||||
|
||||
qmp->dev = dev;
|
||||
dev_set_drvdata(dev, qmp);
|
||||
|
||||
qmp->cfg = of_device_get_match_data(dev);
|
||||
if (!qmp->cfg)
|
||||
|
||||
@@ -1255,7 +1255,7 @@ static ssize_t fc_rport_set_marginal_state(struct device *dev,
|
||||
*/
|
||||
if (rport->port_state == FC_PORTSTATE_ONLINE)
|
||||
rport->port_state = port_state;
|
||||
else
|
||||
else if (port_state != rport->port_state)
|
||||
return -EINVAL;
|
||||
} else if (port_state == FC_PORTSTATE_ONLINE) {
|
||||
/*
|
||||
@@ -1265,7 +1265,7 @@ static ssize_t fc_rport_set_marginal_state(struct device *dev,
|
||||
*/
|
||||
if (rport->port_state == FC_PORTSTATE_MARGINAL)
|
||||
rport->port_state = port_state;
|
||||
else
|
||||
else if (port_state != rport->port_state)
|
||||
return -EINVAL;
|
||||
} else
|
||||
return -EINVAL;
|
||||
|
||||
@@ -1008,6 +1008,7 @@ static int dspi_setup(struct spi_device *spi)
|
||||
u32 cs_sck_delay = 0, sck_cs_delay = 0;
|
||||
struct fsl_dspi_platform_data *pdata;
|
||||
unsigned char pasc = 0, asc = 0;
|
||||
struct gpio_desc *gpio_cs;
|
||||
struct chip_data *chip;
|
||||
unsigned long clkrate;
|
||||
bool cs = true;
|
||||
@@ -1073,7 +1074,10 @@ static int dspi_setup(struct spi_device *spi)
|
||||
chip->ctar_val |= SPI_CTAR_LSBFE;
|
||||
}
|
||||
|
||||
gpiod_direction_output(spi_get_csgpiod(spi, 0), false);
|
||||
gpio_cs = spi_get_csgpiod(spi, 0);
|
||||
if (gpio_cs)
|
||||
gpiod_direction_output(gpio_cs, false);
|
||||
|
||||
dspi_deassert_cs(spi, &cs);
|
||||
|
||||
spi_set_ctldata(spi, chip);
|
||||
|
||||
@@ -1108,6 +1108,11 @@ static int spi_geni_probe(struct platform_device *pdev)
|
||||
init_completion(&mas->tx_reset_done);
|
||||
init_completion(&mas->rx_reset_done);
|
||||
spin_lock_init(&mas->lock);
|
||||
|
||||
ret = geni_icc_get(&mas->se, NULL);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
pm_runtime_use_autosuspend(&pdev->dev);
|
||||
pm_runtime_set_autosuspend_delay(&pdev->dev, 250);
|
||||
ret = devm_pm_runtime_enable(dev);
|
||||
@@ -1117,9 +1122,6 @@ static int spi_geni_probe(struct platform_device *pdev)
|
||||
if (device_property_read_bool(&pdev->dev, "spi-slave"))
|
||||
spi->slave = true;
|
||||
|
||||
ret = geni_icc_get(&mas->se, NULL);
|
||||
if (ret)
|
||||
return ret;
|
||||
/* Set the bus quota to a reasonable value for register access */
|
||||
mas->se.icc_paths[GENI_TO_CORE].avg_bw = Bps_to_icc(CORE_2X_50_MHZ);
|
||||
mas->se.icc_paths[CPU_TO_GENI].avg_bw = GENI_DEFAULT_BW;
|
||||
|
||||
@@ -129,12 +129,15 @@ static unsigned long ad9832_calc_freqreg(unsigned long mclk, unsigned long fout)
|
||||
static int ad9832_write_frequency(struct ad9832_state *st,
|
||||
unsigned int addr, unsigned long fout)
|
||||
{
|
||||
unsigned long clk_freq;
|
||||
unsigned long regval;
|
||||
|
||||
if (fout > (clk_get_rate(st->mclk) / 2))
|
||||
clk_freq = clk_get_rate(st->mclk);
|
||||
|
||||
if (!clk_freq || fout > (clk_freq / 2))
|
||||
return -EINVAL;
|
||||
|
||||
regval = ad9832_calc_freqreg(clk_get_rate(st->mclk), fout);
|
||||
regval = ad9832_calc_freqreg(clk_freq, fout);
|
||||
|
||||
st->freq_data[0] = cpu_to_be16((AD9832_CMD_FRE8BITSW << CMD_SHIFT) |
|
||||
(addr << ADD_SHIFT) |
|
||||
|
||||
@@ -13,48 +13,12 @@ static struct rapl_if_priv rapl_mmio_priv;
|
||||
|
||||
static const struct rapl_mmio_regs rapl_mmio_default = {
|
||||
.reg_unit = 0x5938,
|
||||
.regs[RAPL_DOMAIN_PACKAGE] = { 0x59a0, 0x593c, 0x58f0, 0, 0x5930},
|
||||
.regs[RAPL_DOMAIN_PACKAGE] = { 0x59a0, 0x593c, 0x58f0, 0, 0x5930, 0x59b0},
|
||||
.regs[RAPL_DOMAIN_DRAM] = { 0x58e0, 0x58e8, 0x58ec, 0, 0},
|
||||
.limits[RAPL_DOMAIN_PACKAGE] = BIT(POWER_LIMIT2),
|
||||
.limits[RAPL_DOMAIN_PACKAGE] = BIT(POWER_LIMIT2) | BIT(POWER_LIMIT4),
|
||||
.limits[RAPL_DOMAIN_DRAM] = BIT(POWER_LIMIT2),
|
||||
};
|
||||
|
||||
static int rapl_mmio_cpu_online(unsigned int cpu)
|
||||
{
|
||||
struct rapl_package *rp;
|
||||
|
||||
/* mmio rapl supports package 0 only for now */
|
||||
if (topology_physical_package_id(cpu))
|
||||
return 0;
|
||||
|
||||
rp = rapl_find_package_domain_cpuslocked(cpu, &rapl_mmio_priv, true);
|
||||
if (!rp) {
|
||||
rp = rapl_add_package_cpuslocked(cpu, &rapl_mmio_priv, true);
|
||||
if (IS_ERR(rp))
|
||||
return PTR_ERR(rp);
|
||||
}
|
||||
cpumask_set_cpu(cpu, &rp->cpumask);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rapl_mmio_cpu_down_prep(unsigned int cpu)
|
||||
{
|
||||
struct rapl_package *rp;
|
||||
int lead_cpu;
|
||||
|
||||
rp = rapl_find_package_domain_cpuslocked(cpu, &rapl_mmio_priv, true);
|
||||
if (!rp)
|
||||
return 0;
|
||||
|
||||
cpumask_clear_cpu(cpu, &rp->cpumask);
|
||||
lead_cpu = cpumask_first(&rp->cpumask);
|
||||
if (lead_cpu >= nr_cpu_ids)
|
||||
rapl_remove_package_cpuslocked(rp);
|
||||
else if (rp->lead_cpu == cpu)
|
||||
rp->lead_cpu = lead_cpu;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rapl_mmio_read_raw(int cpu, struct reg_action *ra)
|
||||
{
|
||||
if (!ra->reg.mmio)
|
||||
@@ -82,6 +46,7 @@ static int rapl_mmio_write_raw(int cpu, struct reg_action *ra)
|
||||
int proc_thermal_rapl_add(struct pci_dev *pdev, struct proc_thermal_device *proc_priv)
|
||||
{
|
||||
const struct rapl_mmio_regs *rapl_regs = &rapl_mmio_default;
|
||||
struct rapl_package *rp;
|
||||
enum rapl_domain_reg_id reg;
|
||||
enum rapl_domain_type domain;
|
||||
int ret;
|
||||
@@ -109,25 +74,38 @@ int proc_thermal_rapl_add(struct pci_dev *pdev, struct proc_thermal_device *proc
|
||||
return PTR_ERR(rapl_mmio_priv.control_type);
|
||||
}
|
||||
|
||||
ret = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "powercap/rapl:online",
|
||||
rapl_mmio_cpu_online, rapl_mmio_cpu_down_prep);
|
||||
if (ret < 0) {
|
||||
powercap_unregister_control_type(rapl_mmio_priv.control_type);
|
||||
rapl_mmio_priv.control_type = NULL;
|
||||
return ret;
|
||||
/* Register a RAPL package device for package 0 which is always online */
|
||||
rp = rapl_find_package_domain(0, &rapl_mmio_priv, false);
|
||||
if (rp) {
|
||||
ret = -EEXIST;
|
||||
goto err;
|
||||
}
|
||||
|
||||
rp = rapl_add_package(0, &rapl_mmio_priv, false);
|
||||
if (IS_ERR(rp)) {
|
||||
ret = PTR_ERR(rp);
|
||||
goto err;
|
||||
}
|
||||
rapl_mmio_priv.pcap_rapl_online = ret;
|
||||
|
||||
return 0;
|
||||
|
||||
err:
|
||||
powercap_unregister_control_type(rapl_mmio_priv.control_type);
|
||||
rapl_mmio_priv.control_type = NULL;
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(proc_thermal_rapl_add);
|
||||
|
||||
void proc_thermal_rapl_remove(void)
|
||||
{
|
||||
struct rapl_package *rp;
|
||||
|
||||
if (IS_ERR_OR_NULL(rapl_mmio_priv.control_type))
|
||||
return;
|
||||
|
||||
cpuhp_remove_state(rapl_mmio_priv.pcap_rapl_online);
|
||||
rp = rapl_find_package_domain(0, &rapl_mmio_priv, false);
|
||||
if (rp)
|
||||
rapl_remove_package(rp);
|
||||
powercap_unregister_control_type(rapl_mmio_priv.control_type);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(proc_thermal_rapl_remove);
|
||||
|
||||
@@ -487,11 +487,16 @@ int thermal_zone_device_is_enabled(struct thermal_zone_device *tz)
|
||||
return tz->mode == THERMAL_DEVICE_ENABLED;
|
||||
}
|
||||
|
||||
static bool thermal_zone_is_present(struct thermal_zone_device *tz)
|
||||
{
|
||||
return !list_empty(&tz->node);
|
||||
}
|
||||
|
||||
void thermal_zone_device_update(struct thermal_zone_device *tz,
|
||||
enum thermal_notify_event event)
|
||||
{
|
||||
mutex_lock(&tz->lock);
|
||||
if (device_is_registered(&tz->device))
|
||||
if (thermal_zone_is_present(tz))
|
||||
__thermal_zone_device_update(tz, event);
|
||||
mutex_unlock(&tz->lock);
|
||||
}
|
||||
@@ -800,7 +805,7 @@ static void thermal_release(struct device *dev)
|
||||
tz = to_thermal_zone(dev);
|
||||
thermal_zone_destroy_device_groups(tz);
|
||||
mutex_destroy(&tz->lock);
|
||||
kfree(tz);
|
||||
complete(&tz->removal);
|
||||
} else if (!strncmp(dev_name(dev), "cooling_device",
|
||||
sizeof("cooling_device") - 1)) {
|
||||
cdev = to_cooling_device(dev);
|
||||
@@ -1292,8 +1297,10 @@ thermal_zone_device_register_with_trips(const char *type, struct thermal_trip *t
|
||||
}
|
||||
|
||||
INIT_LIST_HEAD(&tz->thermal_instances);
|
||||
INIT_LIST_HEAD(&tz->node);
|
||||
ida_init(&tz->ida);
|
||||
mutex_init(&tz->lock);
|
||||
init_completion(&tz->removal);
|
||||
id = ida_alloc(&thermal_tz_ida, GFP_KERNEL);
|
||||
if (id < 0) {
|
||||
result = id;
|
||||
@@ -1364,7 +1371,9 @@ thermal_zone_device_register_with_trips(const char *type, struct thermal_trip *t
|
||||
}
|
||||
|
||||
mutex_lock(&thermal_list_lock);
|
||||
mutex_lock(&tz->lock);
|
||||
list_add_tail(&tz->node, &thermal_tz_list);
|
||||
mutex_unlock(&tz->lock);
|
||||
mutex_unlock(&thermal_list_lock);
|
||||
|
||||
/* Bind cooling devices for this zone */
|
||||
@@ -1454,7 +1463,10 @@ void thermal_zone_device_unregister(struct thermal_zone_device *tz)
|
||||
mutex_unlock(&thermal_list_lock);
|
||||
return;
|
||||
}
|
||||
|
||||
mutex_lock(&tz->lock);
|
||||
list_del(&tz->node);
|
||||
mutex_unlock(&tz->lock);
|
||||
|
||||
/* Unbind all cdevs associated with 'this' thermal zone */
|
||||
list_for_each_entry(cdev, &thermal_cdev_list, node)
|
||||
@@ -1471,15 +1483,14 @@ void thermal_zone_device_unregister(struct thermal_zone_device *tz)
|
||||
ida_free(&thermal_tz_ida, tz->id);
|
||||
ida_destroy(&tz->ida);
|
||||
|
||||
mutex_lock(&tz->lock);
|
||||
device_del(&tz->device);
|
||||
mutex_unlock(&tz->lock);
|
||||
|
||||
kfree(tz->tzp);
|
||||
|
||||
put_device(&tz->device);
|
||||
|
||||
thermal_notify_tz_delete(tz_id);
|
||||
|
||||
wait_for_completion(&tz->removal);
|
||||
kfree(tz->tzp);
|
||||
kfree(tz);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(thermal_zone_device_unregister);
|
||||
|
||||
|
||||
@@ -383,6 +383,24 @@ static void tb_increase_tmu_accuracy(struct tb_tunnel *tunnel)
|
||||
device_for_each_child(&sw->dev, NULL, tb_increase_switch_tmu_accuracy);
|
||||
}
|
||||
|
||||
static int tb_switch_tmu_hifi_uni_required(struct device *dev, void *not_used)
|
||||
{
|
||||
struct tb_switch *sw = tb_to_switch(dev);
|
||||
|
||||
if (sw && tb_switch_tmu_is_enabled(sw) &&
|
||||
tb_switch_tmu_is_configured(sw, TB_SWITCH_TMU_MODE_HIFI_UNI))
|
||||
return 1;
|
||||
|
||||
return device_for_each_child(dev, NULL,
|
||||
tb_switch_tmu_hifi_uni_required);
|
||||
}
|
||||
|
||||
static bool tb_tmu_hifi_uni_required(struct tb *tb)
|
||||
{
|
||||
return device_for_each_child(&tb->dev, NULL,
|
||||
tb_switch_tmu_hifi_uni_required) == 1;
|
||||
}
|
||||
|
||||
static int tb_enable_tmu(struct tb_switch *sw)
|
||||
{
|
||||
int ret;
|
||||
@@ -397,12 +415,30 @@ static int tb_enable_tmu(struct tb_switch *sw)
|
||||
ret = tb_switch_tmu_configure(sw,
|
||||
TB_SWITCH_TMU_MODE_MEDRES_ENHANCED_UNI);
|
||||
if (ret == -EOPNOTSUPP) {
|
||||
if (tb_switch_clx_is_enabled(sw, TB_CL1))
|
||||
ret = tb_switch_tmu_configure(sw,
|
||||
TB_SWITCH_TMU_MODE_LOWRES);
|
||||
else
|
||||
ret = tb_switch_tmu_configure(sw,
|
||||
TB_SWITCH_TMU_MODE_HIFI_BI);
|
||||
if (tb_switch_clx_is_enabled(sw, TB_CL1)) {
|
||||
/*
|
||||
* Figure out uni-directional HiFi TMU requirements
|
||||
* currently in the domain. If there are no
|
||||
* uni-directional HiFi requirements we can put the TMU
|
||||
* into LowRes mode.
|
||||
*
|
||||
* Deliberately skip bi-directional HiFi links
|
||||
* as these work independently of other links
|
||||
* (and they do not allow any CL states anyway).
|
||||
*/
|
||||
if (tb_tmu_hifi_uni_required(sw->tb))
|
||||
ret = tb_switch_tmu_configure(sw,
|
||||
TB_SWITCH_TMU_MODE_HIFI_UNI);
|
||||
else
|
||||
ret = tb_switch_tmu_configure(sw,
|
||||
TB_SWITCH_TMU_MODE_LOWRES);
|
||||
} else {
|
||||
ret = tb_switch_tmu_configure(sw, TB_SWITCH_TMU_MODE_HIFI_BI);
|
||||
}
|
||||
|
||||
/* If not supported, fallback to bi-directional HiFi */
|
||||
if (ret == -EOPNOTSUPP)
|
||||
ret = tb_switch_tmu_configure(sw, TB_SWITCH_TMU_MODE_HIFI_BI);
|
||||
}
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
@@ -30,7 +30,7 @@
|
||||
#include <linux/slab.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/timer.h>
|
||||
#include <linux/hrtimer.h>
|
||||
#include <linux/list.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/platform_device.h>
|
||||
@@ -50,6 +50,8 @@
|
||||
#define POWER_BUDGET 500 /* in mA; use 8 for low-power port testing */
|
||||
#define POWER_BUDGET_3 900 /* in mA */
|
||||
|
||||
#define DUMMY_TIMER_INT_NSECS 125000 /* 1 microframe */
|
||||
|
||||
static const char driver_name[] = "dummy_hcd";
|
||||
static const char driver_desc[] = "USB Host+Gadget Emulator";
|
||||
|
||||
@@ -240,7 +242,7 @@ enum dummy_rh_state {
|
||||
struct dummy_hcd {
|
||||
struct dummy *dum;
|
||||
enum dummy_rh_state rh_state;
|
||||
struct timer_list timer;
|
||||
struct hrtimer timer;
|
||||
u32 port_status;
|
||||
u32 old_status;
|
||||
unsigned long re_timeout;
|
||||
@@ -252,6 +254,7 @@ struct dummy_hcd {
|
||||
u32 stream_en_ep;
|
||||
u8 num_stream[30 / 2];
|
||||
|
||||
unsigned timer_pending:1;
|
||||
unsigned active:1;
|
||||
unsigned old_active:1;
|
||||
unsigned resuming:1;
|
||||
@@ -1301,8 +1304,11 @@ static int dummy_urb_enqueue(
|
||||
urb->error_count = 1; /* mark as a new urb */
|
||||
|
||||
/* kick the scheduler, it'll do the rest */
|
||||
if (!timer_pending(&dum_hcd->timer))
|
||||
mod_timer(&dum_hcd->timer, jiffies + 1);
|
||||
if (!dum_hcd->timer_pending) {
|
||||
dum_hcd->timer_pending = 1;
|
||||
hrtimer_start(&dum_hcd->timer, ns_to_ktime(DUMMY_TIMER_INT_NSECS),
|
||||
HRTIMER_MODE_REL_SOFT);
|
||||
}
|
||||
|
||||
done:
|
||||
spin_unlock_irqrestore(&dum_hcd->dum->lock, flags);
|
||||
@@ -1321,9 +1327,10 @@ static int dummy_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status)
|
||||
spin_lock_irqsave(&dum_hcd->dum->lock, flags);
|
||||
|
||||
rc = usb_hcd_check_unlink_urb(hcd, urb, status);
|
||||
if (!rc && dum_hcd->rh_state != DUMMY_RH_RUNNING &&
|
||||
!list_empty(&dum_hcd->urbp_list))
|
||||
mod_timer(&dum_hcd->timer, jiffies);
|
||||
if (rc == 0 && !dum_hcd->timer_pending) {
|
||||
dum_hcd->timer_pending = 1;
|
||||
hrtimer_start(&dum_hcd->timer, ns_to_ktime(0), HRTIMER_MODE_REL_SOFT);
|
||||
}
|
||||
|
||||
spin_unlock_irqrestore(&dum_hcd->dum->lock, flags);
|
||||
return rc;
|
||||
@@ -1777,7 +1784,7 @@ static int handle_control_request(struct dummy_hcd *dum_hcd, struct urb *urb,
|
||||
* drivers except that the callbacks are invoked from soft interrupt
|
||||
* context.
|
||||
*/
|
||||
static void dummy_timer(struct timer_list *t)
|
||||
static enum hrtimer_restart dummy_timer(struct hrtimer *t)
|
||||
{
|
||||
struct dummy_hcd *dum_hcd = from_timer(dum_hcd, t, timer);
|
||||
struct dummy *dum = dum_hcd->dum;
|
||||
@@ -1808,16 +1815,15 @@ static void dummy_timer(struct timer_list *t)
|
||||
break;
|
||||
}
|
||||
|
||||
/* FIXME if HZ != 1000 this will probably misbehave ... */
|
||||
|
||||
/* look at each urb queued by the host side driver */
|
||||
spin_lock_irqsave(&dum->lock, flags);
|
||||
dum_hcd->timer_pending = 0;
|
||||
|
||||
if (!dum_hcd->udev) {
|
||||
dev_err(dummy_dev(dum_hcd),
|
||||
"timer fired with no URBs pending?\n");
|
||||
spin_unlock_irqrestore(&dum->lock, flags);
|
||||
return;
|
||||
return HRTIMER_NORESTART;
|
||||
}
|
||||
dum_hcd->next_frame_urbp = NULL;
|
||||
|
||||
@@ -1993,12 +1999,17 @@ return_urb:
|
||||
if (list_empty(&dum_hcd->urbp_list)) {
|
||||
usb_put_dev(dum_hcd->udev);
|
||||
dum_hcd->udev = NULL;
|
||||
} else if (dum_hcd->rh_state == DUMMY_RH_RUNNING) {
|
||||
} else if (!dum_hcd->timer_pending &&
|
||||
dum_hcd->rh_state == DUMMY_RH_RUNNING) {
|
||||
/* want a 1 msec delay here */
|
||||
mod_timer(&dum_hcd->timer, jiffies + msecs_to_jiffies(1));
|
||||
dum_hcd->timer_pending = 1;
|
||||
hrtimer_start(&dum_hcd->timer, ns_to_ktime(DUMMY_TIMER_INT_NSECS),
|
||||
HRTIMER_MODE_REL_SOFT);
|
||||
}
|
||||
|
||||
spin_unlock_irqrestore(&dum->lock, flags);
|
||||
|
||||
return HRTIMER_NORESTART;
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
@@ -2386,8 +2397,10 @@ static int dummy_bus_resume(struct usb_hcd *hcd)
|
||||
} else {
|
||||
dum_hcd->rh_state = DUMMY_RH_RUNNING;
|
||||
set_link_state(dum_hcd);
|
||||
if (!list_empty(&dum_hcd->urbp_list))
|
||||
mod_timer(&dum_hcd->timer, jiffies);
|
||||
if (!list_empty(&dum_hcd->urbp_list)) {
|
||||
dum_hcd->timer_pending = 1;
|
||||
hrtimer_start(&dum_hcd->timer, ns_to_ktime(0), HRTIMER_MODE_REL_SOFT);
|
||||
}
|
||||
hcd->state = HC_STATE_RUNNING;
|
||||
}
|
||||
spin_unlock_irq(&dum_hcd->dum->lock);
|
||||
@@ -2465,7 +2478,8 @@ static DEVICE_ATTR_RO(urbs);
|
||||
|
||||
static int dummy_start_ss(struct dummy_hcd *dum_hcd)
|
||||
{
|
||||
timer_setup(&dum_hcd->timer, dummy_timer, 0);
|
||||
hrtimer_init(&dum_hcd->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL_SOFT);
|
||||
dum_hcd->timer.function = dummy_timer;
|
||||
dum_hcd->rh_state = DUMMY_RH_RUNNING;
|
||||
dum_hcd->stream_en_ep = 0;
|
||||
INIT_LIST_HEAD(&dum_hcd->urbp_list);
|
||||
@@ -2494,7 +2508,8 @@ static int dummy_start(struct usb_hcd *hcd)
|
||||
return dummy_start_ss(dum_hcd);
|
||||
|
||||
spin_lock_init(&dum_hcd->dum->lock);
|
||||
timer_setup(&dum_hcd->timer, dummy_timer, 0);
|
||||
hrtimer_init(&dum_hcd->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL_SOFT);
|
||||
dum_hcd->timer.function = dummy_timer;
|
||||
dum_hcd->rh_state = DUMMY_RH_RUNNING;
|
||||
|
||||
INIT_LIST_HEAD(&dum_hcd->urbp_list);
|
||||
@@ -2513,8 +2528,12 @@ static int dummy_start(struct usb_hcd *hcd)
|
||||
|
||||
static void dummy_stop(struct usb_hcd *hcd)
|
||||
{
|
||||
device_remove_file(dummy_dev(hcd_to_dummy_hcd(hcd)), &dev_attr_urbs);
|
||||
dev_info(dummy_dev(hcd_to_dummy_hcd(hcd)), "stopped\n");
|
||||
struct dummy_hcd *dum_hcd = hcd_to_dummy_hcd(hcd);
|
||||
|
||||
hrtimer_cancel(&dum_hcd->timer);
|
||||
dum_hcd->timer_pending = 0;
|
||||
device_remove_file(dummy_dev(dum_hcd), &dev_attr_urbs);
|
||||
dev_info(dummy_dev(dum_hcd), "stopped\n");
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
@@ -713,7 +713,7 @@ static int xhci_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
|
||||
pm_runtime_put_noidle(&dev->dev);
|
||||
|
||||
if (pci_choose_state(dev, PMSG_SUSPEND) == PCI_D0)
|
||||
pm_runtime_forbid(&dev->dev);
|
||||
pm_runtime_get(&dev->dev);
|
||||
else if (xhci->quirks & XHCI_DEFAULT_PM_RUNTIME_ALLOW)
|
||||
pm_runtime_allow(&dev->dev);
|
||||
|
||||
@@ -740,7 +740,9 @@ static void xhci_pci_remove(struct pci_dev *dev)
|
||||
|
||||
xhci->xhc_state |= XHCI_STATE_REMOVING;
|
||||
|
||||
if (xhci->quirks & XHCI_DEFAULT_PM_RUNTIME_ALLOW)
|
||||
if (pci_choose_state(dev, PMSG_SUSPEND) == PCI_D0)
|
||||
pm_runtime_put(&dev->dev);
|
||||
else if (xhci->quirks & XHCI_DEFAULT_PM_RUNTIME_ALLOW)
|
||||
pm_runtime_forbid(&dev->dev);
|
||||
|
||||
if (xhci->shared_hcd) {
|
||||
|
||||
@@ -1734,6 +1734,14 @@ static void handle_cmd_completion(struct xhci_hcd *xhci,
|
||||
|
||||
trace_xhci_handle_command(xhci->cmd_ring, &cmd_trb->generic);
|
||||
|
||||
cmd_comp_code = GET_COMP_CODE(le32_to_cpu(event->status));
|
||||
|
||||
/* If CMD ring stopped we own the trbs between enqueue and dequeue */
|
||||
if (cmd_comp_code == COMP_COMMAND_RING_STOPPED) {
|
||||
complete_all(&xhci->cmd_ring_stop_completion);
|
||||
return;
|
||||
}
|
||||
|
||||
cmd_dequeue_dma = xhci_trb_virt_to_dma(xhci->cmd_ring->deq_seg,
|
||||
cmd_trb);
|
||||
/*
|
||||
@@ -1750,14 +1758,6 @@ static void handle_cmd_completion(struct xhci_hcd *xhci,
|
||||
|
||||
cancel_delayed_work(&xhci->cmd_timer);
|
||||
|
||||
cmd_comp_code = GET_COMP_CODE(le32_to_cpu(event->status));
|
||||
|
||||
/* If CMD ring stopped we own the trbs between enqueue and dequeue */
|
||||
if (cmd_comp_code == COMP_COMMAND_RING_STOPPED) {
|
||||
complete_all(&xhci->cmd_ring_stop_completion);
|
||||
return;
|
||||
}
|
||||
|
||||
if (cmd->command_trb != xhci->cmd_ring->dequeue) {
|
||||
xhci_err(xhci,
|
||||
"Command completion event does not match command\n");
|
||||
|
||||
@@ -628,7 +628,7 @@ void devm_usb_put_phy(struct device *dev, struct usb_phy *phy)
|
||||
{
|
||||
int r;
|
||||
|
||||
r = devres_destroy(dev, devm_usb_phy_release, devm_usb_phy_match, phy);
|
||||
r = devres_release(dev, devm_usb_phy_release, devm_usb_phy_match, phy);
|
||||
dev_WARN_ONCE(dev, r, "couldn't find PHY resource\n");
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(devm_usb_put_phy);
|
||||
|
||||
@@ -2194,6 +2194,7 @@ void typec_port_register_altmodes(struct typec_port *port,
|
||||
altmodes[index] = alt;
|
||||
index++;
|
||||
}
|
||||
fwnode_handle_put(altmodes_node);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(typec_port_register_altmodes);
|
||||
|
||||
|
||||
@@ -268,7 +268,7 @@ static int qcom_pmic_typec_probe(struct platform_device *pdev)
|
||||
return 0;
|
||||
|
||||
fwnode_remove:
|
||||
fwnode_remove_software_node(tcpm->tcpc.fwnode);
|
||||
fwnode_handle_put(tcpm->tcpc.fwnode);
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -280,7 +280,7 @@ static void qcom_pmic_typec_remove(struct platform_device *pdev)
|
||||
qcom_pmic_typec_pdphy_stop(tcpm->pmic_typec_pdphy);
|
||||
qcom_pmic_typec_port_stop(tcpm->pmic_typec_port);
|
||||
tcpm_unregister_port(tcpm->tcpm_port);
|
||||
fwnode_remove_software_node(tcpm->tcpc.fwnode);
|
||||
fwnode_handle_put(tcpm->tcpc.fwnode);
|
||||
}
|
||||
|
||||
static struct pmic_typec_pdphy_resources pm8150b_pdphy_res = {
|
||||
|
||||
25
fs/afs/dir.c
25
fs/afs/dir.c
@@ -12,6 +12,7 @@
|
||||
#include <linux/swap.h>
|
||||
#include <linux/ctype.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/iversion.h>
|
||||
#include <linux/task_io_accounting_ops.h>
|
||||
#include "internal.h"
|
||||
#include "afs_fs.h"
|
||||
@@ -1809,6 +1810,8 @@ error:
|
||||
|
||||
static void afs_rename_success(struct afs_operation *op)
|
||||
{
|
||||
struct afs_vnode *vnode = AFS_FS_I(d_inode(op->dentry));
|
||||
|
||||
_enter("op=%08x", op->debug_id);
|
||||
|
||||
op->ctime = op->file[0].scb.status.mtime_client;
|
||||
@@ -1818,6 +1821,22 @@ static void afs_rename_success(struct afs_operation *op)
|
||||
op->ctime = op->file[1].scb.status.mtime_client;
|
||||
afs_vnode_commit_status(op, &op->file[1]);
|
||||
}
|
||||
|
||||
/* If we're moving a subdir between dirs, we need to update
|
||||
* its DV counter too as the ".." will be altered.
|
||||
*/
|
||||
if (S_ISDIR(vnode->netfs.inode.i_mode) &&
|
||||
op->file[0].vnode != op->file[1].vnode) {
|
||||
u64 new_dv;
|
||||
|
||||
write_seqlock(&vnode->cb_lock);
|
||||
|
||||
new_dv = vnode->status.data_version + 1;
|
||||
vnode->status.data_version = new_dv;
|
||||
inode_set_iversion_raw(&vnode->netfs.inode, new_dv);
|
||||
|
||||
write_sequnlock(&vnode->cb_lock);
|
||||
}
|
||||
}
|
||||
|
||||
static void afs_rename_edit_dir(struct afs_operation *op)
|
||||
@@ -1859,6 +1878,12 @@ static void afs_rename_edit_dir(struct afs_operation *op)
|
||||
&vnode->fid, afs_edit_dir_for_rename_2);
|
||||
}
|
||||
|
||||
if (S_ISDIR(vnode->netfs.inode.i_mode) &&
|
||||
new_dvnode != orig_dvnode &&
|
||||
test_bit(AFS_VNODE_DIR_VALID, &vnode->flags))
|
||||
afs_edit_dir_update_dotdot(vnode, new_dvnode,
|
||||
afs_edit_dir_for_rename_sub);
|
||||
|
||||
new_inode = d_inode(new_dentry);
|
||||
if (new_inode) {
|
||||
spin_lock(&new_inode->i_lock);
|
||||
|
||||
@@ -127,10 +127,10 @@ static struct folio *afs_dir_get_folio(struct afs_vnode *vnode, pgoff_t index)
|
||||
/*
|
||||
* Scan a directory block looking for a dirent of the right name.
|
||||
*/
|
||||
static int afs_dir_scan_block(union afs_xdr_dir_block *block, struct qstr *name,
|
||||
static int afs_dir_scan_block(const union afs_xdr_dir_block *block, const struct qstr *name,
|
||||
unsigned int blocknum)
|
||||
{
|
||||
union afs_xdr_dirent *de;
|
||||
const union afs_xdr_dirent *de;
|
||||
u64 bitmap;
|
||||
int d, len, n;
|
||||
|
||||
@@ -492,3 +492,90 @@ error:
|
||||
clear_bit(AFS_VNODE_DIR_VALID, &vnode->flags);
|
||||
goto out_unmap;
|
||||
}
|
||||
|
||||
/*
|
||||
* Edit a subdirectory that has been moved between directories to update the
|
||||
* ".." entry.
|
||||
*/
|
||||
void afs_edit_dir_update_dotdot(struct afs_vnode *vnode, struct afs_vnode *new_dvnode,
|
||||
enum afs_edit_dir_reason why)
|
||||
{
|
||||
union afs_xdr_dir_block *block;
|
||||
union afs_xdr_dirent *de;
|
||||
struct folio *folio;
|
||||
unsigned int nr_blocks, b;
|
||||
pgoff_t index;
|
||||
loff_t i_size;
|
||||
int slot;
|
||||
|
||||
_enter("");
|
||||
|
||||
i_size = i_size_read(&vnode->netfs.inode);
|
||||
if (i_size < AFS_DIR_BLOCK_SIZE) {
|
||||
clear_bit(AFS_VNODE_DIR_VALID, &vnode->flags);
|
||||
return;
|
||||
}
|
||||
nr_blocks = i_size / AFS_DIR_BLOCK_SIZE;
|
||||
|
||||
/* Find a block that has sufficient slots available. Each folio
|
||||
* contains two or more directory blocks.
|
||||
*/
|
||||
for (b = 0; b < nr_blocks; b++) {
|
||||
index = b / AFS_DIR_BLOCKS_PER_PAGE;
|
||||
folio = afs_dir_get_folio(vnode, index);
|
||||
if (!folio)
|
||||
goto error;
|
||||
|
||||
block = kmap_local_folio(folio, b * AFS_DIR_BLOCK_SIZE - folio_pos(folio));
|
||||
|
||||
/* Abandon the edit if we got a callback break. */
|
||||
if (!test_bit(AFS_VNODE_DIR_VALID, &vnode->flags))
|
||||
goto invalidated;
|
||||
|
||||
slot = afs_dir_scan_block(block, &dotdot_name, b);
|
||||
if (slot >= 0)
|
||||
goto found_dirent;
|
||||
|
||||
kunmap_local(block);
|
||||
folio_unlock(folio);
|
||||
folio_put(folio);
|
||||
}
|
||||
|
||||
/* Didn't find the dirent to clobber. Download the directory again. */
|
||||
trace_afs_edit_dir(vnode, why, afs_edit_dir_update_nodd,
|
||||
0, 0, 0, 0, "..");
|
||||
clear_bit(AFS_VNODE_DIR_VALID, &vnode->flags);
|
||||
goto out;
|
||||
|
||||
found_dirent:
|
||||
de = &block->dirents[slot];
|
||||
de->u.vnode = htonl(new_dvnode->fid.vnode);
|
||||
de->u.unique = htonl(new_dvnode->fid.unique);
|
||||
|
||||
trace_afs_edit_dir(vnode, why, afs_edit_dir_update_dd, b, slot,
|
||||
ntohl(de->u.vnode), ntohl(de->u.unique), "..");
|
||||
|
||||
kunmap_local(block);
|
||||
folio_unlock(folio);
|
||||
folio_put(folio);
|
||||
inode_set_iversion_raw(&vnode->netfs.inode, vnode->status.data_version);
|
||||
|
||||
out:
|
||||
_leave("");
|
||||
return;
|
||||
|
||||
invalidated:
|
||||
kunmap_local(block);
|
||||
folio_unlock(folio);
|
||||
folio_put(folio);
|
||||
trace_afs_edit_dir(vnode, why, afs_edit_dir_update_inval,
|
||||
0, 0, 0, 0, "..");
|
||||
clear_bit(AFS_VNODE_DIR_VALID, &vnode->flags);
|
||||
goto out;
|
||||
|
||||
error:
|
||||
trace_afs_edit_dir(vnode, why, afs_edit_dir_update_error,
|
||||
0, 0, 0, 0, "..");
|
||||
clear_bit(AFS_VNODE_DIR_VALID, &vnode->flags);
|
||||
goto out;
|
||||
}
|
||||
|
||||
@@ -1037,6 +1037,8 @@ extern void afs_check_for_remote_deletion(struct afs_operation *);
|
||||
extern void afs_edit_dir_add(struct afs_vnode *, struct qstr *, struct afs_fid *,
|
||||
enum afs_edit_dir_reason);
|
||||
extern void afs_edit_dir_remove(struct afs_vnode *, struct qstr *, enum afs_edit_dir_reason);
|
||||
void afs_edit_dir_update_dotdot(struct afs_vnode *vnode, struct afs_vnode *new_dvnode,
|
||||
enum afs_edit_dir_reason why);
|
||||
|
||||
/*
|
||||
* dir_silly.c
|
||||
|
||||
49
fs/dax.c
49
fs/dax.c
@@ -1262,35 +1262,46 @@ static s64 dax_unshare_iter(struct iomap_iter *iter)
|
||||
{
|
||||
struct iomap *iomap = &iter->iomap;
|
||||
const struct iomap *srcmap = iomap_iter_srcmap(iter);
|
||||
loff_t pos = iter->pos;
|
||||
loff_t length = iomap_length(iter);
|
||||
loff_t copy_pos = iter->pos;
|
||||
u64 copy_len = iomap_length(iter);
|
||||
u32 mod;
|
||||
int id = 0;
|
||||
s64 ret = 0;
|
||||
void *daddr = NULL, *saddr = NULL;
|
||||
|
||||
/* don't bother with blocks that are not shared to start with */
|
||||
if (!(iomap->flags & IOMAP_F_SHARED))
|
||||
return length;
|
||||
if (!iomap_want_unshare_iter(iter))
|
||||
return iomap_length(iter);
|
||||
|
||||
id = dax_read_lock();
|
||||
ret = dax_iomap_direct_access(iomap, pos, length, &daddr, NULL);
|
||||
if (ret < 0)
|
||||
goto out_unlock;
|
||||
|
||||
/* zero the distance if srcmap is HOLE or UNWRITTEN */
|
||||
if (srcmap->flags & IOMAP_F_SHARED || srcmap->type == IOMAP_UNWRITTEN) {
|
||||
memset(daddr, 0, length);
|
||||
dax_flush(iomap->dax_dev, daddr, length);
|
||||
ret = length;
|
||||
goto out_unlock;
|
||||
/*
|
||||
* Extend the file range to be aligned to fsblock/pagesize, because
|
||||
* we need to copy entire blocks, not just the byte range specified.
|
||||
* Invalidate the mapping because we're about to CoW.
|
||||
*/
|
||||
mod = offset_in_page(copy_pos);
|
||||
if (mod) {
|
||||
copy_len += mod;
|
||||
copy_pos -= mod;
|
||||
}
|
||||
|
||||
ret = dax_iomap_direct_access(srcmap, pos, length, &saddr, NULL);
|
||||
mod = offset_in_page(copy_pos + copy_len);
|
||||
if (mod)
|
||||
copy_len += PAGE_SIZE - mod;
|
||||
|
||||
invalidate_inode_pages2_range(iter->inode->i_mapping,
|
||||
copy_pos >> PAGE_SHIFT,
|
||||
(copy_pos + copy_len - 1) >> PAGE_SHIFT);
|
||||
|
||||
id = dax_read_lock();
|
||||
ret = dax_iomap_direct_access(iomap, copy_pos, copy_len, &daddr, NULL);
|
||||
if (ret < 0)
|
||||
goto out_unlock;
|
||||
|
||||
if (copy_mc_to_kernel(daddr, saddr, length) == 0)
|
||||
ret = length;
|
||||
ret = dax_iomap_direct_access(srcmap, copy_pos, copy_len, &saddr, NULL);
|
||||
if (ret < 0)
|
||||
goto out_unlock;
|
||||
|
||||
if (copy_mc_to_kernel(daddr, saddr, copy_len) == 0)
|
||||
ret = iomap_length(iter);
|
||||
else
|
||||
ret = -EIO;
|
||||
|
||||
|
||||
@@ -1273,16 +1273,11 @@ EXPORT_SYMBOL_GPL(iomap_file_buffered_write_punch_delalloc);
|
||||
static loff_t iomap_unshare_iter(struct iomap_iter *iter)
|
||||
{
|
||||
struct iomap *iomap = &iter->iomap;
|
||||
const struct iomap *srcmap = iomap_iter_srcmap(iter);
|
||||
loff_t pos = iter->pos;
|
||||
loff_t length = iomap_length(iter);
|
||||
loff_t written = 0;
|
||||
|
||||
/* don't bother with blocks that are not shared to start with */
|
||||
if (!(iomap->flags & IOMAP_F_SHARED))
|
||||
return length;
|
||||
/* don't bother with holes or unwritten extents */
|
||||
if (srcmap->type == IOMAP_HOLE || srcmap->type == IOMAP_UNWRITTEN)
|
||||
if (!iomap_want_unshare_iter(iter))
|
||||
return length;
|
||||
|
||||
do {
|
||||
|
||||
@@ -981,6 +981,11 @@ void nfs_delegation_mark_returned(struct inode *inode,
|
||||
}
|
||||
|
||||
nfs_mark_delegation_revoked(delegation);
|
||||
clear_bit(NFS_DELEGATION_RETURNING, &delegation->flags);
|
||||
spin_unlock(&delegation->lock);
|
||||
if (nfs_detach_delegation(NFS_I(inode), delegation, NFS_SERVER(inode)))
|
||||
nfs_put_delegation(delegation);
|
||||
goto out_rcu_unlock;
|
||||
|
||||
out_clear_returning:
|
||||
clear_bit(NFS_DELEGATION_RETURNING, &delegation->flags);
|
||||
|
||||
@@ -157,6 +157,9 @@ static int nilfs_symlink(struct mnt_idmap *idmap, struct inode *dir,
|
||||
/* slow symlink */
|
||||
inode->i_op = &nilfs_symlink_inode_operations;
|
||||
inode_nohighmem(inode);
|
||||
mapping_set_gfp_mask(inode->i_mapping,
|
||||
mapping_gfp_constraint(inode->i_mapping,
|
||||
~__GFP_FS));
|
||||
inode->i_mapping->a_ops = &nilfs_aops;
|
||||
err = page_symlink(inode, symname, l);
|
||||
if (err)
|
||||
|
||||
@@ -405,6 +405,7 @@ void nilfs_clear_dirty_page(struct page *page, bool silent)
|
||||
|
||||
ClearPageUptodate(page);
|
||||
ClearPageMappedToDisk(page);
|
||||
ClearPageChecked(page);
|
||||
|
||||
if (page_has_buffers(page)) {
|
||||
struct buffer_head *bh, *head;
|
||||
|
||||
@@ -1173,7 +1173,14 @@ static int ntfs_file_release(struct inode *inode, struct file *file)
|
||||
/* If we are last writer on the inode, drop the block reservation. */
|
||||
if (sbi->options->prealloc &&
|
||||
((file->f_mode & FMODE_WRITE) &&
|
||||
atomic_read(&inode->i_writecount) == 1)) {
|
||||
atomic_read(&inode->i_writecount) == 1)
|
||||
/*
|
||||
* The only file when inode->i_fop = &ntfs_file_operations and
|
||||
* init_rwsem(&ni->file.run_lock) is not called explicitly is MFT.
|
||||
*
|
||||
* Add additional check here.
|
||||
*/
|
||||
&& inode->i_ino != MFT_REC_MFT) {
|
||||
ni_lock(ni);
|
||||
down_write(&ni->file.run_lock);
|
||||
|
||||
|
||||
@@ -102,7 +102,9 @@ void ni_clear(struct ntfs_inode *ni)
|
||||
{
|
||||
struct rb_node *node;
|
||||
|
||||
if (!ni->vfs_inode.i_nlink && ni->mi.mrec && is_rec_inuse(ni->mi.mrec))
|
||||
if (!ni->vfs_inode.i_nlink && ni->mi.mrec &&
|
||||
is_rec_inuse(ni->mi.mrec) &&
|
||||
!(ni->mi.sbi->flags & NTFS_FLAGS_LOG_REPLAYING))
|
||||
ni_delete_all(ni);
|
||||
|
||||
al_destroy(ni);
|
||||
|
||||
@@ -532,11 +532,15 @@ struct inode *ntfs_iget5(struct super_block *sb, const struct MFT_REF *ref,
|
||||
if (inode->i_state & I_NEW)
|
||||
inode = ntfs_read_mft(inode, name, ref);
|
||||
else if (ref->seq != ntfs_i(inode)->mi.mrec->seq) {
|
||||
/* Inode overlaps? */
|
||||
_ntfs_bad_inode(inode);
|
||||
/*
|
||||
* Sequence number is not expected.
|
||||
* Looks like inode was reused but caller uses the old reference
|
||||
*/
|
||||
iput(inode);
|
||||
inode = ERR_PTR(-ESTALE);
|
||||
}
|
||||
|
||||
if (IS_ERR(inode) && name)
|
||||
if (IS_ERR(inode))
|
||||
ntfs_set_state(sb->s_fs_info, NTFS_DIRTY_ERROR);
|
||||
|
||||
return inode;
|
||||
@@ -1699,7 +1703,10 @@ out6:
|
||||
attr = ni_find_attr(ni, NULL, NULL, ATTR_EA, NULL, 0, NULL, NULL);
|
||||
if (attr && attr->non_res) {
|
||||
/* Delete ATTR_EA, if non-resident. */
|
||||
attr_set_size(ni, ATTR_EA, NULL, 0, NULL, 0, NULL, false, NULL);
|
||||
struct runs_tree run;
|
||||
run_init(&run);
|
||||
attr_set_size(ni, ATTR_EA, NULL, 0, &run, 0, NULL, false, NULL);
|
||||
run_close(&run);
|
||||
}
|
||||
|
||||
if (rp_inserted)
|
||||
|
||||
@@ -236,6 +236,9 @@ static inline ssize_t decompress_chunk(u8 *unc, u8 *unc_end, const u8 *cmpr,
|
||||
|
||||
/* Do decompression until pointers are inside range. */
|
||||
while (up < unc_end && cmpr < cmpr_end) {
|
||||
// return err if more than LZNT_CHUNK_SIZE bytes are written
|
||||
if (up - unc > LZNT_CHUNK_SIZE)
|
||||
return -EINVAL;
|
||||
/* Correct index */
|
||||
while (unc + s_max_off[index] < up)
|
||||
index += 1;
|
||||
|
||||
@@ -81,7 +81,7 @@ static struct dentry *ntfs_lookup(struct inode *dir, struct dentry *dentry,
|
||||
if (err < 0)
|
||||
inode = ERR_PTR(err);
|
||||
else {
|
||||
ni_lock(ni);
|
||||
ni_lock_dir(ni);
|
||||
inode = dir_search_u(dir, uni, NULL);
|
||||
ni_unlock(ni);
|
||||
}
|
||||
|
||||
@@ -334,7 +334,7 @@ struct mft_inode {
|
||||
|
||||
/* Nested class for ntfs_inode::ni_lock. */
|
||||
enum ntfs_inode_mutex_lock_class {
|
||||
NTFS_INODE_MUTEX_DIRTY,
|
||||
NTFS_INODE_MUTEX_DIRTY = 1,
|
||||
NTFS_INODE_MUTEX_SECURITY,
|
||||
NTFS_INODE_MUTEX_OBJID,
|
||||
NTFS_INODE_MUTEX_REPARSE,
|
||||
|
||||
@@ -223,29 +223,21 @@ struct ATTRIB *mi_enum_attr(struct mft_inode *mi, struct ATTRIB *attr)
|
||||
prev_type = 0;
|
||||
attr = Add2Ptr(rec, off);
|
||||
} else {
|
||||
/* Check if input attr inside record. */
|
||||
/*
|
||||
* We don't need to check previous attr here. There is
|
||||
* a bounds checking in the previous round.
|
||||
*/
|
||||
off = PtrOffset(rec, attr);
|
||||
if (off >= used)
|
||||
return NULL;
|
||||
|
||||
asize = le32_to_cpu(attr->size);
|
||||
if (asize < SIZEOF_RESIDENT) {
|
||||
/* Impossible 'cause we should not return such attribute. */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Overflow check. */
|
||||
if (off + asize < off)
|
||||
return NULL;
|
||||
|
||||
prev_type = le32_to_cpu(attr->type);
|
||||
attr = Add2Ptr(attr, asize);
|
||||
off += asize;
|
||||
}
|
||||
|
||||
asize = le32_to_cpu(attr->size);
|
||||
|
||||
/* Can we use the first field (attr->type). */
|
||||
/* NOTE: this code also checks attr->size availability. */
|
||||
if (off + 8 > used) {
|
||||
static_assert(ALIGN(sizeof(enum ATTR_TYPE), 8) == 8);
|
||||
return NULL;
|
||||
@@ -265,6 +257,8 @@ struct ATTRIB *mi_enum_attr(struct mft_inode *mi, struct ATTRIB *attr)
|
||||
if (t32 < prev_type)
|
||||
return NULL;
|
||||
|
||||
asize = le32_to_cpu(attr->size);
|
||||
|
||||
/* Check overflow and boundary. */
|
||||
if (off + asize < off || off + asize > used)
|
||||
return NULL;
|
||||
@@ -293,6 +287,10 @@ struct ATTRIB *mi_enum_attr(struct mft_inode *mi, struct ATTRIB *attr)
|
||||
if (attr->non_res != 1)
|
||||
return NULL;
|
||||
|
||||
/* Can we use memory including attr->nres.valid_size? */
|
||||
if (asize < SIZEOF_NONRESIDENT)
|
||||
return NULL;
|
||||
|
||||
t16 = le16_to_cpu(attr->nres.run_off);
|
||||
if (t16 > asize)
|
||||
return NULL;
|
||||
@@ -319,7 +317,8 @@ struct ATTRIB *mi_enum_attr(struct mft_inode *mi, struct ATTRIB *attr)
|
||||
|
||||
if (!attr->nres.svcn && is_attr_ext(attr)) {
|
||||
/* First segment of sparse/compressed attribute */
|
||||
if (asize + 8 < SIZEOF_NONRESIDENT_EX)
|
||||
/* Can we use memory including attr->nres.total_size? */
|
||||
if (asize < SIZEOF_NONRESIDENT_EX)
|
||||
return NULL;
|
||||
|
||||
tot_size = le64_to_cpu(attr->nres.total_size);
|
||||
@@ -329,10 +328,10 @@ struct ATTRIB *mi_enum_attr(struct mft_inode *mi, struct ATTRIB *attr)
|
||||
if (tot_size > alloc_size)
|
||||
return NULL;
|
||||
} else {
|
||||
if (asize + 8 < SIZEOF_NONRESIDENT)
|
||||
if (attr->nres.c_unit)
|
||||
return NULL;
|
||||
|
||||
if (attr->nres.c_unit)
|
||||
if (alloc_size > mi->sbi->volume.size)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
@@ -1783,6 +1783,14 @@ int ocfs2_remove_inode_range(struct inode *inode,
|
||||
return 0;
|
||||
|
||||
if (OCFS2_I(inode)->ip_dyn_features & OCFS2_INLINE_DATA_FL) {
|
||||
int id_count = ocfs2_max_inline_data_with_xattr(inode->i_sb, di);
|
||||
|
||||
if (byte_start > id_count || byte_start + byte_len > id_count) {
|
||||
ret = -EINVAL;
|
||||
mlog_errno(ret);
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = ocfs2_truncate_inline(inode, di_bh, byte_start,
|
||||
byte_start + byte_len, 0);
|
||||
if (ret) {
|
||||
|
||||
@@ -484,10 +484,21 @@ cifsConvertToUTF16(__le16 *target, const char *source, int srclen,
|
||||
/**
|
||||
* Remap spaces and periods found at the end of every
|
||||
* component of the path. The special cases of '.' and
|
||||
* '..' do not need to be dealt with explicitly because
|
||||
* they are addressed in namei.c:link_path_walk().
|
||||
* '..' are need to be handled because of symlinks.
|
||||
* They are treated as non-end-of-string to avoid
|
||||
* remapping and breaking symlinks pointing to . or ..
|
||||
**/
|
||||
if ((i == srclen - 1) || (source[i+1] == '\\'))
|
||||
if ((i == 0 || source[i-1] == '\\') &&
|
||||
source[i] == '.' &&
|
||||
(i == srclen-1 || source[i+1] == '\\'))
|
||||
end_of_string = false; /* "." case */
|
||||
else if (i >= 1 &&
|
||||
(i == 1 || source[i-2] == '\\') &&
|
||||
source[i-1] == '.' &&
|
||||
source[i] == '.' &&
|
||||
(i == srclen-1 || source[i+1] == '\\'))
|
||||
end_of_string = false; /* ".." case */
|
||||
else if ((i == srclen - 1) || (source[i+1] == '\\'))
|
||||
end_of_string = true;
|
||||
else
|
||||
end_of_string = false;
|
||||
|
||||
@@ -14,6 +14,12 @@
|
||||
#include "fs_context.h"
|
||||
#include "reparse.h"
|
||||
|
||||
static int detect_directory_symlink_target(struct cifs_sb_info *cifs_sb,
|
||||
const unsigned int xid,
|
||||
const char *full_path,
|
||||
const char *symname,
|
||||
bool *directory);
|
||||
|
||||
int smb2_create_reparse_symlink(const unsigned int xid, struct inode *inode,
|
||||
struct dentry *dentry, struct cifs_tcon *tcon,
|
||||
const char *full_path, const char *symname)
|
||||
@@ -24,6 +30,7 @@ int smb2_create_reparse_symlink(const unsigned int xid, struct inode *inode,
|
||||
struct inode *new;
|
||||
struct kvec iov;
|
||||
__le16 *path;
|
||||
bool directory;
|
||||
char *sym, sep = CIFS_DIR_SEP(cifs_sb);
|
||||
u16 len, plen;
|
||||
int rc = 0;
|
||||
@@ -45,6 +52,18 @@ int smb2_create_reparse_symlink(const unsigned int xid, struct inode *inode,
|
||||
goto out;
|
||||
}
|
||||
|
||||
/*
|
||||
* SMB distinguish between symlink to directory and symlink to file.
|
||||
* They cannot be exchanged (symlink of file type which points to
|
||||
* directory cannot be resolved and vice-versa). Try to detect if
|
||||
* the symlink target could be a directory or not. When detection
|
||||
* fails then treat symlink as a file (non-directory) symlink.
|
||||
*/
|
||||
directory = false;
|
||||
rc = detect_directory_symlink_target(cifs_sb, xid, full_path, symname, &directory);
|
||||
if (rc < 0)
|
||||
goto out;
|
||||
|
||||
plen = 2 * UniStrnlen((wchar_t *)path, PATH_MAX);
|
||||
len = sizeof(*buf) + plen * 2;
|
||||
buf = kzalloc(len, GFP_KERNEL);
|
||||
@@ -69,7 +88,8 @@ int smb2_create_reparse_symlink(const unsigned int xid, struct inode *inode,
|
||||
iov.iov_base = buf;
|
||||
iov.iov_len = len;
|
||||
new = smb2_get_reparse_inode(&data, inode->i_sb, xid,
|
||||
tcon, full_path, &iov, NULL);
|
||||
tcon, full_path, directory,
|
||||
&iov, NULL);
|
||||
if (!IS_ERR(new))
|
||||
d_instantiate(dentry, new);
|
||||
else
|
||||
@@ -81,6 +101,144 @@ out:
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int detect_directory_symlink_target(struct cifs_sb_info *cifs_sb,
|
||||
const unsigned int xid,
|
||||
const char *full_path,
|
||||
const char *symname,
|
||||
bool *directory)
|
||||
{
|
||||
char sep = CIFS_DIR_SEP(cifs_sb);
|
||||
struct cifs_open_parms oparms;
|
||||
struct tcon_link *tlink;
|
||||
struct cifs_tcon *tcon;
|
||||
const char *basename;
|
||||
struct cifs_fid fid;
|
||||
char *resolved_path;
|
||||
int full_path_len;
|
||||
int basename_len;
|
||||
int symname_len;
|
||||
char *path_sep;
|
||||
__u32 oplock;
|
||||
int open_rc;
|
||||
|
||||
/*
|
||||
* First do some simple check. If the original Linux symlink target ends
|
||||
* with slash, or last path component is dot or dot-dot then it is for
|
||||
* sure symlink to the directory.
|
||||
*/
|
||||
basename = kbasename(symname);
|
||||
basename_len = strlen(basename);
|
||||
if (basename_len == 0 || /* symname ends with slash */
|
||||
(basename_len == 1 && basename[0] == '.') || /* last component is "." */
|
||||
(basename_len == 2 && basename[0] == '.' && basename[1] == '.')) { /* or ".." */
|
||||
*directory = true;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* For absolute symlinks it is not possible to determinate
|
||||
* if it should point to directory or file.
|
||||
*/
|
||||
if (symname[0] == '/') {
|
||||
cifs_dbg(FYI,
|
||||
"%s: cannot determinate if the symlink target path '%s' "
|
||||
"is directory or not, creating '%s' as file symlink\n",
|
||||
__func__, symname, full_path);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* If it was not detected as directory yet and the symlink is relative
|
||||
* then try to resolve the path on the SMB server, check if the path
|
||||
* exists and determinate if it is a directory or not.
|
||||
*/
|
||||
|
||||
full_path_len = strlen(full_path);
|
||||
symname_len = strlen(symname);
|
||||
|
||||
tlink = cifs_sb_tlink(cifs_sb);
|
||||
if (IS_ERR(tlink))
|
||||
return PTR_ERR(tlink);
|
||||
|
||||
resolved_path = kzalloc(full_path_len + symname_len + 1, GFP_KERNEL);
|
||||
if (!resolved_path) {
|
||||
cifs_put_tlink(tlink);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
/*
|
||||
* Compose the resolved SMB symlink path from the SMB full path
|
||||
* and Linux target symlink path.
|
||||
*/
|
||||
memcpy(resolved_path, full_path, full_path_len+1);
|
||||
path_sep = strrchr(resolved_path, sep);
|
||||
if (path_sep)
|
||||
path_sep++;
|
||||
else
|
||||
path_sep = resolved_path;
|
||||
memcpy(path_sep, symname, symname_len+1);
|
||||
if (sep == '\\')
|
||||
convert_delimiter(path_sep, sep);
|
||||
|
||||
tcon = tlink_tcon(tlink);
|
||||
oparms = CIFS_OPARMS(cifs_sb, tcon, resolved_path,
|
||||
FILE_READ_ATTRIBUTES, FILE_OPEN, 0, ACL_NO_MODE);
|
||||
oparms.fid = &fid;
|
||||
|
||||
/* Try to open as a directory (NOT_FILE) */
|
||||
oplock = 0;
|
||||
oparms.create_options = cifs_create_options(cifs_sb,
|
||||
CREATE_NOT_FILE | OPEN_REPARSE_POINT);
|
||||
open_rc = tcon->ses->server->ops->open(xid, &oparms, &oplock, NULL);
|
||||
if (open_rc == 0) {
|
||||
/* Successful open means that the target path is definitely a directory. */
|
||||
*directory = true;
|
||||
tcon->ses->server->ops->close(xid, tcon, &fid);
|
||||
} else if (open_rc == -ENOTDIR) {
|
||||
/* -ENOTDIR means that the target path is definitely a file. */
|
||||
*directory = false;
|
||||
} else if (open_rc == -ENOENT) {
|
||||
/* -ENOENT means that the target path does not exist. */
|
||||
cifs_dbg(FYI,
|
||||
"%s: symlink target path '%s' does not exist, "
|
||||
"creating '%s' as file symlink\n",
|
||||
__func__, symname, full_path);
|
||||
} else {
|
||||
/* Try to open as a file (NOT_DIR) */
|
||||
oplock = 0;
|
||||
oparms.create_options = cifs_create_options(cifs_sb,
|
||||
CREATE_NOT_DIR | OPEN_REPARSE_POINT);
|
||||
open_rc = tcon->ses->server->ops->open(xid, &oparms, &oplock, NULL);
|
||||
if (open_rc == 0) {
|
||||
/* Successful open means that the target path is definitely a file. */
|
||||
*directory = false;
|
||||
tcon->ses->server->ops->close(xid, tcon, &fid);
|
||||
} else if (open_rc == -EISDIR) {
|
||||
/* -EISDIR means that the target path is definitely a directory. */
|
||||
*directory = true;
|
||||
} else {
|
||||
/*
|
||||
* This code branch is called when we do not have a permission to
|
||||
* open the resolved_path or some other client/process denied
|
||||
* opening the resolved_path.
|
||||
*
|
||||
* TODO: Try to use ops->query_dir_first on the parent directory
|
||||
* of resolved_path, search for basename of resolved_path and
|
||||
* check if the ATTR_DIRECTORY is set in fi.Attributes. In some
|
||||
* case this could work also when opening of the path is denied.
|
||||
*/
|
||||
cifs_dbg(FYI,
|
||||
"%s: cannot determinate if the symlink target path '%s' "
|
||||
"is directory or not, creating '%s' as file symlink\n",
|
||||
__func__, symname, full_path);
|
||||
}
|
||||
}
|
||||
|
||||
kfree(resolved_path);
|
||||
cifs_put_tlink(tlink);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int nfs_set_reparse_buf(struct reparse_posix_data *buf,
|
||||
mode_t mode, dev_t dev,
|
||||
struct kvec *iov)
|
||||
@@ -108,8 +266,8 @@ static int nfs_set_reparse_buf(struct reparse_posix_data *buf,
|
||||
buf->InodeType = cpu_to_le64(type);
|
||||
buf->ReparseDataLength = cpu_to_le16(len + dlen -
|
||||
sizeof(struct reparse_data_buffer));
|
||||
*(__le64 *)buf->DataBuffer = cpu_to_le64(((u64)MAJOR(dev) << 32) |
|
||||
MINOR(dev));
|
||||
*(__le64 *)buf->DataBuffer = cpu_to_le64(((u64)MINOR(dev) << 32) |
|
||||
MAJOR(dev));
|
||||
iov->iov_base = buf;
|
||||
iov->iov_len = len + dlen;
|
||||
return 0;
|
||||
@@ -137,7 +295,7 @@ static int mknod_nfs(unsigned int xid, struct inode *inode,
|
||||
};
|
||||
|
||||
new = smb2_get_reparse_inode(&data, inode->i_sb, xid,
|
||||
tcon, full_path, &iov, NULL);
|
||||
tcon, full_path, false, &iov, NULL);
|
||||
if (!IS_ERR(new))
|
||||
d_instantiate(dentry, new);
|
||||
else
|
||||
@@ -283,7 +441,7 @@ static int mknod_wsl(unsigned int xid, struct inode *inode,
|
||||
data.wsl.eas_len = len;
|
||||
|
||||
new = smb2_get_reparse_inode(&data, inode->i_sb,
|
||||
xid, tcon, full_path,
|
||||
xid, tcon, full_path, false,
|
||||
&reparse_iov, &xattr_iov);
|
||||
if (!IS_ERR(new))
|
||||
d_instantiate(dentry, new);
|
||||
@@ -497,7 +655,7 @@ static void wsl_to_fattr(struct cifs_open_info_data *data,
|
||||
else if (!strncmp(name, SMB2_WSL_XATTR_MODE, nlen))
|
||||
fattr->cf_mode = (umode_t)le32_to_cpu(*(__le32 *)v);
|
||||
else if (!strncmp(name, SMB2_WSL_XATTR_DEV, nlen))
|
||||
fattr->cf_rdev = wsl_mkdev(v);
|
||||
fattr->cf_rdev = reparse_mkdev(v);
|
||||
} while (next);
|
||||
out:
|
||||
fattr->cf_dtype = S_DT(fattr->cf_mode);
|
||||
@@ -518,13 +676,13 @@ bool cifs_reparse_point_to_fattr(struct cifs_sb_info *cifs_sb,
|
||||
if (le16_to_cpu(buf->ReparseDataLength) != sizeof(buf->InodeType) + 8)
|
||||
return false;
|
||||
fattr->cf_mode |= S_IFCHR;
|
||||
fattr->cf_rdev = reparse_nfs_mkdev(buf);
|
||||
fattr->cf_rdev = reparse_mkdev(buf->DataBuffer);
|
||||
break;
|
||||
case NFS_SPECFILE_BLK:
|
||||
if (le16_to_cpu(buf->ReparseDataLength) != sizeof(buf->InodeType) + 8)
|
||||
return false;
|
||||
fattr->cf_mode |= S_IFBLK;
|
||||
fattr->cf_rdev = reparse_nfs_mkdev(buf);
|
||||
fattr->cf_rdev = reparse_mkdev(buf->DataBuffer);
|
||||
break;
|
||||
case NFS_SPECFILE_FIFO:
|
||||
fattr->cf_mode |= S_IFIFO;
|
||||
|
||||
@@ -18,14 +18,7 @@
|
||||
*/
|
||||
#define IO_REPARSE_TAG_INTERNAL ((__u32)~0U)
|
||||
|
||||
static inline dev_t reparse_nfs_mkdev(struct reparse_posix_data *buf)
|
||||
{
|
||||
u64 v = le64_to_cpu(*(__le64 *)buf->DataBuffer);
|
||||
|
||||
return MKDEV(v >> 32, v & 0xffffffff);
|
||||
}
|
||||
|
||||
static inline dev_t wsl_mkdev(void *ptr)
|
||||
static inline dev_t reparse_mkdev(void *ptr)
|
||||
{
|
||||
u64 v = le64_to_cpu(*(__le64 *)ptr);
|
||||
|
||||
|
||||
@@ -1198,6 +1198,7 @@ struct inode *smb2_get_reparse_inode(struct cifs_open_info_data *data,
|
||||
const unsigned int xid,
|
||||
struct cifs_tcon *tcon,
|
||||
const char *full_path,
|
||||
bool directory,
|
||||
struct kvec *reparse_iov,
|
||||
struct kvec *xattr_iov)
|
||||
{
|
||||
@@ -1217,7 +1218,7 @@ struct inode *smb2_get_reparse_inode(struct cifs_open_info_data *data,
|
||||
FILE_READ_ATTRIBUTES |
|
||||
FILE_WRITE_ATTRIBUTES,
|
||||
FILE_CREATE,
|
||||
CREATE_NOT_DIR | OPEN_REPARSE_POINT,
|
||||
(directory ? CREATE_NOT_FILE : CREATE_NOT_DIR) | OPEN_REPARSE_POINT,
|
||||
ACL_NO_MODE);
|
||||
if (xattr_iov)
|
||||
oparms.ea_cctx = xattr_iov;
|
||||
|
||||
@@ -61,6 +61,7 @@ struct inode *smb2_get_reparse_inode(struct cifs_open_info_data *data,
|
||||
const unsigned int xid,
|
||||
struct cifs_tcon *tcon,
|
||||
const char *full_path,
|
||||
bool directory,
|
||||
struct kvec *reparse_iov,
|
||||
struct kvec *xattr_iov);
|
||||
int smb2_query_reparse_point(const unsigned int xid,
|
||||
|
||||
@@ -64,7 +64,7 @@ xfs_filestream_pick_ag(
|
||||
struct xfs_perag *pag;
|
||||
struct xfs_perag *max_pag = NULL;
|
||||
xfs_extlen_t minlen = *longest;
|
||||
xfs_extlen_t free = 0, minfree, maxfree = 0;
|
||||
xfs_extlen_t minfree, maxfree = 0;
|
||||
xfs_agnumber_t agno;
|
||||
bool first_pass = true;
|
||||
int err;
|
||||
@@ -107,7 +107,6 @@ restart:
|
||||
!(flags & XFS_PICK_USERDATA) ||
|
||||
(flags & XFS_PICK_LOWSPACE))) {
|
||||
/* Break out, retaining the reference on the AG. */
|
||||
free = pag->pagf_freeblks;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -150,23 +149,25 @@ restart:
|
||||
* grab.
|
||||
*/
|
||||
if (!max_pag) {
|
||||
for_each_perag_wrap(args->mp, 0, start_agno, args->pag)
|
||||
for_each_perag_wrap(args->mp, 0, start_agno, pag) {
|
||||
max_pag = pag;
|
||||
break;
|
||||
atomic_inc(&args->pag->pagf_fstrms);
|
||||
*longest = 0;
|
||||
} else {
|
||||
pag = max_pag;
|
||||
free = maxfree;
|
||||
atomic_inc(&pag->pagf_fstrms);
|
||||
}
|
||||
|
||||
/* Bail if there are no AGs at all to select from. */
|
||||
if (!max_pag)
|
||||
return -ENOSPC;
|
||||
}
|
||||
|
||||
pag = max_pag;
|
||||
atomic_inc(&pag->pagf_fstrms);
|
||||
} else if (max_pag) {
|
||||
xfs_perag_rele(max_pag);
|
||||
}
|
||||
|
||||
trace_xfs_filestream_pick(pag, pino, free);
|
||||
trace_xfs_filestream_pick(pag, pino);
|
||||
args->pag = pag;
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
static struct xfs_inode *
|
||||
|
||||
@@ -672,8 +672,8 @@ DEFINE_FILESTREAM_EVENT(xfs_filestream_lookup);
|
||||
DEFINE_FILESTREAM_EVENT(xfs_filestream_scan);
|
||||
|
||||
TRACE_EVENT(xfs_filestream_pick,
|
||||
TP_PROTO(struct xfs_perag *pag, xfs_ino_t ino, xfs_extlen_t free),
|
||||
TP_ARGS(pag, ino, free),
|
||||
TP_PROTO(struct xfs_perag *pag, xfs_ino_t ino),
|
||||
TP_ARGS(pag, ino),
|
||||
TP_STRUCT__entry(
|
||||
__field(dev_t, dev)
|
||||
__field(xfs_ino_t, ino)
|
||||
@@ -684,14 +684,9 @@ TRACE_EVENT(xfs_filestream_pick,
|
||||
TP_fast_assign(
|
||||
__entry->dev = pag->pag_mount->m_super->s_dev;
|
||||
__entry->ino = ino;
|
||||
if (pag) {
|
||||
__entry->agno = pag->pag_agno;
|
||||
__entry->streams = atomic_read(&pag->pagf_fstrms);
|
||||
} else {
|
||||
__entry->agno = NULLAGNUMBER;
|
||||
__entry->streams = 0;
|
||||
}
|
||||
__entry->free = free;
|
||||
__entry->agno = pag->pag_agno;
|
||||
__entry->streams = atomic_read(&pag->pagf_fstrms);
|
||||
__entry->free = pag->pagf_freeblks;
|
||||
),
|
||||
TP_printk("dev %d:%d ino 0x%llx agno 0x%x streams %d free %d",
|
||||
MAJOR(__entry->dev), MINOR(__entry->dev),
|
||||
|
||||
@@ -65,7 +65,7 @@ struct cpc_desc {
|
||||
int write_cmd_status;
|
||||
int write_cmd_id;
|
||||
/* Lock used for RMW operations in cpc_write() */
|
||||
spinlock_t rmw_lock;
|
||||
raw_spinlock_t rmw_lock;
|
||||
struct cpc_register_resource cpc_regs[MAX_CPC_REG_ENT];
|
||||
struct acpi_psd_package domain_info;
|
||||
struct kobject kobj;
|
||||
|
||||
@@ -102,7 +102,11 @@
|
||||
#define __noscs __attribute__((__no_sanitize__("shadow-call-stack")))
|
||||
#endif
|
||||
|
||||
#ifdef __SANITIZE_HWADDRESS__
|
||||
#define __no_sanitize_address __attribute__((__no_sanitize__("hwaddress")))
|
||||
#else
|
||||
#define __no_sanitize_address __attribute__((__no_sanitize_address__))
|
||||
#endif
|
||||
|
||||
#if defined(__SANITIZE_THREAD__)
|
||||
#define __no_sanitize_thread __attribute__((__no_sanitize_thread__))
|
||||
|
||||
@@ -1063,6 +1063,9 @@ int device_for_each_child(struct device *dev, void *data,
|
||||
int (*fn)(struct device *dev, void *data));
|
||||
int device_for_each_child_reverse(struct device *dev, void *data,
|
||||
int (*fn)(struct device *dev, void *data));
|
||||
int device_for_each_child_reverse_from(struct device *parent,
|
||||
struct device *from, const void *data,
|
||||
int (*fn)(struct device *, const void *));
|
||||
struct device *device_find_child(struct device *dev, void *data,
|
||||
int (*match)(struct device *dev, void *data));
|
||||
struct device *device_find_child_by_name(struct device *parent,
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user